blackveil-dns 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +76 -0
- package/README.md +517 -0
- package/dist/index.d.ts +506 -0
- package/dist/index.js +5546 -0
- package/dist/index.js.map +1 -0
- package/dist/stdio.d.ts +12 -0
- package/dist/stdio.js +9854 -0
- package/dist/stdio.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/config.ts","../src/lib/dns-types.ts","../src/lib/dns-transport.ts","../src/lib/dns-records.ts","../src/lib/dns.ts","../src/lib/scoring-model.ts","../src/lib/context-profiles.ts","../src/lib/scoring-config.ts","../src/lib/scoring-engine.ts","../src/lib/adaptive-weights.ts","../src/lib/scoring.ts","../src/lib/provider-signature-source.ts","../src/lib/provider-signatures.ts","../src/tools/mx-analysis.ts","../src/tools/check-mx.ts","../src/lib/json-rpc.ts","../src/mcp/request.ts","../src/lib/rate-limiter-memory.ts","../src/lib/quota-coordinator.ts","../src/lib/rate-limiter.ts","../src/lib/log.ts","../src/lib/session-memory.ts","../src/lib/session.ts","../src/lib/sse.ts","../src/mcp/route-gates.ts","../src/mcp/execute.ts","../src/lib/sanitize.ts","../src/handlers/tool-args.ts","../src/lib/cache.ts","../src/tools/check-spf.ts","../src/tools/dmarc-utils.ts","../src/tools/spf-analysis.ts","../src/tools/spf-trust-surface.ts","../src/tools/check-dmarc.ts","../src/tools/check-dkim.ts","../src/tools/dkim-analysis.ts","../src/tools/check-dnssec.ts","../src/tools/dnssec-analysis.ts","../src/tools/check-ssl.ts","../src/tools/ssl-analysis.ts","../src/tools/check-mta-sts.ts","../src/tools/mta-sts-analysis.ts","../src/tools/check-ns.ts","../src/tools/ns-analysis.ts","../src/tools/check-caa.ts","../src/tools/caa-analysis.ts","../src/tools/check-bimi.ts","../src/tools/check-tlsrpt.ts","../src/tools/check-lookalikes.ts","../src/tools/lookalike-analysis.ts","../src/tools/check-shadow-domains.ts","../src/lib/public-suffix.ts","../src/tools/check-txt-hygiene.ts","../src/tools/check-http-security.ts","../src/tools/http-security-analysis.ts","../src/tools/check-dane.ts","../src/tools/dane-analysis.ts","../src/tools/check-mx-reputation.ts","../src/tools/mx-reputation-analysis.ts","../src/tools/check-srv.ts","../src/tools/srv-analysis.ts","../src/tools/check-zone-hygiene.ts","../src/tools/zone-hygiene-analysis.ts","../src/tools/scan-domain.ts","../src/tools/check-subdomain-takeover.ts","../src/tools/subdomain-takeover-analysis.ts","../src/tools/scan/post-processing.ts","../src/tools/scan/maturity-staging.ts","../src/lib/output-sanitize.ts","../src/tools/explain-finding-data.ts","../src/tools/explain-finding.ts","../src/tools/scan/format-report.ts","../src/tools/compare-baseline.ts","../src/handlers/tool-execution.ts","../src/handlers/tool-formatters.ts","../src/handlers/tool-schemas.ts","../src/handlers/tools.ts","../src/handlers/resources.ts","../src/handlers/prompts.ts","../src/lib/audit.ts","../src/mcp/dispatch.ts","../src/lib/server-version.ts","../src/stdio.ts"],"names":["parts","usage","selector","matchingType","certData","topCat","topDelta","normalizeDomain","MINUTE_MS","HOUR_MS","DAY_MS","SESSION_CREATE_WINDOW_MS","SESSION_CREATE_LIMIT_PER_MINUTE","checkDnssec","INITIAL_BATCH_SIZE","MIN_BATCH_SIZE","BACKOFF_DELAY_MS","FAILURE_THRESHOLD","PHASE1_DNS_OPTS","filterByNsExistence","usageLabel","findings","extractSpfSignalDomains","evidence","getParentDomain","hasDnssec","checkMx","payload"],"mappings":";;;;;;;;;;;;;;;AAAA,IAKa,kBAaA,aAAA,EACA,mBAAA,EAYA,qBAAA,EACA,iBAAA,EACA,kBACA,WAAA,EAMA,gBAAA,EAGA,cAAA,EAGA,WAAA,EAGA,oBAGA,mBAAA,EAGA,uBAAA,EAMA,mCAAA,EAqBA,uBAAA,EAUA,mBAYA,sBAAA,EA4BA,sBAAA;AApIb,IAAA,WAAA,GAAA,KAAA,CAAA;AAAA,EAAA,mBAAA,GAAA;AAKO,IAAM,gBAAA,GAAmB;AAAA,MAC/B,QAAA;AAAA,MACA,YAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA;AAAA,KACD;AACO,IAAM,aAAA,GAAgB,CAAC,WAAA,EAAa,uBAAuB,CAAA;AAC3D,IAAM,mBAAA,GAAsB;AAAA,MAClC,2CAAA;AAAA,MACA,0CAAA;AAAA,MACA,sDAAA;AAAA,MACA,oCAAA;AAAA,MACA,oCAAA;AAAA,MACA,cAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,kBAAA;AAAA,MACA;AAAA,KACD;AACO,IAAM,qBAAA,GAAwB,CAAC,SAAA,EAAW,WAAA,EAAa,WAAW,aAAa,CAAA;AAC/E,IAAM,iBAAA,GAAoB,GAAA;AAC1B,IAAM,gBAAA,GAAmB,EAAA;AACzB,IAAM,WAAA,GAAc,kCAAA;AAMpB,IAAM,gBAAA,GAAmB,GAAA;AAGzB,IAAM,cAAA,GAAiB,GAAA;AAGvB,IAAM,WAAA,GAAc,CAAA;AAGpB,IAAM,kBAAA,GAAqB,GAAA;AAG3B,IAAM,mBAAA,GAAsB,GAAA;AAG5B,IAAM,uBAAA,GAA0B,EAAA;AAMhC,IAAM,mCAAA,GAAsC,IAAA;AAqB5C,IAAM,uBAAA,GAA0B,GAAA;AAUhC,IAAM,iBAAA,GAAmD;AAAA,MAC/D,IAAA,EAAM,EAAA;AAAA,MACN,KAAA,EAAO,GAAA;AAAA,MACP,SAAA,EAAW,GAAA;AAAA,MACX,UAAA,EAAY,GAAA;AAAA,MACZ,OAAA,EAAS;AAAA,KACV;AAMO,IAAM,sBAAA,GAAiF;AAAA,MAC7F,OAAA,EAAS;AAAA,QACR,WAAA,EAAa,GAAA;AAAA,QACb,IAAA,EAAM,GAAA;AAAA,QACN,gBAAA,EAAkB,GAAA;AAAA,QAClB,SAAA,EAAW,GAAA;AAAA,QACX,WAAA,EAAa,GAAA;AAAA,QACb,UAAA,EAAY,GAAA;AAAA,QACZ,QAAA,EAAU,GAAA;AAAA,QACV,QAAA,EAAU,GAAA;AAAA,QACV,SAAA,EAAW,GAAA;AAAA,QACX,YAAA,EAAc,GAAA;AAAA,QACd,aAAA,EAAe,GAAA;AAAA,QACf,SAAA,EAAW,GAAA;AAAA,QACX,UAAA,EAAY,GAAA;AAAA,QACZ,YAAA,EAAc,GAAA;AAAA,QACd,gBAAA,EAAkB,GAAA;AAAA,QAClB,oBAAA,EAAsB,GAAA;AAAA,QACtB,iBAAA,EAAmB,GAAA;AAAA,QACnB,mBAAA,EAAqB,GAAA;AAAA,QACrB,UAAA,EAAY,GAAA;AAAA,QACZ,mBAAA,EAAqB,GAAA;AAAA,QACrB,SAAA,EAAW,GAAA;AAAA,QACX,kBAAA,EAAoB,GAAA;AAAA,QACpB,eAAA,EAAiB;AAAA;AAClB,KACD;AAEO,IAAM,sBAAA,GAAiD;AAAA,MAC7D,WAAA,EAAa,EAAA;AAAA,MACb,IAAA,EAAM,EAAA;AAAA,MACN,SAAA,EAAW,GAAA;AAAA,MACX,WAAA,EAAa,GAAA;AAAA,MACb,UAAA,EAAY,GAAA;AAAA,MACZ,QAAA,EAAU,GAAA;AAAA,MACV,QAAA,EAAU,GAAA;AAAA,MACV,SAAA,EAAW,GAAA;AAAA,MACX,YAAA,EAAc,GAAA;AAAA,MACd,aAAA,EAAe,GAAA;AAAA,MACf,SAAA,EAAW,GAAA;AAAA,MACX,UAAA,EAAY,GAAA;AAAA,MACZ,YAAA,EAAc,GAAA;AAAA,MACd,gBAAA,EAAkB,EAAA;AAAA,MAClB,eAAA,EAAiB,GAAA;AAAA,MACjB,gBAAA,EAAkB,GAAA;AAAA,MAClB,oBAAA,EAAsB,EAAA;AAAA,MACtB,iBAAA,EAAmB,GAAA;AAAA,MACnB,mBAAA,EAAqB,GAAA;AAAA,MACrB,UAAA,EAAY,GAAA;AAAA,MACZ,mBAAA,EAAqB,EAAA;AAAA,MACrB,SAAA,EAAW,GAAA;AAAA,MACX,kBAAA,EAAoB;AAAA,KACrB;AAAA,EAAA;AAAA,CAAA,CAAA;;;AC5JA,IAGa,UAAA;AAHb,IAAA,cAAA,GAAA,KAAA,CAAA;AAAA,EAAA,sBAAA,GAAA;AAGO,IAAM,UAAA,GAAa;AAAA,MACzB,CAAA,EAAG,CAAA;AAAA,MACH,IAAA,EAAM,EAAA;AAAA,MACN,KAAA,EAAO,CAAA;AAAA,MACP,EAAA,EAAI,EAAA;AAAA,MACJ,GAAA,EAAK,EAAA;AAAA,MACL,EAAA,EAAI,CAAA;AAAA,MACJ,GAAA,EAAK,CAAA;AAAA,MACL,GAAA,EAAK,GAAA;AAAA,MACL,IAAA,EAAM,EAAA;AAAA,MACN,MAAA,EAAQ,EAAA;AAAA,MACR,EAAA,EAAI,EAAA;AAAA,MACJ,KAAA,EAAO,EAAA;AAAA,MACP,GAAA,EAAK,EAAA;AAAA,MACL,GAAA,EAAK;AAAA,KACN;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACVA,SAAS,WAAA,CAAY,QAAA,EAAkB,MAAA,EAAgB,IAAA,EAAsB,WAAA,EAA8B;AAC1G,EAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,IAClC,IAAA,EAAM,MAAA;AAAA,IACN,IAAA;AAAA,IACA,GAAI,WAAA,GAAc,EAAE,EAAA,EAAI,GAAA,KAAQ;AAAC,GACjC,CAAA;AAED,EAAA,OAAO,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,UAAU,CAAA,CAAA;AACxC;AAEA,SAAS,eAAA,CAAgB,UAAuB,IAAA,EAA+B;AAC9E,EAAA,OAAA,CAAQ,QAAA,CAAS,MAAA,IAAU,EAAC,EAAG,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,UAAA,CAAW,IAAI,CAAC,CAAA;AACjF;AAEA,eAAe,gBAAA,CAAiB,KAAa,SAAA,EAAgD;AAC5F,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAE9D,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MACjC,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,EAAE,MAAA,EAAQ,sBAAA,EAAuB;AAAA,MAC1C,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,EAAA,EAAI,EAAE,QAAA,EAAU,kBAAA,EAAoB,iBAAiB,IAAA;AAAK,KAC1D,CAAA;AACD,IAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,IAAA;AACzB,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,QAAQ,OAAQ,IAAA,CAAqB,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAU,IAAA,CAAqB,MAAM,GAAG,OAAO,IAAA;AAC5J,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,SAAE;AACD,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACrB;AACD;AAEA,eAAe,oBAAA,CACd,QAAA,EACA,MAAA,EACA,IAAA,EACA,aACA,SAAA,EAC8B;AAC9B,EAAA,OAAO,iBAAiB,WAAA,CAAY,QAAA,EAAU,QAAQ,IAAA,EAAM,WAAW,GAAG,SAAS,CAAA;AACpF;AAOA,eAAe,gBAAA,CAAiB,GAAA,EAAa,SAAA,EAAmB,KAAA,EAA6C;AAC5G,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC9D,EAAA,IAAI;AACH,IAAA,MAAM,OAAA,GAAkC,EAAE,MAAA,EAAQ,sBAAA,EAAuB;AACzE,IAAA,IAAI,KAAA,EAAO,OAAA,CAAQ,YAAY,CAAA,GAAI,KAAA;AACnC,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MACjC,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA;AAAA,MACA,QAAQ,UAAA,CAAW;AAAA,KACnB,CAAA;AACD,IAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,IAAA;AACzB,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,QAAQ,OAAQ,IAAA,CAAqB,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAU,IAAA,CAAqB,MAAM,GAAG,OAAO,IAAA;AAC5J,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,SAAE;AACD,IAAA,YAAA,CAAa,OAAO,CAAA;AAAA,EACrB;AACD;AA2BA,eAAsB,QAAA,CAAS,MAAA,EAAgB,IAAA,EAAsB,WAAA,GAAc,OAAO,IAAA,EAA8C;AACvI,EAAA,MAAM,QAAQ,IAAA,EAAM,UAAA;AACpB,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,OAAO,gBAAA,CAAiB,MAAA,EAAQ,IAAA,EAAM,WAAA,EAAa,IAAI,CAAA;AAAA,EACxD;AAEA,EAAA,MAAM,WAAW,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,IAAI,IAAI,WAAW,CAAA,CAAA;AACjD,EAAA,MAAM,QAAA,GAAW,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA;AACnC,EAAA,IAAI,QAAA,EAAU;AACb,IAAA,OAAO,QAAA;AAAA,EACR;AAEA,EAAA,MAAM,OAAA,GAAU,gBAAA,CAAiB,MAAA,EAAQ,IAAA,EAAM,aAAa,IAAI,CAAA;AAChE,EAAA,KAAA,CAAM,GAAA,CAAI,UAAU,OAAO,CAAA;AAC3B,EAAA,OAAA,CAAQ,KAAA,CAAM,MAAM,KAAA,CAAM,MAAA,CAAO,QAAQ,CAAC,CAAA;AAC1C,EAAA,OAAO,OAAA;AACR;AAEA,eAAe,gBAAA,CAAiB,MAAA,EAAgB,IAAA,EAAsB,WAAA,GAAc,OAAO,IAAA,EAA8C;AACxI,EAAA,MAAM,SAAA,GAAY,MAAM,SAAA,IAAa,cAAA;AACrC,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,IAAW,WAAA;AACjC,EAAA,MAAM,2BAAA,GAA8B,MAAM,2BAAA,IAA+B,mCAAA;AACzE,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,YAAA,EAAc,MAAA,EAAQ,MAAM,WAAW,CAAA;AAE/D,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,OAAA,EAAS,OAAA,EAAA,EAAW;AACpD,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC9D,IAAA,IAAI,QAAA;AAEJ,IAAA,IAAI;AACH,MAAA,QAAA,GAAW,MAAM,MAAM,GAAA,EAAK;AAAA,QAC3B,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS,EAAE,MAAA,EAAQ,sBAAA,EAAuB;AAAA,QAC1C,QAAQ,UAAA,CAAW,MAAA;AAAA,QACnB,EAAA,EAAI,EAAE,QAAA,EAAU,kBAAA,EAAoB,iBAAiB,IAAA;AAAK,OAC1D,CAAA;AAAA,IACF,SAAS,GAAA,EAAK;AACb,MAAA,YAAA,CAAa,OAAO,CAAA;AACpB,MAAA,IAAI,GAAA,YAAe,YAAA,IAAgB,GAAA,CAAI,IAAA,KAAS,YAAA,EAAc;AAC7D,QAAA,IAAI,UAAU,OAAA,EAAS;AACtB,UAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,EAAG,uBAAA,IAA2B,OAAA,GAAU,CAAA,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAE,CAAC,CAAA;AACpG,UAAA;AAAA,QACD;AACA,QAAA,MAAM,IAAI,aAAA,CAAc,CAAA,0BAAA,EAA6B,SAAS,CAAA,EAAA,CAAA,EAAM,QAAQ,IAAI,CAAA;AAAA,MACjF;AACA,MAAA,IAAI,UAAU,OAAA,EAAS;AACtB,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,EAAG,uBAAA,IAA2B,OAAA,GAAU,CAAA,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAE,CAAC,CAAA;AACpG,QAAA;AAAA,MACD;AACA,MAAA,MAAM,IAAI,aAAA,CAAc,CAAA,kBAAA,EAAqB,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA,EAAI,MAAA,EAAQ,IAAI,CAAA;AAAA,IAC9G;AAEA,IAAA,YAAA,CAAa,OAAO,CAAA;AAEpB,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,MAAA,IAAI,OAAA,GAAU,OAAA,IAAW,QAAA,CAAS,MAAA,IAAU,GAAA,EAAK;AAChD,QAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,CAAA,KAAM,UAAA,CAAW,CAAA,EAAG,uBAAA,IAA2B,OAAA,GAAU,CAAA,CAAA,GAAK,IAAA,CAAK,MAAA,EAAO,GAAI,EAAE,CAAC,CAAA;AACpG,QAAA;AAAA,MACD;AACA,MAAA,MAAM,IAAI,cAAc,CAAA,kBAAA,EAAqB,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,MAAA,EAAQ,IAAA,EAAM,QAAA,CAAS,MAAM,CAAA;AAAA,IAC9F;AAEA,IAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,IAAA,EAAK;AAChC,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,QAAQ,OAAQ,GAAA,CAAoB,MAAA,KAAW,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAU,GAAA,CAAoB,MAAM,CAAA,EAAG;AAChJ,MAAA,MAAM,IAAI,aAAA,CAAc,6BAAA,EAA+B,MAAA,EAAQ,IAAI,CAAA;AAAA,IACpE;AACA,IAAA,MAAM,IAAA,GAAO,GAAA;AAEb,IAAA,IAAI,2BAAA,IAA+B,CAAC,IAAA,EAAM,yBAAA,IAA6B,CAAC,eAAA,CAAgB,IAAA,EAAM,IAAI,CAAA,EAAG;AAEpG,MAAA,IAAI,IAAA,EAAM,cAAc,QAAA,EAAU;AACjC,QAAA,MAAM,QAAQ,MAAM,gBAAA;AAAA,UACnB,YAAY,IAAA,CAAK,YAAA,CAAa,QAAA,EAAU,MAAA,EAAQ,MAAM,WAAW,CAAA;AAAA,UACjE,SAAA;AAAA,UACA,KAAK,YAAA,CAAa;AAAA,SACnB;AACA,QAAA,IAAI,KAAA,IAAS,eAAA,CAAgB,KAAA,EAAO,IAAI,CAAA,EAAG;AAC1C,UAAA,OAAO,KAAA;AAAA,QACR;AAAA,MACD;AAEA,MAAA,MAAM,SAAS,MAAM,oBAAA,CAAqB,qBAAqB,MAAA,EAAQ,IAAA,EAAM,aAAa,SAAS,CAAA;AACnG,MAAA,IAAI,MAAA,IAAU,eAAA,CAAgB,MAAA,EAAQ,IAAI,CAAA,EAAG;AAC5C,QAAA,OAAO,MAAA;AAAA,MACR;AAAA,IACD;AAEA,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,MAAM,IAAI,aAAA,CAAc,gCAAA,EAAkC,MAAA,EAAQ,IAAI,CAAA;AACvE;AArMA,IAKM,cACA,mBAAA,EA4EO,aAAA;AAlFb,IAAA,kBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,0BAAA,GAAA;AAEA,IAAA,WAAA,EAAA;AACA,IAAA,cAAA,EAAA;AAEA,IAAM,YAAA,GAAe,sCAAA;AACrB,IAAM,mBAAA,GAAsB,4BAAA;AA4ErB,IAAM,aAAA,GAAN,cAA4B,KAAA,CAAM;AAAA,MACxC,WAAA,CACC,OAAA,EACgB,MAAA,EACA,UAAA,EACA,MAAA,EACf;AACD,QAAA,KAAA,CAAM,OAAO,CAAA;AAJG,QAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,QAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,QAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAGhB,QAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,MACb;AAAA,KACD;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACvDA,eAAsB,eAAA,CAAgB,MAAA,EAAgB,IAAA,EAAsB,IAAA,EAA2C;AACtH,EAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAA,EAAQ,IAAA,EAAM,OAAO,IAAI,CAAA;AACrD,EAAA,OAAA,CAAQ,KAAK,MAAA,IAAU,EAAC,EAAG,MAAA,CAAO,CAAC,MAAA,KAAW,MAAA,CAAO,IAAA,KAAS,UAAA,CAAW,IAAI,CAAC,CAAA,CAAE,IAAI,CAAC,MAAA,KAAW,OAAO,IAAI,CAAA;AAC5G;AAYA,eAAsB,eAAA,CAAgB,QAAgB,IAAA,EAA2C;AAChG,EAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,MAAA,EAAQ,OAAO,IAAI,CAAA;AACzD,EAAA,OAAO,OAAA,CAAQ,GAAA;AAAA,IAAI,CAAC,MAAA,KACnB,cAAA;AAAA,MACC,OACE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAClB,OAAA,CAAQ,UAAU,EAAE;AAAA;AACvB,GACD;AACD;AASO,SAAS,eAAe,IAAA,EAAsB;AACpD,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KACjB,CAAA,CAAE,QAAQ,kBAAA,EAAoB,CAAC,CAAA,EAAG,OAAA,EAAS,EAAA,KAAO;AACjD,IAAA,IAAI,YAAY,MAAA,EAAW;AAC1B,MAAA,MAAM,IAAA,GAAO,QAAA,CAAS,OAAA,EAAS,EAAE,CAAA;AACjC,MAAA,OAAO,QAAQ,GAAA,GAAM,MAAA,CAAO,aAAa,IAAI,CAAA,GAAI,KAAK,OAAO,CAAA,CAAA;AAAA,IAC9D;AACA,IAAA,OAAO,EAAA;AAAA,EACR,CAAC,CAAA;AAEF,EAAA,IAAI,MAAA,GAAS,IAAA;AACb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC3B,IAAA,MAAM,IAAA,GAAO,SAAS,MAAM,CAAA;AAC5B,IAAA,IAAI,SAAS,MAAA,EAAQ;AACrB,IAAA,MAAA,GAAS,IAAA;AAAA,EACV;AACA,EAAA,OAAO,MAAA;AACR;AAMA,eAAsB,WAAA,CAAY,QAAgB,IAAA,EAA0C;AAC3F,EAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAA,EAAQ,GAAA,EAAK,MAAM,IAAI,CAAA;AACnD,EAAA,OAAO,KAAK,EAAA,KAAO,IAAA;AACpB;AASO,SAAS,eAAe,IAAA,EAAgC;AAC9D,EAAA,IAAI,KAAK,UAAA,CAAW,KAAK,KAAK,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACnD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,IAAA,MAAM,QAAA,GAAW,MAAM,CAAC,CAAA,KAAM,SAAS,KAAA,CAAM,CAAC,CAAA,KAAM,GAAA,GAAM,CAAA,GAAI,CAAA;AAC9D,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AACrC,IAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAEhC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACtC,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACvC,IAAA,IAAI,KAAA,CAAM,KAAK,CAAA,IAAK,KAAA,CAAM,MAAM,KAAK,QAAA,CAAS,MAAA,GAAS,CAAA,GAAI,MAAA,EAAQ,OAAO,IAAA;AAE1E,IAAA,MAAM,MAAM,QAAA,CACV,KAAA,CAAM,GAAG,CAAA,GAAI,MAAM,EACnB,GAAA,CAAI,CAAC,YAAY,MAAA,CAAO,YAAA,CAAa,SAAS,OAAA,EAAS,EAAE,CAAC,CAAC,CAAA,CAC3D,KAAK,EAAE,CAAA;AACT,IAAA,MAAM,QAAQ,QAAA,CACZ,KAAA,CAAM,IAAI,MAAM,CAAA,CAChB,IAAI,CAAC,OAAA,KAAY,MAAA,CAAO,YAAA,CAAa,SAAS,OAAA,EAAS,EAAE,CAAC,CAAC,CAAA,CAC3D,KAAK,EAAE,CAAA;AAET,IAAA,OAAO,EAAE,KAAA,EAAO,GAAA,EAAK,GAAA,CAAI,WAAA,IAAe,KAAA,EAAM;AAAA,EAC/C;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,kCAAkC,CAAA;AAC3D,EAAA,IAAI,KAAA,EAAO;AACV,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAAA,MAC5B,GAAA,EAAK,KAAA,CAAM,CAAC,CAAA,CAAE,WAAA,EAAY;AAAA,MAC1B,KAAA,EAAO,MAAM,CAAC;AAAA,KACf;AAAA,EACD;AAEA,EAAA,OAAO,IAAA;AACR;AAMA,eAAsB,eAAA,CAAgB,QAAgB,IAAA,EAA8C;AACnG,EAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,MAAA,EAAQ,OAAO,IAAI,CAAA;AACzD,EAAA,OAAO,OAAA,CAAQ,IAAI,cAAc,CAAA,CAAE,OAAO,CAAC,MAAA,KAAgC,WAAW,IAAI,CAAA;AAC3F;AAKA,eAAsB,cAAA,CAAe,QAAgB,IAAA,EAAgF;AACpI,EAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAM,IAAI,CAAA;AACxD,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC9B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,IAAA,OAAO;AAAA,MACN,QAAA,EAAU,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAAA,MAC/B,QAAA,EAAU,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE;AAAA,KACrD;AAAA,EACD,CAAC,CAAA;AACF;AAOA,eAAsB,eAAA,CAAgB,IAAY,IAAA,EAA2C;AAC5F,EAAA,MAAM,WAAA,GAAc,GAAG,KAAA,CAAM,GAAG,EAAE,OAAA,EAAQ,CAAE,IAAA,CAAK,GAAG,CAAA,GAAI,eAAA;AACxD,EAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,WAAA,EAAa,OAAO,IAAI,CAAA;AAC9D,EAAA,OAAO,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAW,OAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AACzD;AAMA,eAAsB,eAAA,CACrB,MACA,IAAA,EACqF;AACrF,EAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,IAAA,EAAM,OAAO,IAAI,CAAA;AACvD,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC9B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,IAAA,OAAO;AAAA,MACN,QAAA,EAAU,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAAA,MAC/B,MAAA,EAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAAA,MAC7B,IAAA,EAAM,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAAA,MAC3B,MAAA,EAAQ,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE;AAAA,KACnD;AAAA,EACD,CAAC,CAAA;AACF;AASO,SAAS,gBAAgB,IAAA,EAAiC;AAChE,EAAA,IAAI,KAAK,UAAA,CAAW,KAAK,KAAK,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACnD,IAAA,MAAMA,MAAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,IAAA,MAAM,QAAA,GAAWA,OAAM,CAAC,CAAA,KAAM,SAASA,MAAAA,CAAM,CAAC,CAAA,KAAM,GAAA,GAAM,CAAA,GAAI,CAAA;AAC9D,IAAA,MAAM,QAAA,GAAWA,MAAAA,CAAM,KAAA,CAAM,QAAQ,CAAA;AACrC,IAAA,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAEhC,IAAA,MAAMC,MAAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACtC,IAAA,MAAMC,SAAAA,GAAW,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACzC,IAAA,MAAMC,aAAAA,GAAe,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AAC7C,IAAA,IAAI,KAAA,CAAMF,MAAK,CAAA,IAAK,KAAA,CAAMC,SAAQ,CAAA,IAAK,KAAA,CAAMC,aAAY,CAAA,EAAG,OAAO,IAAA;AAEnE,IAAA,MAAMC,YAAW,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAC1C,IAAA,OAAO,EAAE,OAAAH,MAAAA,EAAO,QAAA,EAAAC,WAAU,YAAA,EAAAC,aAAAA,EAAc,UAAAC,SAAAA,EAAS;AAAA,EAClD;AAEA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAE7B,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACtC,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAC1C,EAAA,IAAI,KAAA,CAAM,KAAK,CAAA,IAAK,KAAA,CAAM,QAAQ,CAAA,IAAK,KAAA,CAAM,YAAY,CAAA,EAAG,OAAO,IAAA;AAEnE,EAAA,MAAM,WAAW,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AACvC,EAAA,OAAO,EAAE,KAAA,EAAO,QAAA,EAAU,YAAA,EAAc,QAAA,EAAS;AAClD;AAnOA,IAAA,gBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,wBAAA,GAAA;AAEA,IAAA,kBAAA,EAAA;AACA,IAAA,cAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACHA,IAAA,QAAA,GAAA,KAAA,CAAA;AAAA,EAAA,gBAAA,GAAA;AAUA,IAAA,cAAA,EAAA;AACA,IAAA,kBAAA,EAAA;AACA,IAAA,gBAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACuEA,SAAS,qBAAqB,KAAA,EAA4C;AACzE,EAAA,OAAO,KAAA,KAAU,eAAA,IAAmB,KAAA,KAAU,WAAA,IAAe,KAAA,KAAU,UAAA;AACxE;AAQO,SAAS,uBAAuB,OAAA,EAAqC;AAC3E,EAAA,MAAM,QAAA,GAAW,QAAQ,QAAA,EAAU,UAAA;AACnC,EAAA,IAAI,oBAAA,CAAqB,QAAQ,CAAA,EAAG,OAAO,QAAA;AAE3C,EAAA,IAAI,OAAA,CAAQ,aAAa,oBAAA,EAAsB;AAC9C,IAAA,MAAM,MAAA,GAAS,QAAQ,QAAA,EAAU,kBAAA;AACjC,IAAA,IAAI,MAAA,KAAW,YAAY,OAAO,UAAA;AAClC,IAAA,OAAO,WAAA;AAAA,EACR;AAEA,EAAA,MAAM,IAAA,GAAO,GAAG,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,MAAM,GAAG,WAAA,EAAY;AAC9D,EAAA,IACC,IAAA,CAAK,QAAA,CAAS,kBAAkB,CAAA,IAChC,IAAA,CAAK,QAAA,CAAS,wBAAwB,CAAA,IACtC,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,IACxB,IAAA,CAAK,QAAA,CAAS,eAAe,CAAA,IAC7B,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,IACxB,IAAA,CAAK,QAAA,CAAS,WAAW,CAAA,IACzB,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA,EAC7B;AACD,IAAA,OAAO,WAAA;AAAA,EACR;AAEA,EAAA,OAAO,eAAA;AACR;AAEA,SAAS,uBAAuB,OAAA,EAA2B;AAC1D,EAAA,MAAM,UAAA,GAAa,uBAAuB,OAAO,CAAA;AACjD,EAAA,OAAO;AAAA,IACN,GAAG,OAAA;AAAA,IACH,QAAA,EAAU;AAAA,MACT,GAAI,OAAA,CAAQ,QAAA,IAAY,EAAC;AAAA,MACzB;AAAA;AACD,GACD;AACD;AAMO,SAAS,qBAAqB,QAAA,EAA6B;AACjE,EAAA,IAAI,KAAA,GAAQ,GAAA;AACZ,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC/B,IAAA,KAAA,IAAS,kBAAA,CAAmB,QAAQ,QAAQ,CAAA;AAAA,EAC7C;AACA,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AACxC;AAKO,SAAS,gBAAA,CAAiB,UAAyB,QAAA,EAAkC;AAC3F,EAAA,MAAM,kBAAA,GAAqB,QAAA,CAAS,GAAA,CAAI,sBAAsB,CAAA;AAC9D,EAAA,MAAM,KAAA,GAAQ,qBAAqB,kBAAkB,CAAA;AACrD,EAAA,OAAO;AAAA,IACN,QAAA;AAAA,IACA,QAAQ,KAAA,IAAS,EAAA;AAAA,IACjB,KAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACX;AACD;AAKO,SAAS,aAAA,CACf,QAAA,EACA,KAAA,EACA,QAAA,EACA,QACA,QAAA,EACU;AACV,EAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,GAAI,QAAA,GAAW,EAAE,QAAA,EAAS,GAAI,EAAC,EAAG;AAC/E;AAvKA,IAmDa,wBAAA,EAwBA,kBAAA;AA3Eb,IAAA,kBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,0BAAA,GAAA;AAmDO,IAAM,wBAAA,GAA0D;AAAA,MACtE,GAAA,EAAK,IAAA;AAAA,MACL,KAAA,EAAO,IAAA;AAAA,MACP,IAAA,EAAM,IAAA;AAAA,MACN,MAAA,EAAQ,IAAA;AAAA,MACR,GAAA,EAAK,IAAA;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,EAAA,EAAI,IAAA;AAAA,MACJ,GAAA,EAAK,IAAA;AAAA,MACL,kBAAA,EAAoB,GAAA;AAAA,MACpB,EAAA,EAAI,CAAA;AAAA,MACJ,IAAA,EAAM,CAAA;AAAA,MACN,MAAA,EAAQ,IAAA;AAAA,MACR,UAAA,EAAY,CAAA;AAAA,MACZ,cAAA,EAAgB,CAAA;AAAA,MAChB,WAAA,EAAa,CAAA;AAAA,MACb,aAAA,EAAe,IAAA;AAAA,MACf,IAAA,EAAM,CAAA;AAAA,MACN,aAAA,EAAe,CAAA;AAAA,MACf,GAAA,EAAK,CAAA;AAAA,MACL,YAAA,EAAc;AAAA,KACf;AAGO,IAAM,kBAAA,GAA+C;AAAA,MAC3D,QAAA,EAAU,EAAA;AAAA,MACV,IAAA,EAAM,EAAA;AAAA,MACN,MAAA,EAAQ,EAAA;AAAA,MACR,GAAA,EAAK,CAAA;AAAA,MACL,IAAA,EAAM;AAAA,KACP;AAAA,EAAA;AAAA,CAAA,CAAA;;;AC4FO,SAAS,oBAAoB,OAAA,EAAuC;AAC1E,EAAA,MAAM,UAAoB,EAAC;AAE3B,EAAA,MAAM,WAAW,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,IAAI,CAAA;AACxD,EAAA,MAAM,YAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,KAAK,CAAA;AAC1D,EAAA,MAAM,YAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,KAAK,CAAA;AAC1D,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAC5D,EAAA,MAAM,eAAe,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,SAAS,CAAA;AACjE,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,MAAM,CAAA;AAG5D,EAAA,MAAM,UAAU,QAAA,GACb,QAAA,CAAS,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM;AAC9B,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,KAAA,CAAM,WAAA,EAAY;AAClC,IAAA,OAAO,MAAM,QAAA,CAAS,eAAe,CAAA,IAAK,KAAA,CAAM,SAAS,SAAS,CAAA;AAAA,EACnE,CAAC,CAAA,GACA,KAAA;AACH,EAAA,MAAM,YAAA,GAAe,QAAA,GAClB,QAAA,CAAS,QAAA,CAAS,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,CAAM,WAAA,EAAY,CAAE,QAAA,CAAS,kBAAkB,CAAC,CAAA,GAChF,KAAA;AACH,EAAA,MAAM,KAAA,GAAQ,QAAA,IAAY,CAAC,OAAA,IAAW,CAAC,YAAA;AAEvC,EAAA,IAAI,KAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,YAAY,CAAA;AACpC,EAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,eAAe,CAAA;AACzC,EAAA,IAAI,YAAA,EAAc,OAAA,CAAQ,IAAA,CAAK,mBAAmB,CAAA;AAGlD,EAAA,IAAI,qBAAA,GAAwB,KAAA;AAC5B,EAAA,IAAI,oBAAA,GAAsC,IAAA;AAC1C,EAAA,IAAI,QAAA,EAAU;AACb,IAAA,KAAA,MAAW,OAAA,IAAW,SAAS,QAAA,EAAU;AACxC,MAAA,MAAM,IAAA,GAAO,GAAG,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,MAAM,GAAG,WAAA,EAAY;AAC9D,MAAA,MAAM,YAAA,GAAe,QAAQ,QAAA,EAAU,QAAA;AACvC,MAAA,MAAM,cAAc,OAAO,YAAA,KAAiB,QAAA,GAAW,YAAA,CAAa,aAAY,GAAI,EAAA;AACpF,MAAA,KAAA,MAAW,YAAY,oBAAA,EAAsB;AAC5C,QAAA,IAAI,KAAK,QAAA,CAAS,QAAQ,KAAK,WAAA,CAAY,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC9D,UAAA,qBAAA,GAAwB,IAAA;AACxB,UAAA,oBAAA,GAAuB,QAAA;AACvB,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,EAAG,QAAQ,CAAA,SAAA,CAAW,CAAA;AACnC,UAAA;AAAA,QACD;AAAA,MACD;AACA,MAAA,IAAI,qBAAA,EAAuB;AAAA,IAC5B;AAAA,EACD;AAGA,EAAA,MAAM,cAAc,UAAA,GACjB,CAAC,WAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM;AACjC,IAAA,MAAM,IAAA,GAAO,GAAG,CAAA,CAAE,KAAK,IAAI,CAAA,CAAE,MAAM,GAAG,WAAA,EAAY;AAClD,IAAA,OAAO,iCAAA,CAAkC,IAAA,CAAK,IAAI,CAAA,IAAK,EAAE,QAAA,KAAa,MAAA;AAAA,EACvE,CAAC,CAAA,GACA,KAAA;AACH,EAAA,IAAI,WAAA,IAAe,KAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,cAAc,CAAA;AAErD,EAAA,MAAM,aAAA,GAAgB,YAAA,GAAe,YAAA,CAAa,MAAA,GAAS,KAAA;AAC3D,EAAA,IAAI,aAAA,EAAe,OAAA,CAAQ,IAAA,CAAK,iBAAiB,CAAA;AAEjD,EAAA,MAAM,WAAA,GAAc,UAAA,GAAa,UAAA,CAAW,MAAA,GAAS,KAAA;AACrD,EAAA,IAAI,WAAA,EAAa,OAAA,CAAQ,IAAA,CAAK,cAAc,CAAA;AAE5C,EAAA,MAAM,kBAAA,GAAqB,eAAe,aAAA,IAAiB,WAAA;AAG3D,EAAA,MAAM,OAAA,GAAU,SAAA,GAAY,SAAA,CAAU,MAAA,GAAS,KAAA;AAC/C,EAAA,MAAM,OAAA,GAAU,SAAA,GAAY,SAAA,CAAU,MAAA,GAAS,KAAA;AAC/C,EAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA;AACrC,EAAA,IAAI,OAAA,EAAS,OAAA,CAAQ,IAAA,CAAK,aAAa,CAAA;AAGvC,EAAA,MAAM,cAAc,OAAA,CAAQ,MAAA;AAC5B,EAAA,MAAM,YAAA,GAAe,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAC,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA;AACtD,EAAA,MAAM,YAAA,GAAe,WAAA,GAAc,CAAA,GAAI,YAAA,GAAe,WAAA,GAAc,CAAA;AACpE,EAAA,IAAI,YAAA,GAAe,GAAA,EAAK,OAAA,CAAQ,IAAA,CAAK,CAAA,CAAA,EAAI,KAAK,KAAA,CAAM,YAAA,GAAe,GAAG,CAAC,CAAA,eAAA,CAAiB,CAAA;AAGxF,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI,OAAA,EAAS;AAEZ,IAAA,IAAI,WAAW,OAAA,EAAS;AACvB,MAAA,OAAA,GAAU,UAAA;AAAA,IACX,CAAA,MAAO;AACN,MAAA,OAAA,GAAU,UAAA;AAAA,IACX;AAAA,EACD,CAAA,MAAA,IAAW,YAAA,IAAgB,CAAC,KAAA,EAAO;AAElC,IAAA,OAAA,GAAU,cAAA;AAAA,EACX,CAAA,MAAA,IAAW,KAAA,IAAS,qBAAA,IAAyB,kBAAA,EAAoB;AAChE,IAAA,OAAA,GAAU,iBAAA;AAAA,EACX,CAAA,MAAO;AACN,IAAA,OAAA,GAAU,cAAA;AAAA,EACX;AAGA,EAAA,IAAI,eAAe,GAAA,EAAK;AACvB,IAAA,OAAA,GAAU,SAAA;AAAA,EACX;AAEA,EAAA,OAAO;AAAA,IACN,OAAA;AAAA,IACA,OAAA;AAAA,IACA,OAAA,EAAS,gBAAgB,OAAO,CAAA;AAAA,IAChC,gBAAA,EAAkB;AAAA,GACnB;AACD;AAGO,SAAS,iBAAA,CACf,SACA,MAAA,EAC2C;AAC3C,EAAA,IAAI,MAAA,EAAQ;AACX,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,cAAA,CAAe,OAAO,CAAA;AAC1C,IAAA,MAAM,SAAS,EAAC;AAChB,IAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAsB;AACvD,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,UAAA,EAAY,IAAA,CAAK,GAAG,CAAA,EAAE;AAAA,IACvC;AACA,IAAA,OAAO,MAAA;AAAA,EACR;AACA,EAAA,OAAO,gBAAgB,OAAO,CAAA;AAC/B;AAtSA,IA6Ba,eAAA,EAkHA,6BASA,4BAAA,EASP,oBAAA;AAjKN,IAAA,qBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,6BAAA,GAAA;AA6BO,IAAM,eAAA,GAAmF;AAAA,MAC/F,YAAA,EAAc;AAAA,QACb,KAAA,EAAO,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACvB,GAAA,EAAK,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACtB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpC,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,OAAA,EAAS,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACzB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC5B,cAAA,EAAgB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAChC,WAAA,EAAa,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC7B,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,YAAA,EAAc,EAAE,UAAA,EAAY,CAAA;AAAE,OAC/B;AAAA,MACA,eAAA,EAAiB;AAAA,QAChB,KAAA,EAAO,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACvB,GAAA,EAAK,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACtB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpC,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,OAAA,EAAS,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACzB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC5B,cAAA,EAAgB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAChC,WAAA,EAAa,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC7B,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,YAAA,EAAc,EAAE,UAAA,EAAY,CAAA;AAAE,OAC/B;AAAA,MACA,QAAA,EAAU;AAAA,QACT,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpC,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,KAAA,EAAO,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACvB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,OAAA,EAAS,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACzB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC5B,cAAA,EAAgB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAChC,WAAA,EAAa,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC7B,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,YAAA,EAAc,EAAE,UAAA,EAAY,CAAA;AAAE,OAC/B;AAAA,MACA,QAAA,EAAU;AAAA,QACT,GAAA,EAAK,EAAE,UAAA,EAAY,EAAA,EAAG;AAAA,QACtB,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpC,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,KAAA,EAAO,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACvB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,OAAA,EAAS,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACzB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC5B,cAAA,EAAgB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAChC,WAAA,EAAa,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC7B,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,YAAA,EAAc,EAAE,UAAA,EAAY,CAAA;AAAE,OAC/B;AAAA,MACA,OAAA,EAAS;AAAA,QACR,KAAA,EAAO,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACvB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,kBAAA,EAAoB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpC,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,EAAA,EAAI,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACpB,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,OAAA,EAAS,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACzB,MAAA,EAAQ,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACxB,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,UAAA,EAAY,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC5B,cAAA,EAAgB,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAChC,WAAA,EAAa,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC7B,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,IAAA,EAAM,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACtB,aAAA,EAAe,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QAC/B,GAAA,EAAK,EAAE,UAAA,EAAY,CAAA,EAAE;AAAA,QACrB,YAAA,EAAc,EAAE,UAAA,EAAY,CAAA;AAAE;AAC/B,KACD;AAGO,IAAM,2BAAA,GAAsE;AAAA,MAClF,cAAc,CAAC,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,OAAO,oBAAoB,CAAA;AAAA,MAClE,iBAAiB,CAAC,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,OAAO,oBAAoB,CAAA;AAAA,MACrE,QAAA,EAAU,CAAC,KAAA,EAAO,oBAAA,EAAsB,eAAe,CAAA;AAAA,MACvD,QAAA,EAAU,CAAC,KAAA,EAAO,oBAAA,EAAsB,eAAe,CAAA;AAAA,MACvD,OAAA,EAAS,CAAC,KAAA,EAAO,oBAAoB;AAAA,KACtC;AAGO,IAAM,4BAAA,GAA+D;AAAA,MAC3E,YAAA,EAAc,IAAA;AAAA,MACd,eAAA,EAAiB,IAAA;AAAA,MACjB,QAAA,EAAU,KAAA;AAAA,MACV,QAAA,EAAU,KAAA;AAAA,MACV,OAAA,EAAS;AAAA,KACV;AAGA,IAAM,oBAAA,GAAuB;AAAA,MAC5B,kBAAA;AAAA,MACA,eAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KACD;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACzCO,SAAS,mBACf,OAAA,EACoC;AACpC,EAAA,MAAM,SAAS,EAAC;AAChB,EAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,EAAU;AAC9C,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,UAAA,EAAY,OAAA,CAAQ,GAAG,CAAA,EAAE;AAAA,EAC1C;AACA,EAAA,OAAO,MAAA;AACR;AAtIA,IAmDa,sBAAA;AAnDb,IAAA,mBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,2BAAA,GAAA;AAmDO,IAAM,sBAAA,GAAwC;AAAA,MACpD,OAAA,EAAS;AAAA,QACR,GAAA,EAAK,EAAA;AAAA,QACL,KAAA,EAAO,EAAA;AAAA,QACP,IAAA,EAAM,EAAA;AAAA,QACN,MAAA,EAAQ,CAAA;AAAA,QACR,GAAA,EAAK,CAAA;AAAA,QACL,OAAA,EAAS,CAAA;AAAA,QACT,EAAA,EAAI,CAAA;AAAA,QACJ,GAAA,EAAK,CAAA;AAAA,QACL,kBAAA,EAAoB,CAAA;AAAA,QACpB,EAAA,EAAI,CAAA;AAAA,QACJ,IAAA,EAAM,CAAA;AAAA,QACN,MAAA,EAAQ,CAAA;AAAA,QACR,UAAA,EAAY,CAAA;AAAA,QACZ,cAAA,EAAgB,CAAA;AAAA,QAChB,WAAA,EAAa,CAAA;AAAA,QACb,aAAA,EAAe,CAAA;AAAA,QACf,IAAA,EAAM,CAAA;AAAA,QACN,aAAA,EAAe,CAAA;AAAA,QACf,GAAA,EAAK,CAAA;AAAA,QACL,YAAA,EAAc;AAAA,OACf;AAAA,MACA,cAAA,EAAgB;AAAA,QACf,cAAc,EAAE,KAAA,EAAO,IAAI,IAAA,EAAM,EAAA,EAAI,KAAK,EAAA,EAAI,GAAA,EAAK,CAAA,EAAG,kBAAA,EAAoB,GAAG,MAAA,EAAQ,CAAA,EAAG,SAAS,CAAA,EAAG,EAAA,EAAI,GAAG,MAAA,EAAQ,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,EAAG,IAAA,EAAM,GAAG,UAAA,EAAY,CAAA,EAAG,gBAAgB,CAAA,EAAG,WAAA,EAAa,GAAG,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,EAAG,aAAA,EAAe,GAAG,GAAA,EAAK,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,QACrQ,iBAAiB,EAAE,KAAA,EAAO,IAAI,IAAA,EAAM,EAAA,EAAI,KAAK,EAAA,EAAI,GAAA,EAAK,CAAA,EAAG,kBAAA,EAAoB,GAAG,MAAA,EAAQ,CAAA,EAAG,SAAS,CAAA,EAAG,EAAA,EAAI,GAAG,MAAA,EAAQ,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,IAAI,CAAA,EAAG,IAAA,EAAM,GAAG,UAAA,EAAY,CAAA,EAAG,gBAAgB,CAAA,EAAG,WAAA,EAAa,GAAG,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,EAAG,aAAA,EAAe,GAAG,GAAA,EAAK,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,QACxQ,UAAU,EAAE,GAAA,EAAK,GAAG,kBAAA,EAAoB,CAAA,EAAG,QAAQ,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,GAAG,EAAA,EAAI,CAAA,EAAG,MAAM,CAAA,EAAG,GAAA,EAAK,GAAG,EAAA,EAAI,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,EAAM,GAAG,UAAA,EAAY,CAAA,EAAG,gBAAgB,CAAA,EAAG,WAAA,EAAa,GAAG,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,EAAG,aAAA,EAAe,GAAG,GAAA,EAAK,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,QAC9P,UAAU,EAAE,GAAA,EAAK,IAAI,kBAAA,EAAoB,CAAA,EAAG,QAAQ,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,KAAA,EAAO,GAAG,EAAA,EAAI,CAAA,EAAG,MAAM,CAAA,EAAG,GAAA,EAAK,GAAG,EAAA,EAAI,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,EAAM,GAAG,UAAA,EAAY,CAAA,EAAG,gBAAgB,CAAA,EAAG,WAAA,EAAa,GAAG,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,EAAG,aAAA,EAAe,GAAG,GAAA,EAAK,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,QAC/P,SAAS,EAAE,KAAA,EAAO,GAAG,GAAA,EAAK,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,GAAA,EAAK,GAAG,kBAAA,EAAoB,CAAA,EAAG,IAAI,CAAA,EAAG,EAAA,EAAI,GAAG,GAAA,EAAK,CAAA,EAAG,OAAA,EAAS,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,EAAM,GAAG,UAAA,EAAY,CAAA,EAAG,gBAAgB,CAAA,EAAG,WAAA,EAAa,GAAG,aAAA,EAAe,CAAA,EAAG,MAAM,CAAA,EAAG,aAAA,EAAe,GAAG,GAAA,EAAK,CAAA,EAAG,cAAc,CAAA;AAAE,OAC9P;AAAA,MACA,UAAA,EAAY;AAAA,QACX,oBAAA,EAAsB,CAAA;AAAA,QACtB,kBAAA,EAAoB,EAAA;AAAA,QACpB,sBAAA,EAAwB,EAAA;AAAA,QACxB,kBAAA,EAAoB;AAAA,OACrB;AAAA,MACA,MAAA,EAAQ;AAAA,QACP,KAAA,EAAO,EAAA;AAAA,QACP,CAAA,EAAG,EAAA;AAAA,QACH,KAAA,EAAO,EAAA;AAAA,QACP,CAAA,EAAG,EAAA;AAAA,QACH,KAAA,EAAO,EAAA;AAAA,QACP,CAAA,EAAG,EAAA;AAAA,QACH,KAAA,EAAO,EAAA;AAAA,QACP,CAAA,EAAG,EAAA;AAAA,QACH,CAAA,EAAG;AAAA,OACJ;AAAA,MACA,oBAAA,EAAsB;AAAA,QACrB,KAAA,EAAO,GAAA;AAAA,QACP,GAAA,EAAK,IAAA;AAAA,QACL,IAAA,EAAM,IAAA;AAAA,QACN,GAAA,EAAK,IAAA;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,MAAA,EAAQ,GAAA;AAAA,QACR,EAAA,EAAI,IAAA;AAAA,QACJ,GAAA,EAAK,GAAA;AAAA,QACL,EAAA,EAAI,IAAA;AAAA,QACJ,IAAA,EAAM,IAAA;AAAA,QACN,MAAA,EAAQ,GAAA;AAAA,QACR,kBAAA,EAAoB,GAAA;AAAA,QACpB,UAAA,EAAY,CAAA;AAAA,QACZ,cAAA,EAAgB,CAAA;AAAA,QAChB,WAAA,EAAa,CAAA;AAAA,QACb,aAAA,EAAe,IAAA;AAAA,QACf,IAAA,EAAM,GAAA;AAAA,QACN,aAAA,EAAe,CAAA;AAAA,QACf,GAAA,EAAK,CAAA;AAAA,QACL,YAAA,EAAc;AAAA;AACf,KACD;AAAA,EAAA;AAAA,CAAA,CAAA;;;AC1EA,SAAS,6BAA6B,QAAA,EAA8B;AACnE,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,CAAC,OAAA,KAAY;AACjC,IAAA,IAAI,QAAQ,QAAA,KAAa,UAAA,IAAc,OAAA,CAAQ,QAAA,KAAa,QAAQ,OAAO,KAAA;AAC3E,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,MAAM,GAAG,WAAA,EAAY;AAC9D,IAAA,OAAO,iDAAA,CAAkD,KAAK,IAAI,CAAA;AAAA,EACnE,CAAC,CAAA;AACF;AAEA,SAAS,aAAa,KAAA,EAAuB;AAC5C,EAAA,OAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AACxC;AAEA,SAAS,kCAAkC,QAAA,EAA6B;AACvE,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC/B,IAAA,MAAM,UAAA,GAAa,QAAQ,QAAA,EAAU,kBAAA;AACrC,IAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,EAAG;AAClE,MAAA,WAAA,CAAY,IAAA,CAAK,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC,CAAC,CAAA;AAAA,IACtD;AAAA,EACD;AAEA,EAAA,IAAI,WAAA,CAAY,MAAA,KAAW,CAAA,EAAG,OAAO,CAAA;AAErC,EAAA,MAAM,aAAA,GAAgB,WAAA,CAAY,MAAA,CAAO,CAAC,GAAA,EAAK,UAAU,GAAA,GAAM,KAAA,EAAO,CAAC,CAAA,GAAI,WAAA,CAAY,MAAA;AACvF,EAAA,MAAM,WAAW,aAAA,GAAgB,GAAA;AACjC,EAAA,OAAO,IAAA,CAAK,KAAA,CAAM,QAAA,GAAW,EAAE,CAAA;AAChC;AAGO,SAAS,YAAA,CAAa,OAAe,MAAA,EAAgC;AAC3E,EAAA,MAAM,CAAA,GAAI,MAAA,EAAQ,MAAA,IAAU,sBAAA,CAAuB,MAAA;AACnD,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,KAAA,EAAO,OAAO,IAAA;AAC7B,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,CAAA,EAAG,OAAO,GAAA;AACzB,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,KAAA,EAAO,OAAO,IAAA;AAC7B,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,CAAA,EAAG,OAAO,GAAA;AACzB,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,KAAA,EAAO,OAAO,IAAA;AAC7B,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,CAAA,EAAG,OAAO,GAAA;AACzB,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,KAAA,EAAO,OAAO,IAAA;AAC7B,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,CAAA,EAAG,OAAO,GAAA;AACzB,EAAA,IAAI,KAAA,IAAS,CAAA,CAAE,CAAA,EAAG,OAAO,GAAA;AACzB,EAAA,OAAO,GAAA;AACR;AAeO,SAAS,gBAAA,CAAiB,OAAA,EAAwB,OAAA,EAAyB,MAAA,EAAmC;AACpH,EAAA,MAAM,gBAAwD,EAAC;AAC/D,EAAA,MAAM,cAAyB,EAAC;AAGhC,EAAA,KAAA,MAAW,QAAA,IAAY,MAAA,CAAO,IAAA,CAAK,wBAAwB,CAAA,EAAsB;AAChF,IAAA,aAAA,CAAc,QAAQ,CAAA,GAAI,GAAA;AAAA,EAC3B;AAGA,EAAA,MAAM,cAAA,GAAiB,aAAA;AAEvB,EAAA,MAAM,MAAM,MAAA,IAAU,sBAAA;AACtB,EAAA,MAAM,oBAAA,GAAuB,IAAI,UAAA,CAAW,oBAAA;AAC5C,EAAA,MAAM,kBAAA,GAAqB,IAAI,UAAA,CAAW,kBAAA;AAC1C,EAAA,MAAM,sBAAA,GAAyB,IAAI,UAAA,CAAW,sBAAA;AAC9C,EAAA,MAAM,kBAAA,GAAqB,IAAI,UAAA,CAAW,kBAAA;AAE1C,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,GAAA;AAAA,MACT,KAAA,EAAO,YAAA,CAAa,GAAA,EAAK,MAAM,CAAA;AAAA,MAC/B,cAAA;AAAA,MACA,UAAU,EAAC;AAAA,MACX,OAAA,EAAS,CAAA,4CAAA,EAA+C,YAAA,CAAa,GAAA,EAAK,MAAM,CAAC,CAAA;AAAA,KAClF;AAAA,EACD;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,cAAA,CAAe,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,KAAA;AACzC,IAAA,WAAA,CAAY,IAAA,CAAK,GAAG,MAAA,CAAO,QAAQ,CAAA;AAAA,EACpC;AAEA,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,IAAI,SAAA,GAAY,CAAA;AAGhB,EAAA,MAAM,gBAAgB,OAAA,GAAU,OAAA,CAAQ,OAAA,GAAU,kBAAA,CAAmB,IAAI,OAAO,CAAA;AAGhF,EAAA,KAAA,MAAW,QAAA,IAAY,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,EAAsB;AACrE,IAAA,MAAM,EAAE,UAAA,EAAW,GAAI,aAAA,CAAc,QAAQ,CAAA;AAC7C,IAAA,SAAA,IAAa,UAAA;AACb,IAAA,IAAI,eAAe,CAAA,EAAG;AAEtB,IAAA,MAAM,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,aAAa,QAAQ,CAAA;AAClE,IAAA,MAAM,QAAA,GAAW,MAAA,GAAS,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA,GAAI,GAAA;AACvD,IAAA,MAAM,iBAAiB,MAAA,IAAU,4BAAA,CAA6B,MAAA,CAAO,QAAQ,IAAI,CAAA,GAAI,QAAA;AACrF,IAAA,YAAA,IAAiB,iBAAiB,GAAA,GAAO,UAAA;AAAA,EAC1C;AAGA,EAAA,MAAM,kBAAA,GAAqB,OAAA,GAAU,4BAAA,CAA6B,OAAA,CAAQ,OAAO,CAAA,GAAI,IAAA;AAErF,EAAA,MAAM,YAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,KAAK,CAAA;AACpE,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,MAAM,CAAA;AACtE,EAAA,MAAM,cAAc,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,OAAO,CAAA;AACxE,EAAA,MAAM,SAAA,GAAY,CAAC,CAAC,SAAA,IAAa,CAAC,6BAA6B,SAAA,CAAU,QAAQ,CAAA,IAAK,SAAA,CAAU,KAAA,IAAS,kBAAA;AACzG,EAAA,MAAM,cAAc,CAAC,CAAC,cAAc,CAAC,4BAAA,CAA6B,WAAW,QAAQ,CAAA;AACrF,EAAA,MAAM,eAAe,CAAC,CAAC,eAAe,CAAC,4BAAA,CAA6B,YAAY,QAAQ,CAAA;AAExF,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,kBAAA,IAAsB,SAAA,IAAa,WAAA,IAAe,YAAA,IAAgB,WAAA,EAAa;AAClF,IAAA,IAAI,WAAA,CAAY,SAAS,EAAA,EAAI;AAC5B,MAAA,UAAA,GAAa,oBAAA;AAAA,IACd,CAAA,MAAA,IAAW,WAAA,CAAY,KAAA,IAAS,EAAA,EAAI;AACnC,MAAA,UAAA,GAAa,IAAA,CAAK,IAAA,CAAK,oBAAA,GAAuB,GAAG,CAAA;AAAA,IAClD,CAAA,MAAO;AACN,MAAA,UAAA,GAAa,IAAA,CAAK,IAAA,CAAK,oBAAA,GAAuB,GAAG,CAAA;AAAA,IAClD;AAAA,EACD;AAEA,EAAA,YAAA,IAAgB,UAAA;AAChB,EAAA,IAAI,aAAa,CAAA,EAAG;AACnB,IAAA,SAAA,IAAa,oBAAA;AAAA,EACd;AAEA,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,SAAA,GAAY,CAAA,GAAI,aAAc,YAAA,GAAe,SAAA,GAAa,GAAG,CAAA,GAAI,CAAC,CAAA;AACjG,EAAA,MAAM,gBAAA,GAAmB,kCAAkC,WAAW,CAAA;AACtE,EAAA,MAAM,aAAA,GAAgB,YAAY,MAAA,CAAO,CAAC,YAAY,OAAA,CAAQ,QAAA,KAAa,UAAU,CAAA,CAAE,MAAA;AACvF,EAAA,MAAM,wBAAwB,WAAA,CAAY,MAAA;AAAA,IACzC,CAAC,OAAA,KAAY,OAAA,CAAQ,aAAa,UAAA,IAAc,sBAAA,CAAuB,OAAO,CAAA,KAAM;AAAA,GACrF,CAAE,MAAA;AACF,EAAA,MAAM,eAAA,GAAkB,qBAAA,GAAwB,CAAA,GAAI,sBAAA,GAAyB,CAAA;AAC7E,EAAA,MAAM,UAAA,GAAa,YAAA,CAAa,WAAA,GAAc,gBAAA,GAAmB,eAAe,CAAA;AAGhF,EAAA,MAAM,kBAAA,GAAqB,OAAA,GACxB,2BAAA,CAA4B,OAAA,CAAQ,OAAO,CAAA,GAC3C,2BAAA;AACH,EAAA,MAAM,cAAA,GAAiB,kBAAA,CAAmB,IAAA,CAAK,CAAC,GAAA,KAAQ;AACvD,IAAA,MAAM,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,GAAG,CAAA;AACrD,IAAA,OAAO,MAAA,IAAU,4BAAA,CAA6B,MAAA,CAAO,QAAQ,CAAA;AAAA,EAC9D,CAAC,CAAA;AACD,EAAA,MAAM,UAAU,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,kBAAkB,CAAA,GAAI,UAAA;AAE5E,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,OAAA,EAAS,MAAM,CAAA;AAE1C,EAAA,MAAM,SAAA,GAAY,YAAY,MAAA,CAAO,CAAC,YAAY,OAAA,CAAQ,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AAC/E,EAAA,MAAM,WAAA,GAAc,YAAY,MAAA,CAAO,CAAC,YAAY,OAAA,CAAQ,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AAEjF,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,gBAAgB,CAAA,EAAG;AACtB,IAAA,OAAA,GAAU,+CAA+C,KAAK,CAAA,CAAA;AAAA,EAC/D,CAAA,MAAA,IAAW,gBAAgB,CAAA,EAAG;AAC7B,IAAA,OAAA,GAAU,CAAA,EAAG,aAAa,CAAA,+DAAA,EAAkE,KAAK,CAAA,CAAA;AAAA,EAClG,CAAA,MAAA,IAAW,YAAY,CAAA,EAAG;AACzB,IAAA,OAAA,GAAU,CAAA,EAAG,SAAS,CAAA,sCAAA,EAAyC,KAAK,CAAA,CAAA;AAAA,EACrE,CAAA,MAAO;AACN,IAAA,OAAA,GAAU,CAAA,EAAG,WAAW,CAAA,wBAAA,EAA2B,KAAK,CAAA,CAAA;AAAA,EACzD;AAEA,EAAA,OAAO;AAAA,IACN,OAAA;AAAA,IACA,KAAA;AAAA,IACA,cAAA;AAAA,IACA,QAAA,EAAU,WAAA;AAAA,IACV;AAAA,GACD;AACD;AA9NA,IA8FM,2BAAA;AA9FN,IAAA,mBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,2BAAA,GAAA;AAEA,IAAA,kBAAA,EAAA;AASA,IAAA,qBAAA,EAAA;AAEA,IAAA,mBAAA,EAAA;AAiFA,IAAM,8BAA+C,CAAC,KAAA,EAAO,OAAA,EAAS,MAAA,EAAQ,OAAO,oBAAoB,CAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACLlG,SAAS,aAAA,CAAc,cAAsB,cAAA,EAAsC;AACzF,EAAA,MAAM,QAAA,GAAW,iBAAiB,CAAA,GAAI,CAAA;AACtC,EAAA,OAAO;AAAA,IACN,GAAA,EAAK,KAAK,GAAA,CAAI,QAAA,EAAU,KAAK,KAAA,CAAM,YAAA,GAAe,GAAG,CAAC,CAAA;AAAA,IACtD,GAAA,EAAK,IAAA,CAAK,IAAA,CAAK,YAAA,GAAe,CAAC,CAAA,GAAI;AAAA,GACpC;AACD;AAwEO,SAAS,wBAAA,CACf,WACA,OAAA,EACuD;AACvD,EAAA,MAAM,aAAA,GAAgB,gBAAgB,OAAO,CAAA;AAC7C,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA;AAC5C,EAAA,MAAM,SAAS,EAAC;AAEhB,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC7B,IAAA,MAAM,KAAA,GAAQ,OAAO,SAAA,GAAY,SAAA,CAAU,GAAG,CAAA,GAAI,aAAA,CAAc,GAAG,CAAA,CAAE,UAAA;AACrE,IAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,IAAK,QAAQ,CAAA,EAAG;AAClC,MAAA,OAAO,IAAA;AAAA,IACR;AACA,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,EAAE,UAAA,EAAY,KAAA,EAAM;AAAA,EACnC;AAEA,EAAA,OAAO,MAAA;AACR;AASO,SAAS,mBAAA,CACf,YAAA,EACA,UAAA,EACA,QAAA,EACgB;AAChB,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,UAAU,CAAA,GAAI,4BAAA,EAA8B;AACxD,IAAA,OAAO,IAAA;AAAA,EACR;AAGA,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,OAAA,CAAQ,YAAY,EAC7C,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,IAAK,CAAC,CAAA,CAClC,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AAEhD,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAE7B,IAAA,MAAM,GAAA,GAAM,OAAO,OAAA,CAAQ,YAAY,EAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAC,CAAA,GAAI,IAAA,CAAK,IAAI,CAAA,CAAE,CAAC,CAAC,CAAC,CAAA;AACvF,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC7B,IAAA,MAAM,CAACC,OAAAA,EAAQC,SAAQ,CAAA,GAAI,IAAI,CAAC,CAAA;AAChC,IAAA,OAAO,UAAA,CAAWD,OAAAA,EAAQC,SAAAA,EAAU,QAAQ,CAAA;AAAA,EAC7C;AAEA,EAAA,IAAI,WAAA,CAAY,UAAU,CAAA,EAAG;AAC5B,IAAA,MAAM,CAACD,OAAM,CAAA,GAAI,WAAA,CAAY,CAAC,CAAA;AAC9B,IAAA,OAAO,CAAA,iHAAA,EAAoHA,OAAAA,CAAO,WAAA,EAAa,CAAA,CAAA,CAAA;AAAA,EAChJ;AAEA,EAAA,MAAM,CAAC,MAAA,EAAQ,QAAQ,CAAA,GAAI,YAAY,CAAC,CAAA;AACxC,EAAA,OAAO,UAAA,CAAW,MAAA,EAAQ,QAAA,EAAU,QAAQ,CAAA;AAC7C;AAGA,SAAS,UAAA,CAAW,QAAA,EAAkB,KAAA,EAAe,QAAA,EAAiC;AACrF,EAAA,MAAM,GAAA,GAAM,SAAS,WAAA,EAAY;AAEjC,EAAA,IAAI,KAAA,GAAQ,KAAK,QAAA,EAAU;AAC1B,IAAA,MAAM,eAAA,GAAkB,gBAAgB,QAAQ,CAAA;AAChD,IAAA,OAAO,CAAA,EAAG,GAAG,CAAA,2CAAA,EAA8C,eAAe,CAAA,qCAAA,CAAA;AAAA,EAC3E;AAEA,EAAA,IAAI,QAAQ,CAAA,EAAG;AACd,IAAA,OAAO,GAAG,GAAG,CAAA,sFAAA,CAAA;AAAA,EACd;AAEA,EAAA,OAAO,GAAG,GAAG,CAAA,sEAAA,CAAA;AACd;AAGA,SAAS,gBAAgB,CAAA,EAAmB;AAC3C,EAAA,OAAO,EAAE,OAAA,CAAQ,OAAA,EAAS,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AACjD;AAnPA,IAwDa,4BAAA,CAAA,CAsBP,wBAAA,CAAA,CAGA,sBAAA;AAjFN,IAAA,qBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,6BAAA,GAAA;AAaA,IAAA,qBAAA,EAAA;AA2CO,IAAM,4BAAA,GAA+B,CAAA;AAsB5C,IAAM,wBAAA,uBAA+B,GAAA,CAAY,CAAC,SAAS,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAC,CAAA;AAGhF,IAAM,yCAAyB,IAAI,GAAA,CAAY,CAAC,cAAA,EAAgB,iBAAiB,CAAC,CAAA;AAiB3E,KAAkF,MAAM;AAC9F,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,IAAA,CAAK,eAAe,CAAA;AAC5C,MAAA,MAAM,SAAS,EAAC;AAEhB,MAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC/B,QAAA,MAAM,OAAA,GAAU,gBAAgB,OAAO,CAAA;AACvC,QAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACtC,QAAA,MAAM,gBAAgB,EAAC;AAEvB,QAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC7B,UAAA,MAAM,aAAa,sBAAA,CAAuB,GAAA,CAAI,OAAO,CAAA,IAAK,wBAAA,CAAyB,IAAI,GAAG,CAAA;AAC1F,UAAA,aAAA,CAAc,GAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,GAAG,CAAA,CAAE,YAAY,UAAU,CAAA;AAAA,QACvE;AAEA,QAAA,MAAA,CAAO,OAAO,CAAA,GAAI,aAAA;AAAA,MACnB;AAEA,MAAA,OAAO,MAAA;AAAA,IACR,CAAA,GAAG;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACpHH,IAAA,YAAA,GAAA,KAAA,CAAA;AAAA,EAAA,oBAAA,GAAA;AAQA,IAAA,kBAAA,EAAA;AAeA,IAAA,mBAAA,EAAA;AAEA,IAAA,qBAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACwBO,SAAS,gBAAgB,KAAA,EAAuB;AACtD,EAAA,OAAO,MAAM,IAAA,EAAK,CAAE,aAAY,CAAE,OAAA,CAAQ,YAAY,EAAE,CAAA;AACzD;AAEO,SAAS,sBAAsB,KAAA,EAAuC;AAC5E,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,SAAU,EAAC;AACnC,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS,KAAK,IAAA,EAAK,CAAE,WAAA,EAAa,EAAE,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,CAAC,CAAA;AACvF;AAEO,SAAS,wBAAA,CAAyB,WAAmB,YAAA,EAA6B;AACxF,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACH,IAAA,GAAA,GAAM,IAAI,IAAI,SAAS,CAAA;AAAA,EACxB,CAAA,CAAA,MAAQ;AACP,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACxD;AAEA,EAAA,IAAI,GAAA,CAAI,aAAa,QAAA,EAAU;AAC9B,IAAA,MAAM,IAAI,MAAM,0DAA0D,CAAA;AAAA,EAC3E;AAEA,EAAA,IAAI,YAAA,CAAa,MAAA,GAAS,CAAA,IAAK,CAAC,YAAA,CAAa,SAAS,GAAA,CAAI,QAAA,CAAS,WAAA,EAAa,CAAA,EAAG;AAClF,IAAA,MAAM,IAAI,MAAM,gEAAgE,CAAA;AAAA,EACjF;AAEA,EAAA,OAAO,GAAA;AACR;AAEA,eAAe,UAAU,KAAA,EAAgC;AACxD,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,KAAK,CAAC,CAAA;AACpF,EAAA,OAAO,MAAM,IAAA,CAAK,IAAI,WAAW,MAAM,CAAA,EAAG,CAAC,IAAA,KAAS,IAAA,CAAK,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AAChG;AAEA,SAAS,gBAAgB,KAAA,EAAuB;AAC/C,EAAA,OAAO,MAAM,IAAA,EAAK,CAAE,aAAY,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACpD;AAEA,SAAS,4BAA4B,KAAA,EAA6D;AACjG,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,SAAU,EAAC;AAEnC,EAAA,OAAO,KAAA,CACL,GAAA,CAAI,CAAC,QAAA,KAAa;AAClB,IAAA,MAAM,IAAA,GAAO,OAAO,QAAA,EAAU,IAAA,KAAS,WAAW,QAAA,CAAS,IAAA,CAAK,MAAK,GAAI,EAAA;AACzE,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,OAAA,CAAQ,QAAA,EAAU,OAAO,IAC5C,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW,eAAA,CAAgB,OAAO,MAAM,CAAC,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,WAAW,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA,GACtG,EAAC;AACJ,IAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,OAAA,CAAQ,QAAA,EAAU,aAAa,CAAA,GACxD,QAAA,CAAS,aAAA,CAAc,GAAA,CAAI,CAAC,QAAA,KAAa,MAAA,CAAO,QAAQ,EAAE,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA,CAAE,MAAA,CAAO,CAAC,QAAA,KAAa,QAAA,CAAS,MAAA,GAAS,CAAC,CAAA,GACxH,EAAC;AACJ,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,GAAI,aAAA,CAAc,MAAA,GAAS,CAAA,GAAI,EAAE,aAAA,EAAc,GAAI,EAAC,EAAG;AAAA,EAChF,CAAC,CAAA,CACA,MAAA,CAAO,CAAC,QAAA,KAAa,QAAA,CAAS,IAAA,CAAK,MAAA,GAAS,CAAA,IAAK,QAAA,CAAS,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAA;AAC/E;AAEO,SAAS,WAAA,CACf,OAAA,EACA,MAAA,EACA,QAAA,EACuB;AACvB,EAAA,MAAM,OAAA,GAAU,2BAAA,CAA4B,OAAA,CAAQ,OAAO,CAAA;AAC3D,EAAA,MAAM,QAAA,GAAW,2BAAA,CAA4B,OAAA,CAAQ,QAAQ,CAAA;AAE7D,EAAA,OAAO;AAAA,IACN,SAAS,OAAA,CAAQ,OAAA,EAAS,IAAA,EAAK,IAAK,oBAAoB,OAAA,IAAW,SAAA;AAAA,IACnE,MAAA;AAAA,IACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,QAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACD;AACD;AAEO,SAAS,wBAAwB,OAAA,EAAuD;AAC9F,EAAA,IAAI,CAAC,OAAA,IAAW,OAAO,OAAA,KAAY,UAAU,OAAO,KAAA;AACpD,EAAA,MAAM,MAAA,GAAS,OAAA;AACf,EAAA,IAAI,OAAO,OAAA,KAAY,MAAA,IAAa,OAAO,MAAA,CAAO,OAAA,KAAY,UAAU,OAAO,KAAA;AAC/E,EAAA,IAAI,MAAA,CAAO,YAAY,MAAA,IAAa,CAAC,MAAM,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,EAAG,OAAO,KAAA;AAC3E,EAAA,IAAI,MAAA,CAAO,aAAa,MAAA,IAAa,CAAC,MAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,EAAG,OAAO,KAAA;AAC7E,EAAA,OAAO,IAAA;AACR;AAEA,eAAsB,oBAAA,CACrB,GAAA,EACA,SAAA,EACA,OAAA,EACA,cAAA,EAC2C;AAC3C,EAAA,KAAA,IAAS,OAAA,GAAU,CAAA,EAAG,OAAA,IAAW,OAAA,EAAS,OAAA,EAAA,EAAW;AACpD,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,UAAU,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC9D,IAAA,IAAI;AACH,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,QACjC,MAAA,EAAQ,KAAA;AAAA,QACR,OAAA,EAAS,EAAE,MAAA,EAAQ,kBAAA,EAAmB;AAAA,QACtC,QAAQ,UAAA,CAAW,MAAA;AAAA,QACnB,QAAA,EAAU;AAAA,OACV,CAAA;AACD,MAAA,IAAI,QAAA,CAAS,MAAA,IAAU,GAAA,IAAO,QAAA,CAAS,SAAS,GAAA,EAAK;AACpD,QAAA,OAAO,IAAA;AAAA,MACR;AACA,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,QAAA,IAAI,OAAA,GAAU,OAAA,IAAW,QAAA,CAAS,MAAA,IAAU,GAAA,EAAK;AACjD,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wCAAA,EAA2C,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,MAC7E;AAEA,MAAA,MAAM,UAAA,GAAa,MAAM,QAAA,CAAS,IAAA,EAAK;AACvC,MAAA,IAAI,CAAC,cAAA,EAAgB;AACpB,QAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,MAC7E;AAEA,MAAA,MAAM,MAAA,GAAS,MAAM,SAAA,CAAU,UAAU,CAAA;AACzC,MAAA,IAAI,MAAA,KAAW,eAAA,CAAgB,cAAc,CAAA,EAAG;AAC/C,QAAA,MAAM,IAAI,MAAM,uDAAuD,CAAA;AAAA,MACxE;AAEA,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AACrC,MAAA,IAAI,CAAC,uBAAA,CAAwB,OAAO,CAAA,EAAG;AACtC,QAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAAA,MAC9E;AAEA,MAAA,OAAO,OAAA;AAAA,IACR,SAAS,KAAA,EAAO;AACf,MAAA,IAAI,UAAU,OAAA,EAAS;AACvB,MAAA,IAAI,KAAA,YAAiB,YAAA,IAAgB,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACjE,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0CAAA,EAA6C,SAAS,CAAA,EAAA,CAAI,CAAA;AAAA,MAC3E;AACA,MAAA,MAAM,KAAA;AAAA,IACP,CAAA,SAAE;AACD,MAAA,YAAA,CAAa,OAAO,CAAA;AAAA,IACrB;AAAA,EACD;AAEA,EAAA,MAAM,IAAI,MAAM,oCAAoC,CAAA;AACrD;AAtLA,IA+Ba,kBAAA,EACA,iBACA,8BAAA,EAEA,mBAAA;AAnCb,IAAA,8BAAA,GAAA,KAAA,CAAA;AAAA,EAAA,sCAAA,GAAA;AA+BO,IAAM,kBAAA,GAAqB,IAAA;AAC3B,IAAM,eAAA,GAAkB,CAAA;AACxB,IAAM,8BAAA,GAAiC,IAAI,EAAA,GAAK,GAAA;AAEhD,IAAM,mBAAA,GAAgD;AAAA,MAC5D,OAAA,EAAS,qBAAA;AAAA,MACT,OAAA,EAAS;AAAA,QACR,EAAE,IAAA,EAAM,kBAAA,EAAoB,OAAA,EAAS,CAAC,YAAA,EAAc,gBAAgB,CAAA,EAAG,aAAA,EAAe,CAAC,QAAQ,CAAA,EAAE;AAAA,QACjG,EAAE,IAAA,EAAM,eAAA,EAAiB,OAAA,EAAS,CAAC,aAAA,EAAe,wBAAwB,CAAA,EAAG,aAAA,EAAe,CAAC,WAAA,EAAa,WAAW,CAAA,EAAE;AAAA,QACvH,EAAE,IAAA,EAAM,YAAA,EAAc,OAAA,EAAS,CAAC,cAAc,CAAA,EAAE;AAAA,QAChD,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,CAAC,cAAc,CAAA,EAAG,aAAA,EAAe,CAAC,UAAU,CAAA,EAAE;AAAA,QAC3E,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,CAAC,aAAa,CAAA,EAAE;AAAA,QAC5C,EAAE,IAAA,EAAM,UAAA,EAAY,OAAA,EAAS,CAAC,cAAc,CAAA,EAAE;AAAA,QAC9C,EAAE,IAAA,EAAM,YAAA,EAAc,OAAA,EAAS,CAAC,eAAe,CAAA;AAAE,OAClD;AAAA,MACA,UAAU;AAAC,KACZ;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACnBA,SAASE,iBAAgB,KAAA,EAAuB;AAC/C,EAAA,OAAO,MAAM,IAAA,EAAK,CAAE,aAAY,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AACpD;AAEA,SAAS,mBAAA,CAAoB,UAAkB,MAAA,EAAyB;AACvE,EAAA,MAAM,IAAA,GAAOA,iBAAgB,QAAQ,CAAA;AACrC,EAAA,MAAM,gBAAA,GAAmBA,iBAAgB,MAAM,CAAA;AAC/C,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,gBAAA,EAAkB,OAAO,KAAA;AACvC,EAAA,OAAO,SAAS,gBAAA,IAAoB,IAAA,CAAK,QAAA,CAAS,CAAA,CAAA,EAAI,gBAAgB,CAAA,CAAE,CAAA;AACzE;AAGA,eAAsB,uBAAuB,OAAA,EAAwE;AACpH,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,IAAa,kBAAA;AACxC,EAAA,MAAM,OAAA,GAAU,SAAS,OAAA,IAAW,eAAA;AACpC,EAAA,MAAM,SAAA,GAAY,OAAA,EAAS,SAAA,EAAW,IAAA,EAAK;AAC3C,EAAA,MAAM,YAAA,GAAe,qBAAA,CAAsB,OAAA,EAAS,YAAY,CAAA;AAChE,EAAA,MAAM,cAAA,GAAiB,OAAA,EAAS,cAAA,EAAgB,IAAA,EAAK;AAErD,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,OAAO,WAAA,CAAY,mBAAA,EAAqB,UAAA,EAAY,KAAK,CAAA;AAAA,EAC1D;AAEA,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,IAAI,yBAAyB,qBAAA,CAAsB,SAAA,KAAc,SAAA,IAAa,qBAAA,CAAsB,YAAY,GAAA,EAAK;AACpH,IAAA,OAAO,qBAAA,CAAsB,MAAA;AAAA,EAC9B;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,YAAA,GAAe,wBAAA,CAAyB,SAAA,EAAW,YAAY,CAAA;AACrE,IAAA,MAAM,OAAA,GAAU,MAAM,oBAAA,CAAqB,YAAA,CAAa,UAAS,EAAG,SAAA,EAAW,SAAS,cAAc,CAAA;AACtG,IAAA,IAAI,CAAC,OAAA,EAAS;AACb,MAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AAAA,IAChE;AACA,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,OAAA,EAAS,SAAA,EAAW,KAAK,CAAA;AACpD,IAAA,aAAA,GAAgB,MAAA;AAChB,IAAA,qBAAA,GAAwB;AAAA,MACvB,SAAA;AAAA,MACA,MAAA;AAAA,MACA,WAAW,GAAA,GAAM;AAAA,KAClB;AACA,IAAA,OAAO,MAAA;AAAA,EACR,CAAA,CAAA,MAAQ;AACP,IAAA,IAAI,aAAA,EAAe;AAClB,MAAA,MAAM,WAAA,GAAc,EAAE,GAAG,aAAA,EAAe,MAAA,EAAQ,OAAA,EAAkB,QAAA,EAAU,IAAA,EAAM,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,aAAY,EAAE;AACtH,MAAA,qBAAA,GAAwB;AAAA,QACvB,SAAA;AAAA,QACA,MAAA,EAAQ,WAAA;AAAA,QACR,WAAW,GAAA,GAAM;AAAA,OAClB;AACA,MAAA,OAAO,WAAA;AAAA,IACR;AACA,IAAA,MAAM,cAAA,GAAiB,WAAA,CAAY,mBAAA,EAAqB,UAAA,EAAY,IAAI,CAAA;AACxE,IAAA,qBAAA,GAAwB;AAAA,MACvB,SAAA;AAAA,MACA,MAAA,EAAQ,cAAA;AAAA,MACR,WAAW,GAAA,GAAM;AAAA,KAClB;AACA,IAAA,OAAO,cAAA;AAAA,EACR;AACD;AAWO,SAAS,qBAAA,CAAsB,OAAiB,UAAA,EAA0D;AAChH,EAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,GAAA,CAAI,CAAC,SAASA,gBAAAA,CAAgB,IAAI,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,CAAC,CAAA;AACnG,EAAA,MAAM,UAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,YAAY,UAAA,EAAY;AAClC,IAAA,MAAM,eAAA,uBAAsB,GAAA,EAAY;AACxC,IAAA,KAAA,MAAW,QAAQ,eAAA,EAAiB;AACnC,MAAA,IAAI,QAAA,CAAS,QAAQ,IAAA,CAAK,CAAC,WAAW,mBAAA,CAAoB,IAAA,EAAM,MAAM,CAAC,CAAA,EAAG;AACzE,QAAA,eAAA,CAAgB,IAAI,IAAI,CAAA;AAAA,MACzB;AAAA,IACD;AACA,IAAA,IAAI,eAAA,CAAgB,OAAO,CAAA,EAAG;AAC7B,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,QAAA,EAAU,QAAA,CAAS,IAAA,EAAM,SAAS,KAAA,CAAM,IAAA,CAAK,eAAe,CAAA,EAAG,CAAA;AAAA,IAC/E;AAAA,EACD;AAEA,EAAA,OAAO,OAAA;AACR;AAEO,SAAS,gCAAA,CAAiC,WAAqB,UAAA,EAA0D;AAC/H,EAAA,MAAM,sBAAsB,SAAA,CAAU,GAAA,CAAI,CAAC,QAAA,KAAa,SAAS,IAAA,EAAK,CAAE,WAAA,EAAa,EAAE,MAAA,CAAO,CAAC,QAAA,KAAa,QAAA,CAAS,SAAS,CAAC,CAAA;AAC/H,EAAA,MAAM,UAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,YAAY,UAAA,EAAY;AAClC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,IAAiB,EAAC;AACzC,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AAExB,IAAA,MAAM,eAAA,GAAkB,oBAAoB,MAAA,CAAO,CAAC,aAAa,KAAA,CAAM,QAAA,CAAS,QAAQ,CAAC,CAAA;AACzF,IAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC/B,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,QAAA,EAAU,QAAA,CAAS,IAAA,EAAM,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,eAAe,CAAC,GAAG,CAAA;AAAA,IACxF;AAAA,EACD;AAEA,EAAA,OAAO,OAAA;AACR;AArIA,IAqBI,aAAA,EACA,qBAAA;AAtBJ,IAAA,wBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,gCAAA,GAAA;AAEA,IAAA,8BAAA,EAAA;AAmBA,IAAI,aAAA,GAA6C,IAAA;AACjD,IAAI,qBAAA,GAIO,IAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACfJ,SAAS,eAAe,OAAA,EAAqC;AACnE,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC9B,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACtC,IAAA,MAAM,QAAA,GAAA,CAAY,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA,IAAK,EAAA,EAAI,OAAA,CAAQ,KAAA,EAAO,EAAE,EAAE,WAAA,EAAY;AACjF,IAAA,OAAO,EAAE,QAAA,EAAU,QAAA,EAAU,GAAA,EAAK,MAAA,EAAO;AAAA,EAC1C,CAAC,CAAA;AACF;AAEO,SAAS,eAAe,MAAA,EAAiC;AAC/D,EAAA,OAAO,MAAA,CAAO,QAAA,KAAa,EAAA,IAAM,MAAA,CAAO,QAAA,KAAa,GAAA;AACtD;AAEO,SAAS,gBAAA,GAA4B;AAC3C,EAAA,OAAO,aAAA,CAAc,IAAA,EAAM,2BAAA,EAA6B,MAAA,EAAQ,yEAAyE,CAAA;AAC1I;AAEO,SAAS,mBAAmB,SAAA,EAAsC;AACxE,EAAA,OAAO,cAAc,IAAA,EAAM,kBAAA,EAAoB,QAAQ,CAAA,EAAG,SAAA,CAAU,MAAM,CAAA,iCAAA,CAAmC,CAAA;AAC9G;AAEO,SAAS,oBAAoB,SAAA,EAAwC;AAC3E,EAAA,MAAM,SAAA,GAAY,sCAAA;AAClB,EAAA,OAAO,SAAA,CAAU,OAAA;AAAA,IAAQ,CAAC,QAAA,KACzB,SAAA,CAAU,IAAA,CAAK,QAAA,CAAS,QAAQ,CAAA,GAC7B;AAAA,MACA,aAAA;AAAA,QACC,IAAA;AAAA,QACA,yBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,WAAA,EAAc,SAAS,GAAG,CAAA,qEAAA;AAAA;AAC3B,QAEA;AAAC,GACL;AACD;AAEO,SAAS,mBAAmB,SAAA,EAA6C;AAC/E,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,OAAO,aAAA,CAAc,IAAA,EAAM,kBAAA,EAAoB,KAAA,EAAO,uEAAuE,CAAA;AAC9H;AAtDA,IAAA,gBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,0BAAA,GAAA;AAGA,IAAA,YAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACHA,IAAA,gBAAA,GAAA,EAAA;AAAA,QAAA,CAAA,gBAAA,EAAA;AAAA,EAAA,OAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAqBA,eAAsB,OAAA,CAAQ,MAAA,EAAgB,OAAA,EAA0B,UAAA,EAAoD;AAC3H,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACH,IAAA,OAAA,GAAU,MAAM,eAAA,CAAgB,MAAA,EAAQ,IAAA,EAAM,UAAU,CAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,gBAAA,CAAiB,MAAM,CAAC,aAAA,CAAc,MAAM,kBAAA,EAAoB,QAAA,EAAU,yBAAyB,CAAC,CAAC,CAAA;AAAA,EAC7G;AAEA,EAAA,IAAI,CAAC,OAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AACrC,IAAA,OAAO,iBAAiB,IAAA,EAAM;AAAA,MAC7B,aAAA;AAAA,QACC,IAAA;AAAA,QACA,qBAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACA,CAAA;AAAA,EACF;AAEA,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,MAAM,SAAA,GAAY,eAAe,OAAO,CAAA;AAGxC,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,IAAA,CAAK,cAAc,CAAA;AAC5C,EAAA,IAAI,MAAA,EAAQ;AACX,IAAA,QAAA,CAAS,IAAA,CAAK,kBAAkB,CAAA;AAChC,IAAA,OAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AAAA,EACvC;AAEA,EAAA,QAAA,CAAS,IAAA,CAAK,kBAAA,CAAmB,SAAS,CAAC,CAAA;AAE3C,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,mBAAA,CAAoB,SAAS,CAAC,CAAA;AAG/C,EAAA,MAAM,SAAA,GAAY,sCAAA;AAClB,EAAA,MAAM,eAAA,GAAkB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,QAAQ,CAAC,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ,GAAA;AAAA,IACjC,eAAA,CAAgB,GAAA,CAAI,OAAO,CAAA,KAAM;AAChC,MAAA,IAAI;AACH,QAAA,MAAM,CAAC,CAAA,EAAG,IAAI,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,UACnC,eAAA,CAAgB,EAAE,QAAA,EAAU,GAAA,EAAK,UAAU,CAAA,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AAAA,UAC3D,eAAA,CAAgB,EAAE,QAAA,EAAU,MAAA,EAAQ,UAAU,CAAA,CAAE,KAAA,CAAM,MAAM,EAAE;AAAA,SAC9D,CAAA;AACD,QAAA,OAAO,EAAE,QAAQ,CAAA,EAAG,QAAA,EAAU,EAAE,MAAA,GAAS,CAAA,IAAK,IAAA,CAAK,MAAA,GAAS,CAAA,EAAE;AAAA,MAC/D,CAAA,CAAA,MAAQ;AACP,QAAA,OAAO,EAAE,MAAA,EAAQ,CAAA,EAAG,QAAA,EAAU,KAAA,EAAM;AAAA,MACrC;AAAA,IACD,CAAC;AAAA,GACF;AACA,EAAA,KAAA,MAAW,EAAE,MAAA,EAAQ,QAAA,EAAS,IAAK,WAAA,EAAa;AAC/C,IAAA,IAAI,CAAC,QAAA,EAAU;AACd,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,IAAA;AAAA,UACA,oBAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,WAAA,EAAc,OAAO,QAAQ,CAAA,iFAAA;AAAA;AAC9B,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,eAAA,GAAkB,mBAAmB,SAAS,CAAA;AACpD,EAAA,IAAI,eAAA,EAAiB;AACpB,IAAA,QAAA,CAAS,KAAK,eAAe,CAAA;AAAA,EAC9B;AAIA,EAAA,MAAM,YAAY,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AACjD,EAAA,MAAM,kBAAA,GAAqB,MAAM,sBAAA,CAAuB;AAAA,IACvD,WAAW,OAAA,EAAS,qBAAA;AAAA,IACpB,cAAc,OAAA,EAAS,8BAAA;AAAA,IACvB,gBAAgB,OAAA,EAAS;AAAA,GACzB,CAAA;AACD,EAAA,MAAM,cAAA,GAAiB,qBAAA,CAAsB,SAAA,EAAW,kBAAA,CAAmB,OAAO,CAAA;AAElF,EAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC9B,IAAA,MAAM,aAAA,GAAgB,eAAe,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACrE,IAAA,MAAM,WAAW,cAAA,CAAe,GAAA,CAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,QAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAC9F,IAAA,MAAM,kBAAA,GAAqB,mBAAmB,MAAA,KAAW,SAAA,GAAY,OAAO,kBAAA,CAAmB,MAAA,KAAW,UAAU,IAAA,GAAO,GAAA;AAE3H,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA,CAAc,MAAM,iCAAA,EAAmC,MAAA,EAAQ,wBAAwB,aAAa,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAA,CAAA,EAAK;AAAA,QAC/H,aAAA,EAAe,SAAA;AAAA,QACf,SAAA,EAAW,cAAA,CAAe,GAAA,CAAI,CAAC,CAAA,MAAO,EAAE,IAAA,EAAM,CAAA,CAAE,QAAA,EAAU,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,CAAA;AAAA,QAC/E,kBAAA;AAAA,QACA,iBAAiB,kBAAA,CAAmB,MAAA;AAAA,QACpC,kBAAkB,kBAAA,CAAmB,OAAA;AAAA,QACrC,oBAAoB,kBAAA,CAAmB;AAAA,OACvC;AAAA,KACF;AAAA,EACD;AAEA,EAAA,IAAI,mBAAmB,QAAA,EAAU;AAChC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,IAAA;AAAA,QACA,uCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,wBAAA,EAA2B,kBAAA,CAAmB,MAAA,KAAW,OAAA,GAAU,iBAAiB,mBAAmB,CAAA,YAAA,CAAA;AAAA,QACvG;AAAA,UACC,aAAA,EAAe,SAAA;AAAA,UACf,kBAAA,EAAoB,kBAAA,CAAmB,MAAA,KAAW,OAAA,GAAU,IAAA,GAAO,IAAA;AAAA,UACnE,iBAAiB,kBAAA,CAAmB,MAAA;AAAA,UACpC,kBAAkB,kBAAA,CAAmB,OAAA;AAAA,UACrC,oBAAoB,kBAAA,CAAmB;AAAA;AACxC;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AACvC;AAxIA,IAAA,aAAA,GAAA,KAAA,CAAA;AAAA,EAAA,uBAAA,GAAA;AAQA,IAAA,YAAA,EAAA;AACA,IAAA,QAAA,EAAA;AAEA,IAAA,wBAAA,EAAA;AACA,IAAA,gBAAA,EAAA;AAAA,EAAA;AAAA,CAAA,CAAA;;;ACMO,IAAM,eAAA,GAAkB;AAAA,EAC9B,WAAA,EAAa,MAAA;AAAA,EACb,eAAA,EAAiB,MAAA;AAAA,EACjB,gBAAA,EAAkB,MAAA;AAAA,EAClB,cAAA,EAAgB,MAAA;AAAA,EAChB,cAAA,EAAgB,MAAA;AAAA,EAChB,YAAA,EAAc,MAAA;AAAA,EACd,YAAA,EAAc;AACf,CAAA;AAGO,SAAS,YAAA,CAAa,EAAA,EAAwC,IAAA,EAAc,OAAA,EAAiB;AACnG,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,IAAI,EAAA,IAAM,IAAA;AAAA,IACV,KAAA,EAAO,EAAE,IAAA,EAAM,OAAA;AAAQ,GACxB;AACD;AAGA,IAAM,sBAAsB,CAAC,kBAAA,EAAoB,SAAA,EAAW,SAAA,EAAW,sBAAsB,qBAAqB,CAAA;AAU3G,SAAS,oBAAA,CAAqB,OAAgB,QAAA,EAA0B;AAC9E,EAAA,IAAI,iBAAiB,KAAA,EAAO;AAC3B,IAAA,KAAA,MAAW,UAAU,mBAAA,EAAqB;AACzC,MAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA,EAAG;AACrC,QAAA,OAAO,KAAA,CAAM,OAAA;AAAA,MACd;AAAA,IACD;AAAA,EACD;AACA,EAAA,OAAO,QAAA;AACR;AAGO,SAAS,cAAA,CAAe,IAAwC,MAAA,EAAiB;AACvF,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,KAAA;AAAA,IACT,IAAI,EAAA,IAAM,IAAA;AAAA,IACV;AAAA,GACD;AACD;;;AC5CO,SAAS,kBAAkB,GAAA,EAA+C;AAChF,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,EAAA,IAAI,CAAC,SAAS,OAAO,MAAA;AACrB,EAAA,OAAO,QACL,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAC,SAAS,IAAA,CAAK,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA,CACvC,MAAA,CAAO,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,CAAC,CAAA;AACnC;AAsDO,SAAS,oBAAoB,OAAA,EAA6C;AAChF,EAAA,IAAI;AACH,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AACjC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG;AAC1B,MAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACxB,QAAA,OAAO;AAAA,UACN,EAAA,EAAI,KAAA;AAAA,UACJ,MAAA,EAAQ,GAAA;AAAA,UACR,OAAA,EAAS,YAAA,CAAa,IAAA,EAAM,eAAA,CAAgB,iBAAiB,6CAA6C;AAAA,SAC3G;AAAA,MACD;AACA,MAAA,OAAO;AAAA,QACN,EAAA,EAAI,IAAA;AAAA,QACJ,IAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS;AAAA,OACV;AAAA,IACD;AACA,IAAA,OAAO;AAAA,MACN,EAAA,EAAI,IAAA;AAAA,MACJ,IAAA,EAAM,MAAA;AAAA;AAAA,MACN,OAAA,EAAS;AAAA,KACV;AAAA,EACD,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO;AAAA,MACN,EAAA,EAAI,KAAA;AAAA,MACJ,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,YAAA,CAAa,IAAA,EAAM,eAAA,CAAgB,aAAa,2BAA2B;AAAA,KACrF;AAAA,EACD;AACD;AAEO,SAAS,uBAAuB,IAAA,EAA6F;AACnI,EAAA,IAAI,KAAK,OAAA,KAAY,KAAA,IAAS,OAAO,IAAA,CAAK,WAAW,QAAA,EAAU;AAC9D,IAAA,OAAO;AAAA,MACN,MAAA,EAAQ,GAAA;AAAA,MACR,SAAS,YAAA,CAAa,IAAA,CAAK,EAAA,EAAI,eAAA,CAAgB,iBAAiB,8BAA8B;AAAA,KAC/F;AAAA,EACD;AAEA,EAAA,IAAI,IAAA,CAAK,EAAA,KAAO,MAAA,IAAa,IAAA,CAAK,EAAA,KAAO,IAAA,IAAQ,OAAO,IAAA,CAAK,EAAA,KAAO,QAAA,IAAY,OAAO,IAAA,CAAK,OAAO,QAAA,EAAU;AAC5G,IAAA,OAAO;AAAA,MACN,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,YAAA,CAAa,IAAA,EAAM,eAAA,CAAgB,iBAAiB,sDAAsD;AAAA,KACpH;AAAA,EACD;AAEA,EAAA,OAAO,MAAA;AACR;;;AC/GA,IAAM,SAAA,GAAY,GAAA;AAClB,IAAM,OAAA,GAAU,IAAA;AAChB,IAAM,MAAA,GAAS,KAAA;AACf,IAAM,mBAAA,GAAsB,GAAA;AAE5B,IAAM,kBAAA,uBAAyB,GAAA,EAA4B;AAC3D,IAAM,kBAAA,uBAAyB,GAAA,EAAqC;AACpE,IAAI,WAAA,GAAc,KAAK,GAAA,EAAI;AAGpB,SAAS,eAAA,CAAgB,UAAA,EAAsB,QAAA,EAAkB,GAAA,EAAuB;AAC9F,EAAA,MAAM,SAAS,GAAA,GAAM,QAAA;AACrB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,OAAO,QAAQ,UAAA,CAAW,MAAA,IAAU,UAAA,CAAW,KAAK,KAAK,MAAA,EAAQ;AAChE,IAAA,KAAA,EAAA;AAAA,EACD;AACA,EAAA,OAAO,KAAA,GAAQ,CAAA,GAAI,UAAA,CAAW,KAAA,CAAM,KAAK,CAAA,GAAI,UAAA;AAC9C;AAEA,SAAS,sBAAsB,GAAA,EAAmB;AACjD,EAAA,IAAI,GAAA,GAAM,cAAc,mBAAA,EAAqB;AAC7C,EAAA,WAAA,GAAc,GAAA;AAEd,EAAA,MAAM,aAAa,GAAA,GAAM,OAAA;AACzB,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,kBAAA,EAAoB;AAC9C,IAAA,IAAI,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,KAAW,KAAK,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA,GAAS,CAAC,KAAK,UAAA,EAAY;AAChH,MAAA,kBAAA,CAAmB,OAAO,GAAG,CAAA;AAAA,IAC9B;AAAA,EACD;AAEA,EAAA,MAAM,YAAY,GAAA,GAAM,MAAA;AACxB,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,kBAAA,EAAoB;AAC9C,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,UAAA,CAAW,KAAA,CAAM,UAAA,CAAW,MAAA,GAAS,CAAC,CAAA,IAAK,SAAA,EAAW;AAChG,MAAA,kBAAA,CAAmB,OAAO,GAAG,CAAA;AAAA,IAC9B;AAAA,EACD;AACD;AAEA,SAAS,iBAAiB,GAAA,EAA6B;AACtD,EAAA,IAAI,KAAA,GAAQ,kBAAA,CAAmB,GAAA,CAAI,GAAG,CAAA;AACtC,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,KAAA,GAAQ;AAAA,MACP,MAAA,EAAQ,EAAE,UAAA,EAAY,EAAC,EAAE;AAAA,MACzB,IAAA,EAAM,EAAE,UAAA,EAAY,EAAC;AAAE,KACxB;AACA,IAAA,kBAAA,CAAmB,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,KAAA;AACR;AAEA,SAAS,mBAAA,CAAoB,IAAY,KAAA,EAA+B;AACvE,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,CAAA,EAAI,EAAE,CAAA,CAAA;AACtB;AAEA,SAAS,0BAA0B,GAAA,EAAsC;AACxE,EAAA,IAAI,KAAA,GAAQ,kBAAA,CAAmB,GAAA,CAAI,GAAG,CAAA;AACtC,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,KAAA,GAAQ,EAAE,UAAA,EAAY,EAAC,EAAE;AACzB,IAAA,kBAAA,CAAmB,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,KAAA;AACR;AAEO,SAAS,4BAAA,CAA6B,EAAA,EAAY,KAAA,EAAuB,WAAA,EAAqB,SAAA,EAAoC;AACxI,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,qBAAA,CAAsB,GAAG,CAAA;AAEzB,EAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,mBAAA,CAAoB,EAAA,EAAI,KAAK,CAAC,CAAA;AAC7D,EAAA,KAAA,CAAM,OAAO,UAAA,GAAa,eAAA,CAAgB,MAAM,MAAA,CAAO,UAAA,EAAY,WAAW,GAAG,CAAA;AACjF,EAAA,KAAA,CAAM,KAAK,UAAA,GAAa,eAAA,CAAgB,MAAM,IAAA,CAAK,UAAA,EAAY,SAAS,GAAG,CAAA;AAE3E,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,MAAA;AAC5C,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,MAAA;AAExC,EAAA,IAAI,eAAe,WAAA,EAAa;AAC/B,IAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,CAAC,CAAA;AAChD,IAAA,MAAM,YAAA,GAAe,iBAAiB,SAAA,GAAY,GAAA;AAClD,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,KAAA;AAAA,MACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,CAAC,CAAA;AAAA,MACtC,eAAA,EAAiB,CAAA;AAAA,MACjB,aAAA,EAAe,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,WAAW,CAAC;AAAA,KACjD;AAAA,EACD;AAEA,EAAA,IAAI,aAAa,SAAA,EAAW;AAC3B,IAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA;AAC9C,IAAA,MAAM,YAAA,GAAe,iBAAiB,OAAA,GAAU,GAAA;AAChD,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,KAAA;AAAA,MACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,CAAC,CAAA;AAAA,MACtC,eAAA,EAAiB,IAAA,CAAK,GAAA,CAAI,WAAA,GAAc,aAAa,CAAC,CAAA;AAAA,MACtD,aAAA,EAAe;AAAA,KAChB;AAAA,EACD;AAEA,EAAA,KAAA,CAAM,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AAChC,EAAA,KAAA,CAAM,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AAE9B,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,IAAA;AAAA,IACT,eAAA,EAAiB,cAAc,WAAA,GAAc,CAAA;AAAA,IAC7C,aAAA,EAAe,YAAY,SAAA,GAAY;AAAA,GACxC;AACD;AAEO,SAAS,+BAAA,CAAgC,WAAA,EAAqB,QAAA,EAAkB,KAAA,EAAyC;AAC/H,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,qBAAA,CAAsB,GAAG,CAAA;AAEzB,EAAA,MAAM,GAAA,GAAM,GAAG,WAAW,CAAA,CAAA,EAAI,SAAS,IAAA,EAAK,CAAE,aAAa,CAAA,CAAA;AAC3D,EAAA,MAAM,KAAA,GAAQ,0BAA0B,GAAG,CAAA;AAC3C,EAAA,KAAA,CAAM,UAAA,GAAa,eAAA,CAAgB,KAAA,CAAM,UAAA,EAAY,QAAQ,GAAG,CAAA;AAEhE,EAAA,MAAM,KAAA,GAAQ,MAAM,UAAA,CAAW,MAAA;AAC/B,EAAA,IAAI,SAAS,KAAA,EAAO;AACnB,IAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,UAAA,CAAW,CAAC,CAAA;AACzC,IAAA,MAAM,YAAA,GAAe,iBAAiB,MAAA,GAAS,GAAA;AAC/C,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,KAAA;AAAA,MACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,CAAC,CAAA;AAAA,MACtC,SAAA,EAAW,CAAA;AAAA,MACX;AAAA,KACD;AAAA,EACD;AAEA,EAAA,KAAA,CAAM,UAAA,CAAW,KAAK,GAAG,CAAA;AACzB,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,IAAA;AAAA,IACT,WAAW,IAAA,CAAK,GAAA,CAAI,QAAQ,KAAA,CAAM,UAAA,CAAW,QAAQ,CAAC,CAAA;AAAA,IACtD;AAAA,GACD;AACD;ACnJA,IAAM,gBAAA,GAAmB,0BAAA;AAkEzB,SAAS,mBAAmB,SAAA,EAA8E;AACzG,EAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AACvB,EAAA,OAAO,SAAA,CAAU,UAAU,gBAAgB,CAAA;AAC5C;AAEA,eAAe,eAAA,CACd,WACA,OAAA,EACyB;AACzB,EAAA,MAAM,IAAA,GAAO,mBAAmB,SAAS,CAAA;AACzC,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAElB,EAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,yBAAA,EAA2B;AAAA,IAC5D,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,IAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,OAAO;AAAA,GAC5B,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,QAAA,CAAS,MAAM,CAAA,CAAE,CAAA;AAAA,EACrE;AAEA,EAAA,IAAI,OAAA,CAAQ,SAAS,OAAA,EAAS;AAC7B,IAAA,OAAO,MAAA;AAAA,EACR;AAEA,EAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAC7B;AAEA,eAAsB,mCAAA,CACrB,EAAA,EACA,KAAA,EACA,WAAA,EACA,WACA,SAAA,EACuC;AACvC,EAAA,OAAO,gBAAiC,SAAA,EAAW;AAAA,IAClD,IAAA,EAAM,aAAA;AAAA,IACN,KAAA;AAAA,IACA,EAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACA,CAAA;AACF;AAEA,eAAsB,sCAAA,CACrB,WAAA,EACA,QAAA,EACA,KAAA,EACA,SAAA,EACgD;AAChD,EAAA,OAAO,gBAA0C,SAAA,EAAW;AAAA,IAC3D,IAAA,EAAM,YAAA;AAAA,IACN,WAAA;AAAA,IACA,QAAA;AAAA,IACA;AAAA,GACA,CAAA;AACF;AAEA,eAAsB,oCAAA,CACrB,OACA,SAAA,EAC6C;AAC7C,EAAA,OAAO,gBAAuC,SAAA,EAAW;AAAA,IACxD,IAAA,EAAM,cAAA;AAAA,IACN;AAAA,GACA,CAAA;AACF;AAEA,eAAsB,0CAAA,CACrB,EAAA,EACA,KAAA,EACA,QAAA,EACA,SAAA,EAC+C;AAC/C,EAAA,OAAO,gBAAyC,SAAA,EAAW;AAAA,IAC1D,IAAA,EAAM,gBAAA;AAAA,IACN,EAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACA,CAAA;AACF;;;ACpGA,IAAM,YAAA,GAAe,EAAA;AACrB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,0BAAA,GAA6B,EAAA;AACnC,IAAM,wBAAA,GAA2B,GAAA;AACjC,IAAMC,UAAAA,GAAY,GAAA;AAClB,IAAMC,QAAAA,GAAU,IAAA;AAChB,IAAMC,OAAAA,GAAS,KAAA;AAIf,IAAM,gBAAA,uBAAuB,GAAA,EAA2B;AAExD,SAAS,uBAAuB,EAAA,EAA6B;AAC5D,EAAA,OAAO,4BAAA,CAA6B,EAAA,EAAI,OAAA,EAAS,YAAA,EAAc,UAAU,CAAA;AAC1E;AAEA,SAAS,mCAAmC,EAAA,EAA6B;AACxE,EAAA,OAAO,4BAAA,CAA6B,EAAA,EAAI,SAAA,EAAW,0BAAA,EAA4B,wBAAwB,CAAA;AACxG;AAGA,SAAS,eAAe,GAAA,EAA4B;AACnD,EAAA,IAAI,CAAC,KAAK,OAAO,CAAA;AACjB,EAAA,MAAM,CAAA,GAAI,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AAC1B,EAAA,OAAO,OAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,IAAK,IAAI,CAAA,GAAI,CAAA;AAC3C;AAMA,eAAe,sBAAA,CACd,EAAA,EACA,KAAA,EACA,WAAA,EACA,WACA,EAAA,EAC2B;AAC3B,EAAA,OAAO,YAAA,CAAa,IAAI,YAAY;AACpC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMF,UAAS,CAAA;AAC/C,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMC,QAAO,CAAA;AAE3C,IAAA,MAAM,SAAA,GAAY,KAAA,KAAU,OAAA,GAAU,CAAA,OAAA,EAAU,EAAE,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA,GAAK,CAAA,WAAA,EAAc,EAAE,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA;AACvG,IAAA,MAAM,OAAA,GAAU,KAAA,KAAU,OAAA,GAAU,CAAA,MAAA,EAAS,EAAE,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA,GAAK,CAAA,UAAA,EAAa,EAAE,CAAA,CAAA,EAAI,UAAU,CAAA,CAAA;AAG/F,IAAA,MAAM,CAAC,SAAA,EAAW,OAAO,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI,CAAC,EAAA,CAAG,GAAA,CAAI,SAAS,CAAA,EAAG,EAAA,CAAG,GAAA,CAAI,OAAO,CAAC,CAAC,CAAA;AAEnF,IAAA,MAAM,WAAA,GAAc,eAAe,SAAS,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAY,eAAe,OAAO,CAAA;AAGxC,IAAA,IAAI,eAAe,WAAA,EAAa;AAC/B,MAAA,MAAM,SAAA,GAAA,CAAa,eAAe,CAAA,IAAKD,UAAAA;AACvC,MAAA,OAAO;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,KAAK,CAAC,CAAA;AAAA,QACzC,eAAA,EAAiB,CAAA;AAAA,QACjB,aAAA,EAAe,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,WAAW,CAAC;AAAA,OACjD;AAAA,IACD;AAGA,IAAA,IAAI,aAAa,SAAA,EAAW;AAC3B,MAAA,MAAM,SAAA,GAAA,CAAa,aAAa,CAAA,IAAKC,QAAAA;AACrC,MAAA,OAAO;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,KAAK,CAAC,CAAA;AAAA,QACzC,eAAA,EAAiB,IAAA,CAAK,GAAA,CAAI,WAAA,GAAc,aAAa,CAAC,CAAA;AAAA,QACtD,aAAA,EAAe;AAAA,OAChB;AAAA,IACD;AAGA,IAAA,MAAM,YAAY,WAAA,GAAc,CAAA;AAChC,IAAA,MAAM,UAAU,SAAA,GAAY,CAAA;AAC5B,IAAA,MAAM,QAAQ,GAAA,CAAI;AAAA,MACjB,EAAA,CAAG,IAAI,SAAA,EAAW,MAAA,CAAO,SAAS,CAAA,EAAG,EAAE,aAAA,EAAe,EAAA,EAAI,CAAA;AAAA,MAC1D,EAAA,CAAG,IAAI,OAAA,EAAS,MAAA,CAAO,OAAO,CAAA,EAAG,EAAE,aAAA,EAAe,IAAA,EAAM;AAAA,KACxD,CAAA;AAED,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,IAAA;AAAA,MACT,iBAAiB,WAAA,GAAc,SAAA;AAAA,MAC/B,eAAe,SAAA,GAAY;AAAA,KAC5B;AAAA,EACA,CAAC,CAAA;AACF;AAEA,eAAe,gBAAA,CAAiB,IAAY,EAAA,EAA2C;AACtF,EAAA,OAAO,sBAAA,CAAuB,EAAA,EAAI,OAAA,EAAS,YAAA,EAAc,YAAY,EAAE,CAAA;AACxE;AAEA,eAAe,4BAAA,CAA6B,IAAY,EAAA,EAA2C;AAClG,EAAA,OAAO,sBAAA,CAAuB,EAAA,EAAI,SAAA,EAAW,0BAAA,EAA4B,0BAA0B,EAAE,CAAA;AACtG;AAEA,eAAe,YAAA,CAAgB,IAAY,IAAA,EAAoC;AAC9E,EAAA,MAAM,WAAW,gBAAA,CAAiB,GAAA,CAAI,EAAE,CAAA,IAAK,QAAQ,OAAA,EAAQ;AAC7D,EAAA,IAAI,OAAA;AACJ,EAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AAC9C,IAAA,OAAA,GAAU,OAAA;AAAA,EACX,CAAC,CAAA;AACD,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AACxC,EAAA,gBAAA,CAAiB,GAAA,CAAI,IAAI,IAAI,CAAA;AAE7B,EAAA,MAAM,QAAA;AACN,EAAA,IAAI;AACH,IAAA,OAAO,MAAM,IAAA,EAAK;AAAA,EACnB,CAAA,SAAE;AACD,IAAA,OAAA,IAAU;AACV,IAAA,IAAI,gBAAA,CAAiB,GAAA,CAAI,EAAE,CAAA,KAAM,IAAA,EAAM;AACtC,MAAA,gBAAA,CAAiB,OAAO,EAAE,CAAA;AAAA,IAC3B;AAAA,EACD;AACD;AAEA,eAAe,yBAAA,CACd,WAAA,EACA,QAAA,EACA,KAAA,EACA,EAAA,EACoC;AACpC,EAAA,OAAO,aAAa,CAAA,KAAA,EAAQ,WAAW,CAAA,CAAA,EAAI,QAAQ,IAAI,YAAY;AAClE,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMC,OAAM,CAAA;AACzC,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,IAAA,EAAK,CAAE,WAAA,EAAY;AAC5C,IAAA,MAAM,MAAM,CAAA,YAAA,EAAe,OAAO,CAAA,CAAA,EAAI,WAAW,IAAI,SAAS,CAAA,CAAA;AAE9D,IAAA,MAAM,UAAA,GAAa,MAAM,EAAA,CAAG,GAAA,CAAI,GAAG,CAAA;AACnC,IAAA,MAAM,YAAA,GAAe,eAAe,UAAU,CAAA;AAE9C,IAAA,IAAI,gBAAgB,KAAA,EAAO;AAC1B,MAAA,MAAM,SAAA,GAAA,CAAa,YAAY,CAAA,IAAKA,OAAAA;AACpC,MAAA,OAAO;AAAA,QACN,OAAA,EAAS,KAAA;AAAA,QACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,KAAK,CAAC,CAAA;AAAA,QACzC,SAAA,EAAW,CAAA;AAAA,QACX;AAAA,OACD;AAAA,IACD;AAEA,IAAA,MAAM,YAAY,YAAA,GAAe,CAAA;AACjC,IAAA,MAAM,EAAA,CAAG,IAAI,GAAA,EAAK,MAAA,CAAO,SAAS,CAAA,EAAG,EAAE,aAAA,EAAe,KAAA,EAAQ,CAAA;AAE9D,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,WAAW,CAAC,CAAA;AAAA,MACxC;AAAA,KACD;AAAA,EACD,CAAC,CAAA;AACF;AAMA,IAAI,eAAA,GAAkB,CAAA;AACtB,IAAI,cAAA,GAAiB,CAAA;AAErB,SAAS,8BAA8B,KAAA,EAAsC;AAC5E,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMA,OAAM,CAAA;AAC7C,EAAA,IAAI,kBAAkB,eAAA,EAAiB;AACtC,IAAA,eAAA,GAAkB,aAAA;AAClB,IAAA,cAAA,GAAiB,CAAA;AAAA,EAClB;AACA,EAAA,IAAI,kBAAkB,KAAA,EAAO;AAC5B,IAAA,MAAM,SAAA,GAAA,CAAa,gBAAgB,CAAA,IAAKA,OAAAA;AACxC,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,GAAA,EAAK,CAAC,CAAA,EAAG,SAAA,EAAW,CAAA,EAAG,KAAA,EAAM;AAAA,EAC1F;AACA,EAAA,cAAA,EAAA;AACA,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,IAAA,CAAK,IAAI,KAAA,GAAQ,cAAA,EAAgB,CAAC,CAAA,EAAG,KAAA,EAAM;AAC/E;AAEA,eAAe,uBAAA,CAAwB,OAAe,EAAA,EAAiD;AACtG,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMA,OAAM,CAAA;AAC7C,EAAA,MAAM,GAAA,GAAM,iBAAiB,aAAa,CAAA,CAAA;AAE1C,EAAA,MAAM,UAAA,GAAa,MAAM,EAAA,CAAG,GAAA,CAAI,GAAG,CAAA;AACnC,EAAA,MAAM,YAAA,GAAe,eAAe,UAAU,CAAA;AAE9C,EAAA,IAAI,gBAAgB,KAAA,EAAO;AAC1B,IAAA,MAAM,SAAA,GAAA,CAAa,gBAAgB,CAAA,IAAKA,OAAAA;AACxC,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,GAAA,EAAK,CAAC,CAAA,EAAG,SAAA,EAAW,CAAA,EAAG,KAAA,EAAM;AAAA,EAC1F;AAEA,EAAA,MAAM,YAAY,YAAA,GAAe,CAAA;AACjC,EAAA,MAAM,EAAA,CAAG,IAAI,GAAA,EAAK,MAAA,CAAO,SAAS,CAAA,EAAG,EAAE,aAAA,EAAe,KAAA,EAAQ,CAAA;AAE9D,EAAA,OAAO,EAAE,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,IAAA,CAAK,IAAI,KAAA,GAAQ,SAAA,EAAW,CAAC,CAAA,EAAG,KAAA,EAAM;AAC1E;AAcA,eAAsB,cAAA,CAAe,EAAA,EAAY,EAAA,EAAkB,gBAAA,EAAqE;AACvI,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,cAAc,MAAM,mCAAA,CAAoC,IAAI,OAAA,EAAS,YAAA,EAAc,YAAY,gBAAgB,CAAA;AACrH,MAAA,IAAI,aAAa,OAAO,WAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,sEAAsE,CAAA;AAAA,IACpF;AAAA,EACD;AACM,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,gBAAA,CAAiB,EAAA,EAAI,EAAE,CAAA;AAAA,IACrC,CAAA,CAAA,MAAQ;AAEP,MAAA,OAAA,CAAQ,KAAK,oDAAoD,CAAA;AAAA,IAClE;AAAA,EACD;AACA,EAAA,OAAO,uBAAuB,EAAE,CAAA;AACvC;AAMA,eAAsB,0BAAA,CACrB,EAAA,EACA,EAAA,EACA,gBAAA,EAC2B;AAC3B,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,cAAc,MAAM,mCAAA,CAAoC,IAAI,SAAA,EAAW,0BAAA,EAA4B,0BAA0B,gBAAgB,CAAA;AACnJ,MAAA,IAAI,aAAa,OAAO,WAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,oFAAoF,CAAA;AAAA,IAClG;AAAA,EACD;AACA,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,4BAAA,CAA6B,EAAA,EAAI,EAAE,CAAA;AAAA,IACjD,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,kEAAkE,CAAA;AAAA,IAChF;AAAA,EACD;AACA,EAAA,OAAO,mCAAmC,EAAE,CAAA;AAC7C;AAMA,eAAsB,uBAAA,CACrB,WAAA,EACA,QAAA,EACA,KAAA,EACA,IACA,gBAAA,EACoC;AACpC,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,cAAc,MAAM,sCAAA,CAAuC,WAAA,EAAa,QAAA,EAAU,OAAO,gBAAgB,CAAA;AAC/G,MAAA,IAAI,aAAa,OAAO,WAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,iFAAiF,CAAA;AAAA,IAC/F;AAAA,EACD;AACA,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,yBAAA,CAA0B,WAAA,EAAa,QAAA,EAAU,OAAO,EAAE,CAAA;AAAA,IACxE,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,+DAA+D,CAAA;AAAA,IAC7E;AAAA,EACD;AACA,EAAA,OAAO,+BAAA,CAAgC,WAAA,EAAa,QAAA,EAAU,KAAK,CAAA;AACpE;AAMA,eAAsB,qBAAA,CACrB,KAAA,EACA,EAAA,EACA,gBAAA,EACiC;AACjC,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,WAAA,GAAc,MAAM,oCAAA,CAAqC,KAAA,EAAO,gBAAgB,CAAA;AACtF,MAAA,IAAI,aAAa,OAAO,WAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,iFAAiF,CAAA;AAAA,IAC/F;AAAA,EACD;AACA,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,uBAAA,CAAwB,KAAA,EAAO,EAAE,CAAA;AAAA,IAC/C,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,+DAA+D,CAAA;AAAA,IAC7E;AAAA,EACD;AACA,EAAA,OAAO,8BAA8B,KAAK,CAAA;AAC3C;;;AChVA,IAAM,QAAA,GAAW,YAAA;AACjB,IAAM,qBAAA,GAAwB,GAAA;AAC9B,IAAM,qBAAA,GAAwB,0FAAA;AAE9B,SAAS,eAAe,GAAA,EAAsB;AAC7C,EAAA,OAAO,CAAC,WAAA,CAAY,IAAA,CAAK,GAAG,CAAA,IAAK,qBAAA,CAAsB,KAAK,GAAG,CAAA;AAChE;AAEA,SAAS,cAAc,KAAA,EAAkD;AACxE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC3E;AAEA,SAAS,eAAe,KAAA,EAAuB;AAC9C,EAAA,OAAO,KAAA,CAAM,SAAS,qBAAA,GAAwB,CAAA,EAAG,MAAM,KAAA,CAAM,CAAA,EAAG,qBAAqB,CAAC,CAAA,GAAA,CAAA,GAAQ,KAAA;AAC/F;AAEO,SAAS,gBAAA,CAAiB,OAAgB,GAAA,EAAuB;AACvE,EAAA,IAAI,GAAA,IAAO,cAAA,CAAe,GAAG,CAAA,EAAG;AAC/B,IAAA,OAAO,QAAA;AAAA,EACR;AAEA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC9B,IAAA,OAAO,eAAe,KAAK,CAAA;AAAA,EAC5B;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,MAAM,GAAA,CAAI,CAAC,IAAA,KAAS,gBAAA,CAAiB,IAAI,CAAC,CAAA;AAAA,EAClD;AAEA,EAAA,IAAI,aAAA,CAAc,KAAK,CAAA,EAAG;AACzB,IAAA,MAAM,YAAqC,EAAC;AAC5C,IAAA,KAAA,MAAW,CAAC,QAAA,EAAU,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC3D,MAAA,SAAA,CAAU,QAAQ,CAAA,GAAI,gBAAA,CAAiB,UAAA,EAAY,QAAQ,CAAA;AAAA,IAC5D;AACA,IAAA,OAAO,SAAA;AAAA,EACR;AAEA,EAAA,OAAO,KAAA;AACR;AAsBO,SAAS,SAAS,KAAA,EAAuB;AAC/C,EAAA,MAAM,GAAA,GAAM;AAAA,IACX,GAAG,KAAA;AAAA,IACH,WAAW,KAAA,CAAM,SAAA,IAAA,iBAAa,IAAI,IAAA,IAAO,WAAA,EAAY;AAAA,IACrD,OAAA,EAAS,gBAAA,CAAiB,KAAA,CAAM,OAAO,CAAA;AAAA,IACvC,KAAA,EAAO,OAAO,KAAA,CAAM,KAAA,KAAU,WAAW,cAAA,CAAe,KAAA,CAAM,KAAK,CAAA,GAAI,KAAA,CAAM;AAAA,GAC9E;AACA,EAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,CAAK,SAAA,CAAU,GAAG,CAAC,CAAA;AAChC;AAKO,SAAS,QAAA,CAAS,OAAuB,OAAA,EAAmC;AAClF,EAAA,QAAA,CAAS;AAAA,IACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,QAAA,EAAU,OAAA;AAAA,IACV,KAAA,EAAO,OAAO,KAAA,KAAU,QAAA,GAAW,QAAQ,KAAA,CAAM,OAAA;AAAA,IACjD,GAAG;AAAA,GACH,CAAA;AACF;;;ACvFO,IAAM,eAAA,uBAAsB,GAAA,EAA2B;AAGvD,IAAM,cAAA,GAAiB,KAAK,EAAA,GAAK,GAAA;AACjC,IAAM,2BAAA,GAA8B,IAAI,EAAA,GAAK,GAAA;AAEpD,IAAM,wBAAA,GAA2B,GAAA;AACjC,IAAM,+BAAA,GAAkC,EAAA;AACxC,IAAM,sBAAA,GAAyB,GAAA;AAC/B,IAAM,2BAAA,GAA8B,IAAI,EAAA,GAAK,GAAA;AAE7C,IAAI,aAAA,GAAgB,CAAA;AACpB,IAAM,oBAAA,uBAA2B,GAAA,EAAsB;AAEvD,SAAS,SAAA,CAAU,gBAAwB,GAAA,EAAsB;AAChE,EAAA,OAAO,MAAM,cAAA,GAAiB,cAAA;AAC/B;AAEA,SAAS,qBAAqB,GAAA,EAAmB;AAChD,EAAA,IAAI,GAAA,GAAM,gBAAgB,2BAAA,EAA6B;AACvD,EAAA,aAAA,GAAgB,GAAA;AAEhB,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,CAAA,IAAK,eAAA,CAAgB,SAAQ,EAAG;AACtD,IAAA,IAAI,SAAA,CAAU,OAAA,CAAQ,cAAA,EAAgB,GAAG,CAAA,EAAG;AAC3C,MAAA,eAAA,CAAgB,OAAO,EAAE,CAAA;AAAA,IAC1B;AAAA,EACD;AACD;AAEA,SAAS,6BAAA,GAAsC;AAC9C,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI,eAAe,MAAA,CAAO,iBAAA;AAE1B,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,OAAO,CAAA,IAAK,eAAA,CAAgB,SAAQ,EAAG;AACtD,IAAA,IAAI,OAAA,CAAQ,iBAAiB,YAAA,EAAc;AAC1C,MAAA,YAAA,GAAe,OAAA,CAAQ,cAAA;AACvB,MAAA,QAAA,GAAW,EAAA;AAAA,IACZ;AAAA,EACD;AAEA,EAAA,IAAI,QAAA,EAAU;AACb,IAAA,eAAA,CAAgB,OAAO,QAAQ,CAAA;AAAA,EAChC;AACD;AAEO,SAAS,oCAAoC,EAAA,EAAqC;AACxF,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,MAAM,EAAA,IAAM,SAAA;AAClB,EAAA,MAAM,QAAA,GAAW,oBAAA,CAAqB,GAAA,CAAI,GAAG,KAAK,EAAC;AACnD,EAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,QAAA,EAAU,wBAAA,EAA0B,GAAG,CAAA;AAEtE,EAAA,IAAI,MAAA,CAAO,UAAU,+BAAA,EAAiC;AACrD,IAAA,MAAM,MAAA,GAAS,OAAO,CAAC,CAAA;AACvB,IAAA,OAAO;AAAA,MACN,OAAA,EAAS,KAAA;AAAA,MACT,cAAc,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,wBAAA,GAA2B,KAAK,CAAC,CAAA;AAAA,MACjE,SAAA,EAAW;AAAA,KACZ;AAAA,EACD;AAEA,EAAA,MAAA,CAAO,KAAK,GAAG,CAAA;AACf,EAAA,oBAAA,CAAqB,GAAA,CAAI,KAAK,MAAM,CAAA;AACpC,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,IAAA;AAAA,IACT,SAAA,EAAW,kCAAkC,MAAA,CAAO;AAAA,GACrD;AACD;AAEO,SAAS,sBAAsB,EAAA,EAAkB;AACvD,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,MAAA,GAAwB,EAAE,SAAA,EAAW,GAAA,EAAK,gBAAgB,GAAA,EAAI;AACpE,EAAA,eAAA,CAAgB,GAAA,CAAI,IAAI,MAAM,CAAA;AAC9B,EAAA,oBAAA,CAAqB,GAAG,CAAA;AACxB,EAAA,IAAI,eAAA,CAAgB,OAAO,sBAAA,EAAwB;AAClD,IAAA,6BAAA,EAA8B;AAAA,EAC/B;AACD;AAEO,SAAS,wBAAwB,EAAA,EAAqB;AAC5D,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,oBAAA,CAAqB,GAAG,CAAA;AAExB,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,GAAA,CAAI,EAAE,CAAA;AACtC,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AAErB,EAAA,IAAI,SAAA,CAAU,OAAA,CAAQ,cAAA,EAAgB,GAAG,CAAA,EAAG;AAC3C,IAAA,eAAA,CAAgB,OAAO,EAAE,CAAA;AACzB,IAAA,OAAO,KAAA;AAAA,EACR;AAEA,EAAA,IAAI,GAAA,GAAM,OAAA,CAAQ,cAAA,IAAkB,2BAAA,EAA6B;AAChE,IAAA,OAAA,CAAQ,cAAA,GAAiB,GAAA;AAAA,EAC1B;AACA,EAAA,OAAO,IAAA;AACR;;;ACnFA,IAAM,mBAAA,GAAsB,IAAA,CAAK,IAAA,CAAK,cAAA,GAAiB,GAAI,CAAA;AAC3D,IAAMC,yBAAAA,GAA2B,GAAA;AACjC,IAAMC,gCAAAA,GAAkC,EAAA;AAExC,IAAM,kBAAA,GAAqB,UAAA;AAC3B,IAAM,8BAAA,GAAiC,mBAAA;AAGvC,SAAS,WAAW,EAAA,EAAoB;AACvC,EAAA,OAAO,CAAA,EAAG,kBAAkB,CAAA,EAAG,EAAE,CAAA,CAAA;AAClC;AAEA,eAAsB,2BAAA,CACrB,EAAA,EACA,EAAA,EACA,gBAAA,EACmC;AACnC,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,cAAc,MAAM,0CAAA;AAAA,QACzB,EAAA;AAAA,QACAA,gCAAAA;AAAA,QACAD,yBAAAA;AAAA,QACA;AAAA,OACD;AACA,MAAA,IAAI,aAAa,OAAO,WAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,iFAAiF,CAAA;AAAA,IAC/F;AAAA,EACD;AACA,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,MAAM,QAAQ,EAAA,IAAM,SAAA;AACpB,MAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,GAAA,GAAMA,yBAAwB,CAAA;AAC9D,MAAA,MAAM,MAAM,CAAA,EAAG,8BAA8B,CAAA,CAAA,EAAI,KAAK,IAAI,YAAY,CAAA,CAAA;AACtE,MAAA,MAAM,UAAA,GAAa,MAAM,EAAA,CAAG,GAAA,CAAI,GAAG,CAAA;AACnC,MAAA,MAAM,MAAA,GAAS,UAAA,GAAa,QAAA,CAAS,UAAA,EAAY,EAAE,CAAA,GAAI,CAAA;AACvD,MAAA,MAAM,eAAe,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,IAAK,MAAA,IAAU,IAAI,MAAA,GAAS,CAAA;AAEvE,MAAA,IAAI,gBAAgBC,gCAAAA,EAAiC;AACpD,QAAA,MAAM,SAAA,GAAA,CAAa,eAAe,CAAA,IAAKD,yBAAAA;AACvC,QAAA,OAAO;AAAA,UACN,OAAA,EAAS,KAAA;AAAA,UACT,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,KAAK,CAAC,CAAA;AAAA,UACzC,SAAA,EAAW;AAAA,SACZ;AAAA,MACD;AAEA,MAAA,MAAM,YAAY,YAAA,GAAe,CAAA;AACjC,MAAA,MAAM,EAAA,CAAG,IAAI,GAAA,EAAK,MAAA,CAAO,SAAS,CAAA,EAAG,EAAE,aAAA,EAAe,EAAA,EAAI,CAAA;AAC1D,MAAA,OAAO;AAAA,QACN,OAAA,EAAS,IAAA;AAAA,QACT,WAAWC,gCAAAA,GAAkC;AAAA,OAC9C;AAAA,IACD,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,+DAA+D,CAAA;AAAA,IAC7E;AAAA,EACD;AAEA,EAAA,OAAO,oCAAoC,EAAE,CAAA;AAC9C;AAEA,eAAe,qBAAA,CAAsB,EAAA,EAAY,EAAA,EAAiB,MAAA,EAAsC;AACvG,EAAA,MAAM,EAAA,CAAG,GAAA,CAAI,UAAA,CAAW,EAAE,CAAA,EAAG,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA,EAAG,EAAE,aAAA,EAAe,mBAAA,EAAqB,CAAA;AAC5F;AAEA,eAAe,mBAAA,CAAoB,IAAY,EAAA,EAAqD;AACnG,EAAA,MAAM,SAAS,MAAM,EAAA,CAAG,IAAI,UAAA,CAAW,EAAE,GAAG,MAAM,CAAA;AAClD,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,MAAA;AAElD,EAAA,MAAM,SAAA,GAAY,MAAA;AAClB,EAAA,IAAI,OAAO,SAAA,CAAU,SAAA,KAAc,YAAY,OAAO,SAAA,CAAU,mBAAmB,QAAA,EAAU;AAC5F,IAAA,OAAO,MAAA;AAAA,EACR;AAEA,EAAA,OAAO;AAAA,IACN,WAAW,SAAA,CAAU,SAAA;AAAA,IACrB,gBAAgB,SAAA,CAAU;AAAA,GAC3B;AACD;AAGO,SAAS,iBAAA,GAA4B;AAC3C,EAAA,MAAM,KAAA,GAAQ,IAAI,UAAA,CAAW,EAAE,CAAA;AAC/B,EAAA,MAAA,CAAO,gBAAgB,KAAK,CAAA;AAC5B,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAO,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,SAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAE,KAAK,EAAE,CAAA;AACzE;AAGA,eAAsB,cAAc,EAAA,EAAmC;AACtE,EAAA,MAAM,KAAK,iBAAA,EAAkB;AAC7B,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,EAAA,MAAM,MAAA,GAAwB,EAAE,SAAA,EAAW,GAAA,EAAK,gBAAgB,GAAA,EAAI;AAEpE,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,MAAM,qBAAA,CAAsB,EAAA,EAAI,EAAA,EAAI,MAAM,CAAA;AAC1C,MAAA,OAAO,EAAA;AAAA,IACR,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,uDAAuD,CAAA;AAAA,IACrE;AAAA,EACD;AAEA,EAAA,qBAAA,CAAsB,EAAE,CAAA;AACxB,EAAA,OAAO,EAAA;AACR;AAGA,eAAsB,eAAA,CAAgB,IAAY,EAAA,EAAoC;AACrF,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,MAAM,MAAA,GAAS,MAAM,mBAAA,CAAoB,EAAA,EAAI,EAAE,CAAA;AAC/C,MAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AAEpB,MAAA,IAAI,GAAA,GAAM,MAAA,CAAO,cAAA,GAAiB,cAAA,EAAgB;AACjD,QAAA,MAAM,EAAA,CAAG,MAAA,CAAO,UAAA,CAAW,EAAE,CAAC,CAAA;AAC9B,QAAA,OAAO,KAAA;AAAA,MACR;AAEA,MAAA,IAAI,GAAA,GAAM,MAAA,CAAO,cAAA,IAAkB,2BAAA,EAA6B;AAC/D,QAAA,MAAA,CAAO,cAAA,GAAiB,GAAA;AACxB,QAAA,IAAI;AACH,UAAA,MAAM,qBAAA,CAAsB,EAAA,EAAI,EAAA,EAAI,MAAM,CAAA;AAAA,QAC3C,CAAA,CAAA,MAAQ;AAEP,UAAA,OAAA,CAAQ,KAAK,yDAAyD,CAAA;AAAA,QACvE;AAAA,MACD;AACA,MAAA,OAAO,IAAA;AAAA,IACR,CAAA,CAAA,MAAQ;AACP,MAAA,OAAA,CAAQ,KAAK,yDAAyD,CAAA;AAAA,IACvE;AAAA,EACD;AAEA,EAAA,OAAO,wBAAwB,EAAE,CAAA;AAClC;;;ACxJO,SAAS,QAAA,CAAS,MAAe,OAAA,EAA0B;AACjE,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,IAAI,OAAA,EAAS;AACZ,IAAA,KAAA,IAAS,OAAO,OAAO;AAAA,CAAA;AAAA,EACxB;AACA,EAAA,KAAA,IAAS,CAAA;AAAA,MAAA,EAAyB,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC;;AAAA,CAAA;AACtD,EAAA,OAAO,KAAA;AACR;AAGO,SAAS,WAAW,MAAA,EAAqC;AAC/D,EAAA,OAAO,CAAC,CAAC,MAAA,IAAU,MAAA,CAAO,SAAS,mBAAmB,CAAA;AACvD;AAUO,SAAS,gBAAA,CACf,OAAA,EACA,MAAA,EACA,MAAA,EACA,cACA,OAAA,EACW;AACX,EAAA,IAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AACvB,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,OAAA,EAAS,OAAO,CAAA;AACtC,IAAA,OAAO,IAAI,SAAS,IAAA,EAAM;AAAA,MACzB,MAAA;AAAA,MACA,OAAA,EAAS;AAAA,QACR,cAAA,EAAgB,mBAAA;AAAA,QAChB,eAAA,EAAiB,UAAA;AAAA,QACjB,gBAAA,EAAkB,OAAO,IAAI,WAAA,GAAc,MAAA,CAAO,IAAI,EAAE,UAAU,CAAA;AAAA,QAClE,GAAG;AAAA;AACJ,KACA,CAAA;AAAA,EACF;AACA,EAAA,OAAO,SAAS,IAAA,CAAK,OAAA,EAAS,EAAE,MAAA,EAAQ,OAAA,EAAS,cAAc,CAAA;AAChE;;;AC/CA,eAAsB,mCACrB,EAAA,EACA,EAAA,EACA,QACA,eAAA,EACA,EAAA,EACA,QACA,gBAAA,EACgC;AAChC,EAAA,IAAI,mBAAmB,MAAA,KAAW,YAAA,IAAgB,OAAO,UAAA,CAAW,gBAAgB,GAAG,OAAO,MAAA;AAE9F,EAAA,MAAM,UAAA,GAAa,MAAM,0BAAA,CAA2B,EAAA,EAAI,IAAI,gBAAgB,CAAA;AAC5E,EAAA,IAAI,UAAA,CAAW,SAAS,OAAO,MAAA;AAE/B,EAAA,MAAM,OAAA,GAAkC;AAAA,IACvC,mBAAA,EAAqB,IAAA;AAAA,IACrB,uBAAA,EAAyB,MAAA,CAAO,UAAA,CAAW,eAAe;AAAA,GAC3D;AACA,EAAA,IAAI,UAAA,CAAW,iBAAiB,MAAA,EAAW;AAC1C,IAAA,OAAA,CAAQ,aAAa,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,UAAA,CAAW,YAAA,GAAe,GAAI,CAAC,CAAA;AAAA,EAC1E;AAEA,EAAA,OAAO,gBAAA;AAAA,IACN,YAAA;AAAA,MACC,EAAA;AAAA,MACA,eAAA,CAAgB,YAAA;AAAA,MAChB,oCAAoC,IAAA,CAAK,IAAA,CAAA,CAAM,WAAW,YAAA,IAAgB,CAAA,IAAK,GAAI,CAAC,CAAA,CAAA;AAAA,KACrF;AAAA,IACA,GAAA;AAAA,IACA,MAAA;AAAA,IACA,OAAA;AAAA,IACA,EAAA,IAAM,IAAA,GAAO,MAAA,CAAO,EAAE,CAAA,GAAI;AAAA,GAC3B;AACD;AAWA,eAAsB,sBAAA,CACrB,SAAA,EACA,YAAA,EACA,EAAA,EACA,OAAA,EAC8C;AAC9C,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,OAAO;AAAA,MACN,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,YAAA,CAAa,EAAA,EAAI,eAAA,CAAgB,iBAAiB,OAAO;AAAA,KACnE;AAAA,EACD;AACA,EAAA,IAAI,CAAE,MAAM,eAAA,CAAgB,SAAA,EAAW,YAAY,CAAA,EAAI;AACtD,IAAA,OAAO;AAAA,MACN,MAAA,EAAQ,GAAA;AAAA,MACR,OAAA,EAAS,YAAA,CAAa,EAAA,EAAI,eAAA,CAAgB,iBAAiB,0CAA0C;AAAA,KACtG;AAAA,EACD;AACA,EAAA,OAAO,MAAA;AACR;;;AChEA,WAAA,EAAA;;;ACDA,WAAA,EAAA;AAwBA,SAAS,qBAAqB,KAAA,EAA8B;AAC3D,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AAEnB,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA,EAAG;AACjC,IAAA,KAAA,GAAQ,EAAA;AACR,IAAA,MAAA,GAAS,KAAA,CAAM,MAAM,CAAC,CAAA;AAAA,EACvB,WAAW,WAAA,CAAY,IAAA,CAAK,KAAK,CAAA,IAAK,KAAA,CAAM,SAAS,CAAA,EAAG;AACvD,IAAA,KAAA,GAAQ,CAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,QAAA,CAAS,MAAA,EAAQ,KAAK,CAAA;AAC3C,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,IAAK,KAAA,GAAQ,GAAG,OAAO,IAAA;AACjD,EAAA,OAAO,KAAA;AACR;AAMA,SAAS,wBAAwB,KAAA,EAA8B;AAC9D,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAA,CAAK,KAAK,GAAG,OAAO,IAAA;AAE1C,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAC7B,EAAA,IAAI,MAAM,MAAA,GAAS,CAAA,IAAK,KAAA,CAAM,MAAA,GAAS,GAAG,OAAO,IAAA;AACjD,EAAA,IAAI,KAAA,CAAM,KAAK,CAAC,IAAA,KAAS,KAAK,MAAA,KAAW,CAAC,GAAG,OAAO,IAAA;AAEpD,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACzB,IAAA,MAAM,MAAA,GAAS,qBAAqB,IAAI,CAAA;AACxC,IAAA,IAAI,MAAA,KAAW,MAAM,OAAO,IAAA;AAC5B,IAAA,MAAA,CAAO,KAAK,MAAM,CAAA;AAAA,EACnB;AAEA,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACxB,IAAA,IAAI,MAAA,CAAO,CAAC,CAAA,GAAI,UAAA,EAAY,OAAO,IAAA;AACnC,IAAA,UAAA,GAAa,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA;AAAA,EAC5B,CAAA,MAAA,IAAW,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC/B,IAAA,IAAI,MAAA,CAAO,CAAC,CAAA,GAAI,GAAA,IAAQ,OAAO,CAAC,CAAA,GAAI,UAAU,OAAO,IAAA;AACrD,IAAA,UAAA,GAAA,CAAe,OAAO,CAAC,CAAA,IAAK,EAAA,GAAM,MAAA,CAAO,CAAC,CAAA,MAAO,CAAA;AAAA,EAClD,CAAA,MAAA,IAAW,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC/B,IAAA,IAAI,MAAA,CAAO,CAAC,CAAA,GAAI,GAAA,IAAQ,MAAA,CAAO,CAAC,CAAA,GAAI,GAAA,IAAQ,MAAA,CAAO,CAAC,CAAA,GAAI,KAAA,EAAQ,OAAO,IAAA;AACvE,IAAA,UAAA,GAAA,CAAe,MAAA,CAAO,CAAC,CAAA,IAAK,EAAA,GAAO,MAAA,CAAO,CAAC,CAAA,IAAK,EAAA,GAAM,MAAA,CAAO,CAAC,CAAA,MAAO,CAAA;AAAA,EACtE,CAAA,MAAO;AACN,IAAA,IAAI,OAAO,IAAA,CAAK,CAAC,UAAU,KAAA,GAAQ,GAAI,GAAG,OAAO,IAAA;AACjD,IAAA,UAAA,GAAA,CAAe,MAAA,CAAO,CAAC,CAAA,IAAK,EAAA,GAAO,OAAO,CAAC,CAAA,IAAK,EAAA,GAAO,MAAA,CAAO,CAAC,CAAA,IAAK,CAAA,GAAK,MAAA,CAAO,CAAC,CAAA,MAAO,CAAA;AAAA,EACzF;AAEA,EAAA,MAAM,IAAA,GAAQ,eAAe,EAAA,GAAM,GAAA;AACnC,EAAA,MAAM,IAAA,GAAQ,eAAe,EAAA,GAAM,GAAA;AACnC,EAAA,MAAM,IAAA,GAAQ,eAAe,CAAA,GAAK,GAAA;AAClC,EAAA,MAAM,OAAO,UAAA,GAAa,GAAA;AAC1B,EAAA,OAAO,GAAG,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,EAAI,IAAI,IAAI,IAAI,CAAA,CAAA;AACvC;AAOO,SAAS,eAAe,KAAA,EAAiC;AAC/D,EAAA,IAAI,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACxC,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,yBAAA,EAA0B;AAAA,EACzD;AAGA,EAAA,MAAM,gBAAA,GAAmB,0CAAA;AACzB,EAAA,IAAI,gBAAA,CAAiB,IAAA,CAAK,KAAK,CAAA,EAAG;AACjC,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,iEAAA,EAAkE;AAAA,EACjG;AACA,EAAA,MAAM,UAAU,KAAA,CAAM,OAAA,CAAQ,gBAAA,EAAkB,EAAE,EAAE,IAAA,EAAK;AACzD,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACzB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,yBAAA,EAA0B;AAAA,EACzD;AAGA,EAAA,IAAI,MAAA,GAAS,OAAA,CAAQ,SAAA,CAAU,KAAK,EAAE,WAAA,EAAY;AAClD,EAAA,IAAI,MAAA,CAAO,SAAS,GAAG,CAAA,WAAY,MAAA,CAAO,KAAA,CAAM,GAAG,EAAE,CAAA;AAGrD,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI;AACH,IAAA,WAAA,GAAuB,iBAAQ,MAAM,CAAA;AAAA,EACtC,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,iEAAA,EAAkE;AAAA,EACjG;AAEA,EAAA,IAAI,WAAA,CAAY,SAAS,iBAAA,EAAmB;AAC3C,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,iCAAA,EAAoC,iBAAiB,CAAA,WAAA,CAAA,EAAc;AAAA,EAClG;AAGA,EAAA,IAAI,aAAA,CAAc,QAAA,CAAS,WAAW,CAAA,EAAG;AACxC,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,QAAA,EAAW,WAAW,CAAA,mCAAA,CAAA,EAAsC;AAAA,EAC3F;AAGA,EAAA,KAAA,MAAW,UAAU,gBAAA,EAAkB;AACtC,IAAA,IAAI,WAAA,KAAgB,OAAO,KAAA,CAAM,CAAC,KAAK,WAAA,CAAY,QAAA,CAAS,MAAM,CAAA,EAAG;AACpE,MAAA,OAAO,EAAE,OAAO,KAAA,EAAO,KAAA,EAAO,WAAW,WAAW,CAAA,gCAAA,EAAmC,MAAM,CAAA,CAAA,CAAA,EAAI;AAAA,IAClG;AAAA,EACD;AAIA,EAAA,MAAM,aAAA,GAAgB,wBAAwB,WAAW,CAAA;AACzD,EAAA,IAAI,aAAA,EAAe;AAClB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,+BAAA,EAAkC,WAAW,CAAA,CAAA,CAAA,EAAI;AAAA,EAChF;AAGA,EAAA,IAAI,qBAAA,CAAsB,IAAA,CAAK,WAAW,CAAA,EAAG;AAC5C,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,+BAAA,EAAkC,WAAW,CAAA,CAAA,CAAA,EAAI;AAAA,EAChF;AAGA,EAAA,KAAA,MAAW,WAAW,mBAAA,EAAqB;AAC1C,IAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,WAAW,CAAA,EAAG;AAC9B,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,+BAAA,EAAkC,WAAW,CAAA,CAAA,CAAA,EAAI;AAAA,IAChF;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,UAAU,qBAAA,EAAuB;AAC3C,IAAA,IAAI,WAAA,KAAgB,OAAO,KAAA,CAAM,CAAC,KAAK,WAAA,CAAY,QAAA,CAAS,MAAM,CAAA,EAAG;AACpE,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,wDAAA,EAAyD;AAAA,IACxF;AAAA,EACD;AAGA,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,CAAM,GAAG,CAAA;AACpC,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACtB,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,0DAAA,EAA2D;AAAA,EAC1F;AACA,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACvB,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,gDAAA,EAAiD;AAAA,IAChF;AACA,IAAA,IAAI,KAAA,CAAM,SAAS,gBAAA,EAAkB;AACpC,MAAA,OAAO,EAAE,OAAO,KAAA,EAAO,KAAA,EAAO,UAAU,KAAK,CAAA,4BAAA,EAA+B,gBAAgB,CAAA,WAAA,CAAA,EAAc;AAAA,IAC3G;AACA,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,KAAK,CAAA,EAAG;AAC7B,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,CAAA,OAAA,EAAU,KAAK,CAAA,6BAAA,CAAA,EAAgC;AAAA,IAC9E;AAAA,EACD;AAEA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACtB;AAMO,SAAS,eAAe,KAAA,EAAuB;AAErD,EAAA,MAAM,UAAU,KAAA,CAAM,OAAA,CAAQ,0CAAA,EAA4C,EAAE,EAAE,IAAA,EAAK;AACnF,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AACjC,EAAA,IAAI,MAAA,GAAS,OAAA,CAAQ,SAAA,CAAU,KAAK,EAAE,WAAA,EAAY;AAClD,EAAA,IAAI,MAAA,CAAO,SAAS,GAAG,CAAA,WAAY,MAAA,CAAO,KAAA,CAAM,GAAG,EAAE,CAAA;AAErD,EAAA,IAAI;AACH,IAAA,OAAgB,iBAAQ,MAAM,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,EAAA;AAAA,EACR;AACD;AAMO,SAAS,aAAA,CAAc,KAAA,EAAe,SAAA,GAAY,GAAA,EAAa;AACrE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,EAAA;AACtC,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,mCAAA,EAAqC,EAAE,CAAA;AACvE,EAAA,OAAO,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA;AACpC;;;AC3MA,IAAM,YAAA,GAAuC;AAAA,EAC5C,IAAA,EAAM;AACP,CAAA;AAEO,SAAS,kBAAkB,IAAA,EAAsB;AACvD,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,IAAA,EAAK,CAAE,WAAA,EAAY;AAC3C,EAAA,OAAO,YAAA,CAAa,UAAU,CAAA,IAAK,UAAA;AACpC;AAEO,SAAS,yBAAyB,IAAA,EAAuC;AAC/E,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AACpB,EAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,OAAO,IAAA,EAAK,CAAE,WAAW,CAAA,EAAG;AAC7D,IAAA,MAAM,IAAI,MAAM,oCAAoC,CAAA;AAAA,EACrD;AACA,EAAA,MAAM,UAAA,GAAa,eAAe,MAAM,CAAA;AACxC,EAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,UAAA,CAAW,KAAA,IAAS,gBAAgB,CAAA;AAAA,EACrD;AACA,EAAA,MAAM,SAAA,GAAY,eAAe,MAAM,CAAA;AACvC,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACvE;AACA,EAAA,OAAO,SAAA;AACR;AAEO,SAAS,oBAAoB,IAAA,EAAmD;AACtF,EAAA,IAAI,OAAO,KAAK,QAAA,KAAa,QAAA,IAAY,KAAK,QAAA,CAAS,IAAA,EAAK,CAAE,MAAA,KAAW,CAAA,EAAG;AAC3E,IAAA,OAAO,MAAA;AAAA,EACR;AACA,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,QAAA,CAAS,IAAA,GAAO,WAAA,EAAY;AAClD,EAAA,IAAI,CAAC,iCAAA,CAAkC,IAAA,CAAK,QAAQ,CAAA,IAAK,QAAA,CAAS,SAAS,EAAA,EAAI;AAC9E,IAAA,MAAM,IAAI,MAAM,2FAA2F,CAAA;AAAA,EAC5G;AACA,EAAA,OAAO,QAAA;AACR;AAEA,IAAM,iBAAiB,CAAC,MAAA,EAAQ,gBAAgB,iBAAA,EAAmB,UAAA,EAAY,YAAY,SAAS,CAAA;AAG7F,SAAS,mBAAmB,IAAA,EAA0E;AAC5G,EAAA,MAAM,UAAU,IAAA,CAAK,OAAA;AACrB,EAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,KAAY,IAAA,EAAM,OAAO,MAAA;AACtD,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAChC,IAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AAAA,EACpD;AACA,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,IAAA,EAAK,CAAE,WAAA,EAAY;AAC9C,EAAA,IAAI,CAAE,cAAA,CAAqC,QAAA,CAAS,UAAU,CAAA,EAAG;AAChE,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,eAAe,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,UAAA;AACR;AAEA,IAAM,YAAA,mBAAe,IAAI,GAAA,CAAI,CAAC,MAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AAG5E,SAAS,gBAAgB,IAAA,EAAwD;AACvF,EAAA,MAAM,MAAM,IAAA,CAAK,QAAA;AACjB,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,GAAA,KAAQ,IAAA,SAAa,EAAC;AAC/C,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,EAAG;AAClD,IAAA,MAAM,IAAI,MAAM,qCAAqC,CAAA;AAAA,EACtD;AACA,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,MAAM,SAAkC,EAAC;AACzC,EAAA,IAAI,CAAA,CAAE,UAAU,MAAA,EAAW;AAC1B,IAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,CAAC,YAAA,CAAa,GAAA,CAAI,CAAA,CAAE,KAAA,CAAM,WAAA,EAAa,CAAA,EAAG;AAC5E,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IACzC;AACA,IAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,KAAA;AAAA,EAClB;AACA,EAAA,IAAI,CAAA,CAAE,UAAU,MAAA,EAAW;AAC1B,IAAA,IAAI,OAAO,EAAE,KAAA,KAAU,QAAA,IAAY,EAAE,KAAA,GAAQ,CAAA,IAAK,CAAA,CAAE,KAAA,GAAQ,GAAA,EAAK;AAChE,MAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,IACxD;AACA,IAAA,MAAA,CAAO,QAAQ,CAAA,CAAE,KAAA;AAAA,EAClB;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,CAAC,uBAAA,EAAyB,aAAA,EAAe,gBAAgB,gBAAA,EAAkB,iBAAA,EAAmB,aAAa,CAAA,EAAY;AACxI,IAAA,IAAI,CAAA,CAAE,GAAG,CAAA,KAAM,MAAA,EAAW;AACzB,MAAA,IAAI,OAAO,CAAA,CAAE,GAAG,CAAA,KAAM,SAAA,EAAW;AAChC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAG,CAAA,iBAAA,CAAmB,CAAA;AAAA,MAC3D;AACA,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAA,CAAE,GAAG,CAAA;AAAA,IACpB;AAAA,EACD;AACA,EAAA,KAAA,MAAW,GAAA,IAAO,CAAC,uBAAA,EAAyB,mBAAmB,CAAA,EAAY;AAC1E,IAAA,IAAI,CAAA,CAAE,GAAG,CAAA,KAAM,MAAA,EAAW;AACzB,MAAA,IAAI,OAAO,CAAA,CAAE,GAAG,CAAA,KAAM,YAAY,CAAA,CAAE,GAAG,CAAA,GAAK,CAAA,IAAK,CAAC,MAAA,CAAO,SAAA,CAAU,CAAA,CAAE,GAAG,CAAC,CAAA,EAAG;AAC3E,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAG,CAAA,gCAAA,CAAkC,CAAA;AAAA,MAC1E;AACA,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,CAAA,CAAE,GAAG,CAAA;AAAA,IACpB;AAAA,EACD;AACA,EAAA,OAAO,MAAA;AACR;AAEO,SAAS,0BAA0B,IAAA,EAIxC;AACD,EAAA,MAAM,YAAY,IAAA,CAAK,SAAA;AACvB,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AACpB,EAAA,IAAI,OAAO,SAAA,KAAc,QAAA,IAAY,OAAO,WAAW,QAAA,EAAU;AAChE,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACpE;AACA,EAAA,IAAI,SAAA,CAAU,SAAS,GAAA,EAAK;AAC3B,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAC/D;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,GAAA,EAAK;AACxB,IAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,EAC5D;AACA,EAAA,MAAM,UAAU,OAAO,IAAA,CAAK,OAAA,KAAY,QAAA,GAAW,KAAK,OAAA,GAAU,MAAA;AAClE,EAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,GAAA,EAAM;AACrC,IAAA,MAAM,IAAI,MAAM,6CAA6C,CAAA;AAAA,EAC9D;AACA,EAAA,OAAO,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAA,EAAQ;AACrC;;;ACrHA,WAAA,EAAA;AAuBA,IAAM,cAAA,GAAiB,IAAI,EAAA,GAAK,GAAA;AAChC,IAAM,mBAAA,GAAsB,GAAA;AAC5B,IAAM,mBAAA,GAAsB,GAAA;AAErB,IAAM,WAAN,MAA4B;AAAA,EACjB,KAAA,uBAAY,GAAA,EAA2B;AAAA,EACvC,KAAA;AAAA,EACA,UAAA;AAAA,EAEjB,WAAA,CAAY,OAAA,GAAwB,EAAC,EAAG;AACvC,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAQ,KAAA,IAAS,cAAA;AAC9B,IAAA,IAAA,CAAK,UAAA,GAAa,QAAQ,UAAA,IAAc,mBAAA;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,GAAA,EAA4B;AAC/B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAChC,IAAA,IAAI,CAAC,KAAA,EAAO;AACX,MAAA,OAAO,MAAA;AAAA,IACR;AACA,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,KAAA,CAAM,SAAA,EAAW;AACjC,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,MAAA,OAAO,MAAA;AAAA,IACR;AACA,IAAA,OAAO,KAAA,CAAM,KAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,GAAA,CAAI,GAAA,EAAa,KAAA,EAAU,KAAA,EAAsB;AAEhD,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAC/D,MAAA,IAAA,CAAK,YAAA,EAAa;AAAA,IACnB;AAEA,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,UAAA,IAAc,CAAC,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA,EAAG;AAC/D,MAAA,MAAM,WAAW,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AAC1C,MAAA,IAAI,aAAa,MAAA,EAAW;AAC3B,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,QAAQ,CAAA;AAAA,MAC3B;AAAA,IACD;AACA,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,GAAA,EAAK;AAAA,MACnB,KAAA;AAAA,MACA,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,IAAK,SAAS,IAAA,CAAK,KAAA;AAAA,KACvC,CAAA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,GAAA,EAAsB;AACzB,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,KAAM,MAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,GAAA,EAAsB;AAC5B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,GAAG,CAAA;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAA,GAAc;AACb,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,IAAA,GAAe;AAClB,IAAA,OAAO,KAAK,KAAA,CAAM,IAAA;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAuB;AACtB,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,KAAK,KAAA,EAAO;AACtC,MAAA,IAAI,GAAA,GAAM,MAAM,SAAA,EAAW;AAC1B,QAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,QAAA,OAAA,EAAA;AAAA,MACD;AAAA,IACD;AACA,IAAA,OAAO,OAAA;AAAA,EACR;AACD,CAAA;AAGA,IAAM,QAAA,uBAAe,GAAA,EAA8B;AAG5C,IAAM,eAAA,GAAkB,IAAI,QAAA,CAAkB;AAAA,EACpD,KAAA,EAAO,cAAA;AAAA,EACP,UAAA,EAAY;AACb,CAAC,CAAA;AAaD,eAAsB,QAAA,CAAY,KAAa,EAAA,EAA0C;AAClF,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,MAAM,GAAA,GAAM,MAAM,EAAA,CAAG,GAAA,CAAI,KAAK,MAAM,CAAA;AACpC,MAAA,OAAQ,GAAA,IAAO,KAAA,CAAA;AAAA,IAChB,CAAA,CAAA,MAAQ;AAEP,MAAA,OAAA,CAAQ,KAAK,kDAAkD,CAAA;AAAA,IAChE;AAAA,EACD;AACA,EAAA,OAAO,eAAA,CAAgB,IAAI,GAAG,CAAA;AACrC;AAmBA,eAAsB,QAAA,CAAS,GAAA,EAAa,KAAA,EAAgB,EAAA,EAAkB,UAAA,EAAoC;AAC3G,EAAA,MAAM,MAAM,UAAA,IAAc,mBAAA;AAC1B,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,IAAI;AACH,MAAA,MAAM,EAAA,CAAG,GAAA,CAAI,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA,EAAG,EAAE,aAAA,EAAe,GAAA,EAAK,CAAA;AAC/D,MAAA;AAAA,IACD,CAAA,CAAA,MAAQ;AAEP,MAAA,OAAA,CAAQ,KAAK,kDAAkD,CAAA;AAAA,IAChE;AAAA,EACD;AACA,EAAA,eAAA,CAAgB,GAAA,CAAI,GAAA,EAAK,KAAA,EAAO,GAAA,GAAM,GAAI,CAAA;AACjD;AAaA,eAAsB,YAAA,CAAgB,GAAA,EAAa,GAAA,EAAuB,EAAA,EAAkB,UAAA,EAAiC;AAC5H,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAY,GAAA,EAAK,EAAE,CAAA;AACxC,EAAA,IAAI,MAAA,KAAW,QAAW,OAAO,MAAA;AAEjC,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA;AACjC,EAAA,IAAI,UAAU,OAAO,QAAA;AAErB,EAAA,MAAM,UAAU,UAAA,CAAW,MAAM,SAAS,MAAA,CAAO,GAAG,GAAG,mBAAmB,CAAA;AAC1E,EAAA,MAAM,OAAA,GAAU,GAAA,EAAI,CAClB,IAAA,CAAK,OAAO,MAAA,KAAW;AACvB,IAAA,MAAM,QAAA,CAAS,GAAA,EAAK,MAAA,EAAQ,EAAA,EAAI,UAAU,CAAA;AAC1C,IAAA,OAAO,MAAA;AAAA,EACR,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACd,IAAA,YAAA,CAAa,OAAO,CAAA;AACpB,IAAA,QAAA,CAAS,OAAO,GAAG,CAAA;AAAA,EACpB,CAAC,CAAA;AAEF,EAAA,QAAA,CAAS,GAAA,CAAI,KAAK,OAAO,CAAA;AACzB,EAAA,OAAO,OAAA;AACR;;;AC9MA,QAAA,EAAA;AAGA,YAAA,EAAA;;;ACTA,QAAA,EAAA;AAEA,YAAA,EAAA;AAIO,SAAS,eAAe,MAAA,EAAqC;AACnE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAoB;AACrC,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACzB,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,GAAG,CAAA;AACnC,IAAA,IAAI,UAAU,CAAA,EAAG;AAChB,MAAA,MAAM,GAAA,GAAM,QAAQ,SAAA,CAAU,CAAA,EAAG,OAAO,CAAA,CAAE,IAAA,GAAO,WAAA,EAAY;AAC7D,MAAA,MAAM,KAAA,GAAQ,QAAQ,SAAA,CAAU,OAAA,GAAU,CAAC,CAAA,CAAE,IAAA,GAAO,WAAA,EAAY;AAChE,MAAA,IAAA,CAAK,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IACpB;AAAA,EACD;AACA,EAAA,OAAO,IAAA;AACR;AAGO,SAAS,wBAAwB,GAAA,EAA4B;AACnE,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,EAAK,CAAE,WAAA,EAAY;AACvC,EAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,SAAS,GAAG,OAAO,IAAA;AAC3C,EAAA,IAAI,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,CAAC,EAAE,IAAA,EAAK;AACtC,EAAA,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA;AAC5C,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,WAAA,CAAY,GAAG,CAAA;AACrC,EAAA,IAAI,OAAA,GAAU,GAAG,OAAO,IAAA;AACxB,EAAA,OAAO,KAAA,CAAM,SAAA,CAAU,OAAA,GAAU,CAAC,CAAA;AACnC;AAMO,SAAS,gBAAgB,GAAA,EAAsB;AACrD,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,EAAK,CAAE,WAAA,EAAY;AACvC,EAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,SAAS,CAAA,EAAG;AACnC,IAAA,OAAO,KAAA;AAAA,EACR;AACA,EAAA,IAAI,KAAA,GAAQ,OAAA,CAAQ,SAAA,CAAU,CAAC,EAAE,IAAA,EAAK;AACtC,EAAA,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,kBAAA,EAAoB,EAAE,CAAA;AAC5C,EAAA,OAAO,4BAAA,CAA6B,KAAK,KAAK,CAAA;AAC/C;AAGO,SAAS,4BAA4B,IAAA,EAA0B;AACrE,EAAA,MAAM,gBAAA,GAAmB;AAAA,IACxB,cAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,gBAAA;AAAA,IACA,iBAAA;AAAA,IACA,mBAAA;AAAA,IACA,cAAA;AAAA,IACA,gBAAA;AAAA,IACA,WAAA;AAAA,IACA,eAAA;AAAA,IACA,cAAA;AAAA,IACA,aAAA;AAAA,IACA,iBAAA;AAAA,IACA,aAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACD;AAEA,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACvB,IAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,IAAA,KAAA,MAAW,cAAc,gBAAA,EAAkB;AAC1C,MAAA,IAAI,KAAA,CAAM,SAAS,UAAU,CAAA,IAAK,CAAC,QAAA,CAAS,QAAA,CAAS,UAAU,CAAA,EAAG;AACjE,QAAA,QAAA,CAAS,KAAK,UAAU,CAAA;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AACA,EAAA,OAAO,QAAA;AACR;AAMA,eAAsB,qBAAA,CAAsB,MAAA,EAAgB,OAAA,EAAmB,UAAA,EAAkD;AAChI,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AAEvC,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AAC1B,IAAA,MAAM,YAAA,GAAe,wBAAwB,GAAG,CAAA;AAChD,IAAA,IAAI,CAAC,YAAA,IAAgB,YAAA,KAAiB,UAAU,cAAA,CAAe,GAAA,CAAI,YAAY,CAAA,EAAG;AAClF,IAAA,cAAA,CAAe,IAAI,YAAY,CAAA;AAE/B,IAAA,IAAI;AACH,MAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB,CAAA,EAAG,MAAM,CAAA,gBAAA,EAAmB,YAAY,IAAI,UAAU,CAAA;AAChG,MAAA,MAAM,OAAA,GAAU,WAAA,CAAY,IAAA,CAAK,CAAC,MAAA,KAAW,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AACxF,MAAA,IAAI,CAAC,OAAA,EAAS;AACb,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,OAAA;AAAA,YACA,gDAAA;AAAA,YACA,QAAA;AAAA,YACA,CAAA,0BAAA,EAA6B,YAAY,CAAA,sDAAA,EAAyD,MAAM,mBAAmB,YAAY,CAAA,8DAAA;AAAA;AACxI,SACD;AAAA,MACD;AAAA,IACD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;AC/GA,QAAA,EAAA;AAGA,YAAA,EAAA;AAGO,IAAM,gBAAA,GAAmB,CAAC,MAAA,EAAQ,MAAM,CAAA;AAGxC,IAAM,mBAAA,GAAsB,EAAA;AAG5B,IAAM,qBAAA,GAAwB,EAAA;AAmB9B,SAAS,uBAAuB,SAAA,EAAsC;AAC5E,EAAA,MAAM,aAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,KAAA,IAAS,SAAA,CAAU,KAAA,CAAM,KAAK,CAAA,EAAG;AAC3C,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,UAAA,EAAY,EAAE,EAAE,WAAA,EAAY;AAC7D,IAAA,IAAI,WAAW,UAAA,CAAW,UAAU,CAAA,EAAG,UAAA,CAAW,KAAK,SAAS,CAAA;AAAA,SAAA,IACvD,UAAA,KAAe,GAAA,IAAO,UAAA,CAAW,UAAA,CAAW,IAAI,CAAA,IAAK,UAAA,CAAW,UAAA,CAAW,IAAI,CAAA,EAAG,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AAAA,SAAA,IACrG,UAAA,KAAe,IAAA,IAAQ,UAAA,CAAW,UAAA,CAAW,KAAK,CAAA,IAAK,UAAA,CAAW,UAAA,CAAW,KAAK,CAAA,EAAG,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAAA,SAAA,IACzG,UAAA,KAAe,SAAS,UAAA,CAAW,UAAA,CAAW,MAAM,CAAA,EAAG,UAAA,CAAW,KAAK,KAAK,CAAA;AAAA,SAAA,IAC5E,WAAW,UAAA,CAAW,SAAS,CAAA,EAAG,UAAA,CAAW,KAAK,QAAQ,CAAA;AAAA,EAIpE;AAEA,EAAA,OAAO,EAAE,KAAA,EAAO,UAAA,CAAW,MAAA,EAAQ,UAAA,EAAW;AAC/C;AAMO,SAAS,wBAAwB,SAAA,EAA0E;AACjH,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,sBAAsB,CAAC,CAAA,CAC1E,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA,CAC5C,OAAO,CAAC,MAAA,KAAW,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AAEtC,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,KAAA,CAAM,sBAAsB,CAAA;AAC5D,EAAA,MAAM,iBAAiB,aAAA,GAAgB,CAAC,CAAA,EAAG,IAAA,GAAO,WAAA,EAAY;AAE9D,EAAA,OAAO;AAAA,IACN,cAAA;AAAA,IACA,GAAI,cAAA,GAAiB,EAAE,cAAA,KAAmB;AAAC,GAC5C;AACD;AAGO,SAAS,qBAAqB,SAAA,EAA8D;AAClG,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,IAAI,QAAA;AAEJ,EAAA,KAAA,MAAW,KAAA,IAAS,SAAA,CAAU,KAAA,CAAM,KAAK,CAAA,EAAG;AAC3C,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,UAAA,EAAY,EAAE,EAAE,WAAA,EAAY;AAC7D,IAAA,IAAI,UAAA,CAAW,UAAA,CAAW,UAAU,CAAA,EAAG;AACtC,MAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,CAAM,UAAA,CAAW,MAAM,CAAA;AACjD,MAAA,IAAI,MAAA,EAAQ,QAAA,CAAS,IAAA,CAAK,MAAM,CAAA;AAAA,IACjC,CAAA,MAAA,IAAW,UAAA,CAAW,UAAA,CAAW,WAAW,CAAA,EAAG;AAC9C,MAAA,MAAM,MAAA,GAAS,UAAA,CAAW,KAAA,CAAM,WAAA,CAAY,MAAM,CAAA;AAClD,MAAA,IAAI,QAAQ,QAAA,GAAW,MAAA;AAAA,IACxB;AAAA,EACD;AAEA,EAAA,OAAO,EAAE,UAAU,QAAA,EAAS;AAC7B;AAMA,eAAsB,qBAAA,CACrB,SAAA,EACA,KAAA,EACA,KAAA,EACA,UAAA,EACkB;AAClB,EAAA,MAAM,KAAA,GAAQ,uBAAuB,SAAS,CAAA;AAC9C,EAAA,IAAI,aAAa,KAAA,CAAM,KAAA;AAEvB,EAAA,IAAI,SAAS,mBAAA,EAAqB;AACjC,IAAA,OAAO,UAAA;AAAA,EACR;AAEA,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAS,GAAI,qBAAqB,SAAS,CAAA;AAC7D,EAAA,MAAM,gBAAA,GAAmB,CAAC,GAAG,QAAQ,CAAA;AACrC,EAAA,IAAI,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,QAAQ,CAAA;AAE5C,EAAA,KAAA,MAAW,gBAAgB,gBAAA,EAAkB;AAC5C,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,EAAG;AACpC,MAAA,IAAI,CAAC,MAAM,gBAAA,EAAkB;AAC5B,QAAA,KAAA,CAAM,gBAAA,GAAmB,IAAA;AACzB,QAAA,KAAA,CAAM,QAAA,CAAS,IAAA;AAAA,UACd,aAAA;AAAA,YACC,KAAA;AAAA,YACA,+BAAA;AAAA,YACA,MAAA;AAAA,YACA,6DAA6D,YAAY,CAAA,yCAAA;AAAA;AAC1E,SACD;AAAA,MACD;AACA,MAAA;AAAA,IACD;AAEA,IAAA,IAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,EAAG;AAClC,MAAA,UAAA,IAAc,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,YAAY,CAAA,CAAG,KAAA;AAC7C,MAAA;AAAA,IACD;AAEA,IAAA,IAAI,KAAA,CAAM,gBAAgB,qBAAA,EAAuB;AAChD,MAAA;AAAA,IACD;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,IAAI,YAAY,CAAA;AAC9B,IAAA,KAAA,CAAM,YAAA,EAAA;AAEN,IAAA,IAAI;AACH,MAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,YAAA,EAAc,UAAU,CAAA;AACjE,MAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,CAAC,MAAA,KAAW,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,QAAQ,CAAC,CAAA;AAEvF,MAAA,IAAI,SAAA,EAAW;AACd,QAAA,MAAM,cAAc,MAAM,qBAAA,CAAsB,WAAW,KAAA,GAAQ,CAAA,EAAG,OAAO,UAAU,CAAA;AACvF,QAAA,KAAA,CAAM,KAAA,CAAM,IAAI,YAAA,EAAc,EAAE,OAAO,WAAA,EAAa,UAAA,EAAY,EAAC,EAAG,CAAA;AACpE,QAAA,UAAA,IAAc,WAAA;AAAA,MACf;AAAA,IACD,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,KAAA,CAAM,OAAA,CAAQ,OAAO,YAAY,CAAA;AAAA,EAClC;AAEA,EAAA,OAAO,UAAA;AACR;AAMO,SAAS,kBAAA,CAAmB,WAAmB,QAAA,EAA8C;AACnG,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,KAAA,MAAW,KAAA,IAAS,SAAA,CAAU,KAAA,CAAM,KAAK,CAAA,EAAG;AAC3C,IAAA,IAAI,CAAC,KAAA,EAAO;AACZ,IAAA,MAAM,aAAa,KAAA,CAAM,OAAA,CAAQ,UAAA,EAAY,EAAE,EAAE,WAAA,EAAY;AAE7D,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,KAAA,CAAM,2BAA2B,CAAA;AAC7D,IAAA,IAAI,QAAA,EAAU;AACb,MAAA,MAAM,MAAA,GAAS,SAAS,CAAC,CAAA,GAAI,SAAS,QAAA,CAAS,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,EAAA;AACzD,MAAA,IAAI,UAAU,CAAA,EAAG;AAChB,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,KAAA;AAAA,YACA,uBAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,qBAAA,EAAwB,KAAK,CAAA,iDAAA,EAAoD,MAAM,CAAA,4EAAA,CAAA;AAAA,YACvF;AAAA;AACD,SACD;AAAA,MACD;AAAA,IACD;AAEA,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,KAAA,CAAM,2BAA2B,CAAA;AAC7D,IAAA,IAAI,QAAA,EAAU;AACb,MAAA,MAAM,MAAA,GAAS,SAAS,CAAC,CAAA,GAAI,SAAS,QAAA,CAAS,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,GAAA;AACzD,MAAA,IAAI,UAAU,EAAA,EAAI;AACjB,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,KAAA;AAAA,YACA,yBAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,qBAAA,EAAwB,KAAK,CAAA,mDAAA,EAAsD,MAAM,CAAA,4EAAA,CAAA;AAAA,YACzF;AAAA;AACD,SACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;ACjMA,YAAA,EAAA;AAcA,IAAM,sBAAA,uBAAgE,GAAA,CAAI;AAAA,EACzE,CAAC,qBAAA,EAAuB,EAAE,MAAM,YAAA,EAAc,IAAA,EAAM,mDAAmD,CAAA;AAAA,EACvG;AAAA,IACC,4BAAA;AAAA,IACA,EAAE,IAAA,EAAM,eAAA,EAAiB,IAAA,EAAM,wEAAA;AAAyE,GACzG;AAAA,EACA,CAAC,iBAAA,EAAmB,EAAE,MAAM,kBAAA,EAAoB,IAAA,EAAM,yDAAyD,CAAA;AAAA,EAC/G,CAAC,cAAA,EAAgB,EAAE,MAAM,UAAA,EAAY,IAAA,EAAM,iDAAiD,CAAA;AAAA,EAC5F,CAAC,qBAAA,EAAuB,EAAE,MAAM,oBAAA,EAAsB,IAAA,EAAM,kDAAkD,CAAA;AAAA,EAC9G,CAAC,kBAAA,EAAoB,EAAE,MAAM,SAAA,EAAW,IAAA,EAAM,gDAAgD,CAAA;AAAA,EAC9F,CAAC,oBAAA,EAAsB,EAAE,MAAM,UAAA,EAAY,IAAA,EAAM,iDAAiD,CAAA;AAAA,EAClG,CAAC,eAAA,EAAiB,EAAE,MAAM,oBAAA,EAAsB,IAAA,EAAM,8CAA8C,CAAA;AAAA,EACpG,CAAC,eAAA,EAAiB,EAAE,MAAM,YAAA,EAAc,IAAA,EAAM,4CAA4C,CAAA;AAAA,EAC1F,CAAC,kBAAA,EAAoB,EAAE,MAAM,WAAA,EAAa,IAAA,EAAM,kDAAkD,CAAA;AAAA,EAClG,CAAC,kBAAA,EAAoB,EAAE,MAAM,SAAA,EAAW,IAAA,EAAM,gDAAgD,CAAA;AAAA,EAC9F,CAAC,cAAA,EAAgB,EAAE,MAAM,SAAA,EAAW,IAAA,EAAM,gDAAgD,CAAA;AAAA,EAC1F,CAAC,cAAA,EAAgB,EAAE,MAAM,YAAA,EAAc,IAAA,EAAM,mDAAmD,CAAA;AAAA,EAChG,CAAC,kBAAA,EAAoB,EAAE,MAAM,UAAA,EAAY,IAAA,EAAM,gDAAgD,CAAA;AAAA,EAC/F,CAAC,eAAA,EAAiB,EAAE,MAAM,WAAA,EAAa,IAAA,EAAM,kDAAkD,CAAA;AAAA,EAC/F,CAAC,qBAAA,EAAuB,EAAE,MAAM,mBAAA,EAAqB,IAAA,EAAM,iCAAiC,CAAA;AAAA,EAC5F,CAAC,oBAAA,EAAsB,EAAE,MAAM,WAAA,EAAa,IAAA,EAAM,kDAAkD,CAAA;AAAA,EACpG,CAAC,UAAA,EAAY,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,6CAA6C;AACjF,CAAC,CAAA;AAKD,SAAS,cAAc,MAAA,EAAiE;AACvF,EAAA,MAAM,KAAA,GAAQ,OAAO,WAAA,EAAY;AACjC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,sBAAA,EAAwB;AACjD,IAAA,IAAI,UAAU,GAAA,IAAO,KAAA,CAAM,SAAS,CAAA,CAAA,EAAI,GAAG,EAAE,CAAA,EAAG;AAC/C,MAAA,OAAO,EAAE,KAAK,IAAA,EAAK;AAAA,IACpB;AAAA,EACD;AACA,EAAA,OAAO,MAAA;AACR;AAKA,SAAS,iCAAiC,SAAA,EAA6B;AACtE,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,YAAA,GAAe,sBAAA;AACrB,EAAA,MAAM,aAAA,GAAgB,uBAAA;AAEtB,EAAA,IAAI,KAAA;AACJ,EAAA,OAAA,CAAQ,KAAA,GAAQ,YAAA,CAAa,IAAA,CAAK,SAAS,OAAO,IAAA,EAAM;AACvD,IAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EACtB;AACA,EAAA,OAAA,CAAQ,KAAA,GAAQ,aAAA,CAAc,IAAA,CAAK,SAAS,OAAO,IAAA,EAAM;AACxD,IAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EACtB;AACA,EAAA,OAAO,OAAA;AACR;AAMO,SAAS,mBAAA,CAAoB,SAAA,EAAmB,OAAA,GAA+B,EAAC,EAAc;AACpG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,OAAA,GAAU,iCAAiC,SAAS,CAAA;AAC1D,EAAA,MAAM,mBAA8D,EAAC;AACrE,EAAA,MAAM,uBAAA,GAA0B,QAAQ,uBAAA,KAA4B,IAAA;AACpE,EAAA,MAAM,eAAA,GAAkB,0BAA0B,QAAA,GAAW,MAAA;AAC7D,EAAA,MAAM,eAAA,GAAkB,0BAA0B,MAAA,GAAS,MAAA;AAC3D,EAAA,MAAM,YAAA,GAAe,0BAClB,kKAAA,GACA,4LAAA;AAEH,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,MAAM,MAAA,GAAS,cAAc,MAAM,CAAA;AACnC,IAAA,IAAI,MAAA,EAAQ;AACX,MAAA,gBAAA,CAAiB,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,CAAO,KAAK,IAAA,EAAM,aAAA,EAAe,QAAQ,CAAA;AACvE,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,KAAA;AAAA,UACA,CAAA,kCAAA,EAAqC,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,UACrD,eAAA;AAAA,UACA,CAAA,YAAA,EAAe,MAAM,CAAA,YAAA,EAAe,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,EAAA,EAAK,YAAY,CAAA,CAAA;AAAA,UAC1F;AAAA,YACC,YAAA,EAAc,IAAA;AAAA,YACd,QAAA,EAAU,OAAO,IAAA,CAAK,IAAA;AAAA,YACtB,aAAA,EAAe,MAAA;AAAA,YACf,iBAAA,EAAmB,uBAAA;AAAA,YACnB,GAAI,QAAQ,WAAA,GAAc,EAAE,aAAa,OAAA,CAAQ,WAAA,KAAgB,EAAC;AAAA,YAClE,GAAI,QAAQ,kBAAA,GAAqB,EAAE,oBAAoB,OAAA,CAAQ,kBAAA,KAAuB;AAAC;AACxF;AACD,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAChC,IAAA,MAAM,aAAA,GAAgB,iBAAiB,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACnE,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,CAAA,mBAAA,EAAsB,iBAAiB,MAAM,CAAA,iBAAA,CAAA;AAAA,QAC7C,eAAA;AAAA,QACA,CAAA,0CAAA,EAA6C,gBAAA,CAAiB,MAAM,CAAA,yBAAA,EAA4B,aAAa,CAAA,sKAAA,CAAA;AAAA,QAC7G;AAAA,UACC,YAAA,EAAc,IAAA;AAAA,UACd,eAAe,gBAAA,CAAiB,MAAA;AAAA,UAChC,SAAA,EAAW,aAAA;AAAA,UACX,iBAAA,EAAmB,uBAAA;AAAA,UACnB,GAAI,QAAQ,WAAA,GAAc,EAAE,aAAa,OAAA,CAAQ,WAAA,KAAgB,EAAC;AAAA,UAClE,GAAI,QAAQ,kBAAA,GAAqB,EAAE,oBAAoB,OAAA,CAAQ,kBAAA,KAAuB;AAAC;AACxF;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;AH7GA,eAAe,2BAAA,CAA4B,QAAgB,UAAA,EAAiE;AAC3H,EAAA,IAAI;AACH,IAAA,MAAM,eAAe,MAAM,eAAA,CAAgB,CAAA,OAAA,EAAU,MAAM,IAAI,UAAU,CAAA;AACzE,IAAA,MAAM,WAAA,GAAc,YAAA,CAAa,IAAA,CAAK,CAAC,MAAA,KAAW,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AAE7F,IAAA,IAAI,CAAC,WAAA,EAAa;AACjB,MAAA,OAAO;AAAA,QACN,uBAAA,EAAyB,IAAA;AAAA,QACzB,WAAA,EAAa,SAAA;AAAA,QACb,kBAAA,EAAoB;AAAA,OACrB;AAAA,IACD;AAEA,IAAA,MAAM,IAAA,GAAO,eAAe,WAAW,CAAA;AACvC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,IAAK,MAAA;AAChC,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA,IAAK,KAAA;AAC/B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA,IAAK,GAAA;AACjC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,IAAK,GAAA;AACnC,IAAA,MAAM,eAAA,GAAkB,MAAA,KAAW,QAAA,IAAY,GAAA,KAAQ,KAAA;AACvD,IAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,GAAA,IAAO,KAAA,KAAU,GAAA;AAChD,IAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,GAAA,IAAO,KAAA,KAAU,MAAM,QAAA,GAAW,SAAA;AAEjE,IAAA,OAAO;AAAA,MACN,yBAAyB,eAAA,IAAmB,aAAA;AAAA,MAC5C,aAAa,GAAA,KAAQ,KAAA,GAAQ,SAAS,CAAA,EAAG,MAAM,SAAS,GAAG,CAAA,CAAA;AAAA,MAC3D,kBAAA,EAAoB;AAAA,KACrB;AAAA,EACD,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO;AAAA,MACN,uBAAA,EAAyB,KAAA;AAAA,MACzB,WAAA,EAAa,SAAA;AAAA,MACb,kBAAA,EAAoB;AAAA,KACrB;AAAA,EACD;AACD;AAOA,eAAsB,QAAA,CAAS,QAAgB,UAAA,EAAoD;AAClG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,EAAQ,UAAU,CAAA;AAG3D,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,QAAQ,CAAC,CAAA;AAEhF,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,qBAAA;AAAA,QACA,UAAA;AAAA,QACA,wCAAwC,MAAM,CAAA,yEAAA;AAAA;AAC/C,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,sBAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,MAAA,EAAS,WAAW,MAAM,CAAA,iHAAA;AAAA;AAC3B,KACD;AAAA,EACD;AAEA,EAAA,MAAM,GAAA,GAAM,WAAW,CAAC,CAAA;AACxB,EAAA,MAAM,UAAA,GAAa,wBAAwB,GAAG,CAAA;AAC9C,EAAA,MAAM,WAAA,GAAc;AAAA,IACnB,UAAA,EAAY,KAAA;AAAA,IACZ,gBAAgB,UAAA,CAAW,cAAA;AAAA,IAC3B,GAAI,WAAW,cAAA,GAAiB,EAAE,gBAAgB,UAAA,CAAW,cAAA,KAAmB;AAAC,GAClF;AAGA,EAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,GAAG,CAAA;AAG3C,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,KAAA,CAAM,YAAY,CAAA;AAC3C,EAAA,IAAI,YAAA,EAAc;AACjB,IAAA,MAAM,SAAA,GAAY,aAAa,CAAC,CAAA;AAChC,IAAA,IAAI,gBAAA,CAAiB,QAAA,CAAS,SAAA,CAAU,WAAA,EAAa,CAAA,EAAG;AACvD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,KAAA;AAAA,UACA,mBAAmB,SAAS,CAAA,CAAA;AAAA,UAC5B,UAAA;AAAA,UACA,CAAA,iBAAA,EAAoB,SAAS,CAAA,2CAAA,EAA8C,MAAM,CAAA,uDAAA,CAAA;AAAA,UACjF;AAAA;AACD,OACD;AAAA,IACD,CAAA,MAAA,IAAW,SAAA,CAAU,WAAA,EAAY,KAAM,MAAA,EAAQ;AAC9C,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,KAAA;AAAA,UACA,sBAAA;AAAA,UACA,KAAA;AAAA,UACA,CAAA,+JAAA,CAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,IACD;AAAA,EAED,CAAA,MAAA,IAAW,CAAC,WAAA,EAAa;AAExB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,oBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,6HAAA,CAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,kBAAA,CAAmB,GAAA,EAAK,WAAW,CAAC,CAAA;AAGrD,EAAA,MAAM,KAAA,GAAwB;AAAA,IAC7B,YAAA,EAAc,CAAA;AAAA,IACd,OAAA,kBAAS,IAAI,GAAA,CAAI,CAAC,MAAM,CAAC,CAAA;AAAA,IACzB,KAAA,sBAAW,GAAA,EAAI;AAAA,IACf,UAAU,EAAC;AAAA,IACX,gBAAA,EAAkB;AAAA,GACnB;AACA,EAAA,MAAM,uBAAuB,MAAM,qBAAA,CAAsB,GAAA,EAAK,CAAA,EAAG,OAAO,UAAU,CAAA;AAGlF,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,KAAA,CAAM,QAAQ,CAAA;AAE/B,EAAA,IAAI,uBAAuB,EAAA,EAAI;AAC9B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,sBAAA;AAAA,QACA,UAAA;AAAA,QACA,uBAAuB,oBAAoB,CAAA,oFAAA,CAAA;AAAA,QAC3C,EAAE,GAAG,WAAA,EAAa,WAAA,EAAa,oBAAA;AAAqB;AACrD,KACD;AAAA,EACD,CAAA,MAAA,IAAW,wBAAwB,CAAA,EAAG;AACrC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,8BAAA;AAAA,QACA,MAAA;AAAA,QACA,uBAAuB,oBAAoB,CAAA,8FAAA,CAAA;AAAA,QAC3C,EAAE,GAAG,WAAA,EAAa,WAAA,EAAa,oBAAA;AAAqB;AACrD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA,EAAG;AACzB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,0BAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,8GAAA,CAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,mBAAA,GAAsB,MAAM,2BAAA,CAA4B,MAAA,EAAQ,UAAU,CAAA;AAChF,EAAA,MAAM,oBAAA,GAAuB,mBAAA,CAAoB,GAAA,EAAK,mBAAmB,CAAA;AACzE,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,oBAAoB,CAAA;AAGrC,EAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,CAAA,CAAE,QAAA,EAAU,YAAA,IAAgB,CAAA,CAAE,QAAA,KAAa,MAAA,CAAO,CAAA;AACjG,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC/B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,uBAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,0CAAA,EAA6C,GAAA,CAAI,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,EAAG,GAAA,CAAI,MAAA,GAAS,GAAA,GAAM,KAAA,GAAQ,EAAE,CAAA,CAAA;AAAA,QAClG;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AACxC;;;AIrNA,QAAA,EAAA;AAEA,YAAA,EAAA;AASA,eAAsB,UAAA,CAAW,QAAgB,UAAA,EAAoD;AACpG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,aAAa,MAAM,eAAA,CAAgB,CAAA,OAAA,EAAU,MAAM,IAAI,UAAU,CAAA;AAGvE,EAAA,MAAM,YAAA,GAAe,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AAEpF,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,uBAAA;AAAA,QACA,UAAA;AAAA,QACA,mCAAmC,MAAM,CAAA,qFAAA;AAAA;AAC1C,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAAA,EAC1C;AAEA,EAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC5B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,wBAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,MAAA,EAAS,aAAa,MAAM,CAAA,8DAAA;AAAA;AAC7B,KACD;AAAA,EACD;AAEA,EAAA,MAAM,KAAA,GAAQ,aAAa,CAAC,CAAA;AAC5B,EAAA,MAAM,IAAA,GAAO,eAAe,KAAK,CAAA;AACjC,EAAA,MAAM,gCAAgB,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,YAAA,EAAc,QAAQ,CAAC,CAAA;AAG9D,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AAC3B,EAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,sBAAA;AAAA,QACA,UAAA;AAAA,QACA,CAAA,8FAAA;AAAA;AACD,KACD;AAAA,EACD,CAAA,MAAA,IAAW,CAAC,aAAA,CAAc,GAAA,CAAI,MAAM,CAAA,EAAG;AACtC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,4BAAA;AAAA,QACA,MAAA;AAAA,QACA,uBAAuB,MAAM,CAAA,6DAAA;AAAA;AAC9B,KACD;AAAA,EACD,CAAA,MAAA,IAAW,WAAW,MAAA,EAAQ;AAC7B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,0BAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,4IAAA;AAAA;AACD,KACD;AAAA,EACD,CAAA,MAAA,IAAW,WAAW,YAAA,EAAc;AACnC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,gCAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,gIAAA;AAAA;AACD,KACD;AAAA,EACD;AAIA,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACxB,EAAA,IAAI,CAAC,EAAA,IAAM,MAAA,KAAW,QAAA,EAAU;AAC/B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,qBAAA;AAAA,QACA,KAAA;AAAA,QACA,6EAA6E,MAAM,CAAA,8CAAA;AAAA;AACpF,KACD;AAAA,EACD,CAAA,MAAA,IAAW,CAAC,EAAA,IAAM,MAAA,KAAW,MAAA,EAAQ;AACpC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,kCAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD,WAAW,EAAA,EAAI;AACd,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,EAAE,CAAA,EAAG;AAC3B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,gCAAA;AAAA,UACA,QAAA;AAAA,UACA,iCAAiC,EAAE,CAAA,6DAAA;AAAA;AACpC,OACD;AAAA,IACD,CAAA,MAAA,IAAW,MAAA,KAAW,QAAA,IAAY,EAAA,KAAO,MAAA,EAAQ;AAChD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,4CAAA;AAAA,UACA,MAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,IACD,CAAA,MAAA,IAAW,MAAA,KAAW,QAAA,IAAY,EAAA,KAAO,YAAA,EAAc;AACtD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,4CAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,IACD,CAAA,MAAA,IAAW,MAAA,KAAW,YAAA,IAAgB,EAAA,KAAO,MAAA,EAAQ;AACpD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,4CAAA;AAAA,UACA,QAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC1B,EAAA,IAAI,GAAA,EAAK;AACR,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AACxC,IAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,IAAK,MAAA,CAAO,KAAA,CAAM,QAAQ,CAAA,IAAK,QAAA,GAAW,CAAA,IAAK,QAAA,GAAW,GAAA,EAAK;AAC3F,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,gCAAA;AAAA,UACA,QAAA;AAAA,UACA,oBAAoB,GAAG,CAAA,qCAAA;AAAA;AACxB,OACD;AAAA,IACD,CAAA,MAAA,IAAW,WAAW,GAAA,EAAK;AAC3B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,iCAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,UAAA,EAAa,QAAQ,CAAA,kCAAA,EAAqC,QAAQ,CAAA,2CAAA;AAAA;AACnE,OACD;AAAA,IACA;AAAA,EACD;AAGA,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACxB,EAAA,IAAI,EAAA,EAAI;AACP,IAAA,MAAM,eAAA,uBAAsB,GAAA,CAAI,CAAC,KAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAC,CAAA;AACpD,IAAA,MAAM,WAAW,EAAA,CACf,KAAA,CAAM,GAAG,CAAA,CACT,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CACnB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAC,CAAA;AAE5B,IAAA,MAAM,SAAA,GAAY,SAAS,MAAA,CAAO,CAAC,MAAM,CAAC,eAAA,CAAgB,GAAA,CAAI,CAAC,CAAC,CAAA;AAChE,IAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,IAAK,SAAA,CAAU,SAAS,CAAA,EAAG;AAClD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,yCAAA;AAAA,UACA,QAAA;AAAA,UACA,mBAAmB,EAAE,CAAA,kCAAA,EAAqC,UAAU,IAAA,CAAK,IAAI,KAAK,MAAM,CAAA,6BAAA;AAAA;AACzF,OACD;AAAA,IACD,WAAW,QAAA,CAAS,MAAA,KAAW,KAAK,QAAA,CAAS,CAAC,MAAM,GAAA,EAAK;AACxD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,0CAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC1B,EAAA,IAAI,CAAC,GAAA,EAAK;AACT,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,wBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,6GAAA;AAAA;AACD,KACD;AAAA,EACD,CAAA,MAAO;AAEN,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA;AAClD,IAAA,MAAM,cAAA,GAAiB,QAAQ,MAAA,CAAO,CAAC,QAAQ,CAAC,eAAA,CAAgB,GAAG,CAAC,CAAA;AACpE,IAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC9B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,qCAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,uCAAA,EAA0C,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,0BAAA;AAAA;AACpE,OACD;AAAA,IACD;AAGA,IAAA,MAAM,WAAA,GAAc,4BAA4B,OAAO,CAAA;AACvD,IAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC3B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,uCAAA;AAAA,UACA,MAAA;AAAA,UACA,CAAA,iCAAA,EAAoC,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,qEAAA,CAAA;AAAA,UAC1D,EAAE,WAAA;AAAY;AACf,OACD;AAAA,IACD;AAGA,IAAA,MAAM,eAAA,GAAkB,MAAM,qBAAA,CAAsB,MAAA,EAAQ,SAAS,UAAU,CAAA;AAC/E,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,eAAe,CAAA;AAAA,EACjC;AAGA,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC1B,EAAA,IAAI,GAAA,EAAK;AACR,IAAA,MAAM,OAAA,GAAU,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA;AAClD,IAAA,MAAM,cAAA,GAAiB,QAAQ,MAAA,CAAO,CAAC,QAAQ,CAAC,eAAA,CAAgB,GAAG,CAAC,CAAA;AACpE,IAAA,IAAI,cAAA,CAAe,SAAS,CAAA,EAAG;AAC9B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,OAAA;AAAA,UACA,oCAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,sCAAA,EAAyC,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,0BAAA;AAAA;AACnE,OACD;AAAA,IACD;AAAA,EACD,WAAW,GAAA,EAAK;AAEf,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,gDAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAC9B,EAAA,IAAI,KAAA,IAAS,KAAA,KAAU,GAAA,IAAO,KAAA,KAAU,GAAA,EAAK;AAC5C,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,6BAAA;AAAA,QACA,QAAA;AAAA,QACA,sBAAsB,KAAK,CAAA,+DAAA;AAAA;AAC5B,KACD;AAAA,EACD,CAAA,MAAA,IAAW,CAAC,KAAA,IAAS,KAAA,KAAU,GAAA,EAAK;AACnC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,wBAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,yGAAA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,MAAM,CAAA;AAC5B,EAAA,IAAI,IAAA,IAAQ,IAAA,KAAS,GAAA,IAAO,IAAA,KAAS,GAAA,EAAK;AACzC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,4BAAA;AAAA,QACA,QAAA;AAAA,QACA,qBAAqB,IAAI,CAAA,+DAAA;AAAA;AAC1B,KACD;AAAA,EACD,CAAA,MAAA,IAAW,CAAC,IAAA,IAAQ,IAAA,KAAS,GAAA,EAAK;AACjC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,uBAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,sGAAA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,oBAAA,GAAuB,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,UAAA,IAAc,CAAA,CAAE,QAAA,KAAa,MAAA,IAAU,CAAA,CAAE,aAAa,QAAQ,CAAA;AAC/H,EAAA,IAAI,CAAC,oBAAA,EAAsB;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,OAAA;AAAA,QACA,2BAAA;AAAA,QACA,MAAA;AAAA,QACA,mCAAmC,MAAM,CAAA,sBAAA;AAAA;AAC1C,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,SAAS,QAAQ,CAAA;AAC1C;;;AC5UA,QAAA,EAAA;AAEA,YAAA,EAAA;;;ACPA,YAAA,EAAA;AAUO,SAAS,eAAA,CAAgB,QAAgB,GAAA,EAAiC;AAChF,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,CAAM,IAAI,OAAO,CAAA,WAAA,EAAc,GAAG,CAAA,QAAA,CAAA,EAAY,GAAG,CAAC,CAAA;AACvE,EAAA,OAAO,KAAA,GAAQ,CAAC,CAAA,EAAG,IAAA,EAAK;AACzB;AAOO,SAAS,kBAAA,CAAmB,iBAAqC,eAAA,EAA0C;AACjH,EAAA,IAAI,CAAC,eAAA,EAAiB;AACrB,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,SAAS,SAAA,EAAU;AAAA,EAC3D;AAEA,EAAA,IAAI,oBAAoB,SAAA,EAAW;AAClC,IAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,MAAA,EAAQ,SAAS,SAAA,EAAU;AAAA,EAC1D;AAEA,EAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAClD,EAAA,MAAM,YAAY,QAAA,CAAS,MAAA;AAE3B,EAAA,IAAI,eAAA,KAAoB,aAAA,IAAiB,SAAA,GAAY,EAAA,EAAI;AACxD,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,SAAS,SAAA,EAAU;AAAA,EAC7D;AAEA,EAAA,IAAI,YAAY,GAAA,EAAK;AACpB,IAAA,OAAO,EAAE,IAAA,EAAM,GAAA,EAAK,QAAA,EAAU,UAAA,EAAY,SAAS,KAAA,EAAM;AAAA,EAC1D;AAEA,EAAA,IAAI,YAAY,GAAA,EAAK;AACpB,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,SAAS,KAAA,EAAM;AAAA,EACvD;AAEA,EAAA,IAAI,YAAY,GAAA,EAAK;AACpB,IAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,SAAS,KAAA,EAAM;AAAA,EACzD;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,MAAA,EAAQ,SAAS,KAAA,EAAM;AACvD;AAEO,SAAS,4CAA4C,QAAA,EAA2B;AACtF,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,KAAA,IAAS,QAAQ,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,KAAA,IAAS,GAAG,KAAA,EAAA,EAAS;AAC1D,IAAA,MAAM,OAAA,GAAU,SAAS,KAAK,CAAA;AAC9B,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtC,IAAA,IAAI,CAAC,CAAC,UAAA,EAAY,MAAA,EAAQ,QAAQ,CAAA,CAAE,QAAA,CAAS,OAAA,CAAQ,QAAQ,CAAA,EAAG;AAChE,IAAA,MAAM,aAAA,GAAgB,QAAQ,QAAA,EAAU,aAAA;AACxC,IAAA,MAAM,OAAA,GAAU,QAAQ,QAAA,EAAU,OAAA;AAClC,IAAA,IAAI,OAAO,aAAA,KAAkB,QAAA,IAAY,OAAA,KAAY,KAAA,EAAO;AAE5D,IAAA,MAAM,MAAM,CAAA,EAAG,OAAA,CAAQ,QAAQ,CAAA,CAAA,EAAI,aAAa,IAAI,OAAO,CAAA,CAAA;AAC3D,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AAClB,MAAA,QAAA,CAAS,MAAA,CAAO,OAAO,CAAC,CAAA;AACxB,MAAA,OAAA,IAAW,CAAA;AACX,MAAA;AAAA,IACD;AAEA,IAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AAAA,EACb;AAEA,EAAA,IAAI,UAAU,CAAA,EAAG;AAChB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,iDAAA;AAAA,QACA,MAAA;AAAA,QACA,gBAAgB,OAAO,CAAA,yHAAA;AAAA;AACxB,KACD;AAAA,EACD;AACD;;;ADxEA,IAAM,gBAAA,GAAmB;AAAA,EACxB,SAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA,IAAA;AAAA;AAAA,EACA,IAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA;AAAA;AACD,CAAA;AAOA,eAAsB,SAAA,CAAU,MAAA,EAAgB,QAAA,EAAmB,UAAA,EAAoD;AACtH,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,gBAAA,GAAmB,QAAA,GAAW,CAAC,QAAQ,CAAA,GAAI,gBAAA;AACjD,EAAA,MAAM,iBAA2B,EAAC;AAClC,EAAA,IAAI,WAAA,GAAc,KAAA;AAGlB,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC7B,gBAAA,CAAiB,GAAA,CAAI,OAAO,GAAA,KAAQ;AACnC,MAAA,IAAI;AACH,QAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,CAAA,EAAG,GAAG,CAAA,YAAA,EAAe,MAAM,IAAI,UAAU,CAAA;AAC/E,QAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,WAAA,EAAY,CAAE,QAAA,CAAS,SAAS,CAAA,IAAK,CAAA,CAAE,QAAA,CAAS,IAAI,CAAC,CAAA;AACjG,QAAA,OAAO,EAAE,QAAA,EAAU,GAAA,EAAK,OAAA,EAAS,WAAA,EAAY;AAAA,MAC9C,CAAA,CAAA,MAAQ;AACP,QAAA,OAAO,EAAE,QAAA,EAAU,GAAA,EAAK,OAAA,EAAS,EAAC,EAAE;AAAA,MACrC;AAAA,IACD,CAAC;AAAA,GACF;AAEA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC9B,MAAA,cAAA,CAAe,IAAA,CAAK,OAAO,QAAQ,CAAA;AAGnC,MAAA,KAAA,MAAW,MAAA,IAAU,OAAO,OAAA,EAAS;AACpC,QAAA,MAAM,YAAY,SAAA,CAAU,IAAA,CAAK,MAAM,CAAA,IAAK,SAAA,CAAU,KAAK,MAAM,CAAA;AACjE,QAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,MAAA,EAAQ,GAAG,CAAA;AAG7C,QAAA,IAAI,SAAA,EAAW;AACd,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA;AAAA,cACC,MAAA;AAAA,cACA,CAAA,kBAAA,EAAqB,OAAO,QAAQ,CAAA,CAAA;AAAA,cACpC,QAAA;AAAA,cACA,CAAA,eAAA,EAAkB,OAAO,QAAQ,CAAA,oEAAA;AAAA;AAClC,WACD;AAAA,QACD,CAAA,MAAO;AACN,UAAA,WAAA,GAAc,IAAA;AAAA,QACf;AAGA,QAAA,MAAM,YAAA,GAAe,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA;AAChD,QAAA,MAAM,gBAAgB,YAAA,GAAe,YAAA,CAAa,CAAC,CAAA,CAAE,aAAY,GAAI,IAAA;AACrE,QAAA,IAAI,YAAA,IAAgB,CAAC,CAAC,KAAA,EAAO,SAAS,CAAA,CAAE,QAAA,CAAS,aAAc,CAAA,EAAG;AACjE,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA;AAAA,cACC,MAAA;AAAA,cACA,CAAA,uBAAA,EAA0B,YAAA,CAAa,CAAC,CAAC,CAAA,CAAA;AAAA,cACzC,QAAA;AAAA,cACA,kBAAkB,MAAA,CAAO,QAAQ,CAAA,yBAAA,EAA4B,YAAA,CAAa,CAAC,CAAC,CAAA,+BAAA;AAAA;AAC7E,WACD;AAAA,QACD;AAGA,QAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,EAAG;AACxB,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA;AAAA,cACC,MAAA;AAAA,cACA,CAAA,sBAAA,EAAyB,OAAO,QAAQ,CAAA,CAAA;AAAA,cACxC,KAAA;AAAA,cACA,CAAA,eAAA,EAAkB,OAAO,QAAQ,CAAA,sEAAA;AAAA;AAClC,WACD;AAAA,QACD;AAKA,QAAA,IAAI,CAAC,aAAa,SAAA,EAAW;AAC5B,UAAA,MAAM,kBAAkB,aAAA,IAAiB,aAAA;AACzC,UAAA,MAAM,WAAA,GAAc,kBAAA,CAAmB,SAAA,EAAW,eAAe,CAAA;AAEjE,UAAA,IAAI,WAAA,CAAY,YAAY,SAAA,EAAW;AAEtC,YAAA,QAAA,CAAS,IAAA;AAAA,cACR,aAAA;AAAA,gBACC,MAAA;AAAA,gBACA,CAAA,sBAAA,EAAyB,OAAO,QAAQ,CAAA,CAAA;AAAA,gBACxC,MAAA;AAAA,gBACA,CAAA,eAAA,EAAkB,OAAO,QAAQ,CAAA,iDAAA,CAAA;AAAA,gBACjC;AAAA,kBACC,OAAA,EAAS,SAAA;AAAA,kBACT,UAAU,MAAA,CAAO;AAAA;AAClB;AACD,aACD;AAAA,UACD,CAAA,MAAA,IAAW,WAAA,CAAY,OAAA,KAAY,SAAA,EAAW;AAE7C,YAAA,QAAA,CAAS,IAAA;AAAA,cACR,aAAA;AAAA,gBACC,MAAA;AAAA,gBACA,CAAA,oBAAA,EAAuB,OAAO,QAAQ,CAAA,CAAA;AAAA,gBACtC,QAAA;AAAA,gBACA,CAAA,eAAA,EAAkB,OAAO,QAAQ,CAAA,mGAAA,CAAA;AAAA,gBACjC;AAAA,kBACC,UAAU,MAAA,CAAO;AAAA;AAClB;AACD,aACD;AAAA,UACD,CAAA,MAAA,IAAW,WAAA,CAAY,OAAA,KAAY,KAAA,EAAO;AACzC,YAAA,MAAM,WAAA,GACL,WAAA,CAAY,QAAA,KAAa,UAAA,GACtB,MAAA,GACA,WAAA,CAAY,QAAA,KAAa,MAAA,GACxB,QAAA,GACA,WAAA,CAAY,QAAA,KAAa,QAAA,GACxB,mBAAA,GACA,QAAA;AACN,YAAA,MAAM,YAAA,GAAuC;AAAA,cAC5C,QAAA,EACC,qBAAqB,MAAA,CAAO,QAAQ,QAAQ,WAAW,CAAA,GAAA,EAAM,YAAY,IAAI,CAAA,mEAAA,CAAA;AAAA,cAC9E,IAAA,EAAM,qBAAqB,MAAA,CAAO,QAAQ,QAAQ,WAAW,CAAA,EAAA,EAAK,YAAY,IAAI,CAAA,sDAAA,CAAA;AAAA,cAClF,MAAA,EAAQ,qBAAqB,MAAA,CAAO,QAAQ,QAAQ,WAAW,CAAA,EAAA,EAAK,YAAY,IAAI,CAAA,0DAAA,CAAA;AAAA,cACpF,MAAM,CAAA,kBAAA,EAAqB,MAAA,CAAO,QAAQ,CAAA,aAAA,EAAgB,YAAY,IAAI,CAAA,OAAA;AAAA,aAC3E;AAEA,YAAA,IAAI,WAAA,CAAY,aAAa,MAAA,EAAQ;AACpC,cAAA,QAAA,CAAS,IAAA;AAAA,gBACR,aAAA;AAAA,kBACC,MAAA;AAAA,kBACA,CAAA,EAAG,WAAA,CAAY,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,WAAA,CAAY,KAAA,CAAM,CAAC,CAAC,CAAA,UAAA,EAAa,OAAO,QAAQ,CAAA,CAAA;AAAA,kBACzF,WAAA,CAAY,QAAA;AAAA,kBACZ,YAAA,CAAa,YAAY,QAAQ,CAAA;AAAA,kBACjC;AAAA,oBACC,eAAe,WAAA,CAAY,IAAA;AAAA,oBAC3B,SAAS,WAAA,CAAY,OAAA;AAAA,oBACrB,UAAU,MAAA,CAAO;AAAA;AAClB;AACD,eACD;AAAA,YACD;AAAA,UACD;AAAA,QACD;AAGA,QAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,MAAA,EAAQ,GAAG,CAAA;AAC9C,QAAA,IAAI,CAAC,UAAA,EAAY;AAChB,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA;AAAA,cACC,MAAA;AAAA,cACA,CAAA,0BAAA,EAA6B,OAAO,QAAQ,CAAA,CAAA;AAAA,cAC5C,QAAA;AAAA,cACA,CAAA,eAAA,EAAkB,OAAO,QAAQ,CAAA,kDAAA;AAAA;AAClC,WACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAIA,EAAA,IAAI,cAAA,CAAe,MAAA,GAAS,CAAA,IAAK,CAAC,WAAA,EAAa;AAC9C,IAAA,MAAM,YAAA,GAAe,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,KAAA,CAAM,UAAA,CAAW,mBAAmB,CAAC,CAAA,CAAE,MAAA;AAErF,IAAA,KAAA,IAAS,IAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC9C,MAAA,IAAI,SAAS,CAAC,CAAA,CAAE,KAAA,CAAM,UAAA,CAAW,mBAAmB,CAAA,EAAG;AACtD,QAAA,QAAA,CAAS,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,MACrB;AAAA,IACD;AACA,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,iCAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAO,YAAY,CAAA,wGAAA;AAAA;AACpB,KACD;AAAA,EACD;AAIA,EAAA,IAAI,CAAC,QAAA,IAAY,cAAA,CAAe,MAAA,GAAS,CAAA,EAAG;AAC3C,IAAA,2CAAA,CAA4C,QAAQ,CAAA;AAAA,EACrD;AAEA,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAChC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,8CAAA;AAAA,QACA,MAAA;AAAA,QACA,kCAAkC,MAAM,CAAA,gCAAA,EAAmC,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAC,CAAA,mIAAA,CAAA;AAAA,QACtG;AAAA,UACC,UAAA,EAAY,MAAA;AAAA,UACZ,eAAA,EAAiB,kBAAA;AAAA,UACjB,gBAAA,EAAkB,gBAAA;AAAA,UAClB,gBAAgB;AAAC;AAClB;AACD,KACD;AAAA,EACD,CAAA,MAAA,IAAW,cAAA,CAAe,MAAA,GAAS,CAAA,IAAK,WAAA,IAAe,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,EAAG;AAGpG,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA,CAAc,QAAQ,iBAAA,EAAmB,MAAA,EAAQ,qCAAqC,cAAA,CAAe,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,EAAI;AAAA,QAClH,UAAA,EAAY,MAAA;AAAA,QACZ,gBAAA,EAAkB,gBAAA;AAAA,QAClB,cAAA,EAAgB;AAAA,OAChB;AAAA,KACF;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,QAAQ,QAAQ,CAAA;AACzC;;;AExOA,QAAA,EAAA;AAEA,YAAA,EAAA;;;ACRA,YAAA,EAAA;AAGA,IAAM,iBAAA,GAA2E;AAAA,EAChF,CAAA,EAAG,EAAE,IAAA,EAAM,WAAA,EAAa,YAAY,IAAA,EAAK;AAAA,EACzC,CAAA,EAAG,EAAE,IAAA,EAAM,eAAA,EAAiB,YAAY,IAAA,EAAK;AAAA,EAC7C,CAAA,EAAG,EAAE,IAAA,EAAM,aAAA,EAAe,YAAY,KAAA,EAAM;AAAA,EAC5C,EAAA,EAAI,EAAE,IAAA,EAAM,aAAA,EAAe,YAAY,KAAA,EAAM;AAAA,EAC7C,EAAA,EAAI,EAAE,IAAA,EAAM,aAAA,EAAe,YAAY,KAAA,EAAM;AAAA,EAC7C,EAAA,EAAI,EAAE,IAAA,EAAM,aAAA,EAAe,YAAY,KAAA,EAAM;AAAA,EAC7C,EAAA,EAAI,EAAE,IAAA,EAAM,SAAA,EAAW,YAAY,KAAA;AACpC,CAAA;AAGA,IAAM,oCAAoB,IAAI,GAAA,CAAI,CAAC,EAAA,EAAI,EAAA,EAAI,EAAE,CAAC,CAAA;AAG9C,IAAM,qBAAA,GAAgD;AAAA,EACrD,CAAA,EAAG;AACJ,CAAA;AAMO,SAAS,qBAAqB,IAAA,EAA6B;AACjE,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAC7B,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACvC,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,GAAI,IAAA,GAAO,SAAA;AAClC;AAMO,SAAS,cAAc,IAAA,EAAgE;AAC7F,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAC7B,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACvC,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACxC,EAAA,IAAI,MAAM,SAAS,CAAA,IAAK,KAAA,CAAM,UAAU,GAAG,OAAO,IAAA;AAClD,EAAA,OAAO,EAAE,WAAW,UAAA,EAAW;AAChC;AAKO,SAAS,qBAAA,CAAsB,QAAgB,aAAA,EAAoC;AACzF,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AAEvC,EAAA,KAAA,MAAW,UAAU,aAAA,EAAe;AACnC,IAAA,MAAM,SAAA,GAAY,qBAAqB,MAAM,CAAA;AAC7C,IAAA,IAAI,SAAA,KAAc,IAAA,IAAQ,cAAA,CAAe,GAAA,CAAI,SAAS,CAAA,EAAG;AACzD,IAAA,cAAA,CAAe,IAAI,SAAS,CAAA;AAE5B,IAAA,MAAM,KAAA,GAAQ,kBAAkB,SAAS,CAAA;AACzC,IAAA,IAAI,OAAO,UAAA,EAAY;AACtB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,CAAA,6BAAA,EAAgC,MAAM,IAAI,CAAA,CAAA,CAAA;AAAA,UAC1C,MAAA;AAAA,UACA,GAAG,MAAM,CAAA,uBAAA,EAA0B,SAAS,CAAA,EAAA,EAAK,MAAM,IAAI,CAAA,gIAAA;AAAA;AAC5D,OACD;AAAA,IACD,CAAA,MAAA,IAAW,iBAAA,CAAkB,GAAA,CAAI,SAAS,CAAA,EAAG;AAC5C,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,CAAA,yBAAA,EAA4B,MAAO,IAAI,CAAA,CAAA,CAAA;AAAA,UACvC,MAAA;AAAA,UACA,GAAG,MAAM,CAAA,uBAAA,EAA0B,SAAS,CAAA,EAAA,EAAK,MAAO,IAAI,CAAA,uCAAA;AAAA;AAC7D,OACD;AAAA,IACD,CAAA,MAAA,IAAW,CAAC,KAAA,EAAO;AAClB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,6BAA6B,SAAS,CAAA,CAAA,CAAA;AAAA,UACtC,QAAA;AAAA,UACA,CAAA,EAAG,MAAM,CAAA,uBAAA,EAA0B,SAAS,CAAA,kFAAA;AAAA;AAC7C,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAKO,SAAS,kBAAA,CAAmB,QAAgB,SAAA,EAAgC;AAClF,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,eAAA,uBAAsB,GAAA,EAAY;AAExC,EAAA,KAAA,MAAW,UAAU,SAAA,EAAW;AAC/B,IAAA,MAAM,MAAA,GAAS,cAAc,MAAM,CAAA;AACnC,IAAA,IAAI,WAAW,IAAA,EAAM;AAErB,IAAA,MAAM,EAAE,YAAW,GAAI,MAAA;AACvB,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,UAAU,CAAA,EAAG;AACrC,IAAA,eAAA,CAAgB,IAAI,UAAU,CAAA;AAE9B,IAAA,MAAM,cAAA,GAAiB,sBAAsB,UAAU,CAAA;AACvD,IAAA,IAAI,cAAA,EAAgB;AACnB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,8BAA8B,cAAc,CAAA,CAAA,CAAA;AAAA,UAC5C,QAAA;AAAA,UACA,CAAA,EAAG,MAAM,CAAA,qBAAA,EAAwB,UAAU,KAAK,cAAc,CAAA,yEAAA;AAAA;AAC/D,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;ADtGA,eAAsBC,YAAAA,CAAY,QAAgB,UAAA,EAAoD;AACrG,EAAA,MAAM,WAAsB,EAAC;AAG7B,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,IAAI;AACH,IAAA,MAAA,GAAS,MAAM,WAAA,CAAe,MAAA,EAAQ,UAAU,CAAA;AAAA,EACjD,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,cAAc,QAAA,EAAU,qBAAA,EAAuB,QAAA,EAAU,CAAA,mCAAA,EAAsC,MAAM,CAAA,uBAAA,CAAyB;AAAA,KAC/H;AACA,IAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,sBAAA;AAAA,QACA,MAAA;AAAA,QACA,gCAAgC,MAAM,CAAA,wGAAA;AAAA;AACvC,KACD;AAAA,EACD;AAGA,EAAA,IAAI;AACH,IAAA,MAAM,aAAA,GAAgB,MAAM,eAAA,CAAgB,MAAA,EAAQ,UAAU,UAAU,CAAA;AACxE,IAAA,IAAI,aAAA,CAAc,MAAA,KAAW,CAAA,IAAK,CAAC,MAAA,EAAQ;AAC1C,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,mBAAA;AAAA,UACA,MAAA;AAAA,UACA,+BAA+B,MAAM,CAAA,6DAAA;AAAA;AACtC,OACD;AAAA,IACD,CAAA,MAAA,IAAW,aAAA,CAAc,MAAA,GAAS,CAAA,EAAG;AACpC,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,qBAAA,CAAsB,MAAA,EAAQ,aAAa,CAAC,CAAA;AAAA,IAC9D;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACH,IAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAM,UAAU,CAAA;AAChE,IAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,IAAK,CAAC,MAAA,EAAQ;AACtC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,QAAA;AAAA,UACA,eAAA;AAAA,UACA,QAAA;AAAA,UACA,+CAA+C,MAAM,CAAA,kFAAA;AAAA;AACtD,OACD;AAAA,IACD,CAAA,MAAA,IAAW,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG;AAChC,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,kBAAA,CAAmB,MAAA,EAAQ,SAAS,CAAC,CAAA;AAAA,IACvD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,8BAAA;AAAA,QACA,MAAA;AAAA,QACA,qCAAqC,MAAM,CAAA,+CAAA;AAAA;AAC5C,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAC3C;;;AEtFA,YAAA,EAAA;AACA,WAAA,EAAA;;;ACTA,YAAA,EAAA;AAEO,SAAS,gBAAA,CAAiB,MAAA,EAAgB,WAAA,EAAiC,UAAA,EAAsC;AACvH,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,WAAA,IAAe,WAAA,CAAY,UAAA,CAAW,SAAS,CAAA,EAAG;AACrD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,yBAAA;AAAA,QACA,UAAA;AAAA,QACA,GAAG,MAAM,CAAA,oEAAA;AAAA;AACV,KACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,UAAA,EAAY;AAChB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,gBAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAG,MAAM,CAAA,yGAAA;AAAA;AACV,KACD;AACA,IAAA,OAAO,QAAA;AAAA,EACR;AAEA,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,KAAA,CAAM,gBAAgB,CAAA;AACrD,EAAA,IAAI,WAAA,EAAa;AAChB,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,WAAA,CAAY,CAAC,GAAG,EAAE,CAAA;AAC1C,IAAA,IAAI,SAAS,OAAA,EAAU;AACtB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,KAAA;AAAA,UACA,wBAAA;AAAA,UACA,KAAA;AAAA,UACA,mBAAmB,MAAM,CAAA,UAAA,EAAa,KAAK,KAAA,CAAM,MAAA,GAAS,KAAK,CAAC,CAAA,iDAAA;AAAA;AACjE,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,oBAAA,CAAqB,IAAA,CAAK,UAAU,CAAA,EAAG;AAC3C,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,gCAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAEO,SAAS,oBAAA,CAAqB,QAAgB,OAAA,EAA0B;AAC9E,EAAA,IAAI,QAAQ,QAAA,CAAS,SAAS,KAAK,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,EAAG;AAC7D,IAAA,OAAO,aAAA;AAAA,MACN,KAAA;AAAA,MACA,0BAAA;AAAA,MACA,MAAA;AAAA,MACA,2CAA2C,MAAM,CAAA,qDAAA;AAAA,KAClD;AAAA,EACD;AAEA,EAAA,OAAO,aAAA;AAAA,IACN,KAAA;AAAA,IACA,yBAAA;AAAA,IACA,UAAA;AAAA,IACA,CAAA,qBAAA,EAAwB,MAAM,CAAA,aAAA,EAAgB,OAAO,CAAA,kDAAA;AAAA,GACtD;AACD;AAEO,SAAS,uBAAA,CAAwB,MAAA,EAAgB,MAAA,EAAgB,QAAA,EAAoC;AAC3G,EAAA,IAAI,UAAU,GAAA,IAAO,MAAA,GAAS,OAAO,QAAA,EAAU,UAAA,CAAW,UAAU,CAAA,EAAG;AACtE,IAAA,OAAO,EAAC;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,IAAU,OAAO,MAAA,GAAS,GAAA,IAAO,YAAY,CAAC,QAAA,CAAS,UAAA,CAAW,UAAU,CAAA,EAAG;AAClF,IAAA,OAAO;AAAA,MACN,aAAA;AAAA,QACC,KAAA;AAAA,QACA,iCAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,iBAAA,EAAoB,MAAM,CAAA,aAAA,EAAgB,QAAQ,CAAA,kBAAA;AAAA;AACnD,KACD;AAAA,EACD;AAEA,EAAA,OAAO;AAAA,IACN,aAAA;AAAA,MACC,KAAA;AAAA,MACA,2BAAA;AAAA,MACA,QAAA;AAAA,MACA,CAAA,iBAAA,EAAoB,MAAM,CAAA,qCAAA,EAAwC,MAAM,CAAA,EAAA;AAAA;AACzE,GACD;AACD;;;ADnFA,eAAsB,SAAS,MAAA,EAAsC;AACpE,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,MAAM,WAAA,GAAc,MAAM,UAAA,CAAW,MAAM,CAAA;AAC3C,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,WAAW,CAAA;AAG5B,EAAA,MAAM,cAAc,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,UAAU,CAAA;AAClE,EAAA,IAAI,CAAC,WAAA,EAAa;AACjB,IAAA,MAAM,cAAA,GAAiB,MAAM,iBAAA,CAAkB,MAAM,CAAA;AACrD,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,cAAc,CAAA;AAAA,EAChC;AAEA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA,CAAK,cAAc,KAAA,EAAO,oCAAA,EAAsC,QAAQ,CAAA,sEAAA,EAAyE,MAAM,6JAA6J,CAAC,CAAA;AAAA,EAC/T;AAEA,EAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AACxC;AAGA,eAAe,WAAW,MAAA,EAAoC;AAC7D,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,CAAA,EAAI;AAAA,MACjD,MAAA,EAAQ,MAAA;AAAA,MACR,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,gBAAgB;AAAA,KAC5C,CAAA;AAED,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,MAAA,IAAU,GAAA,IAAO,SAAS,MAAA,GAAS,GAAA;AAC/D,IAAA,MAAM,WAAW,UAAA,GAAa,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,GAAI,IAAA;AACjE,IAAA,MAAM,WAAA,GAAc,QAAA,EAAU,UAAA,CAAW,SAAS,CAAA,IAAK,KAAA;AACvD,IAAA,MAAM,eAAA,GAAkB,cAAc,CAAC,WAAA;AAKvC,IAAA,IAAI,CAAC,eAAA,EAAiB;AACrB,MAAA,MAAM,cAAA,GAAiB,WAAA,GAAe,QAAA,IAAY,KAAA,CAAA,GAAa,KAAA,CAAA;AAC/D,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,gBAAA,CAAiB,MAAA,EAAQ,cAAA,EAAgB,SAAS,OAAA,CAAQ,GAAA,CAAI,2BAA2B,CAAC,CAAC,CAAA;AAAA,IAC7G;AAAA,EAED,SAAS,GAAA,EAAK;AACb,IAAA,MAAM,OAAA,GAAU,GAAA,YAAe,KAAA,KAAU,GAAA,CAAI,QAAQ,QAAA,CAAS,SAAS,CAAA,IAAK,GAAA,CAAI,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAA,CAAA,GACrG,IAAI,OAAA,GACJ,mBAAA;AACH,IAAA,QAAA,CAAS,IAAA,CAAK,oBAAA,CAAqB,MAAA,EAAQ,OAAO,CAAC,CAAA;AAAA,EACpD;AAEA,EAAA,OAAO,QAAA;AACR;AAGA,eAAe,kBAAkB,MAAA,EAAoC;AACpE,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,OAAA,EAAU,MAAM,CAAA,CAAA,EAAI;AAAA,MAChD,MAAA,EAAQ,MAAA;AAAA,MACR,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,gBAAgB;AAAA,KAC5C,CAAA;AACD,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,uBAAA,CAAwB,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAC,CAAC,CAAA;AAAA,EACpG,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,QAAA;AACR;;;AE/EA,WAAA,EAAA;AACA,QAAA,EAAA;AAEA,YAAA,EAAA;;;ACRA,YAAA,EAAA;AAEO,SAAS,qBAAqB,OAAA,EAAmE;AACvG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,aAAA,GAAgB,QAAQ,MAAA,CAAO,CAAC,WAAW,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAC,CAAA;AAE9E,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC/B,IAAA,OAAO;AAAA,MACN,QAAA,EAAU;AAAA,QACT,aAAA;AAAA,UACC,SAAA;AAAA,UACA,yBAAA;AAAA,UACA,QAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,MACA,YAAA,EAAc;AAAA,KACf;AAAA,EACD;AAEA,EAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC7B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,cAAc,SAAA,EAAW,0BAAA,EAA4B,UAAU,CAAA,MAAA,EAAS,aAAA,CAAc,MAAM,CAAA,wCAAA,CAA0C;AAAA,KACvI;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,aAAA,CAAc,CAAC,CAAA,CAAE,QAAA,CAAS,KAAK,CAAA,EAAG;AACtC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,wBAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,EAAE,QAAA,EAAU,YAAA,EAAc,IAAA,EAAK;AACvC;AAEO,SAAS,kCAAA,CAAmC,UAAqB,MAAA,EAA2B;AAClG,EAAA,OAAO,QAAA,CAAS,GAAA;AAAA,IAAI,CAAC,OAAA,KACpB,OAAA,CAAQ,KAAA,KAAU,yBAAA,GACf,aAAA;AAAA,MACA,SAAA;AAAA,MACA,yBAAA;AAAA,MACA,QAAA;AAAA,MACA,2CAA2C,MAAM,CAAA,wEAAA;AAAA,KAClD,GACC;AAAA,GACJ;AACD;AAEO,SAAS,uBAAA,CAAwB,MAAc,SAAA,EAA8B;AACnF,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,mBAAmB,CAAA;AACnD,EAAA,IAAI,CAAC,YAAA,IAAgB,YAAA,CAAa,CAAC,MAAM,OAAA,EAAS;AACjD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,2CAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,iCAAiC,CAAA;AAE9D,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA,CAAc,SAAA,EAAW,6BAAA,EAA+B,MAAA,EAAQ,iEAAiE;AAAA,KAClI;AAAA,EACD,CAAA,MAAO;AACN,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,CAAC,CAAA,CAAE,WAAA,EAAY;AACtC,IAAA,IAAI,SAAS,SAAA,EAAW;AACvB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA,CAAc,SAAA,EAAW,yBAAA,EAA2B,KAAA,EAAO,qFAAqF;AAAA,OACjJ;AAAA,IACD,CAAA,MAAA,IAAW,SAAS,MAAA,EAAQ;AAC3B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA,CAAc,SAAA,EAAW,yBAAA,EAA2B,QAAA,EAAU,0EAA0E;AAAA,OACzI;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,KAAK,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,mCAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,KAAA,CAAM,mBAAmB,CAAA;AAClD,EAAA,IAAI,CAAC,WAAA,EAAa;AACjB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,gCAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD,CAAA,MAAO;AACN,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,WAAA,CAAY,CAAC,GAAG,EAAE,CAAA;AAC1C,IAAA,IAAI,SAAS,KAAA,EAAO;AACnB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,SAAA;AAAA,UACA,2BAAA;AAAA,UACA,KAAA;AAAA,UACA,sBAAsB,MAAM,CAAA,4FAAA;AAAA;AAC7B,OACD;AAAA,IACD,CAAA,MAAA,IAAW,SAAS,QAAA,EAAU;AAC7B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,SAAA;AAAA,UACA,kCAAA;AAAA,UACA,MAAA;AAAA,UACA,sBAAsB,MAAM,CAAA,0DAAA;AAAA;AAC7B,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,OAAO,EAAC;AAAA,EACT;AAEA,EAAA,OAAO,QAAA,CAAS,GAAA;AAAA,IAAI,CAAC,YACpB,OAAA,CAAQ,KAAA,KAAU,iCAAiC,OAAA,CAAQ,KAAA,KAAU,mCAAA,GAClE,aAAA,CAAc,SAAA,EAAW,OAAA,CAAQ,OAAO,OAAA,CAAQ,QAAA,EAAU,QAAQ,MAAA,CAAO,OAAA,CAAQ,uBAAuB,CAAA,uBAAA,EAA0B,SAAS,CAAA,CAAE,CAAC,CAAA,GAC9I;AAAA,GACJ;AACD;AAEO,SAAS,wBAAwB,IAAA,EAAwB;AAC/D,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,QAAA,CAAS,eAAe,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,KAAA,KAAU,KAAA,CAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AACjF;AAEO,SAAS,gBAAA,CAAiB,UAAkB,OAAA,EAA0B;AAC5E,EAAA,IAAI,OAAA,CAAQ,UAAA,CAAW,IAAI,CAAA,EAAG;AAC7B,IAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,KAAA,CAAM,CAAC,CAAA;AAC9B,IAAA,OAAO,SAAS,QAAA,CAAS,MAAM,KAAK,QAAA,KAAa,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA,EACjE;AAEA,EAAA,OAAO,QAAA,KAAa,OAAA;AACrB;AAEO,SAAS,0BAAA,CAA2B,SAAmB,gBAAA,EAAuC;AACpG,EAAA,OAAO,OAAA,CAAQ,OAAA,CAAQ,CAAC,MAAA,KAAW;AAClC,IAAA,MAAM,QAAA,GAAW,OAAO,WAAA,EAAY;AACpC,IAAA,MAAM,OAAA,GAAU,iBAAiB,IAAA,CAAK,CAAC,YAAY,gBAAA,CAAiB,QAAA,EAAU,OAAO,CAAC,CAAA;AACtF,IAAA,IAAI,OAAA,EAAS;AACZ,MAAA,OAAO,EAAC;AAAA,IACT;AAEA,IAAA,OAAO;AAAA,MACN,aAAA;AAAA,QACC,SAAA;AAAA,QACA,yCAAyC,MAAM,CAAA,CAAA;AAAA,QAC/C,MAAA;AAAA,QACA,eAAe,MAAM,CAAA,+GAAA;AAAA;AACtB,KACD;AAAA,EACD,CAAC,CAAA;AACF;AAMO,SAAS,wBAAwB,OAAA,EAAsE;AAC7G,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,MAAA,CAAO,CAAC,MAAA,KAAW,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,YAAY,CAAC,CAAA;AAC7F,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,IAAA,OAAO;AAAA,MACN,QAAA,EAAU;AAAA,QACT,aAAA;AAAA,UACC,SAAA;AAAA,UACA,wBAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,MACA,eAAA,EAAiB;AAAA,KAClB;AAAA,EACD;AAEA,EAAA,MAAM,YAAA,GAAe,aAAa,CAAC,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,KAAA,CAAM,sBAAsB,CAAA;AAC1D,EAAA,IAAI,CAAC,QAAA,EAAU;AACd,IAAA,OAAO;AAAA,MACN,QAAA,EAAU;AAAA,QACT,aAAA;AAAA,UACC,SAAA;AAAA,UACA,+BAAA;AAAA,UACA,KAAA;AAAA,UACA;AAAA;AACD,OACD;AAAA,MACA,eAAA,EAAiB;AAAA,KAClB;AAAA,EACD;AAEA,EAAA,MAAM,QAAA,GAAW,SAAS,CAAC,CAAA;AAC3B,EAAA,MAAM,aAAA,GAAgB,mCAAA,CAAoC,IAAA,CAAK,QAAQ,CAAA;AACvE,EAAA,MAAM,YAAA,GAAe,eAAA,CAAgB,IAAA,CAAK,QAAQ,CAAA;AAClD,EAAA,IAAI,CAAC,aAAA,IAAiB,CAAC,YAAA,EAAc;AACpC,IAAA,OAAO;AAAA,MACN,QAAA,EAAU;AAAA,QACT,aAAA;AAAA,UACC,SAAA;AAAA,UACA,4BAAA;AAAA,UACA,QAAA;AAAA,UACA,sBAAsB,QAAQ,CAAA,uCAAA;AAAA;AAC/B,OACD;AAAA,MACA,eAAA,EAAiB;AAAA,KAClB;AAAA,EACD;AAEA,EAAA,OAAO,EAAE,QAAA,EAAU,EAAC,EAAG,iBAAiB,IAAA,EAAK;AAC9C;AAEO,SAAS,kCAAA,CAAmC,UAAqB,MAAA,EAA2B;AAClG,EAAA,OAAO,QAAA,CAAS,GAAA;AAAA,IAAI,CAAC,OAAA,KACpB,OAAA,CAAQ,KAAA,KAAU,wBAAA,GACf,aAAA;AAAA,MACA,SAAA;AAAA,MACA,wBAAA;AAAA,MACA,KAAA;AAAA,MACA,yCAAyC,MAAM,CAAA,iEAAA;AAAA,KAChD,GACC;AAAA,GACJ;AACD;AAEO,SAAS,qCAAA,CAAsC,QAAA,EAAqB,YAAA,EAAuB,aAAA,EAAwB,eAAA,EAAmC;AAC5J,EAAA,MAAM,mBAAA,GAAsB,SAAS,IAAA,CAAK,CAAC,YAAY,OAAA,CAAQ,KAAA,CAAM,QAAA,CAAS,kBAAkB,CAAC,CAAA;AACjG,EAAA,OAAO,CAAC,YAAA,IAAgB,aAAA,IAAiB,CAAC,mBAAmB,CAAC,mBAAA;AAC/D;;;AD7NA,eAAsB,WAAA,CAAY,QAAgB,UAAA,EAAoD;AACrG,EAAA,IAAI,WAAsB,EAAC;AAG3B,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,IAAI;AACH,IAAA,MAAM,aAAa,MAAM,eAAA,CAAgB,CAAA,SAAA,EAAY,MAAM,IAAI,UAAU,CAAA;AACzE,IAAA,MAAM,WAAA,GAAc,qBAAqB,UAAU,CAAA;AACnD,IAAA,YAAA,GAAe,WAAA,CAAY,YAAA;AAC3B,IAAA,QAAA,CAAS,KAAK,GAAG,kCAAA,CAAmC,WAAA,CAAY,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,EAClF,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,GAAW,EAAC;AACZ,IAAA,QAAA,CAAS,IAAA,CAAK,cAAc,SAAA,EAAW,0BAAA,EAA4B,OAAO,CAAA,uCAAA,EAA0C,MAAM,GAAG,CAAC,CAAA;AAAA,EAC/H;AAGA,EAAA,IAAI,YAAA,EAAc;AACjB,IAAA,IAAI;AACH,MAAA,MAAM,SAAA,GAAY,mBAAmB,MAAM,CAAA,wBAAA,CAAA;AAC3C,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,SAAA,EAAW;AAAA,QACvC,MAAA,EAAQ,KAAA;AAAA,QACR,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,gBAAgB;AAAA,OAC5C,CAAA;AAED,MAAA,IAAI,CAAC,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA,CAAE,QAAA,CAAS,QAAA,CAAS,MAAM,CAAA,EAAG;AACxD,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,SAAA;AAAA,YACA,0BAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,uBAAA,EAA0B,SAAS,CAAA,eAAA,EAAkB,QAAA,CAAS,MAAM,CAAA,sFAAA;AAAA;AACrE,SACD;AAAA,MACD,CAAA,MAAA,IAAW,CAAC,QAAA,CAAS,EAAA,EAAI;AACxB,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,SAAA;AAAA,YACA,oCAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,uBAAA,EAA0B,SAAS,CAAA,eAAA,EAAkB,QAAA,CAAS,MAAM,CAAA,gDAAA;AAAA;AACrE,SACD;AAAA,MACD,CAAA,MAAO;AACN,QAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,QAAA,QAAA,CAAS,IAAA,CAAK,GAAG,uBAAA,CAAwB,IAAA,EAAM,SAAS,CAAC,CAAA;AAEzD,QAAA,MAAM,gBAAA,GAAmB,wBAAwB,IAAI,CAAA;AACrD,QAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,iCAAiC,CAAA;AAC9D,QAAA,MAAM,aAAa,SAAA,GAAY,SAAA,CAAU,CAAC,CAAA,CAAE,aAAY,GAAI,EAAA;AAC5D,QAAA,IAAI,iBAAiB,MAAA,GAAS,CAAA,KAAM,UAAA,KAAe,SAAA,IAAa,eAAe,SAAA,CAAA,EAAY;AAC1F,UAAA,IAAI;AACH,YAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,MAAA,EAAQ,UAAU,CAAA;AACzD,YAAA,QAAA,CAAS,IAAA,CAAK,GAAG,0BAAA,CAA2B,SAAA,CAAU,GAAA,CAAI,CAAC,EAAA,KAAO,EAAA,CAAG,QAAQ,CAAA,EAAG,gBAAgB,CAAC,CAAA;AAAA,UAClG,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACD;AAAA,MACD;AAAA,IACD,CAAA,CAAA,MAAQ;AACP,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,SAAA;AAAA,UACA,6BAAA;AAAA,UACA,QAAA;AAAA,UACA,4DAA4D,MAAM,CAAA,wBAAA;AAAA;AACnE,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,eAAA,GAAkB,KAAA;AACtB,EAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,EAAA,IAAI;AACH,IAAA,MAAM,gBAAgB,MAAM,eAAA,CAAgB,CAAA,WAAA,EAAc,MAAM,IAAI,UAAU,CAAA;AAC9E,IAAA,aAAA,GAAgB,IAAA;AAChB,IAAA,MAAM,cAAA,GAAiB,wBAAwB,aAAa,CAAA;AAC5D,IAAA,eAAA,GAAkB,cAAA,CAAe,eAAA;AACjC,IAAA,QAAA,CAAS,KAAK,GAAG,kCAAA,CAAmC,cAAA,CAAe,QAAA,EAAU,MAAM,CAAC,CAAA;AAAA,EACrF,CAAA,CAAA,MAAQ;AACP,IAAA,aAAA,GAAgB,IAAA;AAChB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,0BAAA;AAAA,QACA,KAAA;AAAA,QACA,0CAA0C,MAAM,CAAA,CAAA;AAAA;AACjD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,6BAAA;AAAA,QACA,MAAA;AAAA,QACA,sCAAsC,MAAM,CAAA,gCAAA;AAAA;AAC7C,KACD;AAAA,EACD;AAIA,EAAA,IAAI,qCAAA,CAAsC,QAAA,EAAU,YAAA,EAAc,aAAA,EAAe,eAAe,CAAA,EAAG;AAClG,IAAA,QAAA,GAAW,EAAC;AACZ,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,SAAA;AAAA,QACA,qCAAA;AAAA,QACA,QAAA;AAAA,QACA,uDAAuD,MAAM,CAAA,8HAAA;AAAA;AAC9D,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,WAAW,QAAQ,CAAA;AAC5C;;;AE1IA,QAAA,EAAA;AAEA,YAAA,EAAA;;;ACNA,YAAA,EAAA;AAEA,IAAM,sBAAA,GAAiD;AAAA,EACtD,gBAAA,EACC,mJAAA;AAAA,EACD,YAAA,EAAc,qJAAA;AAAA,EACd,YAAA,EACC;AACF,CAAA;AASO,SAAS,mBAAmB,SAAA,EAA+B;AACjE,EAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAC,MAAA,KAAW,MAAA,CAAO,QAAQ,KAAA,EAAO,EAAE,CAAA,CAAE,WAAA,EAAa,CAAA;AACzE;AAEO,SAAS,sBAAA,CAAuB,QAAgB,cAAA,EAAkC;AACxF,EAAA,IAAI,cAAA,EAAgB;AACnB,IAAA,OAAO,aAAA;AAAA,MACN,IAAA;AAAA,MACA,iCAAA;AAAA,MACA,KAAA;AAAA,MACA,8BAA8B,MAAM,CAAA,+EAAA;AAAA,KACrC;AAAA,EACD;AAEA,EAAA,OAAO,aAAA;AAAA,IACN,IAAA;AAAA,IACA,qBAAA;AAAA,IACA,UAAA;AAAA,IACA,mCAAmC,MAAM,CAAA,gDAAA;AAAA,GAC1C;AACD;AAEO,SAAS,mBAAmB,SAAA,EAAqC;AACvE,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,OAAO,aAAA;AAAA,IACN,IAAA;AAAA,IACA,+CAAA;AAAA,IACA,MAAA;AAAA,IACA,CAAA,2BAAA,EAA8B,SAAA,CAAU,CAAC,CAAC,CAAA,2GAAA;AAAA,GAC3C;AACD;AAEO,SAAS,8BAA8B,SAAA,EAAqC;AAClF,EAAA,MAAM,kBAAkB,IAAI,GAAA;AAAA,IAC3B,SAAA,CAAU,GAAA,CAAI,CAAC,MAAA,KAAW;AACzB,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,MAAA,OAAO,KAAA,CAAM,KAAA,CAAM,EAAE,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,IAChC,CAAC;AAAA,GACF;AAEA,EAAA,IAAI,eAAA,CAAgB,IAAA,KAAS,CAAA,IAAK,SAAA,CAAU,UAAU,CAAA,EAAG;AACxD,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,MAAM,cAAA,GAAiB,CAAC,GAAG,eAAe,EAAE,CAAC,CAAA;AAC7C,EAAA,MAAM,eAAA,GACL,sBAAA,CAAuB,cAAc,CAAA,IAAK,4EAAA;AAE3C,EAAA,OAAO,aAAA;AAAA,IACN,IAAA;AAAA,IACA,0BAAA;AAAA,IACA,KAAA;AAAA,IACA,CAAA,0BAAA,EAA6B,cAAc,CAAA,EAAA,EAAK,eAAe,CAAA,iEAAA;AAAA,GAChE;AACD;AAEO,SAAS,eAAe,OAAA,EAAyC;AACvE,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AAC3C,EAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACxB,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACxC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACtC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,QAAA,CAAS,CAAC,GAAG,EAAE,CAAA;AAExC,EAAA,OAAO;AAAA,IACN,OAAA,EAAS,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,IAAA,GAAO,OAAA;AAAA,IACxC,KAAA,EAAO,MAAA,CAAO,KAAA,CAAM,KAAK,IAAI,IAAA,GAAO,KAAA;AAAA,IACpC,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,MAAM,IAAI,IAAA,GAAO,MAAA;AAAA,IACtC,OAAA,EAAS,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,IAAA,GAAO;AAAA,GACzC;AACD;AAEO,SAAS,yBAAyB,SAAA,EAAuC;AAC/E,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,SAAA,CAAU,YAAY,IAAA,EAAM;AAC/B,IAAA,IAAI,SAAA,CAAU,UAAU,GAAA,EAAK;AAC5B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,IAAA;AAAA,UACA,gCAAA;AAAA,UACA,KAAA;AAAA,UACA,CAAA,wBAAA,EAA2B,UAAU,OAAO,CAAA,8FAAA;AAAA;AAC7C,OACD;AAAA,IACD,CAAA,MAAA,IAAW,SAAA,CAAU,OAAA,GAAU,KAAA,EAAO;AACrC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,IAAA;AAAA,UACA,+BAAA;AAAA,UACA,KAAA;AAAA,UACA,CAAA,wBAAA,EAA2B,UAAU,OAAO,CAAA,wGAAA;AAAA;AAC7C,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,SAAA,CAAU,UAAU,IAAA,IAAQ,SAAA,CAAU,YAAY,IAAA,IAAQ,SAAA,CAAU,KAAA,GAAQ,SAAA,CAAU,OAAA,EAAS;AAClG,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,IAAA;AAAA,QACA,oCAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,oBAAA,EAAuB,SAAA,CAAU,KAAK,CAAA,6BAAA,EAAgC,UAAU,OAAO,CAAA,8FAAA;AAAA;AACxF,KACD;AAAA,EACD;AAEA,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,IAAA,IAAQ,SAAA,CAAU,SAAS,MAAA,EAAQ;AAC3D,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,IAAA;AAAA,QACA,sBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,oBAAA,EAAuB,UAAU,MAAM,CAAA,6HAAA;AAAA;AACxC,KACD;AAAA,EACD;AAEA,EAAA,IAAI,SAAA,CAAU,OAAA,KAAY,IAAA,IAAQ,SAAA,CAAU,UAAU,KAAA,EAAO;AAC5D,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,IAAA;AAAA,QACA,iCAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,oCAAA,EAAuC,UAAU,OAAO,CAAA,4HAAA;AAAA;AACzD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAEO,SAAS,uBAAuB,SAAA,EAA8B;AACpE,EAAA,OAAO,aAAA,CAAc,IAAA,EAAM,iCAAA,EAAmC,MAAA,EAAQ,CAAA,EAAG,SAAA,CAAU,MAAM,CAAA,oBAAA,EAAuB,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AACvI;;;ADzIA,eAAsB,OAAA,CAAQ,QAAgB,UAAA,EAAoD;AACjG,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,YAAsB,EAAC;AAC3B,EAAA,IAAI;AACH,IAAA,SAAA,GAAY,mBAAmB,MAAM,eAAA,CAAgB,MAAA,EAAQ,IAAA,EAAM,UAAU,CAAC,CAAA;AAAA,EAC/E,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,CAAS,IAAA,CAAK,cAAc,IAAA,EAAM,iBAAA,EAAmB,YAAY,CAAA,uCAAA,EAA0C,MAAM,GAAG,CAAC,CAAA;AACrH,IAAA,OAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AAAA,EACvC;AAEA,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAE3B,IAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,IAAA,IAAI;AACH,MAAA,MAAM,QAAQ,MAAM,QAAA,CAAS,MAAA,EAAQ,GAAA,EAAK,OAAO,UAAU,CAAA;AAC3D,MAAA,cAAA,GAAA,CAAkB,KAAA,CAAM,MAAA,IAAU,EAAC,EAAG,MAAA,GAAS,CAAA;AAAA,IAChD,CAAA,CAAA,MAAQ;AAAA,IAER;AAEA,IAAA,QAAA,CAAS,IAAA,CAAK,sBAAA,CAAuB,MAAA,EAAQ,cAAc,CAAC,CAAA;AAC5D,IAAA,OAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AAAA,EACvC;AAGA,EAAA,MAAM,eAAA,GAAkB,mBAAmB,SAAS,CAAA;AACpD,EAAA,IAAI,eAAA,EAAiB;AACpB,IAAA,QAAA,CAAS,KAAK,eAAe,CAAA;AAAA,EAC9B;AAEA,EAAA,MAAM,gBAAA,GAAmB,8BAA8B,SAAS,CAAA;AAChE,EAAA,IAAI,gBAAA,EAAkB;AACrB,IAAA,QAAA,CAAS,KAAK,gBAAgB,CAAA;AAAA,EAC/B;AAGA,EAAA,IAAI;AACH,IAAA,MAAM,UAAU,MAAM,QAAA,CAAS,MAAA,EAAQ,KAAA,EAAO,OAAO,UAAU,CAAA;AAC/D,IAAA,MAAM,UAAA,GAAA,CAAc,OAAA,CAAQ,MAAA,IAAU,EAAC,EAAG,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,CAAC,CAAA;AACpE,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,IAAA;AAAA,UACA,eAAA;AAAA,UACA,QAAA;AAAA,UACA,gDAAgD,MAAM,CAAA,6DAAA;AAAA;AACvD,OACD;AAAA,IACD,CAAA,MAAO;AACN,MAAA,MAAM,SAAA,GAAY,cAAA,CAAe,UAAA,CAAW,CAAC,EAAE,IAAI,CAAA;AACnD,MAAA,IAAI,SAAA,EAAW;AACd,QAAA,QAAA,CAAS,IAAA,CAAK,GAAG,wBAAA,CAAyB,SAAS,CAAC,CAAA;AAAA,MACrD;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACH,IAAA,MAAM,SAAA,GAAY,CAAA,UAAA,EAAa,MAAA,CAAO,UAAA,EAAW,CAAE,MAAM,CAAA,EAAG,CAAC,CAAC,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AACxE,IAAA,MAAM,YAAA,GAAe,MAAM,eAAA,CAAgB,SAAA,EAAW,KAAK,UAAU,CAAA;AACrE,IAAA,IAAI,YAAA,CAAa,SAAS,CAAA,EAAG;AAC5B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,IAAA;AAAA,UACA,uBAAA;AAAA,UACA,QAAA;AAAA,UACA,gFAAgF,MAAM,CAAA,0IAAA,CAAA;AAAA,UACtF,EAAE,gBAAA,EAAkB,IAAA,EAAM,cAAA,EAAgB,SAAA;AAAU;AACrD,OACD;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA,CAAK,sBAAA,CAAuB,SAAS,CAAC,CAAA;AAAA,EAChD;AAEA,EAAA,OAAO,gBAAA,CAAiB,MAAM,QAAQ,CAAA;AACvC;;;AErGA,QAAA,EAAA;AAEA,YAAA,EAAA;;;ACLA,YAAA,EAAA;AAEO,SAAS,iBAAiB,UAAA,EAI/B;AACD,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,KAAA,MAAW,UAAU,UAAA,EAAY;AAChC,IAAA,IAAI,MAAA,CAAO,QAAQ,OAAA,EAAS;AAC3B,MAAA,QAAA,GAAW,IAAA;AAAA,IACZ;AACA,IAAA,IAAI,MAAA,CAAO,QAAQ,WAAA,EAAa;AAC/B,MAAA,YAAA,GAAe,IAAA;AAAA,IAChB;AACA,IAAA,IAAI,MAAA,CAAO,QAAQ,OAAA,EAAS;AAC3B,MAAA,QAAA,GAAW,IAAA;AAAA,IACZ;AAAA,EACD;AAEA,EAAA,OAAO,EAAE,QAAA,EAAU,YAAA,EAAc,QAAA,EAAS;AAC3C;AAEO,SAAS,yBAAyB,UAAA,EAAwF;AAChI,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACzB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,kBAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,WAAW,YAAA,EAAc;AAC7B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,sBAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,WAAW,QAAA,EAAU;AACzB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,kBAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAEO,SAAS,uBAAA,GAAmC;AAClD,EAAA,OAAO,aAAA,CAAc,KAAA,EAAO,yBAAA,EAA2B,MAAA,EAAQ,qEAAqE,CAAA;AACrI;;;ADvDA,eAAsB,QAAA,CAAS,QAAgB,UAAA,EAAoD;AAClG,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,aAA0B,EAAC;AAC/B,EAAA,IAAI;AACH,IAAA,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,EAAQ,UAAU,CAAA;AAAA,EACtD,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,CAAS,IAAA,CAAK,cAAc,KAAA,EAAO,kBAAA,EAAoB,UAAU,CAAA,gCAAA,EAAmC,MAAM,GAAG,CAAC,CAAA;AAC9G,IAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAAA,EACxC;AAEA,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,gBAAA;AAAA,QACA,QAAA;AAAA,QACA,4BAA4B,MAAM,CAAA,8HAAA;AAAA;AACnC,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAAA,EACxC;AAEA,EAAA,QAAA,CAAS,KAAK,GAAG,wBAAA,CAAyB,gBAAA,CAAiB,UAAU,CAAC,CAAC,CAAA;AAGvE,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA,CAAK,yBAAyB,CAAA;AAAA,EACxC;AAEA,EAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AACxC;;;AEvCA,QAAA,EAAA;AAGA,YAAA,EAAA;AAOA,eAAsB,SAAA,CAAU,QAAgB,UAAA,EAAoD;AACnG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,UAAA,GAAa,iBAAiB,MAAM,CAAA,CAAA;AAC1C,EAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,UAAA,EAAY,UAAU,CAAA;AAE/D,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,SAAS,CAAC,CAAA;AAElF,EAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAE7B,IAAA,MAAM,eAAe,MAAM,eAAA,CAAgB,CAAA,OAAA,EAAU,MAAM,IAAI,UAAU,CAAA;AACzE,IAAA,MAAM,WAAA,GAAc,YAAA,CAAa,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AACnF,IAAA,MAAM,WAAA,GACL,gBAAgB,eAAA,CAAgB,IAAA,CAAK,WAAW,CAAA,IAAK,mBAAA,CAAoB,KAAK,WAAW,CAAA,CAAA;AAE1F,IAAA,IAAI,CAAC,WAAA,EAAa;AACjB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,sCAAA;AAAA,UACA,MAAA;AAAA,UACA,2BAA2B,UAAU,CAAA,mJAAA;AAAA;AACtC,OACD;AAAA,IACD,CAAA,MAAO;AACN,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,sBAAA;AAAA,UACA,KAAA;AAAA,UACA,2BAA2B,UAAU,CAAA,qLAAA;AAAA;AACtC,OACD;AAAA,IACD;AACA,IAAA,OAAO,gBAAA,CAAiB,QAAQ,QAAQ,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC3B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,uBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,MAAA,EAAS,WAAA,CAAY,MAAM,CAAA,iBAAA,EAAoB,UAAU,CAAA,0CAAA;AAAA;AAC1D,KACD;AAAA,EACD;AAEA,EAAA,MAAM,IAAA,GAAO,YAAY,CAAC,CAAA;AAG1B,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,gBAAgB,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,YAAY,CAAC,CAAA;AAE7B,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,8BAAA;AAAA,QACA,QAAA;AAAA,QACA,kBAAkB,UAAU,CAAA,kHAAA;AAAA;AAC7B,KACD;AAAA,EACD,CAAA,MAAO;AAEN,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,WAAA,EAAY,CAAE,WAAW,UAAU,CAAA;AAC3D,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,WAAA,EAAY,CAAE,SAAS,MAAM,CAAA;AAEnD,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,KAAA,EAAO;AACvB,MAAA,MAAM,SAAmB,EAAC;AAC1B,MAAA,IAAI,CAAC,OAAA,EAAS,MAAA,CAAO,IAAA,CAAK,gBAAgB,CAAA;AAC1C,MAAA,IAAI,CAAC,KAAA,EAAO,MAAA,CAAO,IAAA,CAAK,0CAA0C,CAAA;AAClE,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,8BAAA;AAAA,UACA,QAAA;AAAA,UACA,kBAAkB,OAAO,CAAA,cAAA,EAAiB,MAAA,CAAO,IAAA,CAAK,OAAO,CAAC,CAAA,8DAAA;AAAA;AAC/D,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,gBAAgB,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,YAAY,CAAC,CAAA;AAE7B,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,kCAAA;AAAA,QACA,MAAA;AAAA,QACA,kBAAkB,UAAU,CAAA,+NAAA;AAAA;AAC7B,KACD;AAAA,EACD,CAAA,MAAO;AACN,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,iCAAA;AAAA,QACA,MAAA;AAAA,QACA,qEAAqE,OAAO,CAAA;AAAA;AAC7E,KACD;AAAA,EACD;AAGA,EAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAA,IAAK,OAAA,CAAQ,WAAA,EAAY,CAAE,QAAA,CAAS,MAAM,CAAA,EAAG;AACtG,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,wBAAA;AAAA,QACA,MAAA;AAAA,QACA,uCAAuC,UAAU,CAAA,uCAAA;AAAA;AAClD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,QAAQ,QAAQ,CAAA;AACzC;;;ACjIA,QAAA,EAAA;AAGA,YAAA,EAAA;AAMA,eAAsB,WAAA,CAAY,QAAgB,UAAA,EAAoD;AACrG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,YAAA,GAAe,cAAc,MAAM,CAAA,CAAA;AACzC,EAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,YAAA,EAAc,UAAU,CAAA;AAEjE,EAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,YAAY,CAAC,CAAA;AAEvF,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC/B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,yBAAA;AAAA,QACA,KAAA;AAAA,QACA,2CAA2C,YAAY,CAAA,wKAAA;AAAA;AACxD,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAAA,EAC3C;AAEA,EAAA,IAAI,aAAA,CAAc,SAAS,CAAA,EAAG;AAC7B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,0BAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,MAAA,EAAS,aAAA,CAAc,MAAM,CAAA,oBAAA,EAAuB,YAAY,CAAA,wDAAA;AAAA;AACjE,KACD;AAAA,EACD;AAEA,EAAA,MAAM,MAAA,GAAS,cAAc,CAAC,CAAA;AAG9B,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,KAAA,CAAM,kBAAkB,CAAA;AAChD,EAAA,IAAI,CAAC,QAAA,EAAU;AACd,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,sCAAA;AAAA,QACA,QAAA;AAAA,QACA,qBAAqB,YAAY,CAAA,uHAAA;AAAA;AAClC,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,QAAA,GAAW,SAAS,CAAC,CAAA;AAE3B,EAAA,MAAM,IAAA,GAAO,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA;AACpD,EAAA,MAAM,cAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACvB,IAAA,IAAI,CAAC,GAAA,CAAI,WAAA,EAAY,CAAE,UAAA,CAAW,SAAS,CAAA,IAAK,CAAC,GAAA,CAAI,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAA,EAAG;AAC1F,MAAA,WAAA,CAAY,KAAK,GAAG,CAAA;AAAA,IACrB;AAAA,EACD;AAEA,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC3B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,sCAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,6CAAA,EAAgD,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,+DAAA;AAAA;AACvE,KACD;AAAA,EACD;AAGA,EAAA,IAAI,WAAA,CAAY,MAAA,KAAW,CAAA,IAAK,aAAA,CAAc,UAAU,CAAA,EAAG;AAC1D,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,QAAA;AAAA,QACA,2BAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,uCAAA,EAA0C,YAAY,CAAA,EAAA,EAAK,MAAA,CAAO,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA,EAAG,MAAA,CAAO,MAAA,GAAS,GAAA,GAAM,QAAQ,EAAE,CAAA;AAAA;AACvH,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAC3C;;;ACzFA,QAAA,EAAA;AAGA,YAAA,EAAA;;;ACHA,WAAA,EAAA;AAGA,IAAM,eAAA,GAA4C;AAAA,EACjD,CAAA,EAAG,CAAC,GAAA,EAAK,GAAG,CAAA;AAAA,EACZ,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAG,CAAA;AAAA,EACZ,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAChC,GAAG,CAAC,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EAC3B,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AAAA,EACjB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AAAA,EACjB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAAA,EACtB,CAAA,EAAG,CAAC,GAAA,EAAK,GAAA,EAAK,GAAG;AAClB,CAAA;AAGA,IAAM,UAAA,GAAsC;AAAA,EAC3C,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,KAAK,GAAG,CAAA;AAAA,EACT,CAAC,MAAM,GAAG,CAAA;AAAA,EACV,CAAC,KAAK,IAAI,CAAA;AAAA,EACV,CAAC,MAAM,GAAG,CAAA;AAAA,EACV,CAAC,KAAK,IAAI;AACX,CAAA;AAGA,IAAM,SAAA,GAAqC;AAAA,EAC1C,CAAC,QAAQ,KAAK,CAAA;AAAA,EACd,CAAC,QAAQ,MAAM,CAAA;AAAA,EACf,CAAC,QAAQ,MAAM,CAAA;AAAA,EACf,CAAC,QAAQ,KAAK,CAAA;AAAA,EACd,CAAC,UAAU,MAAM,CAAA;AAAA,EACjB,CAAC,WAAW,MAAM;AACnB,CAAA;AAGA,IAAM,gBAAA,GAAmB,EAAA;AAMzB,SAAS,eAAe,MAAA,EAA+C;AACtE,EAAA,MAAM,gBAAgB,CAAC,QAAA,EAAU,WAAW,QAAA,EAAU,SAAA,EAAW,WAAW,SAAS,CAAA;AACrF,EAAA,KAAA,MAAW,YAAY,aAAA,EAAe;AACrC,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC9B,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG,GAAA,EAAK,QAAA,EAAS;AAAA,IACjE;AAAA,EACD;AACA,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,WAAA,CAAY,GAAG,CAAA;AACtC,EAAA,IAAI,YAAY,EAAA,EAAI,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAK,EAAA,EAAG;AACnD,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,OAAO,CAAA,EAAG,GAAA,EAAK,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,EAAE;AACrE;AAMA,SAAS,cAAc,MAAA,EAAyB;AAC/C,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,iBAAA,EAAmB,OAAO,KAAA;AAC9C,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC/B,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,KAAA;AAC9B,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,MAAM,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,MAAA,GAAS,kBAAkB,OAAO,KAAA;AAClE,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,KAAK,GAAG,OAAO,KAAA;AAAA,EACtC;AACA,EAAA,OAAO,IAAA;AACR;AASO,SAAS,mBAAmB,MAAA,EAA0B;AAC5D,EAAA,MAAM,gBAAA,GAAmB,OAAO,WAAA,EAAY;AAC5C,EAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAI,GAAI,eAAe,gBAAgB,CAAA;AACrD,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAY;AAGnC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,EAAA,GAAK,KAAK,CAAC,CAAA;AACjB,IAAA,MAAM,QAAA,GAAW,gBAAgB,EAAE,CAAA;AACnC,IAAA,IAAI,QAAA,EAAU;AACb,MAAA,KAAA,MAAW,OAAO,QAAA,EAAU;AAC3B,QAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,IAAI,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA;AAC1D,QAAA,UAAA,CAAW,GAAA,CAAI,WAAW,GAAG,CAAA;AAAA,MAC9B;AAAA,IACD;AAAA,EACD;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,QAAA,GAAW,KAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA;AACpD,IAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACxB,MAAA,UAAA,CAAW,GAAA,CAAI,WAAW,GAAG,CAAA;AAAA,IAC9B;AAAA,EACD;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA,GAAI,KAAK,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAI,CAAC,CAAA;AACxE,IAAA,UAAA,CAAW,GAAA,CAAI,WAAW,GAAG,CAAA;AAAA,EAC9B;AAGA,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,QAAQ,CAAA,EAAA,EAAK;AACrC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAC5B,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAC1B,IAAA,IAAI,IAAA,CAAK,MAAA,IAAU,CAAA,IAAK,KAAA,CAAM,UAAU,CAAA,EAAG;AAC1C,MAAA,UAAA,CAAW,GAAA,CAAI,IAAA,GAAO,GAAA,GAAM,KAAA,GAAQ,GAAG,CAAA;AAAA,IACxC;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,KAAK,CAAA,IAAK,SAAA,EAAW;AACzC,IAAA,IAAI,QAAQ,OAAA,EAAS;AACpB,MAAA,UAAA,CAAW,GAAA,CAAI,OAAO,KAAK,CAAA;AAAA,IAC5B,CAAA,MAAA,IAAW,QAAQ,KAAA,EAAO;AACzB,MAAA,UAAA,CAAW,GAAA,CAAI,OAAO,OAAO,CAAA;AAAA,IAC9B;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,EAAE,CAAA,IAAK,UAAA,EAAY;AACpC,IAAA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAA,OAAO,SAAA,IAAa,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,MAAA,EAAQ;AAC9C,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,SAAS,CAAA;AACxC,MAAA,IAAI,QAAQ,EAAA,EAAI;AAChB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA,GAAI,EAAA,GAAK,IAAA,CAAK,KAAA,CAAM,GAAA,GAAM,IAAA,CAAK,MAAM,CAAA;AACvE,MAAA,UAAA,CAAW,GAAA,CAAI,WAAW,GAAG,CAAA;AAC7B,MAAA,SAAA,GAAY,GAAA,GAAM,CAAA;AAAA,IACnB;AAAA,EACD;AAGA,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,IAAA,CAAK,UAAU,EACnC,MAAA,CAAO,CAAC,SAAA,KAAc,SAAA,KAAc,gBAAA,IAAoB,aAAA,CAAc,SAAS,CAAC,EAChF,IAAA,EAAK;AAEP,EAAA,OAAO,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,gBAAgB,CAAA;AACzC;;;AD/JO,IAAM,kBAAA,GAAqB,EAAA;AAC3B,IAAM,cAAA,GAAiB,CAAA;AACvB,IAAM,gBAAA,GAAmB,GAAA;AACzB,IAAM,iBAAA,GAAoB,CAAA;AAGjC,IAAM,oBAAA,GAAuB,GAAA;AAGtB,IAAM,qBAAA,GAAwB,cAAA;AAG9B,IAAM,eAAA,GAAmC;AAAA,EAC/C,SAAA,EAAW,GAAA;AAAA,EACX,OAAA,EAAS,CAAA;AAAA,EACT,yBAAA,EAA2B;AAC5B,CAAA;AAYA,SAAS,eAAe,IAAA,EAAuB;AAE9C,EAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,EAAA,OAAO,OAAA,KAAY,SAAS,OAAA,KAAY,KAAA;AACzC;AAMA,eAAe,eAAe,MAAA,EAA0C;AACvE,EAAA,MAAM,CAAC,QAAA,EAAU,SAAS,CAAA,GAAI,MAAM,QAAQ,UAAA,CAAW;AAAA,IACtD,eAAA,CAAgB,QAAQ,GAAG,CAAA;AAAA,IAC3B,eAAA,CAAgB,QAAQ,IAAI;AAAA,GAC5B,CAAA;AAED,EAAA,MAAM,aAAA,GACL,UAAU,MAAA,KAAW,WAAA,GAAc,UAAU,KAAA,CAAM,MAAA,CAAO,cAAc,CAAA,GAAI,EAAC;AAE9E,EAAA,OAAO;AAAA,IACN,MAAA;AAAA,IACA,MAAM,QAAA,CAAS,MAAA,KAAW,WAAA,IAAe,QAAA,CAAS,MAAM,MAAA,GAAS,CAAA;AAAA,IACjE,KAAA,EAAO,cAAc,MAAA,GAAS;AAAA,GAC/B;AACD;AAKA,SAAS,WAAW,MAAA,EAAwB;AAC3C,EAAA,OAAO,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,CAAE,MAAA;AAC1B;AAMA,SAAS,gBAAgB,MAAA,EAAwB;AAChD,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AAC/B;AAMA,eAAe,sBAAsB,aAAA,EAA+C;AACnF,EAAA,MAAM,eAAA,uBAAsB,GAAA,EAAY;AACxC,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,GAAA,CAAI,OAAO,MAAA,KAAW;AAClD,IAAA,IAAI;AACH,MAAA,MAAM,MAAA,GAAS,CAAA,EAAG,qBAAqB,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,MAAA,EAAQ,GAAG,CAAA;AACjD,MAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvB,QAAA,eAAA,CAAgB,IAAI,MAAM,CAAA;AAAA,MAC3B;AAAA,IACD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACD,CAAC,CAAA;AACD,EAAA,MAAM,OAAA,CAAQ,WAAW,MAAM,CAAA;AAC/B,EAAA,OAAO,eAAA;AACR;AAMA,eAAe,oBAAoB,OAAA,EAAsC;AACxE,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA;AAAA,IAC7B,OAAA,CAAQ,GAAA,CAAI,OAAO,MAAA,KAAW;AAC7B,MAAA,MAAM,EAAA,GAAK,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAM,eAAe,CAAA;AAC9D,MAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,EAAA,CAAG,SAAS,CAAA,EAAE;AAAA,IACvC,CAAC;AAAA,GACF;AACA,EAAA,OAAO,OAAA,CACL,MAAA;AAAA,IACA,CAAC,CAAA,KACA,CAAA,CAAE,MAAA,KAAW,WAAA,IAAe,EAAE,KAAA,CAAM;AAAA,IAErC,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,MAAM,CAAA;AAC5B;AAOA,eAAe,0BACd,YAAA,EACmD;AACnD,EAAA,MAAM,aAAsD,EAAC;AAC7D,EAAA,IAAI,SAAA,GAAY,kBAAA;AAChB,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,MAAA,EAAQ,KAAK,SAAA,EAAW;AACxD,IAAA,IAAI,UAAU,CAAA,EAAG;AAChB,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAC5D;AAEA,IAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA;AACjD,IAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,UAAA,CAAW,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,cAAA,CAAe,CAAC,CAAC,CAAC,CAAA;AACjF,IAAA,UAAA,CAAW,IAAA,CAAK,GAAG,YAAY,CAAA;AAG/B,IAAA,MAAM,QAAA,GAAW,aAAa,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,UAAU,CAAA,CAAE,MAAA;AACrE,IAAA,IAAI,WAAW,iBAAA,EAAmB;AAEjC,MAAA,SAAA,GAAY,KAAK,GAAA,CAAI,cAAA,EAAgB,KAAK,KAAA,CAAM,SAAA,GAAY,CAAC,CAAC,CAAA;AAC9D,MAAA,OAAA,GAAU,gBAAA;AAAA,IACX,CAAA,MAAA,IAAW,OAAA,GAAU,CAAA,IAAK,QAAA,KAAa,CAAA,EAAG;AAEzC,MAAA,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,SAAA,GAAY,CAAC,CAAA;AACtD,MAAA,OAAA,GAAU,CAAA;AAAA,IACX;AAAA,EACD;AAEA,EAAA,OAAO,UAAA;AACR;AAOA,eAAsB,gBAAgB,MAAA,EAAsC;AAC3E,EAAA,OAAO,QAAQ,IAAA,CAAK;AAAA,IACnB,oBAAoB,MAAM,CAAA;AAAA,IAC1B,IAAI,OAAA,CAAe,CAAC,CAAA,EAAG,WAAW,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,2BAA2B,CAAC,CAAA,EAAG,oBAAoB,CAAC;AAAA,GACxH,CAAA,CAAE,KAAA,CAAM,MAAM;AACd,IAAA,OAAO,iBAAiB,YAAA,EAAc;AAAA,MACrC,aAAA;AAAA,QACC,YAAA;AAAA,QACA,4BAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACA,CAAA;AAAA,EACF,CAAC,CAAA;AACF;AAEA,eAAe,oBAAoB,MAAA,EAAsC;AACxE,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,YAAA,GAAe,mBAAmB,MAAM,CAAA;AAE9C,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,YAAA;AAAA,QACA,sCAAA;AAAA,QACA,MAAA;AAAA,QACA,2DAA2D,MAAM,CAAA,CAAA;AAAA;AAClE,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,cAAc,QAAQ,CAAA;AAAA,EAC/C;AAGA,EAAA,MAAM,kBAAA,GAAqB,WAAW,MAAM,CAAA;AAC5C,EAAA,MAAM,mBAAA,uBAA0B,GAAA,EAAsB;AACtD,EAAA,MAAM,uBAAiC,EAAC;AAExC,EAAA,KAAA,MAAW,QAAQ,YAAA,EAAc;AAChC,IAAA,IAAI,UAAA,CAAW,IAAI,CAAA,GAAI,kBAAA,EAAoB;AAC1C,MAAA,MAAM,MAAA,GAAS,gBAAgB,IAAI,CAAA;AACnC,MAAA,MAAM,QAAA,GAAW,mBAAA,CAAoB,GAAA,CAAI,MAAM,CAAA;AAC/C,MAAA,IAAI,QAAA,EAAU;AACb,QAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,MACnB,CAAA,MAAO;AACN,QAAA,mBAAA,CAAoB,GAAA,CAAI,MAAA,EAAQ,CAAC,IAAI,CAAC,CAAA;AAAA,MACvC;AAAA,IACD,CAAA,MAAO;AACN,MAAA,oBAAA,CAAqB,KAAK,IAAI,CAAA;AAAA,IAC/B;AAAA,EACD;AAGA,EAAA,MAAM,eAAA,GAAkB,mBAAA,CAAoB,IAAA,GAAO,CAAA,GAChD,MAAM,qBAAA,CAAsB,CAAC,GAAG,mBAAA,CAAoB,IAAA,EAAM,CAAC,CAAA,uBACvD,GAAA,EAAY;AAGnB,EAAA,MAAM,4BAAsC,EAAC;AAC7C,EAAA,KAAA,MAAW,CAAC,MAAA,EAAQ,KAAK,CAAA,IAAK,mBAAA,EAAqB;AAClD,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,CAAI,MAAM,CAAA,EAAG;AACjC,MAAA,yBAAA,CAA0B,IAAA,CAAK,GAAG,KAAK,CAAA;AAAA,IACxC;AAAA,EACD;AAEA,EAAA,MAAM,YAAA,GAAe,CAAC,GAAG,oBAAA,EAAsB,GAAG,yBAAyB,CAAA;AAG3E,EAAA,MAAM,eAAA,GAAkB,MAAM,mBAAA,CAAoB,YAAY,CAAA;AAE9D,EAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AACjC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,YAAA;AAAA,QACA,sCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,QAAA,EAAW,YAAA,CAAa,MAAM,CAAA,wBAAA,EAA2B,MAAM,CAAA,mCAAA;AAAA;AAChE,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,cAAc,QAAQ,CAAA;AAAA,EAC/C;AAGA,EAAA,MAAM,YAAA,GAAe,MAAM,yBAAA,CAA0B,eAAe,CAAA;AACpE,EAAA,MAAM,UAA6B,EAAC;AACpC,EAAA,KAAA,MAAW,UAAU,YAAA,EAAc;AAClC,IAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AAClC,MAAA,OAAA,CAAQ,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,IAC1B;AAAA,EACD;AAGA,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,IAAI,OAAO,KAAA,EAAO;AACjB,MAAA,SAAA,EAAA;AACA,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,YAAA;AAAA,UACA,CAAA,2CAAA,EAA8C,OAAO,MAAM,CAAA,CAAA;AAAA,UAC3D,MAAA;AAAA,UACA,CAAA,WAAA,EAAc,MAAA,CAAO,MAAM,CAAA,mHAAA,EAAsH,MAAM,CAAA,CAAA,CAAA;AAAA,UACvJ,EAAE,iBAAiB,MAAA,CAAO,MAAA,EAAQ,MAAM,MAAA,CAAO,IAAA,EAAM,KAAA,EAAO,MAAA,CAAO,KAAA;AAAM;AAC1E,OACD;AAAA,IACD,CAAA,MAAA,IAAW,OAAO,IAAA,EAAM;AACvB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,YAAA;AAAA,UACA,CAAA,6BAAA,EAAgC,OAAO,MAAM,CAAA,CAAA;AAAA,UAC7C,QAAA;AAAA,UACA,CAAA,WAAA,EAAc,MAAA,CAAO,MAAM,CAAA,8HAAA,EAAiI,MAAM,CAAA,CAAA,CAAA;AAAA,UAClK,EAAE,iBAAiB,MAAA,CAAO,MAAA,EAAQ,MAAM,MAAA,CAAO,IAAA,EAAM,KAAA,EAAO,MAAA,CAAO,KAAA;AAAM;AAC1E,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,YAAY,CAAA,EAAG;AAClB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,YAAA;AAAA,QACA,GAAG,SAAS,CAAA,iBAAA,EAAoB,SAAA,GAAY,CAAA,GAAI,MAAM,EAAE,CAAA,8BAAA,CAAA;AAAA,QACxD,MAAA;AAAA,QACA,CAAA,EAAG,SAAS,CAAA,iBAAA,EAAoB,SAAA,GAAY,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA,IAAA,EAAO,MAAM,CAAA,CAAA,EAAI,SAAA,GAAY,CAAA,GAAI,SAAS,KAAK,CAAA,sJAAA,CAAA;AAAA,QACvG,EAAE,sBAAsB,SAAA;AAAU;AACnC,KACD;AAAA,EACD;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,YAAA;AAAA,QACA,sCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,QAAA,EAAW,YAAA,CAAa,MAAM,CAAA,wBAAA,EAA2B,MAAM,CAAA,mEAAA;AAAA;AAChE,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,cAAc,QAAQ,CAAA;AAC/C;;;AE/SA,QAAA,EAAA;AAGA,YAAA,EAAA;;;ACHA,IAAM,oBAAA,uBAA2B,GAAA,CAAI;AAAA;AAAA,EAEpC,OAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAEA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,QAAA;AAAA,EACA,QAAA;AAAA,EACA;AACD,CAAC,CAAA;AAaM,SAAS,gBAAgB,MAAA,EAA+B;AAC9D,EAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAGpB,EAAA,MAAM,UAAA,GAAa,OAAO,QAAA,CAAS,GAAG,IAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,MAAA;AAChE,EAAA,IAAI,CAAC,YAAY,OAAO,IAAA;AAExB,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,WAAA,EAAY,CAAE,MAAM,GAAG,CAAA;AACjD,EAAA,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAI9B,EAAA,IAAI,YAAA,GAA8B,IAAA;AAElC,EAAA,KAAA,IAAS,IAAI,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC5C,IAAA,MAAM,YAAY,MAAA,CAAO,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AAC1C,IAAA,IAAI,oBAAA,CAAqB,GAAA,CAAI,SAAS,CAAA,EAAG;AACxC,MAAA,YAAA,GAAe,SAAA;AAAA,IAEhB,CAAA,MAAO;AAEN,MAAA;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,YAAA,EAAc;AAClB,IAAA,YAAA,GAAe,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AAAA,EACxC;AAGA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AACxC,EAAA,IAAI,SAAA,CAAU,MAAA,IAAU,MAAA,CAAO,MAAA,EAAQ;AAEtC,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,OAAO,YAAA;AACR;AAeO,SAAS,iBAAiB,MAAA,EAA+B;AAC/D,EAAA,MAAM,GAAA,GAAM,gBAAgB,MAAM,CAAA;AAClC,EAAA,IAAI,CAAC,KAAK,OAAO,IAAA;AAGjB,EAAA,MAAM,UAAA,GAAa,OAAO,QAAA,CAAS,GAAG,IAAI,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,MAAA;AAChE,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,WAAA,EAAY,CAAE,MAAM,GAAG,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAG/B,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,GAAS,SAAA,CAAU,MAAA,GAAS,CAAA;AACtD,EAAA,IAAI,UAAA,GAAa,GAAG,OAAO,IAAA;AAE3B,EAAA,OAAO,OAAO,UAAU,CAAA;AACzB;;;ADlHA,IAAM,iBAAA,GAAoB,GAAA;AAG1B,IAAMC,mBAAAA,GAAqB,CAAA;AAC3B,IAAMC,eAAAA,GAAiB,CAAA;AACvB,IAAMC,iBAAAA,GAAmB,GAAA;AAElB,IAAMC,kBAAAA,GAAoB,CAAA;AAG1B,IAAMC,gBAAAA,GAAmC;AAAA,EAC/C,SAAA,EAAW,GAAA;AAAA,EACX,OAAA,EAAS,CAAA;AAAA,EACT,yBAAA,EAA2B;AAC5B,CAAA;AAGA,IAAM,WAAA,GAAc;AAAA,EACnB,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,MAAA;AAAA,EAAQ,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EACtC,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,QAAA;AAAA,EAAU,SAAA;AAAA,EACtC,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO;AAC7B,CAAA;AAGA,IAAM,WAAA,GAAc,CAAC,KAAA,EAAO,QAAA,EAAU,SAAA,EAAW,WAAW,UAAA,EAAY,QAAA,EAAU,YAAA,EAAc,SAAA,EAAW,OAAO,CAAA;AAClH,IAAM,WAAA,GAAc,CAAC,QAAA,EAAU,SAAA,EAAW,KAAK,CAAA;AAC/C,IAAM,WAAA,GAAc,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,SAAS,CAAA;AAC/D,IAAM,aAAA,GAAgB,CAAC,MAAA,EAAQ,MAAM,CAAA;AAGrC,IAAM,YAAA,mBAAe,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,KAAK,CAAC,CAAA;AAgBnF,SAAS,gBAAA,CAAiB,KAAA,EAAe,YAAA,EAAsB,aAAA,EAAiC;AACtG,EAAA,MAAM,MAAA,GAAS,aAAa,WAAA,EAAY;AAGxC,EAAA,MAAM,WAAW,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA,GAAI,SAAS,GAAA,GAAM,MAAA;AACzD,EAAA,MAAM,YAAA,GAAe,cAAc,WAAA,EAAY;AAC/C,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAGhC,EAAA,KAAA,MAAW,OAAO,WAAA,EAAa;AAC9B,IAAA,OAAA,CAAQ,IAAI,GAAG,CAAA;AAAA,EAChB;AAGA,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,IAAK,aAAa,OAAA,EAAS;AACrD,IAAA,KAAA,MAAW,GAAA,IAAO,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EAC/C,WAAW,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,SAAA,IAAa,aAAa,KAAA,EAAO;AACjF,IAAA,KAAA,MAAW,GAAA,IAAO,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EAC/C,CAAA,MAAA,IAAW,QAAA,CAAS,QAAA,CAAS,KAAK,CAAA,EAAG;AACpC,IAAA,KAAA,MAAW,GAAA,IAAO,WAAA,EAAa,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EAC/C,CAAA,MAAA,IAAW,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA,EAAG;AACtC,IAAA,KAAA,MAAW,GAAA,IAAO,aAAA,EAAe,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,OAAO,OAAA,EAAS;AAC1B,IAAA,MAAM,SAAA,GAAY,CAAA,EAAG,KAAK,CAAA,EAAG,GAAG,CAAA,CAAA;AAChC,IAAA,IAAI,SAAA,CAAU,WAAA,EAAY,KAAM,YAAA,EAAc;AAE9C,IAAA,MAAM,UAAA,GAAa,eAAe,SAAS,CAAA;AAC3C,IAAA,IAAI,WAAW,KAAA,EAAO;AACrB,MAAA,QAAA,CAAS,KAAK,SAAS,CAAA;AAAA,IACxB;AAAA,EACD;AAEA,EAAA,OAAO,SAAS,IAAA,EAAK;AACtB;AAMA,eAAe,YAAA,CACd,OAAA,EACA,OAAA,EACA,YAAA,EAC8B;AAC9B,EAAA,MAAM,SAAA,GACL,YAAA,KAAiB,MAAA,GAAY,OAAA,CAAQ,OAAA,CAAQ,YAAY,CAAA,GAAI,eAAA,CAAgB,OAAA,EAAS,IAAA,EAAM,OAAO,CAAA;AAEpG,EAAA,MAAM,CAAC,UAAU,OAAA,EAAS,QAAA,EAAU,WAAW,WAAW,CAAA,GAAI,MAAM,OAAA,CAAQ,UAAA,CAAW;AAAA,IACtF,SAAA;AAAA,IACA,eAAA,CAAgB,OAAA,EAAS,GAAA,EAAK,OAAO,CAAA;AAAA,IACrC,cAAA,CAAe,SAAS,OAAO,CAAA;AAAA,IAC/B,eAAA,CAAgB,SAAS,OAAO,CAAA;AAAA,IAChC,eAAA,CAAgB,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAI,OAAO;AAAA,GAC5C,CAAA;AAED,EAAA,MAAM,KAAK,QAAA,CAAS,MAAA,KAAW,WAAA,GAAc,QAAA,CAAS,QAAQ,EAAC;AAC/D,EAAA,MAAM,OAAO,OAAA,CAAQ,MAAA,KAAW,WAAA,IAAe,OAAA,CAAQ,MAAM,MAAA,GAAS,CAAA;AACtE,EAAA,MAAM,EAAA,GAAK,QAAA,CAAS,MAAA,KAAW,WAAA,GAAc,QAAA,CAAS,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAA,GAAI,EAAC;AAGtF,EAAA,MAAM,YAAY,SAAA,CAAU,MAAA,KAAW,WAAA,GAAc,SAAA,CAAU,QAAQ,EAAC;AACxE,EAAA,MAAM,MAAA,GAAS,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,QAAQ,CAAC,CAAA;AAGzE,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,MAAM,cAAc,WAAA,CAAY,MAAA,KAAW,WAAA,GAAc,WAAA,CAAY,QAAQ,EAAC;AAC9E,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AAClF,EAAA,IAAI,WAAA,EAAa;AAChB,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,KAAA,CAAM,kBAAkB,CAAA;AACnD,IAAA,WAAA,GAAc,MAAA,GAAS,MAAA,CAAO,CAAC,CAAA,CAAE,aAAY,GAAI,MAAA;AAAA,EAClD;AAEA,EAAA,OAAO,EAAE,OAAA,EAAS,EAAA,EAAI,IAAA,EAAM,EAAA,EAAI,QAAQ,WAAA,EAAY;AACrD;AAMA,eAAeC,oBAAAA,CACd,UACA,OAAA,EACiC;AACjC,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAsB;AAC7C,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA;AAAA,IAC7B,QAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KAAY;AAC/B,MAAA,MAAM,EAAA,GAAK,MAAM,eAAA,CAAgB,OAAA,EAAS,IAAA,EAAM,EAAE,GAAG,OAAA,EAAS,GAAGD,gBAAAA,EAAiB,CAAA;AAClF,MAAA,OAAO,EAAE,SAAS,EAAA,EAAG;AAAA,IACtB,CAAC;AAAA,GACF;AACA,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,IAAI,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,KAAA,CAAM,EAAA,CAAG,SAAS,CAAA,EAAG;AAChE,MAAA,UAAA,CAAW,IAAI,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,MAAA,CAAO,MAAM,EAAE,CAAA;AAAA,IACrD;AAAA,EACD;AACA,EAAA,OAAO,UAAA;AACR;AAMA,SAAS,aAAA,CAAc,WAAqB,SAAA,EAA8B;AACzE,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,KAAA;AACnC,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,SAAA,CAAU,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAC,CAAA;AACnF,EAAA,OAAO,SAAA,CAAU,KAAA,CAAM,CAAC,CAAA,KAAM,UAAA,CAAW,GAAA,CAAI,CAAA,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAC,CAAA;AACjF;AAKA,SAAS,eAAA,CAAgB,OAA2B,SAAA,EAA8B;AACjF,EAAA,MAAM,EAAE,OAAA,EAAS,EAAA,EAAI,EAAA,EAAI,MAAA,EAAQ,aAAY,GAAI,KAAA;AACjD,EAAA,MAAM,KAAA,GAAQ,GAAG,MAAA,GAAS,CAAA;AAC1B,EAAA,MAAM,KAAA,GAAQ,GAAG,MAAA,GAAS,CAAA;AAC1B,EAAA,MAAM,OAAO,EAAE,OAAA,EAAS,EAAA,EAAI,EAAA,EAAI,QAAQ,WAAA,EAAY;AAEpD,EAAA,IAAI,KAAA,EAAO;AACV,IAAA,IAAI,CAAC,MAAA,IAAU,WAAA,KAAgB,IAAA,EAAM;AAEpC,MAAA,OAAO,aAAA;AAAA,QACN,gBAAA;AAAA,QACA,+BAAA;AAAA,QACA,UAAA;AAAA,QACA,GAAG,OAAO,CAAA,2FAAA,CAAA;AAAA,QACV;AAAA,OACD;AAAA,IACD;AAEA,IAAA,IAAI,MAAA,IAAU,gBAAgB,IAAA,EAAM;AAEnC,MAAA,OAAO,aAAA;AAAA,QACN,gBAAA;AAAA,QACA,2BAAA;AAAA,QACA,MAAA;AAAA,QACA,GAAG,OAAO,CAAA,gGAAA,CAAA;AAAA,QACV;AAAA,OACD;AAAA,IACD;AAEA,IAAA,IAAI,gBAAgB,MAAA,EAAQ;AAE3B,MAAA,OAAO,aAAA;AAAA,QACN,gBAAA;AAAA,QACA,mCAAA;AAAA,QACA,MAAA;AAAA,QACA,GAAG,OAAO,CAAA,sGAAA,CAAA;AAAA,QACV;AAAA,OACD;AAAA,IACD;AAGA,IAAA,IAAI,WAAA,KAAgB,YAAA,IAAgB,WAAA,KAAgB,QAAA,EAAU;AAC7D,MAAA,IAAI,CAAC,aAAA,CAAc,EAAA,EAAI,SAAS,CAAA,EAAG;AAElC,QAAA,OAAO,aAAA;AAAA,UACN,gBAAA;AAAA,UACA,6CAAA;AAAA,UACA,QAAA;AAAA,UACA,GAAG,OAAO,CAAA,2HAAA,CAAA;AAAA,UACV;AAAA,SACD;AAAA,MACD;AAGA,MAAA,OAAO,aAAA;AAAA,QACN,gBAAA;AAAA,QACA,4BAAA;AAAA,QACA,KAAA;AAAA,QACA,GAAG,OAAO,CAAA,4FAAA,CAAA;AAAA,QACV;AAAA,OACD;AAAA,IACD;AAGA,IAAA,IAAI,CAAC,aAAA,CAAc,EAAA,EAAI,SAAS,CAAA,EAAG;AAClC,MAAA,OAAO,aAAA;AAAA,QACN,gBAAA;AAAA,QACA,6CAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAG,OAAO,CAAA,qDAAA,CAAA;AAAA,QACV;AAAA,OACD;AAAA,IACD;AAEA,IAAA,OAAO,aAAA;AAAA,MACN,gBAAA;AAAA,MACA,4BAAA;AAAA,MACA,KAAA;AAAA,MACA,GAAG,OAAO,CAAA,uDAAA,CAAA;AAAA,MACV;AAAA,KACD;AAAA,EACD;AAEA,EAAA,IAAI,KAAA,EAAO;AAEV,IAAA,OAAO,aAAA;AAAA,MACN,gBAAA;AAAA,MACA,mCAAA;AAAA,MACA,MAAA;AAAA,MACA,GAAG,OAAO,CAAA,0EAAA,CAAA;AAAA,MACV;AAAA,KACD;AAAA,EACD;AAGA,EAAA,OAAO,aAAA;AAAA,IACN,gBAAA;AAAA,IACA,4BAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAG,OAAO,CAAA,0FAAA,CAAA;AAAA,IACV;AAAA,GACD;AACD;AAMA,SAAS,eAAe,MAAA,EAAyC;AAChE,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAsB;AAExC,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC3B,IAAA,IAAI,KAAA,CAAM,EAAA,CAAG,MAAA,GAAS,CAAA,EAAG;AACzB,IAAA,MAAM,QAAQ,KAAA,CAAM,EAAA,CAClB,GAAA,CAAI,CAAC,MAAM,CAAA,CAAE,WAAA,EAAY,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAC,EAC7C,IAAA,EAAK,CACL,KAAK,GAAG,CAAA;AACV,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,GAAA,CAAI,KAAK,CAAA;AAChC,IAAA,IAAI,QAAA,EAAU;AACb,MAAA,QAAA,CAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC5B,CAAA,MAAO;AACN,MAAA,KAAA,CAAM,GAAA,CAAI,KAAA,EAAO,CAAC,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,IACjC;AAAA,EACD;AAEA,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,QAAQ,CAAA,IAAK,KAAA,EAAO;AACtC,IAAA,IAAI,QAAA,CAAS,UAAU,CAAA,EAAG;AACzB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,gBAAA;AAAA,UACA,iCAAA;AAAA,UACA,MAAA;AAAA,UACA,GAAG,QAAA,CAAS,IAAA,CAAK,IAAI,CAAC,oCAAoC,KAAK,CAAA,4CAAA,CAAA;AAAA,UAC/D,EAAE,QAAA,EAAU,WAAA,EAAa,KAAA;AAAM;AAChC,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAGA,IAAM,cAAA,GAAyC;AAAA,EAC9C,QAAA,EAAU,CAAA;AAAA,EACV,IAAA,EAAM,CAAA;AAAA,EACN,MAAA,EAAQ,CAAA;AAAA,EACR,GAAA,EAAK,CAAA;AAAA,EACL,IAAA,EAAM;AACP,CAAA;AAOA,eAAsB,kBAAA,CAAmB,QAAgB,UAAA,EAAoD;AAC5G,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,MAAM,WAAW,SAAA,GAAY,iBAAA;AAE7B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,MAAM,CAAA;AACrC,EAAA,MAAM,YAAA,GAAe,gBAAgB,MAAM,CAAA;AAE3C,EAAA,IAAI,CAAC,KAAA,IAAS,CAAC,YAAA,EAAc;AAC5B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,gBAAA;AAAA,QACA,8BAAA;AAAA,QACA,MAAA;AAAA,QACA,yDAAyD,MAAM,CAAA,GAAA;AAAA;AAChE,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,kBAAkB,QAAQ,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,KAAA,EAAO,YAAA,EAAc,MAAM,CAAA;AAE7D,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,gBAAA;AAAA,QACA,qCAAA;AAAA,QACA,MAAA;AAAA,QACA,oDAAoD,MAAM,CAAA,CAAA;AAAA;AAC3D,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,kBAAkB,QAAQ,CAAA;AAAA,EACnD;AAGA,EAAA,MAAM,OAAA,GAA2B,EAAE,GAAG,UAAA,EAAY,2BAA2B,IAAA,EAAK;AAClF,EAAA,IAAI,YAAsB,EAAC;AAC3B,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,MAAA,EAAQ,OAAO,CAAA;AACrD,IAAA,SAAA,GAAY,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAAA,EAC3C,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,MAAM,kBAAA,GAAqB,MAAMC,oBAAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AAGtE,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC/B,IAAA,IAAI,CAAC,kBAAA,CAAmB,GAAA,CAAI,OAAO,CAAA,EAAG;AACrC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,gBAAA;AAAA,UACA,4BAAA;AAAA,UACA,MAAA;AAAA,UACA,GAAG,OAAO,CAAA,0FAAA,CAAA;AAAA,UACV,EAAE,OAAA,EAAS,EAAA,EAAI,EAAC,EAAG,EAAA,EAAI,EAAC,EAAG,MAAA,EAAQ,KAAA,EAAO,WAAA,EAAa,IAAA;AAAK;AAC7D,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,cAAA,GAAiB,CAAC,GAAG,kBAAA,CAAmB,SAAS,CAAA;AACvD,EAAA,IAAI,SAAA,GAAYL,mBAAAA;AAChB,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,MAAM,kBAAwC,EAAC;AAC/C,EAAA,MAAM,kBAAkB,cAAA,CAAe,MAAA;AACvC,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,cAAA,CAAe,MAAA,EAAQ,KAAK,SAAA,EAAW;AAC1D,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,IAAK,QAAA,EAAU;AAC3B,MAAA,QAAA,GAAW,IAAA;AACX,MAAA;AAAA,IACD;AAEA,IAAA,IAAI,UAAU,CAAA,EAAG;AAChB,MAAA,MAAM,IAAI,OAAA,CAAQ,CAAC,YAAY,UAAA,CAAW,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,IAC5D;AAEA,IAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA;AACnD,IAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,UAAA;AAAA,MAClC,KAAA,CAAM,GAAA,CAAI,CAAC,CAAC,OAAA,EAAS,EAAE,CAAA,KAAM,YAAA,CAAa,OAAA,EAAS,OAAA,EAAS,EAAE,CAAC;AAAA,KAChE;AAEA,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,KAAA,MAAW,UAAU,YAAA,EAAc;AAClC,MAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AAClC,QAAA,eAAA,CAAgB,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,MAClC,CAAA,MAAO;AACN,QAAA,QAAA,EAAA;AAAA,MACD;AAAA,IACD;AAGA,IAAA,IAAI,WAAWG,kBAAAA,EAAmB;AACjC,MAAA,SAAA,GAAY,KAAK,GAAA,CAAIF,eAAAA,EAAgB,KAAK,KAAA,CAAM,SAAA,GAAY,CAAC,CAAC,CAAA;AAC9D,MAAA,OAAA,GAAUC,iBAAAA;AAAA,IACX,CAAA,MAAA,IAAW,UAAU,CAAA,EAAG;AACvB,MAAA,SAAA,GAAY,IAAA,CAAK,GAAA,CAAIF,mBAAAA,EAAoB,SAAA,GAAY,CAAC,CAAA;AACtD,MAAA,OAAA,GAAU,CAAA;AAAA,IACX;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACpC,IAAA,QAAA,CAAS,IAAA,CAAK,eAAA,CAAgB,KAAA,EAAO,SAAS,CAAC,CAAA;AAAA,EAChD;AAGA,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,cAAA,CAAe,eAAe,CAAC,CAAA;AAGhD,EAAA,IAAI,QAAA,EAAU;AACb,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,gBAAA;AAAA,QACA,+BAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,qCAAA,EAAmC,eAAe,CAAA,IAAA,EAAO,QAAA,CAAS,MAAM,CAAA,uBAAA;AAAA;AACzE,KACD;AAAA,EACD;AAGA,EAAA,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAA,CAAO,cAAA,CAAe,CAAA,CAAE,QAAQ,CAAA,IAAK,CAAA,KAAM,cAAA,CAAe,CAAA,CAAE,QAAQ,KAAK,CAAA,CAAE,CAAA;AAG7F,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,gBAAA;AAAA,QACA,kCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,QAAA,EAAW,QAAA,CAAS,MAAM,CAAA,2BAAA,EAA8B,MAAM,CAAA,mCAAA;AAAA;AAC/D,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,kBAAkB,QAAQ,CAAA;AACnD;;;AE5cA,QAAA,EAAA;AAKA,YAAA,EAAA;AAaA,IAAM,qBAAA,GAA+C;AAAA;AAAA,EAEpD,EAAE,MAAA,EAAQ,2BAAA,EAA6B,OAAA,EAAS,uBAAA,EAAyB,UAAU,eAAA,EAAgB;AAAA,EACnG,EAAE,QAAQ,sBAAA,EAAwB,OAAA,EAAS,UAAU,QAAA,EAAU,eAAA,EAAiB,cAAc,IAAA,EAAK;AAAA,EACnG,EAAE,MAAA,EAAQ,gBAAA,EAAkB,OAAA,EAAS,MAAA,EAAQ,UAAU,eAAA,EAAgB;AAAA,EACvE,EAAE,QAAQ,0BAAA,EAA4B,OAAA,EAAS,SAAS,QAAA,EAAU,eAAA,EAAiB,cAAc,IAAA,EAAK;AAAA,EACtG,EAAE,MAAA,EAAQ,0BAAA,EAA4B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA;AAAA,EAGlF,EAAE,MAAA,EAAQ,KAAA,EAAO,OAAA,EAAS,eAAA,EAAiB,UAAU,eAAA,EAAgB;AAAA,EACrE,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACpF,EAAE,MAAA,EAAQ,+BAAA,EAAiC,OAAA,EAAS,UAAA,EAAY,UAAU,eAAA,EAAgB;AAAA,EAC1F,EAAE,MAAA,EAAQ,gCAAA,EAAkC,OAAA,EAAS,WAAA,EAAa,UAAU,eAAA,EAAgB;AAAA,EAC5F,EAAE,MAAA,EAAQ,8BAAA,EAAgC,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACtF,EAAE,MAAA,EAAQ,WAAA,EAAa,OAAA,EAAS,UAAA,EAAY,UAAU,eAAA,EAAgB;AAAA,EACtE,EAAE,MAAA,EAAQ,+BAAA,EAAiC,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACvF,EAAE,MAAA,EAAQ,8BAAA,EAAgC,OAAA,EAAS,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA,EAC3F,EAAE,MAAA,EAAQ,2BAAA,EAA6B,OAAA,EAAS,MAAA,EAAQ,UAAU,eAAA,EAAgB;AAAA;AAAA,EAGlF,EAAE,MAAA,EAAQ,oBAAA,EAAsB,OAAA,EAAS,MAAA,EAAQ,UAAU,eAAA,EAAgB;AAAA,EAC3E,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACpF,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACpF,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACpF,EAAE,MAAA,EAAQ,6BAAA,EAA+B,OAAA,EAAS,QAAA,EAAU,UAAU,eAAA,EAAgB;AAAA,EACtF,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,OAAA,EAAS,UAAU,eAAA,EAAgB;AAAA,EACpF,EAAE,MAAA,EAAQ,6BAAA,EAA+B,OAAA,EAAS,YAAA,EAAc,UAAU,eAAA,EAAgB;AAAA;AAAA,EAG1F,EAAE,MAAA,EAAQ,+BAAA,EAAiC,OAAA,EAAS,UAAA,EAAY,UAAU,UAAA,EAAW;AAAA,EACrF,EAAE,MAAA,EAAQ,4BAAA,EAA8B,OAAA,EAAS,SAAA,EAAW,UAAU,UAAA,EAAW;AAAA,EACjF,EAAE,MAAA,EAAQ,6BAAA,EAA+B,OAAA,EAAS,QAAA,EAAU,UAAU,UAAA,EAAW;AAAA,EACjF,EAAE,MAAA,EAAQ,kCAAA,EAAoC,OAAA,EAAS,aAAA,EAAe,UAAU,UAAA,EAAW;AAAA;AAAA,EAG3F,EAAE,MAAA,EAAQ,0CAAA,EAA4C,OAAA,EAAS,2BAAA,EAA6B,UAAU,WAAA,EAAY;AAAA,EAClH,EAAE,MAAA,EAAQ,iCAAA,EAAmC,OAAA,EAAS,SAAA,EAAW,UAAU,WAAA,EAAY;AAAA,EACvF,EAAE,MAAA,EAAQ,SAAA,EAAW,OAAA,EAAS,mBAAA,EAAqB,UAAU,WAAA,EAAY;AAAA,EACzE,EAAE,MAAA,EAAQ,gCAAA,EAAkC,OAAA,EAAS,WAAA,EAAa,UAAU,WAAA,EAAY;AAAA,EACxF,EAAE,MAAA,EAAQ,wBAAA,EAA0B,OAAA,EAAS,UAAA,EAAY,UAAU,WAAA,EAAY;AAAA;AAAA,EAG/E,EAAE,MAAA,EAAQ,qBAAA,EAAuB,OAAA,EAAS,OAAA,EAAS,UAAU,gBAAA,EAAiB;AAAA,EAC9E,EAAE,MAAA,EAAQ,0BAAA,EAA4B,OAAA,EAAS,yBAAA,EAA2B,UAAU,gBAAA,EAAiB;AAAA,EACrG,EAAE,MAAA,EAAQ,iCAAA,EAAmC,OAAA,EAAS,mBAAA,EAAqB,UAAU,gBAAA,EAAiB;AAAA,EACtG,EAAE,MAAA,EAAQ,sBAAA,EAAwB,OAAA,EAAS,QAAA,EAAU,UAAU,gBAAA,EAAiB;AAAA,EAChF,EAAE,MAAA,EAAQ,iCAAA,EAAmC,OAAA,EAAS,YAAA,EAAc,UAAU,gBAAA,EAAiB;AAAA,EAC/F,EAAE,MAAA,EAAQ,0BAAA,EAA4B,OAAA,EAAS,cAAA,EAAgB,UAAU,gBAAA,EAAiB;AAAA,EAC1F,EAAE,MAAA,EAAQ,iCAAA,EAAmC,OAAA,EAAS,cAAA,EAAgB,UAAU,gBAAA,EAAiB;AAAA,EACjG,EAAE,MAAA,EAAQ,WAAA,EAAa,OAAA,EAAS,WAAA,EAAa,UAAU,gBAAA,EAAiB;AAAA;AAAA,EAGxE,EAAE,MAAA,EAAQ,UAAA,EAAY,OAAA,EAAS,OAAA,EAAS,UAAU,YAAA;AACnD,CAAA;AAIA,IAAM,mBAAA,GAAgD;AAAA,EACrD,uBAAA,EAAyB,CAAC,iBAAA,EAAmB,YAAY,CAAA;AAAA,EACzD,eAAA,EAAiB,CAAC,4BAAA,EAA8B,aAAa,CAAA;AAAA,EAC7D,UAAA,EAAY,CAAC,cAAc,CAAA;AAAA,EAC3B,WAAA,EAAa,CAAC,iBAAA,EAAmB,eAAe,CAAA;AAAA,EAChD,SAAA,EAAW,CAAC,kBAAkB,CAAA;AAAA,EAC9B,mBAAA,EAAqB,CAAC,gBAAgB,CAAA;AAAA,EACtC,MAAA,EAAQ,CAAC,UAAA,EAAY,SAAS,CAAA;AAAA,EAC9B,WAAA,EAAa,CAAC,eAAe,CAAA;AAAA,EAC7B,SAAA,EAAW,CAAC,aAAa;AAC1B,CAAA;AAIA,IAAM,eAAA,uBAAsB,GAAA,CAAI;AAAA,EAC/B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA;AACD,CAAC,CAAA;AAED,SAAS,mBAAmB,MAAA,EAAyB;AACpD,EAAA,MAAM,GAAA,GAAM,gBAAgB,MAAM,CAAA;AAClC,EAAA,IAAI,CAAC,KAAK,OAAO,KAAA;AACjB,EAAA,OAAO,eAAA,CAAgB,IAAI,GAAG,CAAA;AAC/B;AAIA,SAAS,mBAAmB,UAAA,EAAgC;AAC3D,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,QAAQ,CAAC,CAAA;AAC7E,EAAA,IAAI,CAAC,SAAA,EAAW,OAAO,EAAC;AACxB,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,KAAA,GAAQ,mBAAA;AACd,EAAA,IAAI,KAAA;AACJ,EAAA,OAAA,CAAQ,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,SAAS,OAAO,IAAA,EAAM;AAChD,IAAA,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,CAAE,aAAa,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,QAAA;AACR;AAIA,SAAS,iBAAiB,WAAA,EAA6B;AACtD,EAAA,IAAI,WAAA,IAAe,IAAI,OAAO,WAAA;AAC9B,EAAA,IAAI,WAAA,IAAe,IAAI,OAAO,WAAA;AAC9B,EAAA,IAAI,WAAA,IAAe,GAAG,OAAO,UAAA;AAC7B,EAAA,OAAO,OAAA;AACR;AAUA,eAAsB,eAAA,CAAgB,QAAgB,UAAA,EAAoD;AACzG,EAAA,MAAM,WAAsB,EAAC;AAG7B,EAAA,MAAM,UAAA,GAAa,eAAe,MAAM,CAAA;AACxC,EAAA,IAAI,CAAC,WAAW,KAAA,EAAO;AACtB,IAAA,OAAO,iBAAiB,aAAA,EAAe;AAAA,MACtC,aAAA,CAAc,eAAe,gBAAA,EAAkB,MAAA,EAAQ,6BAA6B,UAAA,CAAW,KAAA,IAAS,eAAe,CAAA,CAAA,CAAG;AAAA,KAC1H,CAAA;AAAA,EACF;AAGA,EAAA,MAAM,CAAC,UAAA,EAAY,WAAW,CAAA,GAAI,MAAM,QAAQ,UAAA,CAAW;AAAA,IAC1D,eAAA,CAAgB,QAAQ,UAAU,CAAA;AAAA,IAClC,eAAA,CAAgB,CAAA,OAAA,EAAU,MAAM,CAAA,CAAA,EAAI,UAAU;AAAA,GAC9C,CAAA;AACD,EAAA,MAAM,iBAAiB,UAAA,CAAW,MAAA,KAAW,WAAA,GAAc,UAAA,CAAW,QAAQ,EAAC;AAC/E,EAAA,MAAM,kBAAkB,WAAA,CAAY,MAAA,KAAW,WAAA,GAAc,WAAA,CAAY,QAAQ,EAAC;AAGlF,EAAA,IAAI,cAAA,CAAe,WAAW,CAAA,EAAG;AAChC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,sBAAA;AAAA,QACA,MAAA;AAAA,QACA,4BAA4B,MAAM,CAAA,gDAAA;AAAA;AACnC,KACD;AACA,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,4BAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,8EAAA;AAAA;AACD,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,eAAe,QAAQ,CAAA;AAAA,EAChD;AAWA,EAAA,MAAM,kBAAoC,EAAC;AAE3C,EAAA,KAAA,MAAW,UAAU,cAAA,EAAgB;AAEpC,IAAA,IAAI,MAAA,CAAO,WAAA,EAAY,CAAE,UAAA,CAAW,QAAQ,CAAA,EAAG;AAE/C,IAAA,KAAA,MAAW,WAAW,qBAAA,EAAuB;AAC5C,MAAA,IAAI,MAAA,CAAO,UAAA,CAAW,OAAA,CAAQ,MAAM,CAAA,IAAK,MAAA,CAAO,WAAA,EAAY,CAAE,UAAA,CAAW,OAAA,CAAQ,MAAA,CAAO,WAAA,EAAa,CAAA,EAAG;AACvG,QAAA,eAAA,CAAgB,IAAA,CAAK;AAAA,UACpB,SAAS,OAAA,CAAQ,OAAA;AAAA,UACjB,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,cAAc,OAAA,CAAQ,YAAA;AAAA,UACtB,QAAQ,OAAA,CAAQ,MAAA;AAAA,UAChB;AAAA,SACA,CAAA;AACD,QAAA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAKA,EAAA,MAAM,SAAA,GAAY,mBAAmB,MAAM,CAAA;AAC3C,EAAA,MAAM,SAAA,GAAY,gBAAgB,MAAM,CAAA;AAExC,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACpC,IAAA,IAAI,KAAA,CAAM,iBAAiB,IAAA,EAAM;AAEhC,MAAA,IAAI,cAAc,IAAA,EAAM;AAExB,MAAA,IAAI,SAAA,EAAW;AACd,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,aAAA;AAAA,YACA,mDAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,gDAAA,EAAmD,MAAM,CAAA,0FAAA,CAAA;AAAA,YACzE,EAAE,SAAS,KAAA,CAAM,OAAA,EAAS,cAAc,IAAA,EAAM,QAAA,EAAU,MAAM,QAAA;AAAS;AACxE,SACD;AAAA,MACD,CAAA,MAAO;AACN,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,aAAA;AAAA,YACA,oDAAA;AAAA,YACA,QAAA;AAAA,YACA,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,+BAAA,EAAkC,MAAM,CAAA,mIAAA,CAAA;AAAA,YACxD,EAAE,SAAS,KAAA,CAAM,OAAA,EAAS,cAAc,IAAA,EAAM,QAAA,EAAU,MAAM,QAAA;AAAS;AACxE,SACD;AAAA,MACD;AAAA,IACD,CAAA,MAAA,IAAW,KAAA,CAAM,YAAA,KAAiB,IAAA,EAAM;AAEvC,MAAA,IAAI,cAAc,IAAA,EAAM;AAExB,MAAA,IAAI,SAAA,EAAW;AACd,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,aAAA;AAAA,YACA,mDAAA;AAAA,YACA,MAAA;AAAA,YACA,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,gDAAA,EAAmD,MAAM,CAAA,0FAAA,CAAA;AAAA,YACzE,EAAE,SAAS,KAAA,CAAM,OAAA,EAAS,cAAc,IAAA,EAAM,QAAA,EAAU,MAAM,QAAA;AAAS;AACxE,SACD;AAAA,MACD,CAAA,MAAO;AACN,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,aAAA;AAAA,YACA,oDAAA;AAAA,YACA,QAAA;AAAA,YACA,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,+BAAA,EAAkC,MAAM,CAAA,mIAAA,CAAA;AAAA,YACxD,EAAE,SAAS,KAAA,CAAM,OAAA,EAAS,cAAc,IAAA,EAAM,QAAA,EAAU,MAAM,QAAA;AAAS;AACxE,SACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,cAAc,cAAA,CAAe,MAAA;AACnC,EAAA,IAAI,eAAe,EAAA,EAAI;AACtB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,mCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,MAAA,EAAS,WAAW,CAAA,iBAAA,EAAoB,MAAM,CAAA,0JAAA,CAAA;AAAA,QAC9C,EAAE,WAAA;AAAY;AACf,KACD;AAAA,EACD,CAAA,MAAA,IAAW,eAAe,EAAA,EAAI;AAC7B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,yBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,MAAA,EAAS,WAAW,CAAA,iBAAA,EAAoB,MAAM,CAAA,gGAAA,CAAA;AAAA,QAC9C,EAAE,WAAA;AAAY;AACf,KACD;AAAA,EACD;AAGA,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAgD;AACzE,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACpC,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AAC9C,IAAA,IAAI,QAAA,EAAU;AACb,MAAA,QAAA,CAAS,KAAA,EAAA;AAAA,IACV,CAAA,MAAO;AACN,MAAA,YAAA,CAAa,GAAA,CAAI,MAAM,MAAA,EAAQ,EAAE,SAAS,KAAA,CAAM,OAAA,EAAS,KAAA,EAAO,CAAA,EAAG,CAAA;AAAA,IACpE;AAAA,EACD;AACA,EAAA,KAAA,MAAW,GAAG,EAAE,SAAS,KAAA,EAAO,KAAK,YAAA,EAAc;AAClD,IAAA,IAAI,SAAS,CAAA,EAAG;AACf,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,aAAA;AAAA,UACA,mCAAmC,OAAO,CAAA,CAAA;AAAA,UAC1C,QAAA;AAAA,UACA,CAAA,MAAA,EAAS,KAAK,CAAA,0BAAA,EAA6B,OAAO,CAAA,gHAAA,CAAA;AAAA,UAClD,EAAE,OAAA,EAAS,cAAA,EAAgB,KAAA;AAAM;AAClC,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,WAAA,GAAc,cAAA,CAAe,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AACrF,EAAA,IAAI,WAAA,EAAa;AAChB,IAAA,MAAM,gBAAA,GAAmB,eAAA,CAAgB,IAAA,CAAK,CAAC,CAAA,KAAM,EAAE,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AAC3F,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,gCAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,+FAAA,EAAkG,MAAM,CAAA,GAAA,EAAM,gBAAA,GAAmB,8GAAyG,oFAAoF,CAAA;AAAA;AAC/T,KACD;AAAA,EACD;AAGA,EAAA,MAAM,oBAAoB,eAAA,CAAgB,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,0BAA0B,CAAA;AAC7F,EAAA,IAAI,iBAAA,EAAmB;AACtB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,wCAAA;AAAA,QACA,QAAA;AAAA,QACA,4CAA4C,MAAM,CAAA,6JAAA;AAAA;AACnD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,WAAA,GAAc,mBAAmB,cAAc,CAAA;AACrD,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AACpC,IAAA,MAAM,UAAA,GAAa,mBAAA,CAAoB,KAAA,CAAM,OAAO,CAAA;AACpD,IAAA,IAAI,CAAC,UAAA,EAAY;AAEjB,IAAA,MAAM,gBAAgB,UAAA,CAAW,IAAA;AAAA,MAAK,CAAC,SAAA,KACtC,WAAA,CAAY,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,QAAA,CAAS,SAAA,CAAU,WAAA,EAAa,CAAC;AAAA,KACxE;AAEA,IAAA,IAAI,CAAC,aAAA,EAAe;AACnB,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,aAAA;AAAA,UACA,CAAA,oCAAA,EAAuC,MAAM,OAAO,CAAA,CAAA;AAAA,UACpD,KAAA;AAAA,UACA,CAAA,EAAG,MAAM,OAAO,CAAA,+MAAA,CAAA;AAAA,UAChB,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,MAAM,QAAA;AAAS;AACpD,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,MAAM,SAAA,GAAY,eAAe,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,UAAA,CAAW,KAAK,CAAC,CAAA;AAClE,EAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACzB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,6CAAA;AAAA,QACA,KAAA;AAAA,QACA,CAAA,MAAA,EAAS,UAAU,MAAM,CAAA,0JAAA,CAAA;AAAA,QACzB,EAAE,aAAA,EAAe,SAAA,CAAU,MAAA;AAAO;AACnC,KACD;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,SAAS,eAAA,EAAiB;AAEpC,IAAA,IAAI,KAAA,CAAM,QAAA,KAAa,YAAA,IAAgB,KAAA,CAAM,YAAY,OAAA,EAAS;AAElE,IAAA,IAAI,KAAA,CAAM,WAAW,0BAAA,EAA4B;AAEjD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,aAAA;AAAA,QACA,CAAA,+BAAA,EAAkC,MAAM,OAAO,CAAA,CAAA;AAAA,QAC/C,MAAA;AAAA,QACA,CAAA,EAAG,KAAA,CAAM,OAAO,CAAA,mCAAA,EAAsC,MAAM,QAAQ,CAAA,WAAA,CAAA;AAAA,QACpE,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,QAAA,EAAU,MAAM,QAAA;AAAS;AACpD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,MAAA,GAAS,iBAAiB,WAAW,CAAA;AAC3C,EAAA,QAAA,CAAS,IAAA;AAAA,IACR,aAAA;AAAA,MACC,aAAA;AAAA,MACA,4BAAA;AAAA,MACA,MAAA;AAAA,MACA,8BAA8B,MAAM,CAAA,EAAA,EAAK,WAAW,CAAA,WAAA,EAAc,gBAAgB,MAAM,CAAA,kCAAA,CAAA;AAAA,MACxF,EAAE,MAAA,EAAQ,WAAA,EAAa,YAAA,EAAc,gBAAgB,MAAA;AAAO;AAC7D,GACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,eAAe,QAAQ,CAAA;AAChD;;;ACjaA,YAAA,EAAA;AACA,WAAA,EAAA;;;ACRA,YAAA,EAAA;AAGA,IAAM,gBAAA,GAAmB;AAAA,EACxB,yBAAA;AAAA,EACA,iBAAA;AAAA,EACA,wBAAA;AAAA,EACA,oBAAA;AAAA,EACA,iBAAA;AAAA,EACA,8BAAA;AAAA,EACA;AACD,CAAA;AAGA,IAAM,eAAA,GAAkB,eAAA;AAMxB,SAAS,kBAAkB,QAAA,EAA6B;AACvD,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,KAAA,GAAQ,SAAS,WAAA,EAAY;AAGnC,EAAA,MAAM,cAAA,GAAiB,KAAA,CAAM,KAAA,CAAM,sBAAsB,CAAA;AACzD,EAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,KAAA,CAAM,uBAAuB,CAAA;AAC3D,EAAA,MAAM,qBAAqB,cAAA,GAAiB,CAAC,CAAA,IAAK,eAAA,GAAkB,CAAC,CAAA,IAAK,EAAA;AAE1E,EAAA,IAAI,kBAAA,CAAmB,QAAA,CAAS,iBAAiB,CAAA,EAAG;AACnD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,kCAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,IAAI,kBAAA,CAAmB,QAAA,CAAS,eAAe,CAAA,EAAG;AACjD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,wBAAA;AAAA,QACA,QAAA;AAAA,QACA,oCAAoC,eAAe,CAAA,oFAAA;AAAA;AACpD,KACD;AAAA,EACD;AAIA,EAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,KAAA,CAAM,KAAK,CAAA;AAC9C,EAAA,IAAI,QAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,KAAM,GAAG,CAAA,EAAG;AACnC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,0BAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AASO,SAAS,uBAAuB,OAAA,EAA6B;AACnE,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,yBAAyB,CAAA;AACjD,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AACzC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,wBAAwB,CAAA;AACjD,EAAA,MAAM,EAAA,GAAK,OAAA,CAAQ,GAAA,CAAI,oBAAoB,CAAA;AAC3C,EAAA,MAAM,EAAA,GAAK,OAAA,CAAQ,GAAA,CAAI,iBAAiB,CAAA;AACxC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,8BAA8B,CAAA;AACvD,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,4BAA4B,CAAA;AAGrD,EAAA,MAAM,oBAAA,GAAuB,GAAA,GAAM,kBAAA,CAAmB,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA;AAGlE,EAAA,IAAI,CAAC,GAAA,EAAK;AACT,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,4BAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD,CAAA,MAAO;AACN,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,iBAAA,CAAkB,GAAG,CAAC,CAAA;AAAA,EACxC;AAGA,EAAA,IAAI,CAAC,GAAA,IAAO,CAAC,oBAAA,EAAsB;AAClC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,oBAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,IAAA,EAAM;AACV,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,2BAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,EAAA,EAAI;AACR,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,uBAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,EAAA,EAAI;AACR,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,oBAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,IAAA,EAAM;AACV,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,gBAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,CAAC,IAAA,EAAM;AACV,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,gBAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,uCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,IAAA,EAAO,iBAAiB,MAAM,CAAA,mFAAA;AAAA;AAC/B,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;AD9KA,eAAsB,kBAAkB,MAAA,EAAsC;AAC7E,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,QAAA,EAAW,MAAM,CAAA,CAAA,EAAI;AAAA,MACjD,MAAA,EAAQ,MAAA;AAAA,MACR,QAAA,EAAU,QAAA;AAAA;AAAA,MACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,gBAAgB;AAAA,KAC5C,CAAA;AAGD,IAAA,IAAI,QAAA,CAAS,SAAS,GAAA,EAAK;AAC1B,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,sBAAA,CAAuB,QAAA,CAAS,OAAO,CAAC,CAAA;AAAA,IAC1D,CAAA,MAAO;AACN,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,eAAA;AAAA,UACA,cAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,sBAAA,EAAyB,QAAA,CAAS,MAAM,CAAA,KAAA,EAAQ,MAAM,CAAA,kCAAA;AAAA;AACvD,OACD;AAAA,IACD;AAAA,EACD,SAAS,GAAA,EAAK;AACb,IAAA,MAAM,OAAA,GACL,GAAA,YAAe,KAAA,KAAU,GAAA,CAAI,OAAA,CAAQ,QAAA,CAAS,SAAS,CAAA,IAAK,GAAA,CAAI,OAAA,CAAQ,QAAA,CAAS,OAAO,KACrF,sBAAA,GACA,mBAAA;AACJ,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,CAAA,MAAA,EAAS,OAAA,CAAQ,WAAA,EAAa,CAAA,CAAA;AAAA,QAC9B,QAAA;AAAA,QACA,CAAA,wBAAA,EAA2B,MAAM,CAAA,4BAAA,EAA+B,OAAO,CAAA,CAAA;AAAA;AACxE,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,iBAAiB,QAAQ,CAAA;AAClD;;;AE3CA,YAAA,EAAA;AACA,QAAA,EAAA;;;ACLA,YAAA,EAAA;AACA,QAAA,EAAA;AAGA,IAAM,YAAA,GAAuC;AAAA,EAC5C,CAAA,EAAG,yBAAA;AAAA,EACH,CAAA,EAAG,0CAAA;AAAA,EACH,CAAA,EAAG,kCAAA;AAAA,EACH,CAAA,EAAG;AACJ,CAAA;AAWO,SAAS,kBAAA,CAAmB,OAAA,EAAmB,IAAA,EAAc,SAAA,EAA+B;AAClG,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,MAAM,MAAA,GAAS,gBAAgB,MAAM,CAAA;AACrC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,uBAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,gCAAA,EAAmC,IAAI,CAAA,EAAA,EAAK,MAAM,CAAA;AAAA;AACnD,OACD;AACA,MAAA;AAAA,IACD;AAGA,IAAA,IAAI,MAAA,CAAO,KAAA,GAAQ,CAAA,IAAK,MAAA,CAAO,QAAQ,CAAA,EAAG;AACzC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,oBAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,gBAAA,EAAmB,IAAI,CAAA,yBAAA,EAA4B,MAAA,CAAO,KAAK,CAAA,qBAAA,CAAA;AAAA,UAC/D,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA;AAAM;AACvB,OACD;AACA,MAAA;AAAA,IACD;AAGA,IAAA,IAAI,MAAA,CAAO,QAAA,GAAW,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AAC/C,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,uBAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,gBAAA,EAAmB,IAAI,CAAA,4BAAA,EAA+B,MAAA,CAAO,QAAQ,CAAA,qBAAA,CAAA;AAAA,UACrE,EAAE,QAAA,EAAU,MAAA,CAAO,QAAA;AAAS;AAC7B,OACD;AACA,MAAA;AAAA,IACD;AAGA,IAAA,IAAI,MAAA,CAAO,YAAA,GAAe,CAAA,IAAK,MAAA,CAAO,eAAe,CAAA,EAAG;AACvD,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,4BAAA;AAAA,UACA,QAAA;AAAA,UACA,CAAA,gBAAA,EAAmB,IAAI,CAAA,2BAAA,EAA8B,MAAA,CAAO,YAAY,CAAA,qBAAA,CAAA;AAAA,UACxE,EAAE,YAAA,EAAc,MAAA,CAAO,YAAA;AAAa;AACrC,OACD;AACA,MAAA;AAAA,IACD;AAGA,IAAA,IAAA,CAAK,OAAO,KAAA,KAAU,CAAA,IAAK,OAAO,KAAA,KAAU,CAAA,KAAM,CAAC,SAAA,EAAW;AAC7D,MAAA,MAAMM,cAAa,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA,IAAK,CAAA,MAAA,EAAS,OAAO,KAAK,CAAA,CAAA;AACtE,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,qBAAA;AAAA,UACA,MAAA;AAAA,UACA,CAAA,gBAAA,EAAmB,IAAI,CAAA,MAAA,EAASA,WAAU,CAAA,2GAAA,CAAA;AAAA,UAC1C,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,IAAA;AAAK;AAC7B,OACD;AAAA,IACD;AAGA,IAAA,IAAI,MAAA,CAAO,iBAAiB,CAAA,EAAG;AAC9B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,MAAA;AAAA,UACA,qCAAA;AAAA,UACA,KAAA;AAAA,UACA,mBAAmB,IAAI,CAAA,+IAAA,CAAA;AAAA,UACvB,EAAE,YAAA,EAAc,MAAA,CAAO,YAAA,EAAc,IAAA;AAAK;AAC3C,OACD;AAAA,IACD;AAGA,IAAA,MAAM,aAAa,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA,IAAK,CAAA,MAAA,EAAS,OAAO,KAAK,CAAA,CAAA;AACtE,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,4BAA4B,IAAI,CAAA,CAAA;AAAA,QAChC,MAAA;AAAA,QACA,sBAAsB,UAAU,CAAA,WAAA,EAAc,OAAO,QAAQ,CAAA,gBAAA,EAAmB,OAAO,YAAY,CAAA,CAAA,CAAA;AAAA,QACnG,EAAE,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,QAAA,EAAU,OAAO,QAAA,EAAU,YAAA,EAAc,MAAA,CAAO,YAAA,EAAc,IAAA;AAAK;AAC3F,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AASO,SAAS,oBAAA,CAAqB,WAAoB,YAAA,EAAkC;AAC1F,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,6BAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,YAAA,EAAc;AAClB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,wBAAA;AAAA,QACA,KAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;AD3IA,eAAsB,SAAA,CAAU,QAAgB,UAAA,EAAoD;AACnG,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,YAAA,GAAe,KAAA;AAGnB,EAAA,IAAI;AACH,IAAA,SAAA,GAAY,MAAM,WAAA,CAAY,MAAA,EAAQ,UAAU,CAAA;AAAA,EACjD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI;AACH,IAAA,MAAM,SAAA,GAAY,MAAM,cAAA,CAAe,MAAA,EAAQ,UAAU,CAAA;AAEzD,IAAA,KAAA,MAAW,MAAM,SAAA,EAAW;AAC3B,MAAA,MAAM,SAAS,EAAA,CAAG,QAAA;AAClB,MAAA,IAAI,CAAC,MAAA,IAAU,MAAA,KAAW,GAAA,EAAK;AAE/B,MAAA,MAAM,QAAA,GAAW,YAAY,MAAM,CAAA,CAAA;AACnC,MAAA,IAAI;AACH,QAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB,QAAA,EAAU,QAAQ,UAAU,CAAA;AACtE,QAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC3B,UAAA,SAAA,GAAY,IAAA;AACZ,UAAA,QAAA,CAAS,KAAK,GAAG,kBAAA,CAAmB,WAAA,EAAa,QAAA,EAAU,SAAS,CAAC,CAAA;AAAA,QACtE;AAAA,MACD,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAEP,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,iCAAA;AAAA,QACA,KAAA;AAAA,QACA,kCAAkC,MAAM,CAAA,kDAAA;AAAA;AACzC,KACD;AAAA,EACD;AAGA,EAAA,MAAM,aAAA,GAAgB,aAAa,MAAM,CAAA,CAAA;AACzC,EAAA,IAAI;AACH,IAAA,MAAM,gBAAA,GAAmB,MAAM,eAAA,CAAgB,aAAA,EAAe,QAAQ,UAAU,CAAA;AAChF,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAChC,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,QAAA,CAAS,KAAK,GAAG,kBAAA,CAAmB,gBAAA,EAAkB,aAAA,EAAe,SAAS,CAAC,CAAA;AAAA,IAChF;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAGA,EAAA,IAAI,CAAC,SAAA,IAAa,CAAC,YAAA,IAAgB,QAAA,CAAS,MAAM,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,YAAY,CAAC,CAAA,CAAE,MAAM,QAAA,CAAS,WAAW,CAAC,CAAA,EAAG;AACpH,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,oBAAA,CAAqB,SAAA,EAAW,YAAY,CAAC,CAAA;AAAA,EAC/D;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,MAAA;AAAA,QACA,yBAAA;AAAA,QACA,QAAA;AAAA,QACA,gDAAgD,MAAM,CAAA,kCAAA;AAAA;AACvD,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,QAAQ,QAAQ,CAAA;AACzC;;;AEtFA,YAAA,EAAA;AACA,QAAA,EAAA;;;ACNA,YAAA,EAAA;AAGA,IAAM,mBAAA,GAAsB,mFAAA;AAgBrB,SAAS,iBAAA,CAAkB,EAAA,EAAY,YAAA,EAAwB,UAAA,EAAiC;AACtG,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI,YAAA,CAAa,WAAW,CAAA,EAAG;AAC9B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,+BAA+B,EAAE,CAAA,CAAA;AAAA,QACjC,QAAA;AAAA,QACA,MAAM,EAAE,CAAA,gHAAA,CAAA;AAAA,QACR,EAAE,EAAA;AAAG;AACN,KACD;AACA,IAAA,OAAO,QAAA;AAAA,EACR;AAGA,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,QAAA,CAAS,EAAE,CAAA;AAExC,EAAA,IAAI,CAAC,SAAA,EAAW;AACf,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,sCAAsC,EAAE,CAAA,CAAA;AAAA,QACxC,QAAA;AAAA,QACA,CAAA,GAAA,EAAM,EAAE,CAAA,oBAAA,EAAuB,YAAA,CAAa,KAAK,IAAI,CAAC,+BAA+B,EAAE,CAAA,wEAAA,CAAA;AAAA,QACvF,EAAE,EAAA,EAAI,YAAA,EAAc,UAAA;AAAW;AAChC,KACD;AAAA,EACD;AAGA,EAAA,KAAA,MAAW,YAAY,YAAA,EAAc;AACpC,IAAA,IAAI,mBAAA,CAAoB,IAAA,CAAK,QAAQ,CAAA,EAAG;AACvC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,eAAA;AAAA,UACA,8BAAA;AAAA,UACA,KAAA;AAAA,UACA,CAAA,cAAA,EAAiB,QAAQ,CAAA,SAAA,EAAY,EAAE,CAAA,oFAAA,CAAA;AAAA,UACvC,EAAE,IAAI,QAAA;AAAS;AAChB,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,SAAA,IAAa,CAAC,YAAA,CAAa,IAAA,CAAK,CAAC,MAAM,mBAAA,CAAoB,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG;AACxE,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,yBAAyB,EAAE,CAAA,CAAA;AAAA,QAC3B,MAAA;AAAA,QACA,MAAM,EAAE,CAAA,uBAAA,EAA0B,YAAA,CAAa,IAAA,CAAK,IAAI,CAAC,CAAA,2BAAA,CAAA;AAAA,QACzD,EAAE,IAAI,YAAA;AAAa;AACpB,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AASO,SAAS,mBAAA,CAAoB,IAAY,QAAA,EAA+D;AAC9G,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,cAAc,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,MAAM,CAAA;AAEnD,EAAA,IAAI,WAAA,CAAY,SAAS,CAAA,EAAG;AAC3B,IAAA,KAAA,MAAW,WAAW,WAAA,EAAa;AAClC,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,eAAA;AAAA,UACA,CAAA,uBAAA,EAA0B,QAAQ,IAAI,CAAA,CAAA;AAAA,UACtC,MAAA;AAAA,UACA,CAAA,GAAA,EAAM,EAAE,CAAA,oBAAA,EAAuB,OAAA,CAAQ,IAAI,CAAA,iFAAA,CAAA;AAAA,UAC3C,EAAE,EAAA,EAAI,IAAA,EAAM,OAAA,CAAQ,IAAA;AAAK;AAC1B,OACD;AAAA,IACD;AAAA,EACD,CAAA,MAAO;AACN,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,2BAA2B,EAAE,CAAA,CAAA;AAAA,QAC7B,MAAA;AAAA,QACA,CAAA,GAAA,EAAM,EAAE,CAAA,sCAAA,EAAyC,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,EAAA,CAAA;AAAA,QACvF,EAAE,IAAI,KAAA,EAAO,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA;AAAE;AAC1C,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAMO,SAAS,eAAA,GAA4B;AAC3C,EAAA,OAAO,CAAC,kBAAA,EAAoB,gBAAA,EAAkB,wBAAwB,CAAA;AACvE;AASO,SAAS,kBAAkB,EAAA,EAAoB;AACrD,EAAA,OAAO,GAAG,KAAA,CAAM,GAAG,EAAE,OAAA,EAAQ,CAAE,KAAK,GAAG,CAAA;AACxC;;;AD7HA,IAAM,YAAA,GAAe,CAAA;AAcrB,eAAsB,iBAAA,CAAkB,QAAgB,UAAA,EAAoD;AAC3G,EAAA,MAAM,WAAsB,EAAC;AAG7B,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI;AACH,IAAA,SAAA,GAAY,MAAM,cAAA,CAAe,MAAA,EAAQ,UAAU,CAAA;AAAA,EACpD,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,kBAAA;AAAA,QACA,QAAA;AAAA,QACA,kCAAkC,MAAM,CAAA,yCAAA;AAAA;AACzC,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,iBAAiB,QAAQ,CAAA;AAAA,EAClD;AAGA,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,gDAAA;AAAA,QACA,MAAA;AAAA,QACA,GAAG,MAAM,CAAA,qEAAA;AAAA;AACV,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,iBAAiB,QAAQ,CAAA;AAAA,EAClD;AAGA,EAAA,MAAM,YAAA,GAAe,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,YAAY,CAAA;AAEpD,EAAA,KAAA,MAAW,MAAM,YAAA,EAAc;AAC9B,IAAA,MAAM,SAAS,EAAA,CAAG,QAAA;AAClB,IAAA,IAAI,CAAC,MAAA,IAAU,MAAA,KAAW,GAAA,EAAK;AAE/B,IAAA,IAAI;AAEH,MAAA,MAAM,GAAA,GAAM,MAAM,eAAA,CAAgB,MAAA,EAAQ,KAAK,UAAU,CAAA;AACzD,MAAA,IAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AACrB,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,eAAA;AAAA,YACA,2BAA2B,MAAM,CAAA,CAAA;AAAA,YACjC,QAAA;AAAA,YACA,WAAW,MAAM,CAAA,uEAAA,CAAA;AAAA,YACjB,EAAE,MAAA;AAAO;AACV,SACD;AACA,QAAA;AAAA,MACD;AAGA,MAAA,MAAM,EAAA,GAAK,IAAI,CAAC,CAAA;AAChB,MAAA,IAAI,CAAC,yBAAA,CAA0B,IAAA,CAAK,EAAE,CAAA,EAAG;AAGzC,MAAA,IAAI;AACH,QAAA,MAAM,YAAA,GAAe,MAAM,eAAA,CAAgB,EAAA,EAAI,UAAU,CAAA;AAGzD,QAAA,MAAM,aAAuB,EAAC;AAC9B,QAAA,KAAA,MAAW,WAAW,YAAA,EAAc;AACnC,UAAA,IAAI;AACH,YAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,OAAA,EAAS,KAAK,UAAU,CAAA;AAC/D,YAAA,UAAA,CAAW,IAAA,CAAK,GAAG,QAAQ,CAAA;AAAA,UAC5B,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACD;AAEA,QAAA,QAAA,CAAS,KAAK,GAAG,iBAAA,CAAkB,EAAA,EAAI,YAAA,EAAc,UAAU,CAAC,CAAA;AAAA,MACjE,CAAA,CAAA,MAAQ;AACP,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,aAAA;AAAA,YACC,eAAA;AAAA,YACA,yBAAyB,EAAE,CAAA,CAAA;AAAA,YAC3B,KAAA;AAAA,YACA,CAAA,6CAAA,EAAgD,EAAE,CAAA,QAAA,EAAW,MAAM,CAAA,EAAA,CAAA;AAAA,YACnE,EAAE,IAAI,MAAA;AAAO;AACd,SACD;AAAA,MACD;AAGA,MAAA,MAAM,aAAa,eAAA,EAAgB;AACnC,MAAA,MAAM,eAAyD,EAAC;AAEhE,MAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC9B,QAAA,MAAM,YAAY,CAAA,EAAG,iBAAA,CAAkB,EAAE,CAAC,IAAI,IAAI,CAAA,CAAA;AAClD,QAAA,IAAI;AACH,UAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,SAAA,EAAW,KAAK,UAAU,CAAA;AAChE,UAAA,YAAA,CAAa,KAAK,EAAE,IAAA,EAAM,QAAQ,OAAA,CAAQ,MAAA,GAAS,GAAG,CAAA;AAAA,QACvD,CAAA,CAAA,MAAQ;AAEP,UAAA,YAAA,CAAa,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AAAA,QAC1C;AAAA,MACD;AAEA,MAAA,QAAA,CAAS,IAAA,CAAK,GAAG,mBAAA,CAAoB,EAAA,EAAI,YAAY,CAAC,CAAA;AAAA,IACvD,CAAA,CAAA,MAAQ;AACP,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,eAAA;AAAA,UACA,+BAA+B,MAAM,CAAA,CAAA;AAAA,UACrC,KAAA;AAAA,UACA,4CAA4C,MAAM,CAAA,sDAAA,CAAA;AAAA,UAClD,EAAE,MAAA;AAAO;AACV,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,eAAA;AAAA,QACA,4BAAA;AAAA,QACA,MAAA;AAAA,QACA,sBAAsB,MAAM,CAAA,uEAAA;AAAA;AAC7B,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,iBAAiB,QAAQ,CAAA;AAClD;;;AExJA,YAAA,EAAA;AACA,QAAA,EAAA;;;ACRA,YAAA,EAAA;AAMO,IAAM,YAAA,GAAe;AAAA;AAAA,EAE3B,kBAAA;AAAA;AAAA,EACA,YAAA;AAAA;AAAA,EACA,aAAA;AAAA;AAAA,EACA,YAAA;AAAA;AAAA,EACA,aAAA;AAAA;AAAA;AAAA,EAEA,oBAAA;AAAA;AAAA,EACA,eAAA;AAAA;AAAA,EACA,gBAAA;AAAA;AAAA,EACA,cAAA;AAAA;AAAA,EACA,eAAA;AAAA;AAAA;AAAA,EAEA,WAAA;AAAA;AAAA,EACA,WAAA;AAAA;AAAA,EACA,mBAAA;AAAA;AAAA,EACA,mBAAA;AAAA;AAAA;AAAA,EAEA,YAAA;AAAA;AAAA,EACA;AAAA;AACD,CAAA;AASA,IAAM,cAAA,GAAgF;AAAA,EACrF,EAAE,KAAA,EAAO,YAAA,EAAc,SAAA,EAAW,aAAA,EAAe,UAAU,MAAA,EAAO;AAAA,EAClE,EAAE,KAAA,EAAO,YAAA,EAAc,SAAA,EAAW,aAAA,EAAe,UAAU,MAAA;AAC5D,CAAA;AAWO,SAAS,kBAAkB,OAAA,EAAsC;AACvE,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAA,CAAO,CAAC,MAAM,CAAA,CAAE,OAAA,CAAQ,SAAS,CAAC,CAAA;AAE7D,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,IAAA,QAAA,CAAS,KAAK,aAAA,CAAc,KAAA,EAAO,8BAAA,EAAgC,MAAA,EAAQ,8DAA8D,CAAC,CAAA;AAC1I,IAAA,OAAO,QAAA;AAAA,EACR;AAGA,EAAA,KAAA,MAAW,WAAW,UAAA,EAAY;AACjC,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA;AACrC,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,cAAc,KAAA,EAAO,CAAA,wBAAA,EAA2B,OAAA,CAAQ,MAAM,IAAI,MAAA,EAAQ,CAAA,qBAAA,EAAwB,OAAA,CAAQ,MAAM,gBAAgB,WAAA,CAAY,MAAM,CAAA,CAAA,EAAI,WAAA,CAAY,IAAI,CAAA,CAAA,CAAA,EAAK;AAAA,QAC1K,QAAQ,OAAA,CAAQ,MAAA;AAAA,QAChB,MAAM,WAAA,CAAY,IAAA;AAAA,QAClB,QAAQ,WAAA,CAAY;AAAA,OACpB;AAAA,KACF;AAAA,EACD;AAGA,EAAA,MAAM,kBAAA,GAAqB,IAAI,GAAA,CAAI,UAAA,CAAW,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAC,CAAA;AAGlE,EAAA,KAAA,MAAW,QAAQ,cAAA,EAAgB;AAClC,IAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,IAAA,CAAK,KAAK,CAAA,IAAK,CAAC,kBAAA,CAAmB,GAAA,CAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AAClF,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,aAAA;AAAA,UACC,KAAA;AAAA,UACA,CAAA,WAAA,EAAc,KAAK,QAAQ,CAAA,qCAAA,CAAA;AAAA,UAC3B,QAAA;AAAA,UACA,CAAA,EAAG,KAAK,KAAK,CAAA,uBAAA,EAA0B,KAAK,SAAS,CAAA,gDAAA,EAAmD,KAAK,QAAQ,CAAA,2CAAA;AAAA;AACtH,OACD;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,oBAAoB,CAAA,EAAG;AACjD,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA,CAAc,KAAA,EAAO,iCAAA,EAAmC,KAAA,EAAO,qGAAqG;AAAA,KACrK;AAAA,EACD;AAGA,EAAA,MAAM,YAAA,GAAe,CAAC,WAAA,EAAa,WAAA,EAAa,qBAAqB,mBAAmB,CAAA;AACxF,EAAA,MAAM,UAAA,GAAa,aAAa,MAAA,CAAO,CAAC,MAAM,kBAAA,CAAmB,GAAA,CAAI,CAAC,CAAC,CAAA;AACvE,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA,CAAc,OAAO,uCAAA,EAAyC,MAAA,EAAQ,8CAA8C,UAAA,CAAW,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAG;AAAA,KAC7I;AAAA,EACD;AAGA,EAAA,MAAM,cAAc,UAAA,CAAW,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,MAAM,CAAA;AAClD,EAAA,QAAA,CAAS,IAAA;AAAA,IACR,aAAA,CAAc,KAAA,EAAO,CAAA,mBAAA,EAAsB,UAAA,CAAW,MAAM,CAAA,4BAAA,CAAA,EAAgC,MAAA,EAAQ,CAAA,kCAAA,EAAqC,UAAA,CAAW,MAAM,CAAA,oBAAA,EAAuB,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA,EAAK;AAAA,MAC3M,cAAc,UAAA,CAAW,MAAA;AAAA,MACzB,QAAA,EAAU;AAAA,KACV;AAAA,GACF;AAEA,EAAA,OAAO,QAAA;AACR;;;AD3FA,eAAsB,QAAA,CAAS,QAAgB,UAAA,EAAoD;AAClG,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,GAAA,CAAI,OAAO,MAAA,KAAW;AACjD,IAAA,MAAM,IAAA,GAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AAChC,IAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,IAAA,EAAM,UAAU,CAAA;AACtD,IAAA,OAAO,EAAE,QAAQ,OAAA,EAAQ;AAAA,EAC1B,CAAC,CAAA;AAED,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA,CAAW,MAAM,CAAA;AAE/C,EAAA,MAAM,aAA+B,EAAC;AACtC,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,IAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AAClC,MAAA,UAAA,CAAW,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,IAC7B,CAAA,MAAO;AACN,MAAA,WAAA,EAAA;AAAA,IACD;AAAA,EACD;AAGA,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,IAAA,MAAMC,SAAAA,GAAsB;AAAA,MAC3B,aAAA;AAAA,QACC,KAAA;AAAA,QACA,wBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,IAAA,EAAO,YAAA,CAAa,MAAM,CAAA,+BAAA,EAAkC,MAAM,CAAA,wCAAA;AAAA;AACnE,KACD;AACA,IAAA,OAAO,gBAAA,CAAiB,OAAOA,SAAQ,CAAA;AAAA,EACxC;AAEA,EAAA,MAAM,QAAA,GAAW,kBAAkB,UAAU,CAAA;AAG7C,EAAA,IAAI,cAAc,CAAA,EAAG;AACpB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,KAAA;AAAA,QACA,yBAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,EAAG,WAAW,CAAA,IAAA,EAAO,YAAA,CAAa,MAAM,CAAA,sDAAA;AAAA;AACzC,KACD;AAAA,EACD;AAEA,EAAA,OAAO,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AACxC;;;AEhEA,YAAA,EAAA;AACA,QAAA,EAAA;;;ACRA,YAAA,EAAA;AAMO,IAAM,oBAAA,GAAuB;AAAA,EACnC,KAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA;AACD,CAAA;AAqBO,SAAS,eAAe,IAAA,EAAgC;AAC9D,EAAA,IAAI,CAAC,IAAA,IAAQ,OAAO,IAAA,KAAS,UAAU,OAAO,IAAA;AAE9C,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,EAAK,CAAE,MAAM,KAAK,CAAA;AACrC,EAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,IAAA;AAE7B,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACrC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACnC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACpC,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AAErC,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAA,EAAS,KAAA,EAAO,MAAA,EAAQ,OAAO,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAC,MAAA,CAAO,QAAA,CAAS,CAAC,CAAA,IAAK,CAAA,GAAI,CAAC,CAAA,EAAG;AACxF,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,OAAO;AAAA,IACN,WAAW,KAAA,CAAM,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,IACrC,YAAY,KAAA,CAAM,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAAA,IACtC,MAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACD;AACD;AAiBO,SAAS,sBAAsB,SAAA,EAAuC;AAC5E,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,MAAM,YAAY,SAAA,CAAU,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,WAAW,IAAI,CAAA;AACnE,EAAA,MAAM,SAAS,SAAA,CAAU,MAAA,CAAO,CAAC,KAAA,KAAU,KAAA,CAAM,WAAW,IAAI,CAAA;AAEhE,EAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACzB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,8CAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,KAAA,EAAQ,UAAU,MAAM,CAAA,0FAAA;AAAA;AACzB,KACD;AACA,IAAA,OAAO,QAAA;AAAA,EACR;AAGA,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,SAAA,CAAU,IAAI,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAC,CAAA;AAE9D,EAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACvB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,sDAAA;AAAA,QACA,MAAA;AAAA,QACA,OAAO,SAAA,CAAU,MAAM,4CAA4C,SAAA,CAAU,CAAC,EAAE,MAAM,CAAA,6BAAA,CAAA;AAAA,QACtF,EAAE,QAAQ,SAAA,CAAU,CAAC,EAAE,MAAA,EAAQ,OAAA,EAAS,UAAU,MAAA;AAAO;AAC1D,KACD;AAAA,EACD,CAAA,MAAO;AAEN,IAAA,MAAM,YAAsC,EAAC;AAC7C,IAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC9B,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA;AAC/B,MAAA,IAAI,CAAC,SAAA,CAAU,GAAG,GAAG,SAAA,CAAU,GAAG,IAAI,EAAC;AACvC,MAAA,SAAA,CAAU,GAAG,CAAA,CAAE,IAAA,CAAK,KAAA,CAAM,EAAE,CAAA;AAAA,IAC7B;AAEA,IAAA,MAAM,cAAc,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,MAAA,EAAQ,MAAM,CAAA,KAAM,UAAU,MAAM,CAAA,EAAA,EAAK,OAAO,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAEhH,IAAA,MAAM,iBAAyC,EAAC;AAChD,IAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC9B,MAAA,cAAA,CAAe,KAAA,CAAM,EAAE,CAAA,GAAI,KAAA,CAAM,MAAA;AAAA,IAClC;AAEA,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,qCAAA;AAAA,QACA,MAAA;AAAA,QACA,CAAA,oGAAA,EAAuG,WAAA,CAAY,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,QAC7H,EAAE,SAAS,cAAA;AAAe;AAC3B,KACD;AAAA,EACD;AAGA,EAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACtB,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,wBAAA;AAAA,QACA,QAAA;AAAA,QACA,CAAA,EAAG,MAAA,CAAO,MAAM,CAAA,gDAAA,EAAmD,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,6DAAA,CAAA;AAAA,QACrG,EAAE,UAAU,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,EAAE,CAAA;AAAE;AACrC,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;AAkBO,SAAS,2BAA2B,OAAA,EAA4C;AACtF,EAAA,MAAM,WAAsB,EAAC;AAC7B,EAAA,MAAM,YAAY,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAElD,EAAA,IAAI,SAAA,CAAU,WAAW,CAAA,EAAG;AAC3B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,0CAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AACA,IAAA,OAAO,QAAA;AAAA,EACR;AAGA,EAAA,KAAA,MAAW,SAAS,SAAA,EAAW;AAC9B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,CAAA,sCAAA,EAAyC,MAAM,SAAS,CAAA,CAAA;AAAA,QACxD,QAAA;AAAA,QACA,CAAA,cAAA,EAAiB,MAAM,SAAS,CAAA,aAAA,EAAgB,MAAM,GAAA,CAAI,IAAA,CAAK,IAAI,CAAC,CAAA,8EAAA,CAAA;AAAA,QACpE,EAAE,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,GAAA,EAAK,MAAM,GAAA;AAAI;AAC9C,KACD;AAAA,EACD;AAGA,EAAA,IAAI,SAAA,CAAU,UAAU,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,CAAA,uCAAA,EAA0C,UAAU,MAAM,CAAA,OAAA,CAAA;AAAA,QAC1D,QAAA;AAAA,QACA,CAAA,EAAG,SAAA,CAAU,MAAM,CAAA,wCAAA,EAA2C,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,mGAAA,CAAA;AAAA,QAC1G,EAAE,KAAA,EAAO,SAAA,CAAU,MAAA,EAAQ,UAAA,EAAY,SAAA,CAAU,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAAE;AAC1E,KACD;AAAA,EACD;AAEA,EAAA,OAAO,QAAA;AACR;;;ADzLA,eAAsB,gBAAA,CAAiB,QAAgB,UAAA,EAAoD;AAC1G,EAAA,MAAM,WAAsB,EAAC;AAG7B,EAAA,IAAI;AACH,IAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAgB,MAAA,EAAQ,MAAM,UAAU,CAAA;AAChE,IAAA,MAAM,WAAA,GAAc,UAAU,GAAA,CAAI,CAAC,OAAO,EAAA,CAAG,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA;AAE/D,IAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC7B,MAAA,QAAA,CAAS,IAAA;AAAA,QACR,cAAc,cAAA,EAAgB,qBAAA,EAAuB,QAAA,EAAU,CAAA,wCAAA,EAA2C,MAAM,CAAA,8CAAA,CAAgD;AAAA,OACjK;AAAA,IACD,CAAA,MAAO;AAEN,MAAA,MAAM,UAAA,GAAa,MAAM,eAAA,CAAgB,MAAA,EAAQ,OAAO,UAAU,CAAA;AAElE,MAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC5B,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,cAAc,cAAA,EAAgB,qBAAA,EAAuB,QAAA,EAAU,CAAA,+BAAA,EAAkC,MAAM,CAAA,8CAAA,CAAgD;AAAA,SACxJ;AAAA,MACD,CAAA,MAAO;AACN,QAAA,MAAM,GAAA,GAAM,cAAA,CAAe,UAAA,CAAW,CAAC,CAAC,CAAA;AAExC,QAAA,IAAI,CAAC,GAAA,EAAK;AACT,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA,CAAc,cAAA,EAAgB,0BAAA,EAA4B,MAAA,EAAQ,CAAA,mBAAA,EAAsB,MAAM,CAAA,sBAAA,EAAyB,UAAA,CAAW,CAAC,CAAC,CAAA,CAAE;AAAA,WACvI;AAAA,QACD,CAAA,MAAO;AAKN,UAAA,MAAM,SAAA,GAA6B,WAAA,CAAY,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,YAC3D,EAAA;AAAA,YACA,QAAQ,GAAA,CAAI;AAAA,WACb,CAAE,CAAA;AAGF,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,aAAA;AAAA,cACC,cAAA;AAAA,cACA,oBAAA;AAAA,cACA,MAAA;AAAA,cACA,WAAW,MAAM,CAAA,aAAA,EAAgB,IAAI,SAAS,CAAA,SAAA,EAAY,IAAI,MAAM,CAAA,UAAA,EAAa,IAAI,OAAO,CAAA,SAAA,EAAY,IAAI,KAAK,CAAA,UAAA,EAAa,IAAI,MAAM,CAAA,eAAA,EAAkB,IAAI,OAAO,CAAA,EAAA,CAAA;AAAA,cACrK;AAAA,gBACC,WAAW,GAAA,CAAI,SAAA;AAAA,gBACf,QAAQ,GAAA,CAAI,MAAA;AAAA,gBACZ,SAAS,GAAA,CAAI,OAAA;AAAA,gBACb,OAAO,GAAA,CAAI,KAAA;AAAA,gBACX,QAAQ,GAAA,CAAI,MAAA;AAAA,gBACZ,SAAS,GAAA,CAAI,OAAA;AAAA,gBACb;AAAA;AACD;AACD,WACD;AAGA,UAAA,IAAI,GAAA,CAAI,SAAS,MAAA,EAAQ;AACxB,YAAA,QAAA,CAAS,IAAA;AAAA,cACR,aAAA;AAAA,gBACC,cAAA;AAAA,gBACA,2BAAA;AAAA,gBACA,KAAA;AAAA,gBACA,CAAA,sBAAA,EAAyB,IAAI,MAAM,CAAA,wIAAA,CAAA;AAAA,gBACnC,EAAE,MAAA,EAAQ,GAAA,CAAI,MAAA;AAAO;AACtB,aACD;AAAA,UACD;AAGA,UAAA,MAAM,mBAAA,GAAsB,sBAAsB,SAAS,CAAA;AAC3D,UAAA,QAAA,CAAS,IAAA,CAAK,GAAG,mBAAmB,CAAA;AAAA,QACrC;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AACP,IAAA,QAAA,CAAS,IAAA;AAAA,MACR,aAAA;AAAA,QACC,cAAA;AAAA,QACA,+BAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA;AACD,KACD;AAAA,EACD;AAGA,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,MAAM,eAAuC,EAAC;AAE9C,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,oBAAA,CAAqB,MAAA,EAAQ,KAAK,gBAAA,EAAkB;AACvE,IAAA,MAAM,KAAA,GAAQ,oBAAA,CAAqB,KAAA,CAAM,CAAA,EAAG,IAAI,gBAAgB,CAAA;AAChE,IAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,UAAA;AAAA,MAC7B,KAAA,CAAM,GAAA,CAAI,OAAO,SAAA,KAAc;AAC9B,QAAA,MAAM,IAAA,GAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AACnC,QAAA,IAAI;AACH,UAAA,MAAM,QAAA,GAAW,MAAM,eAAA,CAAgB,IAAA,EAAM,KAAK,UAAU,CAAA;AAC5D,UAAA,OAAO;AAAA,YACN,SAAA,EAAW,IAAA;AAAA,YACX,QAAA,EAAU,SAAS,MAAA,GAAS,CAAA;AAAA,YAC5B,GAAA,EAAK;AAAA,WACN;AAAA,QACD,CAAA,CAAA,MAAQ;AACP,UAAA,OAAO;AAAA,YACN,SAAA,EAAW,IAAA;AAAA,YACX,QAAA,EAAU,KAAA;AAAA,YACV,KAAK;AAAC,WACP;AAAA,QACD;AAAA,MACD,CAAC;AAAA,KACF;AACA,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,MAAA,IAAI,MAAA,CAAO,WAAW,WAAA,EAAa;AAClC,QAAA,YAAA,CAAa,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,MAC/B;AAAA,IACD;AAAA,EACD;AAEA,EAAA,MAAM,iBAAA,GAAoB,2BAA2B,YAAY,CAAA;AACjE,EAAA,QAAA,CAAS,IAAA,CAAK,GAAG,iBAAiB,CAAA;AAElC,EAAA,OAAO,gBAAA,CAAiB,gBAAgB,QAAQ,CAAA;AACjD;;;AE7IA,YAAA,EAAA;AAYA,qBAAA,EAAA;;;AChBA,YAAA,EAAA;;;ACNA,QAAA,EAAA;AAEA,WAAA,EAAA;AACA,YAAA,EAAA;AAIO,IAAM,gBAAA,GAAmB;AAAA,EAC/B,KAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA;AACD,CAAA;AAEA,IAAM,iBAAA,GAAoB;AAAA,EACzB,gBAAA;AAAA,EACA,eAAA;AAAA,EACA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,YAAA;AAAA,EACA,aAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,iBAAA;AAAA,EACA,YAAA;AAAA,EACA,gBAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA;AAAA,EACA,aAAA;AAAA,EACA,iBAAA;AAAA,EACA,iBAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,eAAA;AAAA,EACA;AACD,CAAA;AAEA,IAAM,qBAAA,GAAgD;AAAA,EACrD,WAAA,EAAa,sCAAA;AAAA,EACb,eAAA,EAAiB,aAAA;AAAA,EACjB,eAAA,EAAiB,cAAA;AAAA,EACjB,gBAAA,EAAkB,cAAA;AAAA,EAClB,YAAA,EAAc,8BAAA;AAAA,EACd,aAAA,EAAe,wBAAA;AAAA,EACf,iBAAA,EAAmB,yBAAA;AAAA,EACnB,YAAA,EAAc,sBAAA;AAAA,EACd,UAAA,EAAY;AACb,CAAA;AAEA,IAAM,qBAAA,GAAgD;AAAA,EACrD,WAAA,EAAa,cAAA;AAAA,EACb,eAAA,EAAiB,QAAA;AAAA,EACjB,gBAAA,EAAkB,QAAA;AAAA,EAClB,YAAA,EAAc,QAAA;AAAA,EACd,aAAA,EAAe,SAAA;AAAA,EACf,iBAAA,EAAmB,UAAA;AAAA,EACnB,YAAA,EAAc,QAAA;AAAA,EACd,UAAA,EAAY;AACb,CAAA;AAEO,SAAS,qBAAA,CACf,KAAA,EACA,QAAA,EACA,MAAA,EACA,oBACA,QAAA,EACU;AACV,EAAA,OAAO,aAAA,CAAc,oBAAA,EAAsB,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ;AAAA,IACnE,kBAAA;AAAA,IACA;AAAA,GACA,CAAA;AACF;AAEO,SAAS,4BAA4B,KAAA,EAAwB;AACnE,EAAA,OAAO,kBAAkB,IAAA,CAAK,CAAC,YAAY,KAAA,CAAM,QAAA,CAAS,OAAO,CAAC,CAAA;AACnE;AAMA,eAAsB,oBAAA,CAAqB,MAAc,KAAA,EAAuC;AAC/F,EAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,OAAA,CAAQ,qBAAqB,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,OAAO,CAAA,KAAM,KAAA,CAAM,QAAA,CAAS,OAAO,CAAC,CAAA;AAC3G,EAAA,IAAI,eAAA,CAAgB,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAEzC,EAAA,IAAI;AACH,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,QAAA,EAAW,IAAI,CAAA,CAAA,EAAI;AAAA,MAC/C,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,WAAA,CAAY,OAAA,CAAQ,gBAAgB;AAAA,KAC5C,CAAA;AAED,IAAA,IAAI,SAAS,MAAA,IAAU,GAAA,IAAO,QAAA,CAAS,MAAA,GAAS,KAAK,OAAO,IAAA;AAC5D,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,KAAA,MAAW,CAAC,OAAA,EAAS,WAAW,CAAA,IAAK,eAAA,EAAiB;AACrD,MAAA,IAAI,YAAY,eAAA,EAAiB;AAChC,QAAA,IAAI,KAAK,QAAA,CAAS,aAAa,KAAK,IAAA,CAAK,QAAA,CAAS,aAAa,CAAA,EAAG;AACjE,UAAA,OAAO,QAAA;AAAA,QACR;AAAA,MACD,CAAA,MAAA,IAAW,IAAA,CAAK,QAAA,CAAS,WAAW,CAAA,EAAG;AACtC,QAAA,OAAO,qBAAA,CAAsB,OAAO,CAAA,IAAK,OAAA;AAAA,MAC1C;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,IAAA;AACR;AAEA,eAAsB,wBAAA,CAAyB,MAAA,EAAgB,SAAA,EAAmB,UAAA,EAAkD;AACnI,EAAA,MAAM,IAAA,GAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA;AACnC,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,IAAI;AACH,IAAA,MAAM,YAAA,GAAe,MAAM,eAAA,CAAgB,IAAA,EAAM,SAAS,UAAU,CAAA;AACpE,IAAA,KAAA,MAAW,YAAY,YAAA,EAAc;AACpC,MAAA,MAAM,QAAQ,QAAA,CAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,EAAE,WAAA,EAAY;AACtD,MAAA,IAAI,CAAC,2BAAA,CAA4B,KAAK,CAAA,EAAG;AAEzC,MAAA,IAAI;AACH,QAAA,MAAM,eAAA,GAAkB,MAAM,eAAA,CAAgB,KAAA,EAAO,KAAK,UAAU,CAAA;AACpE,QAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AACjC,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,qBAAA;AAAA,cACC,CAAA,gBAAA,EAAmB,IAAI,CAAA,QAAA,EAAM,KAAK,CAAA,CAAA;AAAA,cAClC,MAAA;AAAA,cACA,CAAA,UAAA,EAAa,IAAI,CAAA,WAAA,EAAc,KAAK,CAAA,uIAAA,CAAA;AAAA,cACpC,WAAA;AAAA,cACA,CAAC,yBAAyB;AAAA;AAC3B,WACD;AACA,UAAA;AAAA,QACD;AAEA,QAAA,MAAM,iBAAA,GAAoB,MAAM,oBAAA,CAAqB,IAAA,EAAM,KAAK,CAAA;AAChE,QAAA,IAAI,iBAAA,EAAmB;AACtB,UAAA,QAAA,CAAS,IAAA;AAAA,YACR,qBAAA;AAAA,cACC,qCAAqC,iBAAiB,CAAA,CAAA,CAAA;AAAA,cACtD,UAAA;AAAA,cACA,CAAA,UAAA,EAAa,IAAI,CAAA,WAAA,EAAc,KAAK,kCAAkC,iBAAiB,CAAA,gIAAA,CAAA;AAAA,cACvF,UAAA;AAAA,cACA,CAAC,kBAAkB,oCAAoC;AAAA;AACxD,WACD;AAAA,QACD;AAAA,MACD,CAAA,CAAA,MAAQ;AACP,QAAA,QAAA,CAAS,IAAA;AAAA,UACR,qBAAA;AAAA,YACC,CAAA,yBAAA,EAA4B,IAAI,CAAA,QAAA,EAAM,KAAK,CAAA,CAAA;AAAA,YAC3C,MAAA;AAAA,YACA,CAAA,+BAAA,EAAkC,KAAK,CAAA,KAAA,EAAQ,IAAI,CAAA,uEAAA,CAAA;AAAA,YACnD,WAAA;AAAA,YACA,CAAC,+BAA+B;AAAA;AACjC,SACD;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,OAAO,QAAA;AACR;AAEO,SAAS,qBAAqB,MAAA,EAAyB;AAC7D,EAAA,OAAO,qBAAA;AAAA,IACN,iCAAA;AAAA,IACA,MAAA;AAAA,IACA,8CAA8C,MAAM,CAAA,+BAAA,CAAA;AAAA,IACpD,iBAAA;AAAA,IACA,CAAC,8BAA8B;AAAA,GAChC;AACD;;;ADrLA,eAAsB,sBAAA,CAAuB,QAAgB,UAAA,EAAoD;AAChH,EAAA,MAAM,WAAsB,EAAC;AAE7B,EAAA,MAAM,oBAAA,GAAuB,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC1C,gBAAA,CAAiB,IAAI,CAAC,SAAA,KAAc,yBAAyB,MAAA,EAAQ,SAAA,EAAW,UAAU,CAAC;AAAA,GAC5F;AAEA,EAAA,KAAA,MAAW,qBAAqB,oBAAA,EAAsB;AACrD,IAAA,QAAA,CAAS,IAAA,CAAK,GAAG,iBAAiB,CAAA;AAAA,EACnC;AAEA,EAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC1B,IAAA,QAAA,CAAS,IAAA,CAAK,oBAAA,CAAqB,MAAM,CAAC,CAAA;AAAA,EAC3C;AAEA,EAAA,OAAO,gBAAA,CAAiB,sBAAsB,QAAQ,CAAA;AACvD;;;ADYA,aAAA,EAAA;;;AGzCA,YAAA,EAAA;AACA,QAAA,EAAA;AACA,wBAAA,EAAA;AAiBA,eAAsB,uBAAA,CACrB,MAAA,EACA,YAAA,EACA,cAAA,EACyB;AACzB,EAAA,IAAI,OAAA,GAAU,YAAA;AACd,EAAA,MAAM,WAAW,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,IAAI,CAAA;AAClE,EAAA,MAAM,OAAA,GAAU,QAAA,GAAW,QAAA,CAAS,QAAA,CAAS,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,KAAA,KAAU,qBAAqB,CAAA,GAAI,KAAA;AAE1G,EAAA,IAAI,OAAA,EAAS;AACZ,IAAA,MAAM,UAAA,GAAa,MAAM,oBAAA,CAAqB,MAAM,CAAA;AACpD,IAAA,OAAA,GAAU,sBAAA,CAAuB,SAAS,UAAU,CAAA;AAAA,EACrD,WAAW,QAAA,EAAU;AACpB,IAAA,OAAA,GAAU,0BAAA,CAA2B,QAAQ,OAAO,CAAA;AAAA,EACrD;AAEA,EAAA,OAAO,4BAAA,CAA6B,SAAS,cAAc,CAAA;AAC5D;AAEA,SAASC,yBAAwB,MAAA,EAA2C;AAC3E,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACtC,IAAA,MAAM,WAAW,OAAA,CAAQ,QAAA;AACzB,IAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAE/C,IAAA,MAAM,iBAAiB,QAAA,CAAS,cAAA;AAChC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,cAAc,CAAA,EAAG;AAClC,MAAA,KAAA,MAAW,UAAU,cAAA,EAAgB;AACpC,QAAA,IAAI,OAAO,MAAA,KAAW,QAAA,IAAY,OAAO,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AAC3D,UAAA,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,IAAA,EAAK,CAAE,aAAa,CAAA;AAAA,QACxC;AAAA,MACD;AAAA,IACD;AAEA,IAAA,MAAM,iBAAiB,QAAA,CAAS,cAAA;AAChC,IAAA,IAAI,OAAO,cAAA,KAAmB,QAAA,IAAY,eAAe,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AAC3E,MAAA,OAAA,CAAQ,GAAA,CAAI,cAAA,CAAe,IAAA,EAAK,CAAE,aAAa,CAAA;AAAA,IAChD;AAAA,EACD;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,OAAO,CAAA;AAC1B;AAEA,SAAS,2BAA2B,MAAA,EAA2C;AAC9E,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AAErB,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACtC,IAAA,MAAM,WAAW,OAAA,CAAQ,QAAA;AACzB,IAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,QAAA,EAAU;AAE/C,IAAA,MAAM,iBAAiB,QAAA,CAAS,cAAA;AAChC,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,cAAc,CAAA,EAAG;AAEpC,IAAA,KAAA,MAAW,YAAY,cAAA,EAAgB;AACtC,MAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,SAAS,IAAA,EAAK,CAAE,SAAS,CAAA,EAAG;AAC/D,QAAA,SAAA,CAAU,GAAA,CAAI,QAAA,CAAS,IAAA,EAAK,CAAE,aAAa,CAAA;AAAA,MAC5C;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,SAAS,CAAA;AAC5B;AAEA,SAAS,iBAAA,CAAkB,SAAwB,OAAA,EAAqC;AACvF,EAAA,OAAO,OAAA,CAAQ,IAAI,CAAC,MAAA,KAAY,OAAO,QAAA,KAAa,OAAA,CAAQ,QAAA,GAAW,OAAA,GAAU,MAAO,CAAA;AACzF;AAEA,eAAe,4BAAA,CAA6B,SAAwB,cAAA,EAA6D;AAChI,EAAA,MAAM,YAAY,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,KAAK,CAAA;AACpE,EAAA,MAAM,aAAa,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,MAAA,CAAO,aAAa,MAAM,CAAA;AAEtE,EAAA,MAAM,aAAA,GAAgBA,yBAAwB,SAAS,CAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,2BAA2B,UAAU,CAAA;AAC3D,EAAA,IAAI,cAAc,MAAA,KAAW,CAAA,IAAK,aAAA,CAAc,MAAA,KAAW,GAAG,OAAO,OAAA;AAErE,EAAA,MAAM,UAAA,GAAa,MAAM,sBAAA,CAAuB;AAAA,IAC/C,WAAW,cAAA,EAAgB,qBAAA;AAAA,IAC3B,cAAc,cAAA,EAAgB,8BAAA;AAAA,IAC9B,gBAAgB,cAAA,EAAgB;AAAA,GAChC,CAAA;AACD,EAAA,MAAM,eAAe,UAAA,CAAW,QAAA,CAAS,SAAS,CAAA,GAAI,UAAA,CAAW,WAAW,UAAA,CAAW,OAAA;AACvF,EAAA,MAAM,WAAA,GAAc,qBAAA,CAAsB,aAAA,EAAe,YAAY,CAAA;AACrE,EAAA,MAAM,eAAA,GAAkB,gCAAA,CAAiC,aAAA,EAAe,YAAY,CAAA;AAEpF,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAAyB;AACnD,EAAA,KAAA,MAAW,SAAS,CAAC,GAAG,WAAA,EAAa,GAAG,eAAe,CAAA,EAAG;AACzD,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAA,EAAG;AACvC,MAAA,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,QAAA,kBAAU,IAAI,KAAa,CAAA;AAAA,IACpD;AACA,IAAA,KAAA,MAAWC,SAAAA,IAAY,MAAM,OAAA,EAAS;AACrC,MAAA,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,QAAQ,CAAA,EAAG,IAAIA,SAAQ,CAAA;AAAA,IAChD;AAAA,EACD;AAEA,EAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,IAAA,CAAK,aAAA,CAAc,OAAA,EAAS,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,QAAA,EAAU,OAAO,CAAA,MAAO;AAAA,IACzF,QAAA;AAAA,IACA,OAAA,EAAS,KAAA,CAAM,IAAA,CAAK,OAAO;AAAA,GAC5B,CAAE,CAAA;AACF,EAAA,IAAI,eAAA,CAAgB,MAAA,KAAW,CAAA,EAAG,OAAO,OAAA;AAEzC,EAAA,MAAM,aAAA,GAAgB,gBAAgB,GAAA,CAAI,CAAC,UAAU,KAAA,CAAM,QAAQ,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAC9E,EAAA,MAAM,WAAW,eAAA,CAAgB,GAAA,CAAI,CAAC,KAAA,KAAU,GAAG,KAAA,CAAM,QAAQ,CAAA,EAAA,EAAK,KAAA,CAAM,QAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AAC3G,EAAA,MAAM,cAAc,aAAA,CAAc,MAAA,GAAS,KAAK,aAAA,CAAc,MAAA,GAAS,IAAI,IAAA,GAAO,CAAA;AAClF,EAAA,MAAM,cAAA,GAAiB,WAAW,MAAA,KAAW,SAAA,GAAY,OAAO,UAAA,CAAW,MAAA,KAAW,UAAU,GAAA,GAAM,IAAA;AACtG,EAAA,MAAM,kBAAA,GAAqB,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,iBAAiB,WAAW,CAAA;AAEtE,EAAA,MAAM,WAAA,GAAc,SAAA,IAAa,gBAAA,CAAiB,KAAA,EAAO,EAAE,CAAA;AAC3D,EAAA,MAAM,UAAA,GAAa,iBAAiB,KAAA,EAAO;AAAA,IAC1C,GAAG,WAAA,CAAY,QAAA;AAAA,IACf,aAAA,CAAc,OAAO,kCAAA,EAAoC,MAAA,EAAQ,yBAAyB,aAAa,CAAA,YAAA,EAAe,QAAQ,CAAA,CAAA,CAAA,EAAK;AAAA,MAClI,aAAA,EAAe,UAAA;AAAA,MACf,SAAA,EAAW,eAAA,CAAgB,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,IAAA,EAAM,KAAA,CAAM,QAAA,EAAU,OAAA,EAAS,KAAA,CAAM,OAAA,EAAQ,CAAE,CAAA;AAAA,MAC5F,WAAA,EAAa;AAAA,QACZ,UAAA,EAAY,aAAA;AAAA,QACZ;AAAA,OACD;AAAA,MACA,kBAAA;AAAA,MACA,iBAAiB,UAAA,CAAW,MAAA;AAAA,MAC5B,kBAAkB,UAAA,CAAW,OAAA;AAAA,MAC7B,oBAAoB,UAAA,CAAW;AAAA,KAC/B;AAAA,GACD,CAAA;AAED,EAAA,OAAO,iBAAA,CAAkB,SAAS,UAAU,CAAA;AAC7C;AAEA,SAASC,iBAAgB,MAAA,EAA+B;AACvD,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA;AAC9B,EAAA,IAAI,KAAA,CAAM,MAAA,IAAU,CAAA,EAAG,OAAO,IAAA;AAC9B,EAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AAC/B;AAEA,eAAe,qBAAqB,MAAA,EAAkC;AACrE,EAAA,MAAM,MAAA,GAASA,iBAAgB,MAAM,CAAA;AACrC,EAAA,IAAI,CAAC,QAAQ,OAAO,KAAA;AAEpB,EAAA,IAAI;AACH,IAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,CAAA,OAAA,EAAU,MAAM,CAAA,CAAE,CAAA;AACxD,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,IAAA,CAAK,CAAC,MAAA,KAAW,OAAO,WAAA,EAAY,CAAE,UAAA,CAAW,UAAU,CAAC,CAAA;AACxF,IAAA,IAAI,CAAC,aAAa,OAAO,KAAA;AAEzB,IAAA,MAAM,IAAA,GAAO,eAAe,WAAW,CAAA;AACvC,IAAA,MAAM,eAAA,GAAkB,KAAK,GAAA,CAAI,IAAI,KAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,IAAK,EAAA;AAC3D,IAAA,OAAO,eAAA,KAAoB,gBAAgB,eAAA,KAAoB,QAAA;AAAA,EAChE,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,KAAA;AAAA,EACR;AACD;AAEA,SAAS,uBAAuB,OAAA,EAAqD;AACpF,EAAA,MAAM,IAAA,GAAO,GAAG,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,MAAM,GAAG,WAAA,EAAY;AAC9D,EAAA,OAAO,+DAAA,CAAgE,KAAK,IAAI,CAAA;AACjF;AAEA,SAAS,0BAAA,CAA2B,QAAgB,OAAA,EAAuC;AAC1F,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC9B,IAAA,IAAI,MAAA,CAAO,QAAA,KAAa,SAAA,EAAW,OAAO,MAAA;AAC1C,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,KAAY;AACjD,MAAA,IAAI,OAAA,CAAQ,UAAU,qCAAA,EAAuC;AAC5D,QAAA,OAAO;AAAA,UACN,GAAG,OAAA;AAAA,UACH,MAAA,EAAQ,uDAAuD,MAAM,CAAA,oIAAA;AAAA,SACtE;AAAA,MACD;AACA,MAAA,OAAO,OAAA;AAAA,IACR,CAAC,CAAA;AACD,IAAA,OAAO,gBAAA,CAAiB,MAAA,CAAO,QAAA,EAAU,QAAQ,CAAA;AAAA,EAClD,CAAC,CAAA;AACF;AAEA,SAAS,sBAAA,CAAuB,SAAwB,eAAA,EAAyC;AAChG,EAAA,MAAM,eAAA,GAAmC,CAAC,KAAA,EAAO,OAAA,EAAS,QAAQ,SAAS,CAAA;AAC3E,EAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,CAAC,MAAA,KAAW;AAC9B,IAAA,IAAI,CAAC,eAAA,CAAgB,QAAA,CAAS,MAAA,CAAO,QAAQ,GAAG,OAAO,MAAA;AACvD,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,KAAY;AACjD,MAAA,IAAA,CAAK,OAAA,CAAQ,aAAa,UAAA,IAAc,OAAA,CAAQ,aAAa,MAAA,KAAW,sBAAA,CAAuB,OAAO,CAAA,EAAG;AACxG,QAAA,MAAM,MAAA,GAAS,kBACZ,gFAAA,GACA,0CAAA;AACH,QAAA,OAAO,EAAE,GAAG,OAAA,EAAS,QAAA,EAAU,MAAA,EAAiB,MAAA,EAAQ,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA,CAAA,EAAI;AAAA,MACzF;AACA,MAAA,OAAO,OAAA;AAAA,IACR,CAAC,CAAA;AACD,IAAA,OAAO,gBAAA,CAAiB,MAAA,CAAO,QAAA,EAAU,QAAQ,CAAA;AAAA,EAClD,CAAC,CAAA;AACF;;;AC5LO,SAAS,qBAAqB,MAAA,EAAsC;AAC1E,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,QAAA,EAAU,CAAC,CAAC,CAAC,CAAA;AAE7D,EAAA,MAAM,OAAA,GAAU,UAAA,CAAW,GAAA,CAAI,IAAI,CAAA;AACnC,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,KAAK,CAAA;AACrC,EAAA,MAAM,UAAA,GAAa,UAAA,CAAW,GAAA,CAAI,OAAO,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACvC,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA;AAC5C,EAAA,MAAM,WAAA,GAAc,UAAA,CAAW,GAAA,CAAI,QAAQ,CAAA;AAC3C,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AAOvC,EAAA,MAAM,OAAA,GAAU,OAAA,IAAW,IAAA,IAAQ,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,qBAAqB,CAAA;AACjG,EAAA,IAAI,OAAA,EAAS;AACZ,IAAA,MAAMC,UAAAA,GAAY,aAAa,MAAA,IAAU,KAAA;AACzC,IAAA,OAAO;AAAA,MACN,KAAA,EAAOA,aAAY,CAAA,GAAI,CAAA;AAAA,MACvB,KAAA,EAAOA,aAAY,UAAA,GAAa,aAAA;AAAA,MAChC,WAAA,EAAaA,aACV,uEAAA,GACA,sDAAA;AAAA,MACH,QAAA,EAAUA,aAAY,EAAA,GAAK;AAAA,KAC5B;AAAA,EACD;AAGA,EAAA,MAAM,MAAA,GAAS,QAAA,IAAY,IAAA,IAAQ,CAAC,QAAA,CAAS,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,gBAAA,CAAiB,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AAGhG,EAAA,MAAM,QAAA,GAAW,UAAA,IAAc,IAAA,IAAQ,CAAC,UAAA,CAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,kBAAA,CAAmB,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AACxG,EAAA,MAAM,eAAA,GAAkB,UAAA,EAAY,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,qBAAA,CAAsB,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA,IAAK,KAAA;AACjG,EAAA,MAAM,qBAAA,GAAwB,UAAA,EAAY,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,2BAAA,CAA4B,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA,IAAK,KAAA;AAE7G,EAAA,MAAM,iBAAA,GAAoB,QAAA,IAAY,CAAC,eAAA,IAAmB,CAAC,qBAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,UAAA,IAAc,IAAA,IAAQ,CAAC,UAAA,CAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,yBAAA,CAA0B,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AAG7G,EAAA,MAAM,OAAA,GAAU,SAAA,IAAa,IAAA,IAAQ,CAAC,SAAA,CAAU,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,wBAAA,CAAyB,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA;AAG3G,EAAA,MAAM,SAAA,GAAY,aAAa,MAAA,IAAU,KAAA;AACzC,EAAA,MAAM,SAAA,GAAY,aAAa,MAAA,IAAU,KAAA;AACzC,EAAA,MAAM,OAAA,GAAU,SAAA,EAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,yBAAA,CAA0B,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA,IAAK,KAAA;AAG5F,EAAA,MAAM,SAAA,GAAY,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACvC,EAAA,MAAM,OAAA,GAAU,SAAA,EAAW,QAAA,CAAS,IAAA,CAAK,CAAC,CAAA,KAAM,uBAAA,CAAwB,IAAA,CAAK,CAAA,CAAE,KAAK,CAAC,CAAA,IAAK,KAAA;AAG1F,EAAA,MAAM,WAAA,GAAc,MAAA,IAAU,OAAA,IAAW,QAAA,KAAa,iBAAA,IAAqB,qBAAA,CAAA;AAC3E,EAAA,MAAM,cAAA,GAAiB,CAAC,SAAA,EAAW,SAAA,EAAW,SAAS,OAAO,CAAA,CAAE,MAAA,CAAO,OAAO,CAAA,CAAE,MAAA;AAEhF,EAAA,IAAI,WAAA,IAAe,kBAAkB,CAAA,EAAG;AACvC,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,CAAA;AAAA,MACP,KAAA,EAAO,UAAA;AAAA,MACP,WAAA,EAAa,qEAAA;AAAA,MACb,QAAA,EAAU;AAAA,KACX;AAAA,EACD;AAGA,EAAA,IAAI,WAAA,EAAa;AAChB,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,CAAA;AAAA,MACP,KAAA,EAAO,WAAA;AAAA,MACP,WAAA,EAAa,8FAAA;AAAA,MACb,QAAA,EAAU;AAAA,KACX;AAAA,EACD;AAGA,EAAA,IAAI,MAAA,IAAU,QAAA,IAAY,eAAA,IAAmB,MAAA,EAAQ;AACpD,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,CAAA;AAAA,MACP,KAAA,EAAO,YAAA;AAAA,MACP,WAAA,EAAa,0EAAA;AAAA,MACb,QAAA,EAAU;AAAA,KACX;AAAA,EACD;AAGA,EAAA,IAAI,UAAU,QAAA,EAAU;AACvB,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,CAAA;AAAA,MACP,KAAA,EAAO,OAAA;AAAA,MACP,WAAA,EAAa,gEAAA;AAAA,MACb,QAAA,EAAU;AAAA,KACX;AAAA,EACD;AAGA,EAAA,OAAO;AAAA,IACN,KAAA,EAAO,CAAA;AAAA,IACP,KAAA,EAAO,aAAA;AAAA,IACP,WAAA,EAAa,0EAAA;AAAA,IACb,QAAA,EAAU;AAAA,GACX;AACD;;;ACvHA,IAAM,eAAA,GAAkB,gBAAA;AAEjB,SAAS,kBAAA,CAAmB,KAAA,EAAe,SAAA,GAAY,GAAA,EAAa;AAC1E,EAAA,MAAM,UAAU,aAAA,CAAc,KAAA,EAAO,YAAY,CAAC,CAAA,CAChD,QAAQ,wBAAA,EAA0B,EAAE,CAAA,CACpC,OAAA,CAAQ,iBAAiB,GAAG,CAAA,CAC5B,QAAQ,MAAA,EAAQ,GAAG,EACnB,IAAA,EAAK;AAEP,EAAA,IAAI,OAAA,CAAQ,UAAU,SAAA,EAAW;AAChC,IAAA,OAAO,OAAA;AAAA,EACR;AAEA,EAAA,OAAO,CAAA,EAAG,QAAQ,KAAA,CAAM,CAAA,EAAG,YAAY,CAAC,CAAA,CAAE,SAAS,CAAA,GAAA,CAAA;AACpD;;;ACGO,IAAM,YAAA,GAAoD;AAAA,EAChE,2BAAA,EAA6B;AAAA,IAC5B,KAAA,EAAO,+CAAA;AAAA,IACP,QAAA,EAAU,UAAA;AAAA,IACV,WAAA,EACC,2NAAA;AAAA,IACD,MAAA,EAAQ,sHAAA;AAAA,IACR,mBAAA,EACC,2HAAA;AAAA,IACD,cAAA,EAAgB,kHAAA;AAAA,IAChB,UAAA,EAAY;AAAA,MACX,mDAAA;AAAA,MACA,yDAAA;AAAA,MACA;AAAA;AACD,GACD;AAAA,EACA,uBAAA,EAAyB;AAAA,IACxB,KAAA,EAAO,qDAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,oJAAA;AAAA,IACD,MAAA,EAAQ,4GAAA;AAAA,IACR,mBAAA,EAAqB,mHAAA;AAAA,IACrB,cAAA,EAAgB,iHAAA;AAAA,IAChB,UAAA,EAAY;AAAA,MACX,mDAAA;AAAA,MACA;AAAA;AACD,GACD;AAAA,EACA,uBAAA,EAAyB;AAAA,IACxB,KAAA,EAAO,iCAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,mHAAA;AAAA,IACb,cAAA,EAAgB,2EAAA;AAAA,IAChB,UAAA,EAAY,CAAC,mDAAmD;AAAA,GACjE;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,eAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,2IAAA;AAAA,IACD,cAAA,EAAgB,sGAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,uBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,kHAAA;AAAA,IACb,MAAA,EAAQ,yGAAA;AAAA,IACR,mBAAA,EACC,oHAAA;AAAA,IACD,cAAA,EACC,uIAAA;AAAA,IACD,UAAA,EAAY,CAAC,+CAAA,EAAiD,qEAAqE;AAAA,GACpI;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,eAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,6GAAA;AAAA,IACb,MAAA,EAAQ,kGAAA;AAAA,IACR,mBAAA,EAAqB,gGAAA;AAAA,IACrB,cAAA,EAAgB,4FAAA;AAAA,IAChB,UAAA,EAAY,CAAC,2DAA2D;AAAA,GACzE;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,qBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,sNAAA;AAAA,IACD,MAAA,EAAQ,+GAAA;AAAA,IACR,mBAAA,EAAqB,6GAAA;AAAA,IACrB,cAAA,EAAgB,sHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,qEAAqE;AAAA,GACpI;AAAA,EACA,UAAA,EAAY;AAAA,IACX,KAAA,EAAO,wBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,4JAAA;AAAA,IACD,cAAA,EACC,sIAAA;AAAA,IACD,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,UAAA,EAAY;AAAA,IACX,KAAA,EAAO,uBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,6JAAA;AAAA,IACD,MAAA,EAAQ,sGAAA;AAAA,IACR,mBAAA,EAAqB,qGAAA;AAAA,IACrB,cAAA,EAAgB,wGAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,uEAAuE;AAAA,GACtI;AAAA,EACA,aAAA,EAAe;AAAA,IACd,KAAA,EAAO,4BAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,qHAAA;AAAA,IACb,MAAA,EAAQ,iGAAA;AAAA,IACR,mBAAA,EAAqB,yGAAA;AAAA,IACrB,cAAA,EAAgB,2GAAA;AAAA,IAChB,UAAA,EAAY,CAAC,2DAA2D;AAAA,GACzE;AAAA,EACA,SAAA,EAAW;AAAA,IACV,KAAA,EAAO,gBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,kIAAA;AAAA,IACD,cAAA,EAAgB,yFAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,SAAA,EAAW;AAAA,IACV,KAAA,EAAO,uBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,2JAAA;AAAA,IACD,MAAA,EAAQ,uGAAA;AAAA,IACR,mBAAA,EACC,2HAAA;AAAA,IACD,cAAA,EAAgB,qGAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,sEAAsE;AAAA,GACrI;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,gBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,oIAAA;AAAA,IACD,cAAA,EAAgB,uFAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,sBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,yKAAA;AAAA,IACD,MAAA,EAAQ,qGAAA;AAAA,IACR,mBAAA,EAAqB,yHAAA;AAAA,IACrB,cAAA,EAAgB,iHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,yDAAyD;AAAA,GACxH;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,mBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,yEAAA;AAAA,IACb,cAAA,EAAgB,oFAAA;AAAA,IAChB,UAAA,EAAY,CAAC,6BAA6B;AAAA,GAC3C;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,qBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,gJAAA;AAAA,IACD,MAAA,EAAQ,2FAAA;AAAA,IACR,mBAAA,EAAqB,sHAAA;AAAA,IACrB,cAAA,EAAgB,wGAAA;AAAA,IAChB,UAAA,EAAY,CAAC,0BAAA,EAA4B,iCAAiC;AAAA,GAC3E;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,kCAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,6EAAA;AAAA,IACb,MAAA,EAAQ,+GAAA;AAAA,IACR,mBAAA,EAAqB,qGAAA;AAAA,IACrB,cAAA,EAAgB,yFAAA;AAAA,IAChB,UAAA,EAAY,CAAC,iCAAiC;AAAA,GAC/C;AAAA,EACA,UAAA,EAAY;AAAA,IACX,KAAA,EAAO,yBAAA;AAAA,IACP,QAAA,EAAU,QAAA;AAAA,IACV,WAAA,EACC,0LAAA;AAAA,IACD,MAAA,EAAQ,wGAAA;AAAA,IACR,mBAAA,EAAqB,0GAAA;AAAA,IACrB,cAAA,EACC,sJAAA;AAAA,IACD,UAAA,EAAY,CAAC,6BAAA,EAA+B,qFAAqF;AAAA,GAClI;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,+BAAA;AAAA,IACP,QAAA,EAAU,KAAA;AAAA,IACV,WAAA,EACC,+HAAA;AAAA,IACD,MAAA,EAAQ,oGAAA;AAAA,IACR,mBAAA,EAAqB,kHAAA;AAAA,IACrB,cAAA,EACC,8IAAA;AAAA,IACD,UAAA,EAAY;AAAA,MACX,0BAAA;AAAA,MACA;AAAA;AACD,GACD;AAAA,EACA,YAAA,EAAc;AAAA,IACb,KAAA,EAAO,iBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,qHAAA;AAAA,IACb,cAAA,EAAgB,0FAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,YAAA,EAAc;AAAA,IACb,KAAA,EAAO,yBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EACC,yIAAA;AAAA,IACD,MAAA,EAAQ,wFAAA;AAAA,IACR,mBAAA,EAAqB,kGAAA;AAAA,IACrB,cAAA,EACC,+HAAA;AAAA,IACD,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,eAAA,EAAiB;AAAA,IAChB,KAAA,EAAO,yBAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,wFAAA;AAAA,IACb,MAAA,EAAQ,0GAAA;AAAA,IACR,mBAAA,EAAqB,4GAAA;AAAA,IACrB,cAAA,EAAgB,8FAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,uBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,gFAAA;AAAA,IACb,cAAA,EAAgB,yHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,4BAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,2HAAA;AAAA,IACb,MAAA,EAAQ,4FAAA;AAAA,IACR,mBAAA,EAAqB,yFAAA;AAAA,IACrB,cAAA,EAAgB,wHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,oEAAoE;AAAA,GACnI;AAAA,EACA,UAAA,EAAY;AAAA,IACX,KAAA,EAAO,qCAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,wGAAA;AAAA,IACb,MAAA,EAAQ,4GAAA;AAAA,IACR,mBAAA,EAAqB,wFAAA;AAAA,IACrB,cAAA,EAAgB,yGAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,wBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,0IAAA;AAAA,IACb,cAAA,EAAgB,gHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,QAAA,EAAU;AAAA,IACT,KAAA,EAAO,sBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,4HAAA;AAAA,IACb,MAAA,EAAQ,2GAAA;AAAA,IACR,mBAAA,EAAqB,6GAAA;AAAA,IACrB,cAAA,EAAgB,gHAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,qEAAqE;AAAA,GACpI;AAAA,EACA,WAAA,EAAa;AAAA,IACZ,KAAA,EAAO,8BAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,gHAAA;AAAA,IACb,MAAA,EAAQ,4GAAA;AAAA,IACR,mBAAA,EAAqB,4FAAA;AAAA,IACrB,cAAA,EAAgB,qIAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,sBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,kGAAA;AAAA,IACb,cAAA,EAAgB,0EAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,qBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,2IAAA;AAAA,IACb,MAAA,EAAQ,mFAAA;AAAA,IACR,mBAAA,EAAqB,oGAAA;AAAA,IACrB,cAAA,EAAgB,4HAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAAA,EAAiD,+CAA+C;AAAA,GAC9G;AAAA,EACA,UAAA,EAAY;AAAA,IACX,KAAA,EAAO,6BAAA;AAAA,IACP,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,iHAAA;AAAA,IACb,MAAA,EAAQ,mFAAA;AAAA,IACR,mBAAA,EAAqB,+FAAA;AAAA,IACrB,cAAA,EAAgB,4EAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,oBAAA;AAAA,IACP,QAAA,EAAU,MAAA;AAAA,IACV,WAAA,EAAa,gEAAA;AAAA,IACb,cAAA,EAAgB,oEAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,MAAA,EAAQ;AAAA,IACP,KAAA,EAAO,oCAAA;AAAA,IACP,QAAA,EAAU,KAAA;AAAA,IACV,WAAA,EAAa,kGAAA;AAAA,IACb,MAAA,EAAQ,sEAAA;AAAA,IACR,mBAAA,EAAqB,sFAAA;AAAA,IACrB,cAAA,EAAgB,6EAAA;AAAA,IAChB,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,OAAA,EAAS;AAAA,IACR,KAAA,EAAO,wBAAA;AAAA,IACP,QAAA,EAAU,QAAA;AAAA,IACV,WAAA,EACC,2LAAA;AAAA,IACD,MAAA,EAAQ,wHAAA;AAAA,IACR,mBAAA,EAAqB,+FAAA;AAAA,IACrB,cAAA,EACC,yHAAA;AAAA,IACD,UAAA,EAAY,CAAC,+CAA+C;AAAA,GAC7D;AAAA,EACA,SAAA,EAAW;AAAA,IACV,KAAA,EAAO,qBAAA;AAAA,IACP,QAAA,EAAU,QAAA;AAAA,IACV,WAAA,EACC,iHAAA;AAAA,IACD,MAAA,EAAQ,0FAAA;AAAA,IACR,mBAAA,EAAqB,6GAAA;AAAA,IACrB,cAAA,EACC,gIAAA;AAAA,IACD,UAAA,EAAY,CAAC,+CAAA,EAAiD,+CAA+C;AAAA;AAE/G,CAAA;AAEO,IAAM,mBAAA,GAA2C;AAAA,EACvD,KAAA,EAAO,yBAAA;AAAA,EACP,QAAA,EAAU,MAAA;AAAA,EACV,WAAA,EAAa,yGAAA;AAAA,EACb,cAAA,EAAgB,2EAAA;AAAA,EAChB,UAAA,EAAY,CAAC,sDAAsD;AACpE,CAAA;AAEO,IAAM,qBAAA,GAAgD;AAAA,EAC5D,GAAA,EAAK,KAAA;AAAA,EACL,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ,QAAA;AAAA,EACR,GAAA,EAAK,KAAA;AAAA,EACL,OAAA,EAAS,SAAA;AAAA,EACT,EAAA,EAAI,IAAA;AAAA,EACJ,GAAA,EAAK,KAAA;AAAA,EACL,EAAA,EAAI,IAAA;AAAA,EACJ,kBAAA,EAAoB;AACrB,CAAA;AAEO,IAAM,wBAAA,GAA4D;AAAA,EACxE,GAAA,EAAK;AAAA,IACJ,MAAA,EAAQ,sFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,KAAA,EAAO;AAAA,IACN,MAAA,EAAQ,8DAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,IAAA,EAAM;AAAA,IACL,MAAA,EAAQ,wFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,MAAA,EAAQ;AAAA,IACP,MAAA,EAAQ,oEAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,GAAA,EAAK;AAAA,IACJ,MAAA,EAAQ,wFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,OAAA,EAAS;AAAA,IACR,MAAA,EAAQ,6EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,EAAA,EAAI;AAAA,IACH,MAAA,EAAQ,4EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,GAAA,EAAK;AAAA,IACJ,MAAA,EAAQ,6EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,EAAA,EAAI;AAAA,IACH,MAAA,EAAQ,yEAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,kBAAA,EAAoB;AAAA,IACnB,MAAA,EAAQ,kEAAA;AAAA,IACR,mBAAA,EAAqB;AAAA;AAEvB,CAAA;AAEO,IAAM,wBAAA,GAA4D;AAAA,EACxE,QAAA,EAAU;AAAA,IACT,MAAA,EAAQ,2EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,IAAA,EAAM;AAAA,IACL,MAAA,EAAQ,qEAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,MAAA,EAAQ;AAAA,IACP,MAAA,EAAQ,6EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,OAAA,EAAS;AAAA,IACR,MAAA,EAAQ,2EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,IAAA,EAAM;AAAA,IACL,MAAA,EAAQ,+DAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA,GAAA,EAAK;AAAA,IACJ,MAAA,EAAQ,yDAAA;AAAA,IACR,mBAAA,EAAqB;AAAA;AAEvB,CAAA;AAEO,IAAM,qBAAA,GAA8C;AAAA,EAC1D;AAAA,IACC,SAAA,EAAW,MAAA;AAAA,IACX,aAAA,EAAe,CAAC,cAAc,CAAA;AAAA,IAC9B,MAAA,EAAQ,8EAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,KAAA;AAAA,IACX,aAAA,EAAe,CAAC,gBAAA,EAAkB,2BAAA,EAA6B,eAAe,CAAA;AAAA,IAC9E,MAAA,EAAQ,8FAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,OAAA;AAAA,IACX,aAAA,EAAe,CAAC,wBAAwB,CAAA;AAAA,IACxC,MAAA,EAAQ,kFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,IAAA;AAAA,IACX,aAAA,EAAe,CAAC,qBAAA,EAAuB,wBAAwB,CAAA;AAAA,IAC/D,MAAA,EAAQ,mFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,IAAA;AAAA,IACX,aAAA,EAAe,CAAC,eAAA,EAAiB,YAAA,EAAc,0BAA0B,CAAA;AAAA,IACzE,MAAA,EAAQ,gGAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,KAAA;AAAA,IACX,aAAA,EAAe,CAAC,gBAAA,EAAkB,WAAA,EAAa,OAAO,CAAA;AAAA,IACtD,MAAA,EAAQ,iGAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,KAAA;AAAA,IACX,aAAA,EAAe,CAAC,sBAAA,EAAwB,sBAAsB,CAAA;AAAA,IAC9D,cAAA,EAAgB,CAAC,MAAA,EAAQ,kBAAkB,CAAA;AAAA,IAC3C,MAAA,EAAQ,kGAAA;AAAA,IACR,mBAAA,EAAqB;AAAA,GACtB;AAAA,EACA;AAAA,IACC,SAAA,EAAW,SAAA;AAAA,IACX,aAAA,EAAe,CAAC,YAAA,EAAc,cAAA,EAAgB,SAAS,CAAA;AAAA,IACvD,MAAA,EAAQ,qFAAA;AAAA,IACR,mBAAA,EAAqB;AAAA;AAEvB,CAAA;;;AC5cA,SAAS,WAAA,CAAY,YAAkC,MAAA,EAAyB;AAC/E,EAAA,IAAI,CAAC,UAAA,IAAc,UAAA,CAAW,MAAA,KAAW,GAAG,OAAO,IAAA;AACnD,EAAA,OAAO,WAAW,IAAA,CAAK,CAAC,UAAU,MAAA,CAAO,QAAA,CAAS,KAAK,CAAC,CAAA;AACzD;AAEA,SAAS,yBAAyB,MAAA,EAIF;AAC/B,EAAA,MAAM,SAAA,GAAY,MAAA,CAAO,SAAA,EAAW,WAAA,EAAY;AAChD,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,EAAO,WAAA,EAAY,IAAK,EAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,MAAA,CAAO,MAAA,EAAQ,WAAA,EAAY,IAAK,EAAA;AAE/C,EAAA,KAAA,MAAW,QAAQ,qBAAA,EAAuB;AACzC,IAAA,IAAI,IAAA,CAAK,SAAA,IAAa,SAAA,IAAa,IAAA,CAAK,cAAc,SAAA,EAAW;AACjE,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,aAAA,EAAe,KAAK,CAAA,EAAG;AAC7C,IAAA,IAAI,CAAC,WAAA,CAAY,IAAA,CAAK,cAAA,EAAgB,MAAM,CAAA,EAAG;AAC/C,IAAA,OAAO;AAAA,MACN,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,qBAAqB,IAAA,CAAK;AAAA,KAC3B;AAAA,EACD;AAEA,EAAA,OAAO,MAAA;AACR;AAEA,SAAS,sBAAsB,KAAA,EAAkE;AAChG,EAAA,IAAI,CAAC,OAAO,OAAO,MAAA;AACnB,EAAA,IAAI,CAAC,KAAA,CAAM,MAAA,IAAU,CAAC,KAAA,CAAM,qBAAqB,OAAO,MAAA;AACxD,EAAA,OAAO;AAAA,IACN,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,qBAAqB,KAAA,CAAM;AAAA,GAC5B;AACD;AAMO,SAAS,uBAAuB,MAAA,EAOnB;AACnB,EAAA,MAAM,mBAAA,GAAsB,MAAA,CAAO,SAAA,EAAW,WAAA,EAAY;AAC1D,EAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,MAAA,EAAQ,WAAA,EAAY;AACpD,EAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,QAAA,EAAU,WAAA,EAAY;AACxD,EAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,GAAW,qBAAA,CAAsB,OAAO,QAAA,CAAS,WAAA,EAAa,CAAA,GAAI,MAAA;AAElG,EAAA,IAAI,uBAAuB,gBAAA,EAAkB;AAC5C,IAAA,MAAM,SAAA,GAAY,sBAAsB,YAAA,CAAa,CAAA,EAAG,mBAAmB,CAAA,CAAA,EAAI,gBAAgB,EAAE,CAAC,CAAA;AAClG,IAAA,IAAI,WAAW,OAAO,SAAA;AAAA,EACvB;AAEA,EAAA,IAAI,uBAAuB,kBAAA,EAAoB;AAC9C,IAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,YAAA,CAAa,CAAA,EAAG,mBAAmB,IAAI,kBAAA,CAAmB,WAAA,EAAa,CAAA,CAAE,CAAC,CAAA;AAClH,IAAA,IAAI,WAAW,OAAO,SAAA;AAAA,EACvB;AAEA,EAAA,IAAI,oBAAoB,gBAAA,EAAkB;AACzC,IAAA,MAAM,SAAA,GAAY,sBAAsB,YAAA,CAAa,CAAA,EAAG,gBAAgB,CAAA,CAAA,EAAI,gBAAgB,EAAE,CAAC,CAAA;AAC/F,IAAA,IAAI,WAAW,OAAO,SAAA;AAAA,EACvB;AAEA,EAAA,IAAI,oBAAoB,kBAAA,EAAoB;AAC3C,IAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,YAAA,CAAa,CAAA,EAAG,gBAAgB,IAAI,kBAAA,CAAmB,WAAA,EAAa,CAAA,CAAE,CAAC,CAAA;AAC/G,IAAA,IAAI,WAAW,OAAO,SAAA;AAAA,EACvB;AAEA,EAAA,MAAM,oBAAoB,wBAAA,CAAyB;AAAA,IAClD,WAAW,mBAAA,IAAuB,gBAAA;AAAA,IAClC,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,QAAQ,MAAA,CAAO;AAAA,GACf,CAAA;AACD,EAAA,IAAI,mBAAmB,OAAO,iBAAA;AAE9B,EAAA,IAAI,mBAAA,IAAuB,wBAAA,CAAyB,mBAAmB,CAAA,EAAG;AACzE,IAAA,OAAO,yBAAyB,mBAAmB,CAAA;AAAA,EACpD;AAEA,EAAA,IAAI,gBAAA,IAAoB,wBAAA,CAAyB,gBAAgB,CAAA,EAAG;AACnE,IAAA,OAAO,yBAAyB,gBAAgB,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,kBAAA,IAAsB,wBAAA,CAAyB,kBAAkB,CAAA,EAAG;AACvE,IAAA,OAAO,yBAAyB,kBAAkB,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,EAAC;AACT;AAEO,SAAS,cAAA,CAAe,SAAA,EAAmB,MAAA,EAAgB,OAAA,EAAqC;AACtG,EAAA,MAAM,cAAA,GAAiB,UAAU,WAAA,EAAY;AAC7C,EAAA,MAAM,MAAM,CAAA,EAAG,cAAc,CAAA,CAAA,EAAI,MAAA,CAAO,aAAa,CAAA,CAAA;AAGrD,EAAA,IAAI,KAAA,GAAyC,aAAa,GAAG,CAAA;AAG7D,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,KAAA,GAAQ,mBAAA;AAAA,EACT;AAEA,EAAA,MAAM,SAAA,GAAY,uBAAuB,EAAE,SAAA,EAAW,gBAAgB,MAAA,EAAQ,MAAA,EAAQ,SAAS,CAAA;AAE/F,EAAA,OAAO;AAAA,IACN,SAAA,EAAW,cAAA;AAAA,IACX,MAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAG,KAAA;AAAA,IACH,MAAA,EAAQ,KAAA,CAAM,MAAA,IAAU,SAAA,CAAU,MAAA;AAAA,IAClC,mBAAA,EAAqB,KAAA,CAAM,mBAAA,IAAuB,SAAA,CAAU;AAAA,GAC7D;AACD;AAEO,SAAS,kBAAkB,MAAA,EAAmC;AACpE,EAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,GAAA,EAAM,MAAA,CAAO,KAAK,CAAA,CAAA,EAAI,CAAA,gBAAA,EAAmB,MAAA,CAAO,SAAS,CAAA,eAAA,EAAkB,MAAA,CAAO,MAAM,IAAI,EAAE,CAAA;AAE7G,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,mBAAA,CAAA,EAAuB,MAAA,CAAO,WAAA,EAAa,EAAE,CAAA;AAExD,EAAA,IAAI,OAAO,MAAA,EAAQ;AAClB,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,oBAAA,CAAA,EAAwB,MAAA,CAAO,MAAA,EAAQ,EAAE,CAAA;AAAA,EACrD;AAEA,EAAA,IAAI,OAAO,mBAAA,EAAqB;AAC/B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,wBAAA,CAAA,EAA4B,MAAA,CAAO,mBAAA,EAAqB,EAAE,CAAA;AAAA,EACtE;AAEA,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,CAAA,EAAsB,MAAA,CAAO,cAAA,EAAgB,IAAI,CAAA,cAAA,CAAA,EAAkB,GAAG,MAAA,CAAO,UAAA,CAAW,IAAI,CAAC,SAAA,KAAc,CAAA,EAAA,EAAK,SAAS,EAAE,CAAC,CAAA;AACvI,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACvB;;;AC/IO,SAAS,0BAA0B,MAAA,EAAgD;AACzF,EAAA,OAAO;AAAA,IACN,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,KAAA,EAAO,OAAO,KAAA,CAAM,OAAA;AAAA,IACpB,KAAA,EAAO,OAAO,KAAA,CAAM,KAAA;AAAA,IACpB,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,OAAA,IAAW,EAAA;AAAA,IAChC,aAAA,EAAe,MAAA,CAAO,QAAA,EAAU,KAAA,IAAS,IAAA;AAAA,IACzC,aAAA,EAAe,MAAA,CAAO,QAAA,EAAU,KAAA,IAAS,IAAA;AAAA,IACzC,cAAA,EAAgB,OAAO,KAAA,CAAM,cAAA;AAAA,IAC7B,aAAA,EAAe;AAAA,MACd,QAAA,EAAU,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,UAAU,CAAA,CAAE,MAAA;AAAA,MACzE,IAAA,EAAM,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AAAA,MACjE,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,QAAQ,CAAA,CAAE,MAAA;AAAA,MACrE,GAAA,EAAK,MAAA,CAAO,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,KAAK,CAAA,CAAE;AAAA,KAChE;AAAA,IACA,cAAA,EAAgB,MAAA,CAAO,OAAA,EAAS,OAAA,IAAW,cAAA;AAAA,IAC3C,cAAA,EAAA,CAAiB,MAAA,CAAO,OAAA,EAAS,OAAA,IAAW,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAC,CAAA;AAAA,IACpF,WAAA,EAAa,OAAO,WAAA,IAAe,IAAA;AAAA,IACnC,oBAAA,EAAsB,OAAO,oBAAA,IAAwB,IAAA;AAAA,IACrD,WAAW,MAAA,CAAO,SAAA;AAAA,IAClB,QAAQ,MAAA,CAAO;AAAA,GAChB;AACD;AAEO,SAAS,iBAAiB,MAAA,EAAkC;AAClE,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,mBAAA,EAAsB,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAChD,EAAA,KAAA,CAAM,KAAK,CAAA,EAAG,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA,CAAE,CAAA;AAC9B,EAAA,KAAA,CAAM,IAAA,CAAK,kBAAkB,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,MAAA,EAAS,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,CAAA,CAAG,CAAA;AAC/E,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAG,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AACpC,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,OAAO,QAAA,EAAU;AACpB,IAAA,KAAA,CAAM,IAAA,CAAK,kCAAkC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,QAAA,EAAM,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,CAAE,CAAA;AAC/F,IAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,QAAA,CAAS,WAAW,CAAA;AACtC,IAAA,IAAI,MAAA,CAAO,SAAS,QAAA,EAAU;AAC7B,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,CAAE,CAAA;AAAA,IACpD;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACd;AAEA,EAAA,IAAI,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,MAAA,GAAS,CAAA,GAAI,MAAA,CAAO,OAAA,CAAQ,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,GAAI,SAAA;AAC9F,IAAA,KAAA,CAAM,KAAK,CAAA,iBAAA,EAAoB,MAAA,CAAO,QAAQ,OAAO,CAAA,EAAA,EAAK,aAAa,CAAA,CAAA,CAAG,CAAA;AAC1E,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACd;AAEA,EAAA,IAAI,OAAO,WAAA,EAAa;AACvB,IAAA,KAAA,CAAM,IAAA,CAAK,OAAO,WAAW,CAAA;AAC7B,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACd;AAEA,EAAA,KAAA,CAAM,KAAK,kBAAkB,CAAA;AAC7B,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AACzB,EAAA,KAAA,MAAW,CAAC,UAAU,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,cAAc,CAAA,EAAG;AAC5E,IAAA,MAAM,SAAS,KAAA,IAAS,EAAA,GAAK,QAAA,GAAM,KAAA,IAAS,KAAK,QAAA,GAAM,QAAA;AACvD,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,MAAM,CAAA,CAAA,EAAI,QAAA,CAAS,WAAA,EAAY,CAAE,MAAA,CAAO,EAAE,CAAC,CAAA,CAAA,EAAI,KAAK,CAAA,IAAA,CAAM,CAAA;AAAA,EAC3E;AACA,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,MAAM,eAAA,GAAkB,OAAO,KAAA,CAAM,QAAA,CAAS,OAAO,CAAC,OAAA,KAAY,OAAA,CAAQ,QAAA,KAAa,MAAM,CAAA;AAC7F,EAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC/B,IAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,IAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AACzB,IAAA,KAAA,MAAW,WAAW,eAAA,EAAiB;AACtC,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,GAAA,EAAM,OAAA,CAAQ,QAAA,CAAS,WAAA,EAAa,CAAA,EAAA,EAAK,kBAAA,CAAmB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AAC5F,MAAA,KAAA,CAAM,KAAK,CAAA,IAAA,EAAO,kBAAA,CAAmB,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,CAAA;AACtD,MAAA,MAAM,kBAAA,GACL,OAAA,CAAQ,QAAA,KAAa,oBAAA,IAAwB,OAAA,CAAQ,QAAA,EAAU,kBAAA,GAC5D,MAAA,CAAO,OAAA,CAAQ,QAAA,CAAS,kBAAkB,CAAA,GAC1C,MAAA;AACJ,MAAA,IAAI,kBAAA,EAAoB;AACvB,QAAA,KAAA,CAAM,KAAK,CAAA,2BAAA,EAA8B,kBAAA,CAAmB,kBAAA,EAAoB,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,MACtF;AACA,MAAA,MAAM,UAAA,GAAa,QAAQ,QAAA,EAAU,UAAA,GAAa,OAAO,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,GAAI,MAAA;AACxF,MAAA,IAAI,UAAA,EAAY;AACf,QAAA,KAAA,CAAM,KAAK,CAAA,gBAAA,EAAmB,kBAAA,CAAmB,UAAA,EAAY,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,MACnE;AACA,MAAA,MAAM,YAAY,sBAAA,CAAuB;AAAA,QACxC,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,OAAO,OAAA,CAAQ,KAAA;AAAA,QACf,QAAQ,OAAA,CAAQ;AAAA,OAChB,CAAA;AACD,MAAA,IAAI,UAAU,MAAA,EAAQ;AACrB,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,sBAAA,EAAyB,SAAA,CAAU,MAAM,CAAA,CAAE,CAAA;AAAA,MACvD;AACA,MAAA,IAAI,UAAU,mBAAA,EAAqB;AAClC,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,0BAAA,EAA6B,SAAA,CAAU,mBAAmB,CAAA,CAAE,CAAA;AAAA,MACxE;AAAA,IACD;AAAA,EACD,CAAA,MAAO;AACN,IAAA,KAAA,CAAM,KAAK,2BAA2B,CAAA;AAAA,EACvC;AAEA,EAAA,IAAI,OAAO,MAAA,EAAQ;AAClB,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,IAAA,KAAA,CAAM,KAAK,6BAA6B,CAAA;AAAA,EACzC;AAEA,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,gBAAA,EAAmB,MAAA,CAAO,SAAS,CAAA,CAAE,CAAA;AAChD,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACvB;;;ARzEA,IAAM,YAAA,GAAe,QAAA;AAGrB,IAAM,oBAAA,GAAuB,GAAA;AAG7B,IAAM,eAAA,GAAkB,IAAA;AAGxB,IAAM,mBAAA,uBAA0B,GAAA,EAAmE;AAGnG,IAAM,qBAAA,GAAwB,GAAA;AAG9B,IAAM,0BAAA,GAA6B,GAAA;AAGnC,IAAM,yBAAA,GAA4B,GAAA;AAsBlC,eAAsB,UAAA,CAAW,MAAA,EAAgB,EAAA,EAAkB,cAAA,EAAgE;AAClI,EAAA,MAAM,kBAAkB,cAAA,EAAgB,OAAA;AACxC,EAAA,MAAM,UAAA,GAAa,mBAAmB,eAAA,KAAoB,MAAA;AAC1D,EAAA,MAAM,QAAA,GAAW,UAAA,GACd,CAAA,EAAG,YAAY,CAAA,EAAG,MAAM,CAAA,SAAA,EAAY,eAAe,CAAA,CAAA,GACnD,CAAA,EAAG,YAAY,CAAA,EAAG,MAAM,CAAA,CAAA;AAG3B,EAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAA2B,QAAA,EAAU,EAAE,CAAA;AAC5D,EAAA,IAAI,MAAA,EAAQ;AACX,IAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAK;AAAA,EAClC;AAKA,EAAA,MAAM,oBAAA,GAAwC;AAAA,IAC7C,KAAA;AAAA,IAAO,OAAA;AAAA,IAAS,MAAA;AAAA,IAAQ,QAAA;AAAA,IAAU,KAAA;AAAA,IAAO,SAAA;AAAA,IAAW,IAAA;AAAA,IAAM,KAAA;AAAA,IAAO,MAAA;AAAA,IAAQ,QAAA;AAAA,IAAU,oBAAA;AAAA,IAAsB,eAAA;AAAA,IAAiB,MAAA;AAAA,IAAQ;AAAA,GACnI;AAIA,EAAA,MAAM,OAAA,GAA2B;AAAA,IAChC,yBAAA,EAA2B,IAAA;AAAA,IAC3B,UAAA,sBAAgB,GAAA,EAAI;AAAA,IACpB,cAAc,cAAA,EAAgB;AAAA,GAC/B;AAEA,EAAA,MAAM,aAAA,GAAgB;AAAA,IACrB,cAAA,CAAe,MAAA,EAAQ,KAAA,EAAO,MAAM,SAAA,CAAU,KAAA,EAAO,MAAM,QAAA,CAAS,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IACzF,cAAA,CAAe,MAAA,EAAQ,OAAA,EAAS,MAAM,SAAA,CAAU,OAAA,EAAS,MAAM,UAAA,CAAW,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAC/F,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,MAAA,EAAW,OAAO,CAAC,GAAG,EAAE,CAAA;AAAA,IACvG,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,MAAM,SAAA,CAAU,QAAA,EAAU,MAAMZ,YAAAA,CAAY,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAClG,cAAA,CAAe,MAAA,EAAQ,KAAA,EAAO,MAAM,SAAA,CAAU,KAAA,EAAO,MAAM,QAAA,CAAS,MAAM,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAChF,cAAA,CAAe,MAAA,EAAQ,SAAA,EAAW,MAAM,SAAA,CAAU,SAAA,EAAW,MAAM,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IACpG,cAAA,CAAe,MAAA,EAAQ,IAAA,EAAM,MAAM,SAAA,CAAU,IAAA,EAAM,MAAM,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IACtF,cAAA,CAAe,MAAA,EAAQ,KAAA,EAAO,MAAM,SAAA,CAAU,KAAA,EAAO,MAAM,QAAA,CAAS,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IACzF,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAC5F,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,MAAM,SAAA,CAAU,QAAA,EAAU,MAAM,WAAA,CAAY,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAClG,cAAA,CAAe,MAAA,EAAQ,oBAAA,EAAsB,MAAM,SAAA,CAAU,oBAAA,EAAsB,MAAM,sBAAA,CAAuB,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IACrI,cAAA,CAAe,MAAA,EAAQ,eAAA,EAAiB,MAAM,SAAA,CAAU,eAAA,EAAiB,MAAM,iBAAA,CAAkB,MAAM,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAC7G,cAAA,CAAe,MAAA,EAAQ,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,OAAO,CAAC,CAAA,EAAG,EAAE,CAAA;AAAA,IAC5F,cAAA;AAAA,MACC,MAAA;AAAA,MACA,IAAA;AAAA,MACA,MACC,SAAA;AAAA,QACC,IAAA;AAAA,QACA,MACC,QAAQ,MAAA,EAAQ;AAAA,UACf,uBAAuB,cAAA,EAAgB,qBAAA;AAAA,UACvC,gCAAgC,cAAA,EAAgB,8BAAA;AAAA,UAChD,0BAA0B,cAAA,EAAgB;AAAA,WACxC,OAAO;AAAA,OACZ;AAAA,MACD;AAAA;AACD,GACD;AAEA,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,IAClC,OAAA,CAAQ,WAAW,aAAa,CAAA;AAAA,IAChC,IAAI,OAAA;AAAA,MAA6C,CAAC,OAAA,KACjD,UAAA,CAAW,MAAM;AAChB,QAAA,QAAA,GAAW,IAAA;AAEX,QAAA,OAAA;AAAA,UACC,OAAA,CAAQ,UAAA;AAAA,YACP,aAAA,CAAc,IAAI,CAAC,CAAA,KAAM,QAAQ,IAAA,CAAK,CAAC,GAAG,IAAI,OAAA,CAAe,CAAC,CAAA,EAAG,MAAA,KAAW,OAAO,IAAI,KAAA,CAAM,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;AAAA;AACtH,SACD;AAAA,MACD,GAAG,eAAe;AAAA;AACnB,GACA,CAAA;AAED,EAAA,IAAI,YAAA,GAAe,OAAA,CACjB,MAAA,CAAO,CAAC,CAAA,KAAgD,CAAA,CAAE,MAAA,KAAW,WAAW,CAAA,CAChF,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAGpB,EAAA,IAAI,QAAA,EAAU;AACb,IAAA,MAAM,mBAAA,GAAsB,IAAI,GAAA,CAAI,YAAA,CAAa,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAC,CAAA;AACvE,IAAA,KAAA,MAAW,YAAY,oBAAA,EAAsB;AAC5C,MAAA,IAAI,CAAC,mBAAA,CAAoB,GAAA,CAAI,QAAQ,CAAA,EAAG;AACvC,QAAA,YAAA,CAAa,IAAA;AAAA,UACZ,iBAAiB,QAAA,EAAU;AAAA,YAC1B,aAAA;AAAA,cACC,QAAA;AAAA,cACA,CAAA,EAAG,QAAA,CAAS,WAAA,EAAa,CAAA,gBAAA,CAAA;AAAA,cACzB,KAAA;AAAA,cACA,CAAA,kCAAA,EAAqC,kBAAkB,GAAI,CAAA,uDAAA;AAAA;AAC5D,WACA;AAAA,SACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACH,IAAA,YAAA,GAAe,MAAM,uBAAA,CAAwB,MAAA,EAAQ,YAAA,EAAc,cAAc,CAAA;AAGjF,IAAA,IAAI,aAAA,GAAgB,oBAAoB,YAAY,CAAA;AAGpD,IAAA,IAAI,UAAA,EAAY;AACf,MAAA,aAAA,GAAgB;AAAA,QACf,OAAA,EAAS,eAAA;AAAA,QACT,SAAS,CAAC,GAAG,cAAc,OAAA,EAAS,CAAA,2BAAA,EAA8B,eAAe,CAAA,CAAE,CAAA;AAAA,QACnF,OAAA,EAAS,iBAAA,CAAkB,eAAA,EAAkC,cAAA,EAAgB,aAAa,CAAA;AAAA,QAC1F,kBAAkB,aAAA,CAAc;AAAA,OACjC;AAAA,IACD;AAKA,IAAA,MAAM,cAAA,GAAiB,aAAa,aAAA,GAAgB,KAAA,CAAA;AAGpD,IAAA,IAAI,gBAAA,GAAmD,IAAA;AACvD,IAAA,IAAI,gBAAgB,kBAAA,EAAoB;AACvC,MAAA,gBAAA,GAAmB,MAAM,oBAAA;AAAA,QACxB,cAAA,CAAe,kBAAA;AAAA,QACf,aAAA,CAAc,OAAA;AAAA,QACd,aAAA,CAAc;AAAA,OACf;AAAA,IACD;AAGA,IAAA,IAAI,gBAAA,EAAkB,UAAU,MAAA,EAAQ;AACvC,MAAA,aAAA,CAAc,OAAA,CAAQ,KAAK,CAAA,qBAAA,EAAwB,gBAAA,CAAiB,UAAU,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,IAC3F;AAEA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,IAAA,IAAI,oBAAA,GAAsD,IAAA;AAE1D,IAAA,IAAI,gBAAA,IAAoB,gBAAA,CAAiB,WAAA,GAAc,CAAA,EAAG;AACzD,MAAA,MAAM,eAAA,GAAkB,wBAAA,CAAyB,gBAAA,CAAiB,OAAA,EAAS,cAAc,OAAO,CAAA;AAChG,MAAA,IAAI,eAAA,EAAiB;AAEpB,QAAA,MAAM,eAAA,GAAiC,EAAE,GAAG,aAAA,EAAe,SAAS,eAAA,EAAgB;AACpF,QAAA,MAAM,aAAA,GAAgB,gBAAA,CAAiB,YAAA,EAAc,eAAA,EAAiB,gBAAgB,aAAa,CAAA;AAGnG,QAAA,MAAM,aAAA,GAA+B;AAAA,UACpC,GAAG,aAAA;AAAA,UACH,OAAA,EAAS,iBAAA,CAAkB,aAAA,CAAc,OAAA,EAAS,gBAAgB,aAAa;AAAA,SAChF;AACA,QAAA,MAAM,cAAc,gBAAA,CAAiB,YAAA,EAAc,cAAA,IAAkB,aAAA,EAAe,gBAAgB,aAAa,CAAA;AAGjH,QAAA,MAAM,aAAA,GAAgB,iBAAA,CAAkB,aAAA,CAAc,OAAA,EAAS,gBAAgB,aAAa,CAAA;AAC5F,QAAA,MAAM,SAAiC,EAAC;AACxC,QAAA,KAAA,MAAW,GAAA,IAAO,MAAA,CAAO,IAAA,CAAK,aAAa,CAAA,EAAsB;AAChE,UAAA,MAAA,CAAO,GAAG,IAAI,eAAA,CAAgB,GAAG,EAAE,UAAA,GAAa,aAAA,CAAc,GAAG,CAAA,CAAE,UAAA;AAAA,QACpE;AAEA,QAAA,MAAM,UAAA,GAAa,aAAA,CAAc,OAAA,GAAU,WAAA,CAAY,OAAA;AACvD,QAAA,WAAA,GAAc,mBAAA,CAAoB,MAAA,EAAQ,UAAA,EAAY,aAAA,CAAc,gBAAgB,CAAA;AACpF,QAAA,oBAAA,GAAuB,MAAA;AACvB,QAAA,KAAA,GAAQ,aAAA;AAAA,MACT,CAAA,MAAO;AACN,QAAA,KAAA,GAAQ,gBAAA,CAAiB,YAAA,EAAc,cAAA,EAAgB,cAAA,EAAgB,aAAa,CAAA;AAAA,MACrF;AAAA,IACD,CAAA,MAAO;AACN,MAAA,KAAA,GAAQ,gBAAA,CAAiB,YAAA,EAAc,cAAA,EAAgB,cAAA,EAAgB,aAAa,CAAA;AAAA,IACrF;AAEA,IAAA,MAAM,QAAA,GAAW,qBAAqB,YAAY,CAAA;AAElD,IAAA,MAAA,GAAS;AAAA,MACR,MAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA,EAAQ,YAAA;AAAA,MACR,QAAA;AAAA,MACA,OAAA,EAAS,aAAA;AAAA,MACT,MAAA,EAAQ,KAAA;AAAA,MACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,WAAA;AAAA,MACA;AAAA,KACD;AAGA,IAAA,IAAI,gBAAgB,kBAAA,EAAoB;AACvC,MAAA,MAAM,SAAA,GAA2B;AAAA,QAChC,SAAS,aAAA,CAAc,OAAA;AAAA,QACvB,UAAU,aAAA,CAAc,gBAAA;AAAA,QACxB,gBAAA,EAAkB,YAAA,CAAa,GAAA,CAAI,CAAC,OAAO,EAAE,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,OAAO,CAAA,CAAE,KAAA,EAAO,MAAA,EAAQ,CAAA,CAAE,QAAO,CAAE,CAAA;AAAA,QACtG,SAAA,EAAW,KAAK,GAAA;AAAI,OACrB;AACA,MAAA,MAAM,oBAAoB,YAAY;AACrC,QAAA,IAAI;AACH,UAAA,MAAM,IAAA,GAAO,eAAe,kBAAA,CAAoB,GAAA;AAAA,YAC/C,cAAA,CAAe,kBAAA,CAAoB,UAAA,CAAW,QAAQ;AAAA,WACvD;AACA,UAAA,MAAM,IAAA,CAAK,KAAA;AAAA,YACV,IAAI,QAAQ,mBAAA,EAAqB;AAAA,cAChC,MAAA,EAAQ,MAAA;AAAA,cACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,cAC9C,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,SAAS;AAAA,aAC9B;AAAA,WACF;AAAA,QACD,CAAA,CAAA,MAAQ;AAAA,QAER;AAAA,MACD,CAAA,GAAG;AACH,MAAA,IAAI,cAAA,CAAe,SAAA,EAAW,cAAA,CAAe,SAAA,CAAU,gBAAgB,CAAA;AAAA,IACxE;AAAA,EACD,CAAA,CAAA,MAAQ;AAEP,IAAA,IAAI,eAAA,GAAkB,oBAAoB,YAAY,CAAA;AACtD,IAAA,IAAI,UAAA,EAAY;AACf,MAAA,eAAA,GAAkB;AAAA,QACjB,OAAA,EAAS,eAAA;AAAA,QACT,SAAS,CAAC,GAAG,gBAAgB,OAAA,EAAS,CAAA,2BAAA,EAA8B,eAAe,CAAA,CAAE,CAAA;AAAA,QACrF,OAAA,EAAS,iBAAA,CAAkB,eAAA,EAAkC,cAAA,EAAgB,aAAa,CAAA;AAAA,QAC1F,kBAAkB,eAAA,CAAgB;AAAA,OACnC;AAAA,IACD;AACA,IAAA,MAAM,sBAAA,GAAyB,aAAa,eAAA,GAAkB,MAAA;AAC9D,IAAA,MAAM,KAAA,GAAQ,gBAAA,CAAiB,YAAA,EAAc,sBAAA,EAAwB,gBAAgB,aAAa,CAAA;AAClG,IAAA,MAAM,QAAA,GAAW,qBAAqB,YAAY,CAAA;AAClD,IAAA,MAAA,GAAS;AAAA,MACR,MAAA;AAAA,MACA,KAAA;AAAA,MACA,MAAA,EAAQ,YAAA;AAAA,MACR,QAAA;AAAA,MACA,OAAA,EAAS,eAAA;AAAA,MACT,MAAA,EAAQ,KAAA;AAAA,MACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,WAAA,EAAa,IAAA;AAAA,MACb,oBAAA,EAAsB;AAAA,KACvB;AAAA,EACD;AAGA,EAAA,MAAM,QAAA,CAAS,QAAA,EAAU,MAAA,EAAQ,EAAA,EAAI,gBAAgB,eAAe,CAAA;AAEpE,EAAA,OAAO,MAAA;AACR;AAMA,eAAe,oBAAA,CACd,WAAA,EACA,OAAA,EACA,QAAA,EAC0C;AAC1C,EAAA,MAAM,QAAA,GAAW,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,YAAY,EAAE,CAAA,CAAA;AAC7C,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAGrB,EAAA,MAAM,MAAA,GAAS,mBAAA,CAAoB,GAAA,CAAI,QAAQ,CAAA;AAC/C,EAAA,IAAI,MAAA,IAAU,MAAA,CAAO,OAAA,GAAU,GAAA,EAAK;AACnC,IAAA,OAAO,MAAA,CAAO,OAAA;AAAA,EACf;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,OAAO,WAAA,CAAY,GAAA,CAAI,WAAA,CAAY,UAAA,CAAW,QAAQ,CAAC,CAAA;AAC7D,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,oBAAoB,CAAA;AACxC,IAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,SAAA,EAAW,OAAO,CAAA;AACvC,IAAA,IAAI,QAAA,EAAU,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,YAAY,QAAQ,CAAA;AAEvD,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,MACnC,KAAK,KAAA,CAAM,IAAI,QAAQ,GAAA,CAAI,QAAA,EAAU,CAAC,CAAA;AAAA,MACtC,IAAI,OAAA,CAAe,CAAC,CAAA,EAAG,WAAW,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,+BAA+B,CAAC,CAAA,EAAG,yBAAyB,CAAC;AAAA,KACjI,CAAA;AAED,IAAA,IAAI,CAAC,QAAA,CAAS,EAAA,EAAI,OAAO,IAAA;AAEzB,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,IAAI,mBAAA,CAAoB,IAAA,IAAQ,0BAAA,EAA4B,mBAAA,CAAoB,KAAA,EAAM;AACtF,IAAA,mBAAA,CAAoB,GAAA,CAAI,UAAU,EAAE,OAAA,EAAS,MAAM,OAAA,EAAS,GAAA,GAAM,uBAAuB,CAAA;AACzF,IAAA,OAAO,IAAA;AAAA,EACR,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,IAAA;AAAA,EACR;AACD;AAEA,eAAe,cAAA,CACd,MAAA,EACA,QAAA,EACA,GAAA,EACA,EAAA,EACuB;AACvB,EAAA,OAAO,YAAA,CAAa,GAAG,YAAY,CAAA,EAAG,MAAM,CAAA,OAAA,EAAU,QAAQ,CAAA,CAAA,EAAI,GAAA,EAAK,EAAE,CAAA;AAC1E;AAQA,eAAe,SAAA,CAAU,UAAyB,EAAA,EAAsD;AACvG,EAAA,IAAI;AACH,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,IAAA,CAAK;AAAA,MACjC,EAAA,EAAG;AAAA,MACH,IAAI,OAAA,CAAe,CAAC,CAAA,EAAG,WAAW,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,iBAAiB,CAAC,CAAA,EAAG,oBAAoB,CAAC;AAAA,KAC9G,CAAA;AACD,IAAA,OAAO,MAAA;AAAA,EACR,SAAS,GAAA,EAAK;AACb,IAAA,MAAM,OAAA,GAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,cAAA;AACrD,IAAA,MAAM,QAAA,GAAW,CAAC,aAAA,CAAc,QAAA,EAAU,CAAA,EAAG,QAAA,CAAS,WAAA,EAAa,CAAA,YAAA,CAAA,EAAgB,MAAA,EAAQ,CAAA,cAAA,EAAiB,OAAO,EAAE,CAAC,CAAA;AACtH,IAAA,OAAO,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AAAA,EAC3C;AACD;;;AS7YA,IAAM,WAAA,GAAc,CAAC,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,GAAA,EAAK,GAAA,EAAK,GAAG,CAAA;AAEzE,IAAM,qBAAA,GAAsG;AAAA,EAC3G,EAAE,GAAA,EAAK,aAAA,EAAe,QAAA,EAAU,KAAA,EAAO,OAAO,KAAA,EAAM;AAAA,EACpD,EAAE,GAAA,EAAK,cAAA,EAAgB,QAAA,EAAU,MAAA,EAAQ,OAAO,MAAA,EAAO;AAAA,EACvD,EAAE,GAAA,EAAK,gBAAA,EAAkB,QAAA,EAAU,QAAA,EAAU,OAAO,QAAA,EAAS;AAAA,EAC7D,EAAE,GAAA,EAAK,iBAAA,EAAmB,QAAA,EAAU,SAAA,EAAW,OAAO,SAAA,EAAU;AAAA,EAChE,EAAE,GAAA,EAAK,aAAA,EAAe,QAAA,EAAU,KAAA,EAAO,OAAO,KAAA;AAC/C,CAAA;AAkCA,SAAS,cAAA,CAAe,QAAgB,OAAA,EAA0B;AACjE,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,OAAA,CAAQ,MAAsC,CAAA;AAC9E,EAAA,MAAM,YAAA,GAAe,WAAA,CAAY,OAAA,CAAQ,OAAuC,CAAA;AAChF,EAAA,IAAI,WAAA,KAAgB,EAAA,IAAM,YAAA,KAAiB,EAAA,EAAI,OAAO,KAAA;AACtD,EAAA,OAAO,WAAA,GAAc,YAAA;AACtB;AAEA,SAAS,cAAA,CAAe,MAAwB,QAAA,EAAkC;AACjF,EAAA,MAAM,KAAA,GAAQ,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,aAAa,QAAQ,CAAA;AACrE,EAAA,OAAO,OAAO,MAAA,IAAU,KAAA;AACzB;AAEA,SAAS,cAAc,IAAA,EAAiC;AACvD,EAAA,MAAM,UAAA,GAAa,KAAK,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,aAAa,OAAO,CAAA;AACzE,EAAA,IAAI,CAAC,YAAY,OAAO,KAAA;AAExB,EAAA,MAAM,oBAAA,GAAuB,UAAA,CAAW,QAAA,CAAS,IAAA,CAAK,CAAC,OAAA,KAAY;AAClE,IAAA,MAAM,IAAA,GAAO,GAAG,OAAA,CAAQ,KAAK,IAAI,OAAA,CAAQ,MAAM,GAAG,WAAA,EAAY;AAC9D,IAAA,OAAO,OAAA,CAAQ,aAAa,MAAA,KAAW,IAAA,CAAK,SAAS,QAAQ,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA,CAAA;AAAA,EACjG,CAAC,CAAA;AAED,EAAA,OAAO,UAAA,CAAW,UAAU,CAAC,oBAAA;AAC9B;AAGO,SAAS,eAAA,CAAgB,MAAwB,QAAA,EAA0C;AACjG,EAAA,MAAM,aAAkC,EAAC;AACzC,EAAA,IAAI,YAAA,GAAe,CAAA;AAEnB,EAAA,IAAI,QAAA,CAAS,UAAU,MAAA,EAAW;AACjC,IAAA,YAAA,EAAA;AACA,IAAA,IAAI,eAAe,IAAA,CAAK,KAAA,CAAM,KAAA,EAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACrD,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,OAAA;AAAA,QACN,SAAS,CAAA,MAAA,EAAS,IAAA,CAAK,MAAM,KAAK,CAAA,kBAAA,EAAqB,SAAS,KAAK,CAAA,CAAA;AAAA,QACrE,UAAU,QAAA,CAAS,KAAA;AAAA,QACnB,MAAA,EAAQ,KAAK,KAAA,CAAM;AAAA,OACnB,CAAA;AAAA,IACF;AAAA,EACD;AAEA,EAAA,IAAI,QAAA,CAAS,UAAU,MAAA,EAAW;AACjC,IAAA,YAAA,EAAA;AACA,IAAA,IAAI,IAAA,CAAK,KAAA,CAAM,OAAA,GAAU,QAAA,CAAS,KAAA,EAAO;AACxC,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,OAAA;AAAA,QACN,SAAS,CAAA,MAAA,EAAS,IAAA,CAAK,MAAM,OAAO,CAAA,kBAAA,EAAqB,SAAS,KAAK,CAAA,CAAA;AAAA,QACvE,UAAU,QAAA,CAAS,KAAA;AAAA,QACnB,MAAA,EAAQ,KAAK,KAAA,CAAM;AAAA,OACnB,CAAA;AAAA,IACF;AAAA,EACD;AAEA,EAAA,IAAI,SAAS,qBAAA,EAAuB;AACnC,IAAA,YAAA,EAAA;AACA,IAAA,IAAI,CAAC,aAAA,CAAc,IAAI,CAAA,EAAG;AACzB,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,uBAAA;AAAA,QACN,OAAA,EAAS,sEAAA;AAAA,QACT,QAAA,EAAU,IAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACR,CAAA;AAAA,IACF;AAAA,EACD;AAEA,EAAA,KAAA,MAAW,eAAe,qBAAA,EAAuB;AAChD,IAAA,IAAI,QAAA,CAAS,WAAA,CAAY,GAAG,CAAA,EAAG;AAC9B,MAAA,YAAA,EAAA;AACA,MAAA,IAAI,CAAC,cAAA,CAAe,IAAA,EAAM,WAAA,CAAY,QAAQ,CAAA,EAAG;AAChD,QAAA,UAAA,CAAW,IAAA,CAAK;AAAA,UACf,MAAM,WAAA,CAAY,GAAA;AAAA,UAClB,OAAA,EAAS,CAAA,EAAG,WAAA,CAAY,KAAK,CAAA,mCAAA,CAAA;AAAA,UAC7B,QAAA,EAAU,IAAA;AAAA,UACV,MAAA,EAAQ;AAAA,SACR,CAAA;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,QAAA,CAAS,0BAA0B,MAAA,EAAW;AACjD,IAAA,YAAA,EAAA;AACA,IAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,CAAQ,QAAA,KAAa,UAAU,CAAA,CAAE,MAAA;AAC/F,IAAA,IAAI,aAAA,GAAgB,SAAS,qBAAA,EAAuB;AACnD,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,uBAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,aAAa,CAAA,qCAAA,EAAwC,SAAS,qBAAqB,CAAA,CAAA;AAAA,QAC/F,UAAU,QAAA,CAAS,qBAAA;AAAA,QACnB,MAAA,EAAQ;AAAA,OACR,CAAA;AAAA,IACF;AAAA,EACD;AAEA,EAAA,IAAI,QAAA,CAAS,sBAAsB,MAAA,EAAW;AAC7C,IAAA,YAAA,EAAA;AACA,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,QAAA,CAAS,MAAA,CAAO,CAAC,OAAA,KAAY,OAAA,CAAQ,QAAA,KAAa,MAAM,CAAA,CAAE,MAAA;AACvF,IAAA,IAAI,SAAA,GAAY,SAAS,iBAAA,EAAmB;AAC3C,MAAA,UAAA,CAAW,IAAA,CAAK;AAAA,QACf,IAAA,EAAM,mBAAA;AAAA,QACN,OAAA,EAAS,CAAA,EAAG,SAAS,CAAA,iCAAA,EAAoC,SAAS,iBAAiB,CAAA,CAAA;AAAA,QACnF,UAAU,QAAA,CAAS,iBAAA;AAAA,QACnB,MAAA,EAAQ;AAAA,OACR,CAAA;AAAA,IACF;AAAA,EACD;AAEA,EAAA,OAAO;AAAA,IACN,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,MAAA,EAAQ,WAAW,MAAA,KAAW,CAAA;AAAA,IAC9B,UAAA;AAAA,IACA,YAAA;AAAA,IACA,cAAA,EAAgB,KAAK,OAAA,EAAS,OAAA;AAAA,IAC9B,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,GACnC;AACD;AAGO,SAAS,qBAAqB,MAAA,EAAgC;AACpE,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,wBAAA,EAA2B,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AACrD,EAAA,KAAA,CAAM,KAAK,CAAA,YAAA,EAAe,MAAA,CAAO,MAAA,GAAS,MAAA,GAAS,MAAM,CAAA,CAAE,CAAA;AAC3D,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,mBAAA,EAAsB,MAAA,CAAO,YAAY,CAAA,CAAE,CAAA;AACtD,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,gBAAA,EAAmB,MAAA,CAAO,UAAA,CAAW,MAAM,CAAA,CAAE,CAAA;AACxD,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,MAAA,CAAO,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG;AACnC,IAAA,KAAA,CAAM,KAAK,yBAAyB,CAAA;AACpC,IAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,EACvB;AAEA,EAAA,KAAA,CAAM,KAAK,gBAAgB,CAAA;AAC3B,EAAA,KAAA,MAAW,SAAA,IAAa,OAAO,UAAA,EAAY;AAC1C,IAAA,KAAA,CAAM,KAAK,CAAA,IAAA,EAAO,SAAA,CAAU,IAAI,CAAA,KAAA,EAAQ,SAAA,CAAU,OAAO,CAAA,CAAE,CAAA;AAC3D,IAAA,KAAA,CAAM,KAAK,CAAA,YAAA,EAAe,SAAA,CAAU,QAAQ,CAAA,WAAA,EAAc,SAAA,CAAU,MAAM,CAAA,CAAE,CAAA;AAAA,EAC7E;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACvB;;;AC1KO,SAAS,eAAe,OAAA,EAKtB;AACR,EAAA,OAAA,CAAQ,WAAW,aAAA,CAAc;AAAA,IAChC,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,OAAA,EAAS,KAAA;AAAA,IACT,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,UAAU,OAAA,CAAQ;AAAA,GAClB,CAAA;AAED,EAAA,QAAA,CAAS;AAAA,IACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,MAAM,OAAA,CAAQ,QAAA;AAAA,IACd,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,QAAQ,OAAA,CAAQ,SAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,UAAA;AAAA,IACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,UAAU,OAAA,CAAQ,QAAA,KAAa,OAAA,CAAQ,MAAA,KAAW,SAAS,MAAA,GAAS,MAAA;AAAA,GACpE,CAAA;AACF;AAEO,SAAS,eAAe,OAAA,EAItB;AACR,EAAA,OAAA,CAAQ,WAAW,aAAA,CAAc;AAAA,IAChC,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,MAAA,EAAQ,OAAA;AAAA,IACR,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,OAAA,EAAS,IAAA;AAAA,IACT,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,UAAU,OAAA,CAAQ;AAAA,GAClB,CAAA;AAED,EAAA,QAAA,CAAS,OAAA,CAAQ,iBAAiB,KAAA,GAAQ,OAAA,CAAQ,QAAQ,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAAA,IAChF,MAAM,OAAA,CAAQ,QAAA;AAAA,IACd,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,SAAS,OAAA,CAAQ,IAAA;AAAA,IACjB,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,GAC9B,CAAA;AACF;;;AC1DO,SAAS,SAAS,OAAA,EAA6B;AACrD,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,OAAA,EAAU,OAAO,CAAA,CAAA,EAAG;AAClD;AAEO,SAAS,QAAQ,IAAA,EAA0B;AACjD,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAK;AAC7B;AAEO,SAAS,kBAAkB,MAAA,EAA6B;AAC9D,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,KAAK,CAAA,GAAA,EAAM,MAAA,CAAO,QAAA,CAAS,WAAA,EAAa,CAAA,MAAA,CAAQ,CAAA;AACtD,EAAA,KAAA,CAAM,KAAK,CAAA,YAAA,EAAe,MAAA,CAAO,MAAA,GAAS,eAAA,GAAa,eAAU,CAAA,CAAE,CAAA;AACnE,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,MAAA,CAAO,KAAK,CAAA,IAAA,CAAM,CAAA;AAC3C,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC/B,IAAA,KAAA,CAAM,KAAK,cAAc,CAAA;AACzB,IAAA,KAAA,MAAW,OAAA,IAAW,OAAO,QAAA,EAAU;AACtC,MAAA,MAAM,OACL,OAAA,CAAQ,QAAA,KAAa,MAAA,GAClB,cAAA,GACA,QAAQ,QAAA,KAAa,KAAA,GACpB,cAAA,GACA,OAAA,CAAQ,aAAa,QAAA,GACpB,WAAA,GACA,OAAA,CAAQ,QAAA,KAAa,SACpB,WAAA,GACA,WAAA;AACL,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,EAAA,EAAK,IAAI,CAAA,IAAA,EAAO,QAAQ,QAAA,CAAS,WAAA,EAAa,CAAA,IAAA,EAAO,kBAAA,CAAmB,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACxG,MAAA,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,kBAAA,CAAmB,OAAA,CAAQ,MAAM,CAAC,CAAA,CAAE,CAAA;AAEtD,MAAA,MAAM,kBAAA,GACL,OAAA,CAAQ,QAAA,KAAa,oBAAA,IAAwB,OAAA,CAAQ,QAAA,EAAU,kBAAA,GAC5D,MAAA,CAAO,OAAA,CAAQ,QAAA,CAAS,kBAAkB,CAAA,GAC1C,MAAA;AACJ,MAAA,IAAI,kBAAA,EAAoB;AACvB,QAAA,KAAA,CAAM,KAAK,CAAA,yBAAA,EAA4B,kBAAA,CAAmB,kBAAA,EAAoB,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,MACpF;AAEA,MAAA,MAAM,UAAA,GAAa,QAAQ,QAAA,EAAU,UAAA,GAAa,OAAO,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,GAAI,MAAA;AACxF,MAAA,IAAI,UAAA,EAAY;AACf,QAAA,KAAA,CAAM,KAAK,CAAA,cAAA,EAAiB,kBAAA,CAAmB,UAAA,EAAY,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,MACjE;AAEA,MAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAQ;AAChC,QAAA,MAAM,YAAY,sBAAA,CAAuB;AAAA,UACxC,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,UAAU,OAAA,CAAQ,QAAA;AAAA,UAClB,OAAO,OAAA,CAAQ,KAAA;AAAA,UACf,QAAQ,OAAA,CAAQ;AAAA,SAChB,CAAA;AACD,QAAA,IAAI,UAAU,MAAA,EAAQ;AACrB,UAAA,KAAA,CAAM,IAAA,CAAK,CAAA,oBAAA,EAAuB,SAAA,CAAU,MAAM,CAAA,CAAE,CAAA;AAAA,QACrD;AACA,QAAA,IAAI,UAAU,mBAAA,EAAqB;AAClC,UAAA,KAAA,CAAM,IAAA,CAAK,CAAA,wBAAA,EAA2B,SAAA,CAAU,mBAAmB,CAAA,CAAE,CAAA;AAAA,QACtE;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACvB;;;ACnDO,IAAM,mBAAA,GAAsB;AAAA,EAClC,IAAA,EAAM,QAAA;AAAA,EACN,UAAA,EAAY;AAAA,IACX,MAAA,EAAQ;AAAA,MACP,IAAA,EAAM,QAAA;AAAA,MACN,WAAA,EAAa;AAAA;AACd,GACD;AAAA,EACA,QAAA,EAAU,CAAC,QAAQ;AACpB,CAAA;AAGO,IAAM,KAAA,GAAmB;AAAA,EAC/B;AAAA,IACC,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EACC,6MAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACC,wOAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACC,4NAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACC,wKAAA;AAAA,IACD,WAAA,EAAa;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACX,MAAA,EAAQ;AAAA,UACP,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACd;AAAA,QACA,QAAA,EAAU;AAAA,UACT,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACd,OACD;AAAA,MACA,QAAA,EAAU,CAAC,QAAQ;AAAA;AACpB,GACD;AAAA,EACA;AAAA,IACC,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EACC,6MAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACC,qLAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,eAAA;AAAA,IACN,WAAA,EACC,kMAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,UAAA;AAAA,IACN,WAAA,EACC,wKAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACC,2LAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACC,4LAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,cAAA;AAAA,IACN,WAAA,EACC,iNAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,qBAAA;AAAA,IACN,WAAA,EACC,mNAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,YAAA;AAAA,IACN,WAAA,EACC,+JAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EACC,8QAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,aAAA;AAAA,IACN,WAAA,EACC,sYAAA;AAAA,IACD,WAAA,EAAa;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACX,MAAA,EAAQ;AAAA,UACP,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACd;AAAA,QACA,OAAA,EAAS;AAAA,UACR,IAAA,EAAM,QAAA;AAAA,UACN,MAAM,CAAC,MAAA,EAAQ,gBAAgB,iBAAA,EAAmB,UAAA,EAAY,YAAY,SAAS,CAAA;AAAA,UACnF,WAAA,EACC;AAAA;AACF,OACD;AAAA,MACA,QAAA,EAAU,CAAC,QAAQ;AAAA;AACpB,GACD;AAAA,EACA;AAAA,IACC,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EACC,qQAAA;AAAA,IACD,WAAA,EAAa;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACX,MAAA,EAAQ;AAAA,UACP,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACd;AAAA,QACA,QAAA,EAAU;AAAA,UACT,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa,mFAAA;AAAA,UACb,UAAA,EAAY;AAAA,YACX,KAAA,EAAO;AAAA,cACN,IAAA,EAAM,QAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,KAAA,EAAO;AAAA,cACN,IAAA,EAAM,QAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,qBAAA,EAAuB;AAAA,cACtB,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,WAAA,EAAa;AAAA,cACZ,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,YAAA,EAAc;AAAA,cACb,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,cAAA,EAAgB;AAAA,cACf,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,eAAA,EAAiB;AAAA,cAChB,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,WAAA,EAAa;AAAA,cACZ,IAAA,EAAM,SAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,qBAAA,EAAuB;AAAA,cACtB,IAAA,EAAM,QAAA;AAAA,cACN,WAAA,EAAa;AAAA,aACd;AAAA,YACA,iBAAA,EAAmB;AAAA,cAClB,IAAA,EAAM,QAAA;AAAA,cACN,WAAA,EAAa;AAAA;AACd;AACD;AACD,OACD;AAAA,MACA,QAAA,EAAU,CAAC,QAAA,EAAU,UAAU;AAAA;AAChC,GACD;AAAA,EACA;AAAA,IACC,IAAA,EAAM,sBAAA;AAAA,IACN,WAAA,EACC,sSAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,mBAAA;AAAA,IACN,WAAA,EACC,kQAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,qBAAA;AAAA,IACN,WAAA,EACC,4LAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,WAAA;AAAA,IACN,WAAA,EACC,mLAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,oBAAA;AAAA,IACN,WAAA,EACC,wMAAA;AAAA,IACD,WAAA,EAAa;AAAA,GACd;AAAA,EACA;AAAA,IACC,IAAA,EAAM,iBAAA;AAAA,IACN,WAAA,EACC,2LAAA;AAAA,IACD,WAAA,EAAa;AAAA,MACZ,IAAA,EAAM,QAAA;AAAA,MACN,UAAA,EAAY;AAAA,QACX,SAAA,EAAW;AAAA,UACV,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACd;AAAA,QACA,MAAA,EAAQ;AAAA,UACP,IAAA,EAAM,QAAA;AAAA,UACN,IAAA,EAAM,CAAC,MAAA,EAAQ,MAAA,EAAQ,WAAW,UAAA,EAAY,MAAA,EAAQ,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AAAA,UAC7E,WAAA,EAAa;AAAA,SACd;AAAA,QACA,OAAA,EAAS;AAAA,UACR,IAAA,EAAM,QAAA;AAAA,UACN,WAAA,EAAa;AAAA;AACd,OACD;AAAA,MACA,QAAA,EAAU,CAAC,WAAA,EAAa,QAAQ;AAAA;AACjC;AAEF,CAAA;;;AC9NO,SAAS,eAAA,GAAwC;AACvD,EAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AACvB;AAuBA,SAAS,gBAAgB,cAAA,EAAkE;AAC1F,EAAA,IAAI,CAAC,cAAA,EAAgB,YAAA,EAAc,OAAO,MAAA;AAC1C,EAAA,OAAO,EAAE,YAAA,EAAc,cAAA,CAAe,YAAA,EAAa;AACpD;AAEA,eAAe,cAAA,CAAe,QAAgB,cAAA,EAA2D;AACxG,EAAA,MAAM,EAAE,OAAA,EAAAa,QAAAA,EAAQ,GAAI,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,aAAA,EAAA,EAAA,gBAAA,CAAA,CAAA;AAC1B,EAAA,OAAOA,SAAQ,MAAA,EAAQ;AAAA,IACtB,uBAAuB,cAAA,EAAgB,qBAAA;AAAA,IACvC,gCAAgC,cAAA,EAAgB,8BAAA;AAAA,IAChD,0BAA0B,cAAA,EAAgB;AAAA,GAC3C,EAAG,eAAA,CAAgB,cAAc,CAAC,CAAA;AACnC;AAMA,IAAM,aAAA,GAOF;AAAA,EACH,QAAA,EAAU,EAAE,QAAA,EAAU,MAAM,IAAA,EAAM,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,EAAA,KAAO,cAAA,CAAe,CAAA,EAAG,EAAE,CAAA,EAAE;AAAA,EACnF,SAAA,EAAW,EAAE,QAAA,EAAU,MAAM,OAAO,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,QAAA,CAAS,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EAChG,WAAA,EAAa,EAAE,QAAA,EAAU,MAAM,SAAS,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,UAAA,CAAW,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACtG,UAAA,EAAY;AAAA,IACX,QAAA,EAAU,CAAC,IAAA,KAAS;AACnB,MAAA,MAAM,GAAA,GAAM,oBAAoB,IAAI,CAAA;AACpC,MAAA,OAAO,GAAA,GAAM,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAA,GAAK,MAAA;AAAA,IAC9B,CAAA;AAAA,IACA,OAAA,EAAS,CAAC,CAAA,EAAG,IAAA,EAAM,EAAA,KAAO,SAAA,CAAU,CAAA,EAAG,mBAAA,CAAoB,IAAI,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC;AAAA,GACtF;AAAA,EACA,YAAA,EAAc,EAAE,QAAA,EAAU,MAAM,UAAU,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAOb,YAAAA,CAAY,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACzG,SAAA,EAAW,EAAE,QAAA,EAAU,MAAM,KAAA,EAAO,SAAS,CAAC,CAAA,KAAM,QAAA,CAAS,CAAC,CAAA,EAAE;AAAA,EAChE,aAAA,EAAe,EAAE,QAAA,EAAU,MAAM,WAAW,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EAC3G,QAAA,EAAU,EAAE,QAAA,EAAU,MAAM,MAAM,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,OAAA,CAAQ,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EAC7F,SAAA,EAAW,EAAE,QAAA,EAAU,MAAM,OAAO,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,QAAA,CAAS,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EAChG,UAAA,EAAY,EAAE,QAAA,EAAU,MAAM,QAAQ,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,SAAA,CAAU,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACnG,YAAA,EAAc,EAAE,QAAA,EAAU,MAAM,UAAU,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,WAAA,CAAY,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACzG,gBAAA,EAAkB,EAAE,QAAA,EAAU,MAAM,YAAA,EAAc,OAAA,EAAS,CAAC,CAAA,KAAM,eAAA,CAAgB,CAAC,CAAA,EAAG,eAAA,EAAiB,IAAA,EAAK;AAAA,EAC5G,sBAAsB,EAAE,QAAA,EAAU,MAAM,gBAAA,EAAkB,SAAS,CAAC,CAAA,EAAG,KAAA,EAAO,EAAA,KAAO,mBAAmB,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAG,iBAAiB,IAAA,EAAK;AAAA,EACvJ,iBAAA,EAAmB,EAAE,QAAA,EAAU,MAAM,eAAe,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,eAAA,CAAgB,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACvH,mBAAA,EAAqB,EAAE,QAAA,EAAU,MAAM,eAAA,EAAiB,SAAS,CAAC,CAAA,KAAM,iBAAA,CAAkB,CAAC,CAAA,EAAE;AAAA,EAC7F,UAAA,EAAY,EAAE,QAAA,EAAU,MAAM,QAAQ,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,SAAA,CAAU,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EACnG,qBAAqB,EAAE,QAAA,EAAU,MAAM,eAAA,EAAiB,SAAS,CAAC,CAAA,EAAG,KAAA,EAAO,EAAA,KAAO,kBAAkB,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAG,iBAAiB,IAAA,EAAK;AAAA,EACpJ,SAAA,EAAW,EAAE,QAAA,EAAU,MAAM,OAAO,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,QAAA,CAAS,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA,EAAE;AAAA,EAChG,kBAAA,EAAoB,EAAE,QAAA,EAAU,MAAM,gBAAgB,OAAA,EAAS,CAAC,CAAA,EAAG,KAAA,EAAO,OAAO,gBAAA,CAAiB,CAAA,EAAG,eAAA,CAAgB,EAAE,CAAC,CAAA;AACzH,CAAA;AAEA,SAAS,qBAAqB,OAAA,EAAgC;AAC7D,EAAA,OAAO,EAAE,SAAS,CAAC,QAAA,CAAS,OAAO,CAAC,CAAA,EAAG,SAAS,IAAA,EAAK;AACtD;AAEA,SAAS,mCAAA,CACR,IAAA,EACA,UAAA,EACA,cAAA,EACgB;AAChB,EAAA,MAAM,KAAA,GAAQ,IAAI,KAAA,CAAM,mDAAmD,CAAA;AAC3E,EAAA,cAAA,CAAe;AAAA,IACd,QAAA,EAAU,iBAAA;AAAA,IACV,UAAA;AAAA,IACA,WAAW,cAAA,EAAgB,SAAA;AAAA,IAC3B,KAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA,EAAU,MAAA;AAAA,IACV,SAAS,cAAA,EAAgB,OAAA;AAAA,IACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,IAC5B,UAAU,cAAA,EAAgB;AAAA,GAC1B,CAAA;AACD,EAAA,OAAO,oBAAA,CAAqB,MAAM,OAAO,CAAA;AAC1C;AAUA,IAAM,oBAAA,GAAuB,IAAA;AAE7B,eAAsB,eAAA,CACrB,MAAA,EAIA,WAAA,EACA,cAAA,EACyB;AACzB,EAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,MAAA,CAAO,IAAI,CAAA;AAC1C,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,SAAA,IAAa,EAAC;AAClC,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI;AAEH,IAAA,IAAI,SAAS,iBAAA,EAAmB;AAC/B,MAAA,MAAA,GAAS,yBAAyB,IAAI,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,cAAsB,MAAA,IAAU,EAAA;AAEtC,IAAA,MAAM,kBAAkB,YAAoC;AAE3D,MAAA,MAAM,cAAA,GAAiB,cAAc,IAAI,CAAA;AACzC,MAAA,IAAI,cAAA,EAAgB;AACnB,QAAA,MAAM,SAAA,GAAY,cAAA,CAAe,QAAA,CAAS,IAAI,CAAA;AAC9C,QAAA,MAAM,QAAA,GAAW,CAAA,MAAA,EAAS,WAAW,CAAA,OAAA,EAAU,SAAS,CAAA,CAAA;AACxD,QAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,QAAA,EAAU,MAAM,cAAA,CAAe,OAAA,CAAQ,WAAA,EAAa,IAAA,EAAM,cAAc,CAAA,EAAG,WAAA,EAAa,eAAe,eAAe,CAAA;AACxJ,QAAA,cAAA,EAAgB,gBAAgB,MAAM,CAAA;AACtC,QAAA,SAAA,GAAY,MAAA,CAAO,SAAS,MAAA,GAAS,MAAA;AACrC,QAAA,UAAA,GAAa,MAAA;AACb,QAAA,cAAA,CAAe;AAAA,UACd,QAAA,EAAU,IAAA;AAAA,UACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,UACzB,MAAA;AAAA,UACA,WAAW,cAAA,EAAgB,SAAA;AAAA,UAC3B,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,MAAA,GAAS,MAAA;AAAA,UACjC,SAAA;AAAA,UACA,UAAA;AAAA,UACA,SAAS,cAAA,EAAgB,OAAA;AAAA,UACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,UAC5B,UAAU,cAAA,EAAgB;AAAA,SAC1B,CAAA;AACD,QAAA,OAAO,EAAE,SAAS,CAAC,OAAA,CAAQ,kBAAkB,MAAM,CAAC,CAAC,CAAA,EAAE;AAAA,MACxD;AAEA,MAAA,QAAQ,IAAA;AAAM,QACb,KAAK,aAAA,EAAe;AACnB,UAAA,MAAM,OAAA,GAAU,mBAAmB,IAAI,CAAA;AACvC,UAAA,MAAM,cAAc,OAAA,GAAU,EAAE,GAAG,cAAA,EAAgB,SAAQ,GAAI,cAAA;AAC/D,UAAA,MAAM,MAAA,GAAS,MAAM,UAAA,CAAW,WAAA,EAAa,aAAa,WAAW,CAAA;AACrE,UAAA,SAAA,GAAY,OAAO,KAAA,CAAM,KAAA;AACzB,UAAA,UAAA,GAAa,MAAA;AACb,UAAA,cAAA,CAAe;AAAA,YACd,QAAA,EAAU,IAAA;AAAA,YACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,YACzB,MAAA;AAAA,YACA,WAAW,cAAA,EAAgB,SAAA;AAAA,YAC3B,MAAA,EAAQ,MAAA,CAAO,KAAA,CAAM,OAAA,IAAW,KAAK,MAAA,GAAS,MAAA;AAAA,YAC9C,SAAA;AAAA,YACA,UAAA;AAAA,YACA,QAAA,EAAU,MAAA;AAAA,YACV,SAAS,cAAA,EAAgB,OAAA;AAAA,YACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,YAC5B,UAAU,cAAA,EAAgB;AAAA,WAC1B,CAAA;AACD,UAAA,MAAM,UAAA,GAAa,0BAA0B,MAAM,CAAA;AACnD,UAAA,OAAO;AAAA,YACN,OAAA,EAAS;AAAA,cACR,OAAA,CAAQ,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAAA,cAChC,OAAA,CAAQ,CAAA;AAAA,EAA2B,IAAA,CAAK,SAAA,CAAU,UAAU,CAAC;AAAA,qBAAA,CAAyB;AAAA;AACvF,WACD;AAAA,QACD;AAAA,QACA,KAAK,kBAAA,EAAoB;AACxB,UAAA,MAAM,QAAA,GAAW,gBAAgB,IAAI,CAAA;AACrC,UAAA,MAAM,IAAA,GAAO,MAAM,UAAA,CAAW,WAAA,EAAa,aAAa,cAAc,CAAA;AACtE,UAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,IAAA,EAAM,QAAQ,CAAA;AAC7C,UAAA,SAAA,GAAY,MAAA,CAAO,SAAS,MAAA,GAAS,MAAA;AACrC,UAAA,UAAA,GAAa,MAAA;AACb,UAAA,cAAA,CAAe;AAAA,YACd,QAAA,EAAU,IAAA;AAAA,YACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,YACzB,MAAA;AAAA,YACA,WAAW,cAAA,EAAgB,SAAA;AAAA,YAC3B,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,MAAA,GAAS,MAAA;AAAA,YACjC,SAAA;AAAA,YACA,UAAA;AAAA,YACA,QAAA,EAAU,MAAA;AAAA,YACV,SAAS,cAAA,EAAgB,OAAA;AAAA,YACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,YAC5B,UAAU,cAAA,EAAgB;AAAA,WAC1B,CAAA;AACD,UAAA,OAAO,EAAE,SAAS,CAAC,OAAA,CAAQ,qBAAqB,MAAM,CAAC,CAAC,CAAA,EAAE;AAAA,QAC3D;AAAA,QACA,KAAK,iBAAA,EAAmB;AACvB,UAAA,IAAI,WAAA;AACJ,UAAA,IAAI;AACH,YAAA,WAAA,GAAc,0BAA0B,IAAI,CAAA;AAAA,UAC7C,CAAA,CAAA,MAAQ;AACP,YAAA,OAAO,oCAAoC,IAAA,EAAM,IAAA,CAAK,GAAA,EAAI,GAAI,WAAW,cAAc,CAAA;AAAA,UACxF;AACA,UAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAQ,OAAA,EAAQ,GAAI,WAAA;AACvC,UAAA,MAAM,MAAA,GAAS,cAAA,CAAe,SAAA,EAAW,MAAA,EAAQ,OAAO,CAAA;AACxD,UAAA,cAAA,CAAe;AAAA,YACd,QAAA,EAAU,IAAA;AAAA,YACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,YACzB,WAAW,cAAA,EAAgB,SAAA;AAAA,YAC3B,MAAA,EAAQ,MAAA;AAAA,YACR,SAAA,EAAW,MAAA;AAAA,YACX,UAAA,EAAY,EAAE,SAAA,EAAW,OAAA,EAAQ;AAAA,YACjC,QAAA,EAAU,MAAA;AAAA,YACV,SAAS,cAAA,EAAgB,OAAA;AAAA,YACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,YAC5B,UAAU,cAAA,EAAgB;AAAA,WAC1B,CAAA;AACD,UAAA,OAAO,EAAE,SAAS,CAAC,OAAA,CAAQ,kBAAkB,MAAM,CAAC,CAAC,CAAA,EAAE;AAAA,QACxD;AAAA,QACA;AACC,UAAA,cAAA,CAAe;AAAA,YACd,QAAA,EAAU,IAAA;AAAA,YACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,YACzB,MAAA;AAAA,YACA,WAAW,cAAA,EAAgB,SAAA;AAAA,YAC3B,KAAA,EAAO,iBAAiB,IAAI,CAAA,CAAA;AAAA,YAC5B,IAAA;AAAA,YACA,SAAS,cAAA,EAAgB,OAAA;AAAA,YACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,YAC5B,UAAU,cAAA,EAAgB;AAAA,WAC1B,CAAA;AACD,UAAA,OAAO,oBAAA,CAAqB,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAE,CAAA;AAAA;AACrD,IACD,CAAA;AAEA,IAAA,OAAO,MAAM,QAAQ,IAAA,CAAK;AAAA,MACzB,eAAA,EAAgB;AAAA,MAChB,IAAI,OAAA,CAAe,CAAC,CAAA,EAAG,WAAW,UAAA,CAAW,MAAM,MAAA,CAAO,IAAI,KAAA,CAAM,kBAAkB,CAAC,CAAA,EAAG,oBAAoB,CAAC;AAAA,KAC/G,CAAA;AAAA,EACF,SAAS,GAAA,EAAK;AACb,IAAA,IAAI,GAAA,YAAe,KAAA,IAAS,GAAA,CAAI,OAAA,KAAY,kBAAA,EAAoB;AAC/D,MAAA,cAAA,CAAe;AAAA,QACd,QAAA,EAAU,IAAA;AAAA,QACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QACzB,MAAA;AAAA,QACA,WAAW,cAAA,EAAgB,SAAA;AAAA,QAC3B,KAAA,EAAO,qBAAA;AAAA,QACP,IAAA;AAAA,QACA,SAAS,cAAA,EAAgB,OAAA;AAAA,QACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,QAC5B,UAAU,cAAA,EAAgB;AAAA,OAC1B,CAAA;AACD,MAAA,OAAO;AAAA,QACN,OAAA,EAAS,CAAC,QAAA,CAAS,CAAA,EAAG,IAAI,CAAA,iBAAA,EAAoB,oBAAA,GAAuB,GAAI,CAAA,kFAAA,CAA+E,CAAC,CAAA;AAAA,QACzJ,OAAA,EAAS;AAAA,OACV;AAAA,IACD;AACA,IAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,GAAA,EAAK,8BAA8B,CAAA;AACxE,IAAA,cAAA,CAAe;AAAA,MACd,QAAA,EAAU,IAAA;AAAA,MACV,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,MACzB,MAAA;AAAA,MACA,WAAW,cAAA,EAAgB,SAAA;AAAA,MAC3B,KAAA,EAAO,GAAA;AAAA,MACP,IAAA;AAAA,MACA,SAAS,cAAA,EAAgB,OAAA;AAAA,MACzB,YAAY,cAAA,EAAgB,UAAA;AAAA,MAC5B,UAAU,cAAA,EAAgB;AAAA,KAC1B,CAAA;AACD,IAAA,OAAO,qBAAqB,OAAO,CAAA;AAAA,EACpC;AACD;;;AChTA,IAAM,SAAA,GAA2B;AAAA,EAChC;AAAA,IACE,GAAA,EAAK,uCAAA;AAAA,IACL,IAAA,EAAM,2BAAA;AAAA,IACN,WAAA,EACA,kKAAA;AAAA,IACA,QAAA,EAAU;AAAA,GACZ;AAAA,EACA;AAAA,IACE,GAAA,EAAK,+BAAA;AAAA,IACL,IAAA,EAAM,qBAAA;AAAA,IACN,WAAA,EAAa,6GAAA;AAAA,IACb,QAAA,EAAU;AAAA,GACZ;AAAA,EACA;AAAA,IACC,GAAA,EAAK,oCAAA;AAAA,IACL,IAAA,EAAM,4BAAA;AAAA,IACN,WAAA,EAAa,yFAAA;AAAA,IACb,QAAA,EAAU;AAAA,GACX;AAAA,EACA;AAAA,IACC,GAAA,EAAK,uCAAA;AAAA,IACL,IAAA,EAAM,sBAAA;AAAA,IACN,WAAA,EAAa,mFAAA;AAAA,IACb,QAAA,EAAU;AAAA;AAEZ,CAAA;AAGA,IAAM,gBAAA,GAA2C;AAAA,EAChD,uCAAA,EAAyC,CAAA;;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;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,CAAA;AAAA,EA8GzC,+BAAA,EAAiC,CAAA;;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,CAAA;AAAA,EAsDjC,uCAAA,EAAyC,CAAA;;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,CAAA;AAAA,EA0DzC,oCAAA,EAAsC,CAAA;;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAqBvC,CAAA;AAMO,SAAS,mBAAA,GAAoD;AACnE,EAAA,OAAO,EAAE,WAAW,SAAA,EAAU;AAC/B;AAMO,SAAS,oBAAoB,MAAA,EAElC;AACD,EAAA,MAAM,MAAM,MAAA,CAAO,GAAA;AACnB,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC5B,IAAA,MAAM,IAAI,MAAM,iCAAiC,CAAA;AAAA,EAClD;AACA,EAAA,MAAM,OAAA,GAAU,iBAAiB,GAAG,CAAA;AACpC,EAAA,IAAI,CAAC,OAAA,EAAS;AACb,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,oBAAA,EAAuB,GAAG,CAAA,CAAE,CAAA;AAAA,EAC7C;AACA,EAAA,MAAM,WAAW,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,GAAG,CAAA;AACpD,EAAA,OAAO;AAAA,IACN,QAAA,EAAU;AAAA,MACT;AAAA,QACC,GAAA;AAAA,QACA,QAAA,EAAU,UAAU,QAAA,IAAY,YAAA;AAAA,QAChC,IAAA,EAAM;AAAA;AACP;AACD,GACD;AACD;;;AC7SA,IAAM,OAAA,GAAuB;AAAA,EAC5B;AAAA,IACC,IAAA,EAAM,qBAAA;AAAA,IACN,WAAA,EAAa,4EAAA;AAAA,IACb,SAAA,EAAW;AAAA,MACV;AAAA,QACC,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,yCAAA;AAAA,QACb,QAAA,EAAU;AAAA;AACX;AACD,GACD;AAAA,EACA;AAAA,IACC,IAAA,EAAM,kBAAA;AAAA,IACN,WAAA,EAAa,yEAAA;AAAA,IACb,SAAA,EAAW;AAAA,MACV;AAAA,QACC,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,yCAAA;AAAA,QACb,QAAA,EAAU;AAAA;AACX;AACD,GACD;AAAA,EACA;AAAA,IACC,IAAA,EAAM,yBAAA;AAAA,IACN,WAAA,EAAa,+EAAA;AAAA,IACb,SAAA,EAAW;AAAA,MACV;AAAA,QACC,IAAA,EAAM,QAAA;AAAA,QACN,WAAA,EAAa,yCAAA;AAAA,QACb,QAAA,EAAU;AAAA,OACX;AAAA,MACA;AAAA,QACC,IAAA,EAAM,eAAA;AAAA,QACN,WAAA,EAAa,gDAAA;AAAA,QACb,QAAA,EAAU;AAAA;AACX;AACD;AAEF,CAAA;AAGA,SAAS,iBAAA,CAAkB,MAAc,IAAA,EAAkD;AAC1F,EAAA,MAAM,SAAS,IAAA,CAAK,MAAA;AAEpB,EAAA,QAAQ,IAAA;AAAM,IACb,KAAK,qBAAA;AACJ,MAAA,OAAO;AAAA,QACN;AAAA,UACC,IAAA,EAAM,MAAA;AAAA,UACN,OAAA,EAAS;AAAA,YACR,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,uDAAuD,MAAM,CAAA;;AAAA,mCAAA,EAEpC,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+DAAA;AAAA;AAOtC;AACD,OACD;AAAA,IAED,KAAK,kBAAA;AACJ,MAAA,OAAO;AAAA,QACN;AAAA,UACC,IAAA,EAAM,MAAA;AAAA,UACN,OAAA,EAAS;AAAA,YACR,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,8CAA8C,MAAM,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAA,EAOzC,MAAM,CAAA,uFAAA;AAAA;AACxB;AACD,OACD;AAAA,IAED,KAAK,yBAAA,EAA2B;AAC/B,MAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,IAAiB,GAAA;AACpC,MAAA,OAAO;AAAA,QACN;AAAA,UACC,IAAA,EAAM,MAAA;AAAA,UACN,OAAA,EAAS;AAAA,YACR,IAAA,EAAM,MAAA;AAAA,YACN,IAAA,EAAM,YAAY,MAAM,CAAA;;AAAA,wBAAA,EAEJ,MAAM,CAAA;AAAA;AAAA,YAAA,EAElB,KAAK,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA,uIAAA;AAAA;AAQd;AACD,OACD;AAAA,IACD;AAAA,IAEA;AACC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,CAAE,CAAA;AAAA;AAEjD;AAMO,SAAS,iBAAA,GAA8C;AAC7D,EAAA,OAAO,EAAE,SAAS,OAAA,EAAQ;AAC3B;AAMO,SAAS,iBAAiB,MAAA,EAG/B;AACD,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC7B,IAAA,MAAM,IAAI,MAAM,kCAAkC,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,IAAI,CAAA;AAClD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACZ,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,qBAAA,EAAwB,IAAI,CAAA,CAAE,CAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAA,CAAO,SAAA,IAAwC,EAAC;AAC9D,EAAA,MAAM,QAAA,GAAW,iBAAA,CAAkB,IAAA,EAAM,IAAI,CAAA;AAE7C,EAAA,OAAO;AAAA,IACN,aAAa,MAAA,CAAO,WAAA;AAAA,IACpB;AAAA,GACD;AACD;;;ACvJO,SAAS,SAAS,KAAA,EAA4B;AACpD,EAAA,QAAA,CAAS;AAAA,IACR,WAAW,KAAA,CAAM,SAAA,IAAA,iBAAa,IAAI,IAAA,IAAO,WAAA,EAAY;AAAA,IACrD,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,QAAA,EAAU,OAAA;AAAA,IACV,OAAA,EAAS;AAAA,MACR,WAAW,KAAA,CAAM,SAAA;AAAA,MACjB,IAAI,KAAA,CAAM,EAAA;AAAA,MACV,YAAA,EAAc,OAAA,CAAQ,KAAA,CAAM,SAAS,CAAA;AAAA,MACrC,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,GAAG,KAAA,CAAM;AAAA;AACV,GACA,CAAA;AACF;AAKO,SAAS,mBAAA,CAAoB,IAAY,SAAA,EAAyB;AACxE,EAAA,QAAA,CAAS;AAAA,IACR,SAAA,EAAW,iBAAA;AAAA,IACX,EAAA;AAAA,IACA,SAAA;AAAA,IACA,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,IAClC,QAAA,EAAU,MAAA;AAAA,IACV,OAAA,EAAS;AAAA,GACT,CAAA;AACF;;;ACMA,eAAsB,kBAAkB,OAAA,EAAqE;AAC5G,EAAA,QAAQ,QAAQ,MAAA;AAAQ,IACvB,KAAK,YAAA,EAAc;AACjB,MAAA,MAAM,yBAAA,GAA4B,QAAQ,yBAAA,KAA8B,KAAA;AACxE,MAAA,IAAI,yBAAA,IAA6B,CAAC,OAAA,CAAQ,eAAA,EAAiB;AAC3D,QAAA,MAAM,iBAAA,GAAoB,MAAM,2BAAA,CAA4B,OAAA,CAAQ,IAAI,OAAA,CAAQ,WAAA,EAAa,QAAQ,gBAAgB,CAAA;AACrH,QAAA,IAAI,CAAC,kBAAkB,OAAA,EAAS;AAC/B,UAAA,MAAM,oBAAoB,IAAA,CAAK,IAAA,CAAA,CAAM,iBAAA,CAAkB,YAAA,IAAgB,KAAK,GAAI,CAAA;AAChF,UAAA,OAAO;AAAA,YACN,IAAA,EAAM,aAAA;AAAA,YACN,OAAA,EAAS,aAAa,OAAA,CAAQ,EAAA,EAAI,gBAAgB,YAAA,EAAc,CAAA,iCAAA,EAAoC,iBAAiB,CAAA,CAAA,CAAG,CAAA;AAAA,YACxH,MAAA,EAAQ,GAAA;AAAA,YACR,OAAA,EAAS;AAAA,cACR,GAAG,OAAA,CAAQ,WAAA;AAAA,cACX,aAAA,EAAe,OAAO,iBAAiB;AAAA;AACxC,WACD;AAAA,QACD;AAAA,MACD;AAEC,MAAA,MAAM,YAAY,yBAAA,GAA4B,MAAM,cAAc,OAAA,CAAQ,YAAY,IAAI,OAAA,CAAQ,iBAAA;AAClG,MAAA,IAAI,6BAA6B,SAAA,EAAW;AAC3C,QAAA,mBAAA,CAAoB,OAAA,CAAQ,IAAI,SAAS,CAAA;AACzC,QAAA,OAAA,CAAQ,WAAW,gBAAA,CAAiB;AAAA,UACnC,MAAA,EAAQ,SAAA;AAAA,UACR,SAAS,OAAA,CAAQ,OAAA;AAAA,UACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,UACpB,UAAU,OAAA,CAAQ;AAAA,SAClB,CAAA;AAAA,MACF;AAED,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI;AAAA,UACnC,eAAA,EAAiB,YAAA;AAAA,UACjB,YAAA,EAAc;AAAA,YACb,KAAA,EAAO,EAAE,WAAA,EAAa,KAAA,EAAM;AAAA,YAC5B,SAAA,EAAW,EAAE,SAAA,EAAW,KAAA,EAAO,aAAa,KAAA,EAAM;AAAA,YAClD,OAAA,EAAS,EAAE,WAAA,EAAa,KAAA;AAAM,WAC/B;AAAA,UACA,UAAA,EAAY;AAAA,YACX,IAAA,EAAM,eAAA;AAAA,YACN,SAAS,OAAA,CAAQ,aAAA;AAAA,YACjB,WAAA,EACC;AAAA,WACF;AAAA,UACA,YAAA,EAAc,CAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;;AAAA,iJAAA;AAAA,SAgBd,CAAA;AAAA,QACD,YAAA,EAAc,4BAA4B,SAAA,GAAY,MAAA;AAAA,QACtD,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA,IACD;AAAA,IAEA,KAAK,YAAA;AACJ,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,iBAAiB,CAAA;AAAA,QACrD,WAAA,EAAa,OAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA,IAED,KAAK,YAAA,EAAc;AAElB,MAAA,MAAM,aAAa,OAAA,CAAQ,MAAA;AAC3B,MAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,UAAA,EAAY,QAAQ,SAAA,EAAW;AAAA,QACnE,uBAAuB,OAAA,CAAQ,qBAAA;AAAA,QAC/B,8BAAA,EAAgC,iBAAA,CAAkB,OAAA,CAAQ,8BAA8B,CAAA;AAAA,QACxF,0BAA0B,OAAA,CAAQ,wBAAA;AAAA,QAClC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,oBAAoB,OAAA,CAAQ,kBAAA;AAAA,QAC5B,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,eAAe,OAAA,CAAQ,aAAA;AAAA,QACvB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,QACzB,YAAA,EAAc,OAAA,CAAQ,oBAAA,GACnB,EAAE,QAAA,EAAU,QAAQ,oBAAA,EAAsB,KAAA,EAAO,OAAA,CAAQ,iBAAA,EAAkB,GAC3E,MAAA;AAAA,QACH,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,QACpB,UAAU,OAAA,CAAQ;AAAA,OAClB,CAAA;AAED,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,MAAM,CAAA;AAAA,QAC1C,WAAA,EAAa,OAAA;AAAA,QACb,SAAS,UAAA,CAAW,IAAA;AAAA;AAAA,QAErB,SAAA,EAAW,OAAO,MAAA,KAAW,QAAA,IAAY,MAAA,IAAU,YAAY,MAAA,GAAS,MAAA,CAAQ,MAAA,CAA+B,MAAM,CAAA,GAAI,MAAA;AAAA,QACxH,UAAA,EAAY;AAAA,OACb;AAAA,IACD;AAAA,IAEA,KAAK,gBAAA;AACJ,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,qBAAqB,CAAA;AAAA,QACzD,WAAA,EAAa,WAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA,IAED,KAAK,gBAAA,EAAkB;AAEtB,MAAA,MAAM,iBAAiB,OAAA,CAAQ,MAAA;AAC/B,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,SAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,mBAAA,CAAoB,cAAc,CAAC,CAAA;AAAA,QACvE,WAAA,EAAa,WAAA;AAAA,QACb,SAAA,EAAW,MAAA;AAAA,QACX,UAAA,EAAY;AAAA,OACb;AAAA,IACD;AAAA,IAEA,KAAK,cAAA;AACJ,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,mBAAmB,CAAA;AAAA,QACvD,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA,IAED,KAAK,aAAA,EAAe;AACnB,MAAA,MAAM,eAAe,OAAA,CAAQ,MAAA;AAC7B,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,SAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,gBAAA,CAAiB,YAAY,CAAC,CAAA;AAAA,QAClE,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW,KAAA;AAAA,QACX,UAAA,EAAY;AAAA,OACb;AAAA,IACD;AAAA,IAEA,KAAK,MAAA;AACJ,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,cAAA,CAAe,OAAA,CAAQ,EAAA,EAAI,EAAE,CAAA;AAAA,QACtC,WAAA,EAAa,SAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA,IAED;AACC,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,SAAA;AAAA,QACN,OAAA,EAAS,aAAa,OAAA,CAAQ,EAAA,EAAI,gBAAgB,gBAAA,EAAkB,CAAA,kBAAA,EAAqB,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAAA,QACzG,WAAA,EAAa,OAAA;AAAA,QACb,SAAA,EAAW;AAAA,OACZ;AAAA;AAEH;;;AvD5JA,SAAS,oBAAoB,MAAA,EAAiE;AAC7F,EAAA,OAAO,OAAO,WAAW,QAAA,IAAY,MAAA,IAAU,YAAY,MAAA,GAAS,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA;AAC7F;AAEA,SAAS,eAAe,QAAA,EAA4C;AACnE,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,QAAA,CAAS,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AACxC,IAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,EAAY;AAC9B,IAAA,IAAI,KAAA,KAAU,cAAA,IAAkB,KAAA,KAAU,eAAA,IAAmB,UAAU,gBAAA,EAAkB;AACzF,IAAA,OAAA,CAAQ,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAA,OAAO,OAAA;AACR;AAEA,eAAe,mBAAmB,QAAA,EAA8D;AAC/F,EAAA,MAAM,cAAc,QAAA,CAAS,OAAA,CAAQ,IAAI,cAAc,CAAA,EAAG,aAAY,IAAK,EAAA;AAC3E,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,mBAAmB,CAAA,EAAG;AAC9C,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,IAAA,MAAM,QAAA,GAAW,IAAA,CACf,KAAA,CAAM,IAAI,CAAA,CACV,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAC,CAAA;AAC1C,IAAA,IAAI,CAAC,QAAA,EAAU;AACd,MAAA,OAAO,YAAA,CAAa,IAAA,EAAM,eAAA,CAAgB,cAAA,EAAgB,uBAAuB,CAAA;AAAA,IAClF;AACA,IAAA,OAAO,KAAK,KAAA,CAAM,QAAA,CAAS,KAAA,CAAM,QAAA,CAAS,MAAM,CAAC,CAAA;AAAA,EAClD;AAEA,EAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAC7B;AAEA,SAAS,oBAAA,CACR,OAAA,EACA,MAAA,EACA,MAAA,EACA,eAAA,EACO;AACP,EAAA,OAAA,CAAQ,WAAW,gBAAA,CAAiB;AAAA,IACnC,MAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,SAAA;AAAA,IACjC,iBAAiB,OAAA,CAAQ,eAAA;AAAA,IACzB,eAAA;AAAA,IACA,WAAW,OAAA,CAAQ,iBAAA;AAAA,IACnB,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,IACpB,UAAU,OAAA,CAAQ,QAAA;AAAA,IAClB,aAAa,OAAA,CAAQ;AAAA,GACrB,CAAA;AACF;AAEA,eAAsB,kBAAkB,OAAA,EAAoE;AAC3G,EAAA,MAAM,eAAA,GAAkB,sBAAA,CAAuB,OAAA,CAAQ,IAAI,CAAA;AAC3D,EAAA,IAAI,eAAA,EAAiB;AACpB,IAAA,oBAAA;AAAA,MACC,OAAA;AAAA,MACA,OAAO,OAAA,CAAQ,IAAA,EAAM,WAAW,QAAA,GAAW,OAAA,CAAQ,KAAK,MAAA,GAAS,SAAA;AAAA,MACjE,OAAA;AAAA,MACA;AAAA,KACD;AACA,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,SAAS,eAAA,CAAgB,OAAA;AAAA,MACzB,SAAS,EAAC;AAAA,MACV,YAAY,eAAA,CAAgB,MAAA;AAAA,MAC5B,gBAAA,EAAkB,IAAA;AAAA,MAClB,OAAA,EAAS,QAAQ,IAAA,CAAK,EAAA,IAAM,OAAO,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,EAAE,CAAA,GAAI;AAAA,KAC9D;AAAA,EACD;AAEA,EAAA,MAAM,EAAE,EAAA,EAAI,MAAA,EAAQ,MAAA,KAAW,OAAA,CAAQ,IAAA;AACvC,EAAA,MAAM,OAAA,GAAU,EAAA,IAAM,IAAA,GAAO,MAAA,CAAO,EAAE,CAAA,GAAI,MAAA;AAE1C,EAAA,IAAI,QAAQ,SAAA,IAAa,OAAA,CAAQ,SAAA,GAAY,CAAA,IAAK,WAAW,YAAA,EAAc;AAC1E,IAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS,YAAA,CAAa,EAAA,EAAI,eAAA,CAAgB,iBAAiB,kFAAkF,CAAA;AAAA,MAC7I,SAAS,EAAC;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,gBAAA,EAAkB,IAAA;AAAA,MAClB;AAAA,KACD;AAAA,EACD;AAEA,EAAA,IAAI,cAAsC,EAAC;AAC3C,EAAA,IAAI,CAAC,OAAA,CAAQ,eAAA,IAAmB,MAAA,KAAW,YAAA,EAAc;AACxD,IAAA,MAAM,eAAe,MAAM,qBAAA,CAAsB,yBAAyB,OAAA,CAAQ,WAAA,EAAa,QAAQ,gBAAgB,CAAA;AACvH,IAAA,IAAI,CAAC,aAAa,OAAA,EAAS;AAC1B,MAAA,MAAM,gBAAwC,EAAC;AAC/C,MAAA,IAAI,YAAA,CAAa,iBAAiB,MAAA,EAAW;AAC5C,QAAA,aAAA,CAAc,aAAa,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,YAAA,CAAa,YAAA,GAAe,GAAI,CAAC,CAAA;AAAA,MAClF;AACA,MAAA,OAAA,CAAQ,WAAW,kBAAA,CAAmB;AAAA,QACrC,SAAA,EAAW,cAAA;AAAA,QACX,QAAA,EAAU,KAAA;AAAA,QACV,KAAA,EAAO,uBAAA;AAAA,QACP,SAAA,EAAW,CAAA;AAAA,QACX,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,UAAU,OAAA,CAAQ;AAAA,OAClB,CAAA;AACD,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,YAAA;AAAA,UACR,EAAA;AAAA,UACA,eAAA,CAAgB,YAAA;AAAA,UAChB;AAAA,SACD;AAAA,QACA,OAAA,EAAS,aAAA;AAAA,QACT,UAAA,EAAY,GAAA;AAAA,QACZ,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAEA,IAAA,MAAM,UAAA,GAAa,MAAM,cAAA,CAAe,OAAA,CAAQ,IAAI,OAAA,CAAQ,WAAA,EAAa,QAAQ,gBAAgB,CAAA;AACjG,IAAA,WAAA,GAAc;AAAA,MACb,mBAAA,EAAqB,IAAA;AAAA,MACrB,uBAAA,EAAyB,MAAA,CAAO,UAAA,CAAW,eAAe;AAAA,KAC3D;AACA,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AACxB,MAAA,IAAI,UAAA,CAAW,iBAAiB,MAAA,EAAW;AAC1C,QAAA,WAAA,CAAY,aAAa,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,UAAA,CAAW,YAAA,GAAe,GAAI,CAAC,CAAA;AAAA,MAC9E;AACA,MAAA,OAAA,CAAQ,WAAW,kBAAA,CAAmB;AAAA,QACrC,SAAA,EAAW,QAAA;AAAA,QACX,QAAA,EAAU,KAAA;AAAA,QACV,KAAA,EAAO,EAAA;AAAA,QACP,WAAW,UAAA,CAAW,eAAA;AAAA,QACtB,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,UAAU,OAAA,CAAQ;AAAA,OAClB,CAAA;AACD,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,YAAA;AAAA,UACR,EAAA;AAAA,UACA,eAAA,CAAgB,YAAA;AAAA,UAChB,oCAAoC,IAAA,CAAK,IAAA,CAAA,CAAM,WAAW,YAAA,IAAgB,CAAA,IAAK,GAAI,CAAC,CAAA,CAAA;AAAA,SACrF;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,UAAA,EAAY,GAAA;AAAA,QACZ,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAEA,IAAA,MAAM,WAAA,GAAc,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,MAAA,IAAU,MAAA,GAAU,MAAA,CAAmC,IAAA,GAAO,MAAA;AACnI,IAAA,MAAM,WAAW,OAAO,WAAA,KAAgB,QAAA,GAAW,iBAAA,CAAkB,WAAW,CAAA,GAAI,EAAA;AACpF,IAAA,MAAM,cAAA,GAAiB,QAAA,GAAW,sBAAA,CAAuB,QAAQ,CAAA,GAAI,MAAA;AACrE,IAAA,IAAI,mBAAmB,MAAA,EAAW;AACjC,MAAA,MAAM,kBAAkB,MAAM,uBAAA;AAAA,QAC7B,OAAA,CAAQ,EAAA;AAAA,QACR,QAAA;AAAA,QACA,cAAA;AAAA,QACA,OAAA,CAAQ,WAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACT;AACA,MAAA,WAAA,CAAY,eAAe,CAAA,GAAI,MAAA,CAAO,eAAA,CAAgB,KAAK,CAAA;AAC3D,MAAA,WAAA,CAAY,mBAAmB,CAAA,GAAI,MAAA,CAAO,eAAA,CAAgB,SAAS,CAAA;AACnE,MAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC7B,QAAA,IAAI,eAAA,CAAgB,iBAAiB,MAAA,EAAW;AAC/C,UAAA,WAAA,CAAY,aAAa,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,eAAA,CAAgB,YAAA,GAAe,GAAI,CAAC,CAAA;AAAA,QACnF;AACA,QAAA,OAAA,CAAQ,WAAW,kBAAA,CAAmB;AAAA,UACrC,SAAA,EAAW,YAAA;AAAA,UACX,QAAA;AAAA,UACA,KAAA,EAAO,cAAA;AAAA,UACP,SAAA,EAAW,CAAA;AAAA,UACX,SAAS,OAAA,CAAQ,OAAA;AAAA,UACjB,QAAA,EAAU,QAAQ,QAAA,IAAY;AAAA,SAC9B,CAAA;AACD,QAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,QAAA,OAAO;AAAA,UACN,IAAA,EAAM,UAAA;AAAA,UACN,OAAA,EAAS,YAAA;AAAA,YACR,EAAA;AAAA,YACA,eAAA,CAAgB,YAAA;AAAA,YAChB,CAAA,qBAAA,EAAwB,QAAQ,CAAA,eAAA,EAAkB,cAAc,CAAA,sCAAA;AAAA,WACjE;AAAA,UACA,OAAA,EAAS,WAAA;AAAA,UACT,UAAA,EAAY,GAAA;AAAA,UACZ,gBAAA,EAAkB,IAAA;AAAA,UAClB;AAAA,SACD;AAAA,MACD;AAAA,IACD;AAAA,EACD,CAAA,MAAA,IAAW,QAAQ,cAAA,EAAgB,aAAA,IAAiB,QAAQ,cAAA,CAAe,IAAA,IAAQ,WAAW,YAAA,EAAc;AAE3G,IAAA,MAAM,IAAA,GAAO,QAAQ,cAAA,CAAe,IAAA;AACpC,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,cAAA,CAAe,OAAA,IAAW,OAAA,CAAQ,EAAA;AAE9D,IAAA,MAAM,WAAA,GAAc,OAAO,MAAA,KAAW,QAAA,IAAY,WAAW,IAAA,IAAQ,MAAA,IAAU,MAAA,GAAU,MAAA,CAAmC,IAAA,GAAO,MAAA;AACnI,IAAA,MAAM,WAAW,OAAO,WAAA,KAAgB,QAAA,GAAW,iBAAA,CAAkB,WAAW,CAAA,GAAI,SAAA;AAGpF,IAAA,MAAM,aAAa,sBAAA,CAAuB,IAAI,IAAI,QAAQ,CAAA,IAAK,kBAAkB,IAAI,CAAA;AAErF,IAAA,MAAM,kBAAkB,MAAM,uBAAA;AAAA,MAC7B,WAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA;AAAA,MACA,OAAA,CAAQ,WAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AACA,IAAA,WAAA,CAAY,eAAe,CAAA,GAAI,MAAA,CAAO,eAAA,CAAgB,KAAK,CAAA;AAC3D,IAAA,WAAA,CAAY,mBAAmB,CAAA,GAAI,MAAA,CAAO,eAAA,CAAgB,SAAS,CAAA;AACnE,IAAA,WAAA,CAAY,cAAc,CAAA,GAAI,IAAA;AAC9B,IAAA,IAAI,CAAC,gBAAgB,OAAA,EAAS;AAC7B,MAAA,IAAI,eAAA,CAAgB,iBAAiB,MAAA,EAAW;AAC/C,QAAA,WAAA,CAAY,aAAa,IAAI,MAAA,CAAO,IAAA,CAAK,KAAK,eAAA,CAAgB,YAAA,GAAe,GAAI,CAAC,CAAA;AAAA,MACnF;AACA,MAAA,OAAA,CAAQ,WAAW,kBAAA,CAAmB;AAAA,QACrC,SAAA,EAAW,YAAA;AAAA,QACX,QAAA;AAAA,QACA,KAAA,EAAO,UAAA;AAAA,QACP,SAAA,EAAW,CAAA;AAAA,QACX,SAAS,OAAA,CAAQ,OAAA;AAAA,QACjB,QAAA,EAAU;AAAA,OACV,CAAA;AACD,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,YAAA;AAAA,UACR,EAAA;AAAA,UACA,eAAA,CAAgB,YAAA;AAAA,UAChB,CAAA,qBAAA,EAAwB,IAAI,CAAA,oBAAA,EAAuB,UAAU,CAAA,kBAAA;AAAA,SAC9D;AAAA,QACA,OAAA,EAAS,WAAA;AAAA,QACT,UAAA,EAAY,GAAA;AAAA,QACZ,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,WAAW,YAAA,EAAc;AAC5B,IAAA,MAAM,sBAAsB,MAAM,kCAAA;AAAA,MACjC,OAAA,CAAQ,EAAA;AAAA,MACR,OAAA,CAAQ,WAAA;AAAA,MACR,MAAA;AAAA,MACA,OAAA,CAAQ,eAAA;AAAA,MACR,EAAA;AAAA,MACA,OAAA,CAAQ,MAAA;AAAA,MACR,OAAA,CAAQ;AAAA,KACT;AACA,IAAA,IAAI,mBAAA,EAAqB;AACxB,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,OAAA,EAAS,MAAM,kBAAA,CAAmB,mBAAmB,CAAA;AAAA,QACrD,OAAA,EAAS,eAAe,mBAAmB,CAAA;AAAA,QAC3C,YAAY,mBAAA,CAAoB,MAAA;AAAA,QAChC,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,IAAI,OAAA,CAAQ,mBAAmB,MAAA,KAAW,YAAA,IAAgB,CAAC,MAAA,CAAO,UAAA,CAAW,gBAAgB,CAAA,EAAG;AAC/F,IAAA,MAAM,eAAe,MAAM,sBAAA;AAAA,MAC1B,OAAA,CAAQ,SAAA;AAAA,MACR,OAAA,CAAQ,YAAA;AAAA,MACR,EAAA;AAAA,MACA,QAAQ,mBAAA,IAAuB;AAAA,KAChC;AACA,IAAA,IAAI,YAAA,EAAc;AACjB,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,SAAS,YAAA,CAAa,OAAA;AAAA,QACtB,SAAS,EAAC;AAAA,QACV,YAAY,YAAA,CAAa,MAAA;AAAA,QACzB,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAAA,EACD;AAEA,EAAA,MAAM,cAAA,GAAiB,EAAA,KAAO,MAAA,IAAa,EAAA,KAAO,IAAA;AAClD,EAAA,IAAI,cAAA,IAAkB,WAAW,YAAA,EAAc;AAC9C,IAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,IAAA,EAAM,KAAK,CAAA;AACjD,IAAA,OAAO,EAAE,MAAM,cAAA,EAAe;AAAA,EAC/B;AAEA,EAAA,IAAI,OAAA,CAAQ,cAAA,IAAkB,MAAA,KAAW,YAAA,IAAgB,OAAA,CAAQ,sBAAsB,KAAA,IAAS,UAAA,CAAW,OAAA,CAAQ,MAAM,CAAA,EAAG;AAC3H,IAAA,MAAM,kBAAkB,iBAAA,CAAkB;AAAA,MACzC,EAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,iBAAiB,OAAA,CAAQ,eAAA;AAAA,MACzB,WAAA;AAAA,MACA,eAAe,OAAA,CAAQ,aAAA;AAAA,MACvB,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,kBAAkB,OAAA,CAAQ,gBAAA;AAAA,MAC1B,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,uBAAuB,OAAA,CAAQ,qBAAA;AAAA,MAC/B,gCAAgC,OAAA,CAAQ,8BAAA;AAAA,MACxC,0BAA0B,OAAA,CAAQ,wBAAA;AAAA,MAClC,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,oBAAoB,OAAA,CAAQ,kBAAA;AAAA,MAC5B,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,2BAA2B,OAAA,CAAQ,yBAAA;AAAA,MACnC,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,eAAe,OAAA,CAAQ,aAAA;AAAA,MACvB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,MACzB,sBAAsB,OAAA,CAAQ,oBAAA;AAAA,MAC9B,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,UAAU,OAAA,CAAQ;AAAA,KAClB,CAAA,CAAE,IAAA,CAAK,CAAC,cAAA,KAAmB;AAC3B,MAAA,IAAI,cAAA,CAAe,SAAS,aAAA,EAAe;AAC1C,QAAA,OAAO,cAAA,CAAe,OAAA;AAAA,MACvB;AAEA,MAAA,QAAA,CAAS;AAAA,QACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAClC,SAAA,EAAW,OAAO,EAAA,KAAO,QAAA,GAAW,EAAA,GAAK,MAAA;AAAA,QACzC,IAAI,OAAA,CAAQ,EAAA;AAAA,QACZ,MAAM,cAAA,CAAe,OAAA;AAAA,QACrB,UAAU,cAAA,CAAe,WAAA;AAAA,QACzB,QAAQ,cAAA,CAAe,SAAA;AAAA,QACvB,SAAS,cAAA,CAAe,UAAA;AAAA,QACxB,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,SAAA;AAAA,QACjC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,QAAA,EAAU,cAAA,CAAe,WAAA,KAAgB,OAAA,GAAU,OAAA,GAAU,MAAA;AAAA,QAC7D,MAAA,EAAQ,oBAAoB,MAAM;AAAA,OAClC,CAAA;AAED,MAAA,MAAM,eAAA,GAAkB,OAAO,cAAA,CAAe,OAAA,KAAY,YAAY,cAAA,CAAe,OAAA,KAAY,IAAA,IAAQ,OAAA,IAAW,cAAA,CAAe,OAAA;AACnI,MAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,eAAA,GAAkB,OAAA,GAAU,MAAM,eAAe,CAAA;AACvF,MAAA,OAAO,cAAA,CAAe,OAAA;AAAA,IACvB,CAAC,CAAA;AAED,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS,IAAA;AAAA,MACT,OAAA,EAAS,EAAE,GAAG,WAAA,EAAY;AAAA,MAC1B,UAAA,EAAY,GAAA;AAAA,MACZ,gBAAA,EAAkB,KAAA;AAAA,MAClB,OAAA;AAAA,MACA,eAAA,EAAiB;AAAA,KAClB;AAAA,EACD;AAEA,EAAA,IAAI;AACH,IAAA,MAAM,cAAA,GAAiB,MAAM,iBAAA,CAAkB;AAAA,MAC9C,EAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,iBAAiB,OAAA,CAAQ,eAAA;AAAA,MACzB,WAAA;AAAA,MACA,eAAe,OAAA,CAAQ,aAAA;AAAA,MACvB,aAAa,OAAA,CAAQ,WAAA;AAAA,MACrB,kBAAkB,OAAA,CAAQ,gBAAA;AAAA,MAC1B,cAAc,OAAA,CAAQ,YAAA;AAAA,MACtB,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,uBAAuB,OAAA,CAAQ,qBAAA;AAAA,MAC/B,gCAAgC,OAAA,CAAQ,8BAAA;AAAA,MACxC,0BAA0B,OAAA,CAAQ,wBAAA;AAAA,MAClC,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,oBAAoB,OAAA,CAAQ,kBAAA;AAAA,MAC5B,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,2BAA2B,OAAA,CAAQ,yBAAA;AAAA,MACnC,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,eAAe,OAAA,CAAQ,aAAA;AAAA,MACvB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,MACzB,sBAAsB,OAAA,CAAQ,oBAAA;AAAA,MAC9B,mBAAmB,OAAA,CAAQ,iBAAA;AAAA,MAC3B,SAAS,OAAA,CAAQ,OAAA;AAAA,MACjB,YAAY,OAAA,CAAQ,UAAA;AAAA,MACpB,UAAU,OAAA,CAAQ;AAAA,KAClB,CAAA;AAED,IAAA,IAAI,cAAA,CAAe,SAAS,aAAA,EAAe;AAC1C,MAAA,OAAO;AAAA,QACN,IAAA,EAAM,UAAA;AAAA,QACN,SAAS,cAAA,CAAe,OAAA;AAAA,QACxB,SAAS,cAAA,CAAe,OAAA;AAAA,QACxB,YAAY,cAAA,CAAe,MAAA;AAAA,QAC3B,gBAAA,EAAkB,IAAA;AAAA,QAClB;AAAA,OACD;AAAA,IACD;AAEA,IAAA,MAAM,UAAkC,EAAC;AACzC,IAAA,IAAI,eAAe,YAAA,EAAc;AAChC,MAAA,OAAA,CAAQ,gBAAgB,IAAI,cAAA,CAAe,YAAA;AAAA,IAC5C;AACA,IAAA,MAAA,CAAO,MAAA,CAAO,SAAS,WAAW,CAAA;AAElC,IAAA,QAAA,CAAS;AAAA,MACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,MAClC,SAAA,EAAW,OAAO,EAAA,KAAO,QAAA,GAAW,EAAA,GAAK,KAAA,CAAA;AAAA,MACzC,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,MAAM,cAAA,CAAe,OAAA;AAAA,MACrB,UAAU,cAAA,CAAe,WAAA;AAAA,MACzB,QAAQ,cAAA,CAAe,SAAA;AAAA,MACvB,SAAS,cAAA,CAAe,UAAA;AAAA,MACxB,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,SAAA;AAAA,MACjC,WAAW,OAAA,CAAQ,SAAA;AAAA,MACnB,QAAA,EAAU,cAAA,CAAe,WAAA,KAAgB,OAAA,GAAU,OAAA,GAAU,MAAA;AAAA,MAC7D,MAAA,EAAQ,oBAAoB,MAAM;AAAA,KAClC,CAAA;AAED,IAAA,MAAM,eAAA,GAAkB,OAAO,cAAA,CAAe,OAAA,KAAY,YAAY,cAAA,CAAe,OAAA,KAAY,IAAA,IAAQ,OAAA,IAAW,cAAA,CAAe,OAAA;AACnI,IAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,eAAA,GAAkB,OAAA,GAAU,MAAM,eAAe,CAAA;AAEvF,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,SAAS,cAAA,CAAe,OAAA;AAAA,MACxB,OAAA;AAAA,MACA,UAAA,EAAY,GAAA;AAAA,MACZ,gBAAA,EAAkB,KAAA;AAAA,MAClB;AAAA,KACD;AAAA,EACD,SAAS,GAAA,EAAK;AACb,IAAA,oBAAA,CAAqB,OAAA,EAAS,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AACnD,IAAA,QAAA,CAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,GAAM,MAAA,CAAO,GAAG,CAAA,EAAG;AAAA,MAClD,QAAA,EAAU,OAAA;AAAA,MACV,IAAI,OAAA,CAAQ,EAAA;AAAA,MACZ,SAAA,EAAW,OAAO,OAAA,CAAQ,IAAA,EAAM,OAAO,QAAA,GAAW,OAAA,CAAQ,KAAK,EAAA,GAAK,MAAA;AAAA,MACpE,IAAA,EAAM,OAAO,OAAA,CAAQ,IAAA,EAAM,WAAW,QAAA,GAAW,OAAA,CAAQ,KAAK,MAAA,GAAS,MAAA;AAAA,MACvE,OAAA,EAAS,EAAE,MAAA,EAAQ,OAAA,CAAQ,IAAA,EAAM,MAAA,IAAU,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAA,KAAW,QAAA,GAAW,EAAE,IAAA,EAAM,OAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,CAAE,IAAA,EAAK,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,EAAE,GAAI,MAAA,EAAU;AAAA,MAChK,UAAA,EAAY,IAAA,CAAK,GAAA,EAAI,GAAI,OAAA,CAAQ,SAAA;AAAA,MACjC,WAAW,OAAA,CAAQ;AAAA,KACnB,CAAA;AACD,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,OAAA,EAAS,aAAa,EAAA,EAAI,eAAA,CAAgB,gBAAgB,oBAAA,CAAqB,GAAA,EAAK,uBAAuB,CAAC,CAAA;AAAA,MAC5G,SAAS,EAAC;AAAA,MACV,UAAA,EAAY,GAAA;AAAA,MACZ,gBAAA,EAAkB,IAAA;AAAA,MAClB;AAAA,KACD;AAAA,EACD;AACD;;;AwDzfO,IAAM,cAAA,GAAiB,OAAA;;;ACkC9B,SAAS,yBAAyB,EAAA,EAAyE;AAC1G,EAAA,OAAO,YAAA,CAAa,EAAA,EAAI,eAAA,CAAgB,eAAA,EAAiB,wBAAwB,CAAA;AAClF;AAEA,SAAS,iCAAiC,EAAA,EAAyE;AAClH,EAAA,OAAO,YAAA,CAAa,EAAA,EAAI,eAAA,CAAgB,eAAA,EAAiB,kFAAkF,CAAA;AAC5I;AAEA,eAAe,cAAA,CACd,OAAA,EACA,KAAA,EACA,SAAA,EAC8C;AAC9C,EAAA,MAAM,EAAE,EAAA,EAAI,MAAA,EAAO,GAAI,OAAA;AACvB,EAAA,IAAI,SAAA,GAAY,CAAA,IAAK,MAAA,KAAW,YAAA,EAAc;AAC7C,IAAA,OAAO,iCAAiC,EAAE,CAAA;AAAA,EAC3C;AAEA,EAAA,MAAM,cAAA,GAAiB,EAAA,KAAO,MAAA,IAAa,EAAA,KAAO,IAAA;AAClD,EAAA,IAAI,MAAA,KAAW,YAAA,IAAgB,CAAC,KAAA,CAAM,WAAA,EAAa;AAClD,IAAA,OAAO,cAAA,GAAiB,MAAA,GAAY,wBAAA,CAAyB,EAAE,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,cAAA,EAAgB;AACnB,IAAA,IAAI,WAAW,2BAAA,EAA6B;AAC3C,MAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AAAA,IACrB;AACA,IAAA,OAAO,MAAA;AAAA,EACR;AAEA,EAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAkB;AAAA,IACtC,IAAA,EAAM,OAAA;AAAA,IACN,cAAA,EAAgB,KAAA;AAAA,IAChB,WAAW,SAAA,GAAY,CAAA;AAAA,IACvB,SAAA;AAAA,IACA,iBAAA,EAAmB,MAAA;AAAA,IACnB,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,IACpB,EAAA,EAAI,OAAA;AAAA,IACJ,eAAA,EAAiB,IAAA;AAAA,IACjB,eAAA,EAAiB,KAAA;AAAA,IACjB,yBAAA,EAA2B,KAAA;AAAA,IAC3B,aAAA,EAAe;AAAA,GACf,CAAA;AACD,EAAA,IAAI,MAAA,CAAO,SAAS,cAAA,EAAgB;AACnC,IAAA,OAAO,MAAA;AAAA,EACR;AAEA,EAAA,IAAI,WAAW,YAAA,EAAc;AAC5B,IAAA,KAAA,CAAM,WAAA,GAAc,IAAA;AAAA,EACrB;AAEA,EAAA,OAAO,MAAA,CAAO,OAAA;AACf;AAEA,eAAe,qBAAA,CACd,KAAA,EACA,KAAA,EACA,SAAA,EAC8C;AAC9C,EAAA,IAAI,CAAC,SAAS,OAAO,KAAA,KAAU,YAAY,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChE,IAAA,OAAO,YAAA,CAAa,IAAA,EAAM,eAAA,CAAgB,eAAA,EAAiB,8BAA8B,CAAA;AAAA,EAC1F;AAEA,EAAA,OAAO,cAAA,CAAe,KAAA,EAAyB,KAAA,EAAO,SAAS,CAAA;AAChE;AAEO,SAAS,iBAAA,GAAiC;AAChD,EAAA,MAAM,KAAA,GAA0B,EAAE,WAAA,EAAa,KAAA,EAAM;AAErD,EAAA,OAAO;AAAA,IACN,KAAA;AAAA,IACA,MAAM,cAAc,UAAA,EAAuC;AAC1D,MAAA,MAAM,OAAA,GAAU,WAAW,IAAA,EAAK;AAChC,MAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAC;AAEtB,MAAA,MAAM,MAAA,GAAS,oBAAoB,OAAO,CAAA;AAC1C,MAAA,IAAI,CAAC,OAAO,EAAA,EAAI;AACf,QAAA,OAAO,CAAC,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA,MACvC;AAEA,MAAA,IAAI,OAAO,OAAA,EAAS;AACnB,QAAA,MAAM,UAAU,MAAA,CAAO,IAAA;AACvB,QAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,GAAA;AAAA,UAC9B,OAAA,CAAQ,IAAI,CAAC,KAAA,KAAU,sBAAsB,KAAA,EAAO,KAAA,EAAO,OAAA,CAAQ,MAAM,CAAC;AAAA,SAC3E;AACA,QAAA,MAAM,YAAY,QAAA,CAAS,MAAA,CAAO,CAACc,QAAAA,KAA+CA,aAAY,MAAS,CAAA;AACvG,QAAA,OAAO,SAAA,CAAU,SAAS,CAAA,GAAI,CAAC,KAAK,SAAA,CAAU,SAAS,CAAC,CAAA,GAAI,EAAC;AAAA,MAC9D;AAEA,MAAA,MAAM,UAAU,MAAM,qBAAA,CAAsB,MAAA,CAAO,IAAA,EAAM,OAAO,CAAC,CAAA;AACjE,MAAA,OAAO,UAAU,CAAC,IAAA,CAAK,UAAU,OAAO,CAAC,IAAI,EAAC;AAAA,IAC/C;AAAA,GACD;AACD;AAEA,eAAsB,cAAA,GAAgC;AACrD,EAAA,MAAM,SAAS,iBAAA,EAAkB;AACjC,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,IAAI,OAAA,GAAU,QAAQ,OAAA,EAAQ;AAE9B,EAAA,MAAM,SAAA,GAAY,CAAC,IAAA,KAAuB;AACzC,IAAA,OAAA,GAAU,OAAA,CACR,KAAK,YAAY;AACjB,MAAA,MAAM,OAAA,GAAU,MAAM,MAAA,CAAO,aAAA,CAAc,IAAI,CAAA;AAC/C,MAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC7B,QAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,MAAM;AAAA,CAAI,CAAA;AAAA,MACnC;AAAA,IACD,CAAC,CAAA,CACA,KAAA,CAAM,CAAC,KAAA,KAAmB;AAC1B,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,4BAAA;AACzD,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,oBAAA,EAAuB,OAAO;AAAA,CAAI,CAAA;AACvD,MAAA,OAAA,CAAQ,QAAA,GAAW,CAAA;AAAA,IACpB,CAAC,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,OAAA,CAAQ,KAAA,CAAM,YAAY,MAAM,CAAA;AAChC,EAAA,OAAA,CAAQ,KAAA,CAAM,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAAkB;AAC3C,IAAA,MAAA,IAAU,KAAA;AACV,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA;AAClC,IAAA,MAAA,GAAS,KAAA,CAAM,KAAI,IAAK,EAAA;AACxB,IAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACzB,MAAA,SAAA,CAAU,IAAI,CAAA;AAAA,IACf;AAAA,EACD,CAAC,CAAA;AAED,EAAA,OAAA,CAAQ,KAAA,CAAM,EAAA,CAAG,KAAA,EAAO,MAAM;AAC7B,IAAA,IAAI,MAAA,CAAO,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG;AAC7B,MAAA,SAAA,CAAU,MAAM,CAAA;AAChB,MAAA,MAAA,GAAS,EAAA;AAAA,IACV;AAAA,EACD,CAAC,CAAA;AAED,EAAA,OAAA,CAAQ,MAAM,MAAA,EAAO;AACrB,EAAA,MAAM,OAAA;AACP;AAEA,IAAM,kBAAA,GAAqB,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,IAAK,EAAA;AAC9C,IAAM,WAAA,GAAc,OAAO,kBAAA,KAAuB,QAAA,IAAY,MAAA,CAAA,IAAA,CAAY,QAAQ,IAAI,GAAA,CAAI,kBAAA,EAAoB,OAAO,CAAA,CAAE,IAAA;AAEvH,IAAI,WAAA,EAAa;AAChB,EAAA,KAAK,cAAA,EAAe;AACrB","file":"stdio.js","sourcesContent":["// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Centralized configuration for domain normalization and validation.\n */\nexport const BLOCKED_SUFFIXES = [\n\t'.local',\n\t'.localhost',\n\t'.internal',\n\t'.example',\n\t'.invalid',\n\t'.test',\n\t'.onion',\n\t'.lan',\n\t'.home',\n\t'.corp',\n\t'.intranet',\n];\nexport const BLOCKED_HOSTS = ['localhost', 'localhost.localdomain'];\nexport const BLOCKED_IP_PATTERNS = [\n\t/^127\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^10\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^172\\.(1[6-9]|2[0-9]|3[01])\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^192\\.168\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^169\\.254\\.[0-9]{1,3}\\.[0-9]{1,3}$/,\n\t/^0\\.0\\.0\\.0$/,\n\t/^::1$/,\n\t/^fc00:/i,\n\t/^fd[0-9a-f]{2}:/i,\n\t/^fe[89ab][0-9a-f]:/i,\n];\nexport const BLOCKED_DNS_REBINDING = ['.nip.io', '.sslip.io', '.xip.io', '.nip.direct'];\nexport const MAX_DOMAIN_LENGTH = 253;\nexport const MAX_LABEL_LENGTH = 63;\nexport const LABEL_REGEX = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/i;\n\n/** Hard limit on incoming JSON-RPC request body size (bytes). */\nexport const MAX_REQUEST_BODY_BYTES = 10_240;\n\n/** Timeout for outbound HTTPS fetches (SSL, MTA-STS policy, etc.). */\nexport const HTTPS_TIMEOUT_MS = 4_000;\n\n/** Default timeout for DNS-over-HTTPS queries. CF DoH p99 is <500ms. */\nexport const DNS_TIMEOUT_MS = 3_000;\n\n/** Default number of retry attempts for DNS-over-HTTPS queries. */\nexport const DNS_RETRIES = 1;\n\n/** Edge cache TTL (seconds) for outbound DoH fetch requests via Cloudflare's cf API. */\nexport const DOH_EDGE_CACHE_TTL = 300;\n\n/** Timeout (ms) after which a stuck INFLIGHT promise is evicted from the dedup map. */\nexport const INFLIGHT_CLEANUP_MS = 30_000;\n\n/** Base delay (ms) between DNS retry attempts. Actual delay = base * (attempt+1) + jitter. */\nexport const DNS_RETRY_BASE_DELAY_MS = 75;\n\n/**\n * When true, empty DoH answers from the primary resolver are optionally\n * confirmed with a secondary resolver to reduce false negatives.\n */\nexport const DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY = true;\n\n/** Default cache TTL in seconds. Override via CACHE_TTL_SECONDS env var. */\nexport const DEFAULT_CACHE_TTL_SECONDS = 300;\n\n/**\n * Parse CACHE_TTL_SECONDS env var, clamping to [60, 3600].\n * Returns DEFAULT_CACHE_TTL_SECONDS when absent or invalid.\n */\nexport function parseCacheTtl(envValue?: string): number {\n\tif (!envValue) return DEFAULT_CACHE_TTL_SECONDS;\n\tconst parsed = Number(envValue);\n\tif (!Number.isFinite(parsed) || parsed < 60) return DEFAULT_CACHE_TTL_SECONDS;\n\treturn Math.min(parsed, 3600);\n}\n\n/**\n * Global daily free-tier request ceiling across all unauthenticated IPs.\n * Protects from abuse by capping free usage at a service-wide level.\n * Authenticated requests are exempt.\n */\nexport const GLOBAL_DAILY_TOOL_LIMIT = 500_000;\n\n/**\n * Free-tier daily tool quotas for unauthenticated callers.\n * Tools omitted from this map are governed only by baseline per-IP rate limits.\n */\n/** MCP API key tiers with daily scan quotas. */\nexport type McpApiKeyTier = 'free' | 'agent' | 'developer' | 'enterprise' | 'partner';\n\n/** Daily scan limits per API key tier (applies per tool unless overridden by TIER_TOOL_DAILY_LIMITS). */\nexport const TIER_DAILY_LIMITS: Record<McpApiKeyTier, number> = {\n\tfree: 50,\n\tagent: 200,\n\tdeveloper: 500,\n\tenterprise: 10_000,\n\tpartner: 100_000,\n};\n\n/**\n * Per-tool daily limit overrides for specific tiers.\n * When a tier+tool combo exists here, it takes precedence over the flat TIER_DAILY_LIMITS value.\n */\nexport const TIER_TOOL_DAILY_LIMITS: Partial<Record<McpApiKeyTier, Record<string, number>>> = {\n\tpartner: {\n\t\tscan_domain: 100_000,\n\t\tscan: 100_000,\n\t\tcompare_baseline: 100_000,\n\t\tcheck_spf: 500_000,\n\t\tcheck_dmarc: 500_000,\n\t\tcheck_dkim: 500_000,\n\t\tcheck_mx: 500_000,\n\t\tcheck_ns: 500_000,\n\t\tcheck_ssl: 500_000,\n\t\tcheck_dnssec: 500_000,\n\t\tcheck_mta_sts: 500_000,\n\t\tcheck_caa: 500_000,\n\t\tcheck_bimi: 500_000,\n\t\tcheck_tlsrpt: 500_000,\n\t\tcheck_lookalikes: 50_000,\n\t\tcheck_shadow_domains: 50_000,\n\t\tcheck_txt_hygiene: 500_000,\n\t\tcheck_http_security: 500_000,\n\t\tcheck_dane: 500_000,\n\t\tcheck_mx_reputation: 50_000,\n\t\tcheck_srv: 500_000,\n\t\tcheck_zone_hygiene: 500_000,\n\t\texplain_finding: 500_000,\n\t},\n};\n\nexport const FREE_TOOL_DAILY_LIMITS: Record<string, number> = {\n\tscan_domain: 75,\n\tscan: 75,\n\tcheck_spf: 200,\n\tcheck_dmarc: 200,\n\tcheck_dkim: 200,\n\tcheck_mx: 200,\n\tcheck_ns: 200,\n\tcheck_ssl: 200,\n\tcheck_dnssec: 200,\n\tcheck_mta_sts: 200,\n\tcheck_caa: 200,\n\tcheck_bimi: 200,\n\tcheck_tlsrpt: 200,\n\tcheck_lookalikes: 20,\n\texplain_finding: 200,\n\tcompare_baseline: 150,\n\tcheck_shadow_domains: 20,\n\tcheck_txt_hygiene: 200,\n\tcheck_http_security: 200,\n\tcheck_dane: 200,\n\tcheck_mx_reputation: 20,\n\tcheck_srv: 200,\n\tcheck_zone_hygiene: 200,\n};\n","// SPDX-License-Identifier: BUSL-1.1\n\n/** Standard DNS record type codes */\nexport const RecordType = {\n\tA: 1,\n\tAAAA: 28,\n\tCNAME: 5,\n\tMX: 15,\n\tTXT: 16,\n\tNS: 2,\n\tSOA: 6,\n\tCAA: 257,\n\tTLSA: 52,\n\tDNSKEY: 48,\n\tDS: 43,\n\tRRSIG: 46,\n\tPTR: 12,\n\tSRV: 33,\n} as const;\n\nexport type RecordTypeName = keyof typeof RecordType;\n\n/** A single DNS answer record from the DoH JSON response */\nexport interface DnsAnswer {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** A single DNS authority record */\nexport interface DnsAuthority {\n\tname: string;\n\ttype: number;\n\tTTL: number;\n\tdata: string;\n}\n\n/** Cloudflare DoH JSON wire-format response */\nexport interface DohResponse {\n\tStatus: number;\n\tTC: boolean;\n\tRD: boolean;\n\tRA: boolean;\n\tAD: boolean;\n\tCD: boolean;\n\tQuestion: Array<{ name: string; type: number }>;\n\tAnswer?: DnsAnswer[];\n\tAuthority?: DnsAuthority[];\n}\n\n/** Configuration for a custom secondary DoH resolver (e.g., bv-dns on Oracle Cloud). */\nexport interface SecondaryDohConfig {\n\t/** DoH endpoint URL (e.g. https://harlan.blackveilsecurity.com/dns-query) */\n\tendpoint: string;\n\t/** Optional auth token sent as X-BV-Token header */\n\ttoken?: string;\n}\n\nexport interface QueryDnsOptions {\n\ttimeoutMs?: number;\n\tretries?: number;\n\tconfirmWithSecondaryOnEmpty?: boolean;\n\t/** When true, skip secondary resolver confirmation on empty results. Used in scan context for speed. */\n\tskipSecondaryConfirmation?: boolean;\n\t/** Scan-scoped DNS query cache. Stores Promises keyed by `domain:type:dnssecCheck` to deduplicate concurrent and sequential identical queries within a single scan. */\n\tqueryCache?: Map<string, Promise<DohResponse>>;\n\t/** Custom secondary DoH resolver. When set, used instead of Google DoH for empty-result confirmation. Falls back to Google if this resolver fails. */\n\tsecondaryDoh?: SecondaryDohConfig;\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { DNS_TIMEOUT_MS, DNS_RETRIES, DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY, DOH_EDGE_CACHE_TTL, DNS_RETRY_BASE_DELAY_MS } from './config';\nimport { type DohResponse, type QueryDnsOptions, RecordType, type RecordTypeName } from './dns-types';\n\nconst DOH_ENDPOINT = 'https://cloudflare-dns.com/dns-query';\nconst GOOGLE_DOH_ENDPOINT = 'https://dns.google/resolve';\n\nfunction buildDohUrl(endpoint: string, domain: string, type: RecordTypeName, dnssecCheck: boolean): string {\n\tconst params = new URLSearchParams({\n\t\tname: domain,\n\t\ttype,\n\t\t...(dnssecCheck ? { cd: '0' } : {}),\n\t});\n\n\treturn `${endpoint}?${params.toString()}`;\n}\n\nfunction hasTypedAnswers(response: DohResponse, type: RecordTypeName): boolean {\n\treturn (response.Answer ?? []).some((answer) => answer.type === RecordType[type]);\n}\n\nasync function fetchDohResponse(url: string, timeoutMs: number): Promise<DohResponse | null> {\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\theaders: { Accept: 'application/dns-json' },\n\t\t\tsignal: controller.signal,\n\t\t\tcf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true },\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst data = await response.json();\n\t\tif (typeof data !== 'object' || data === null || typeof (data as DohResponse).Status !== 'number' || !Number.isFinite((data as DohResponse).Status)) return null;\n\t\treturn data as DohResponse;\n\t} catch {\n\t\treturn null;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\nasync function queryDnsFromEndpoint(\n\tendpoint: string,\n\tdomain: string,\n\ttype: RecordTypeName,\n\tdnssecCheck: boolean,\n\ttimeoutMs: number,\n): Promise<DohResponse | null> {\n\treturn fetchDohResponse(buildDohUrl(endpoint, domain, type, dnssecCheck), timeoutMs);\n}\n\n/**\n * Fetch a DoH response from an endpoint with optional auth header.\n * Used for custom secondary resolvers (e.g., bv-dns) that may require authentication.\n * Does NOT use Cloudflare edge cache (`cf` directive) since the target is an external origin.\n */\nasync function fetchDohWithAuth(url: string, timeoutMs: number, token?: string): Promise<DohResponse | null> {\n\tconst controller = new AbortController();\n\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\ttry {\n\t\tconst headers: Record<string, string> = { Accept: 'application/dns-json' };\n\t\tif (token) headers['X-BV-Token'] = token;\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: 'GET',\n\t\t\theaders,\n\t\t\tsignal: controller.signal,\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst data = await response.json();\n\t\tif (typeof data !== 'object' || data === null || typeof (data as DohResponse).Status !== 'number' || !Number.isFinite((data as DohResponse).Status)) return null;\n\t\treturn data as DohResponse;\n\t} catch {\n\t\treturn null;\n\t} finally {\n\t\tclearTimeout(timeout);\n\t}\n}\n\n/** Error thrown when a DNS query fails */\nexport class DnsQueryError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly domain: string,\n\t\tpublic readonly recordType: string,\n\t\tpublic readonly status?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DnsQueryError';\n\t}\n}\n\n/**\n * Query Cloudflare DoH for DNS records.\n *\n * When `opts.queryCache` is provided, deduplicates concurrent and sequential\n * identical queries within a single scan by caching the Promise keyed by\n * `domain:type:dnssecCheck`. Failed queries are evicted so retries can re-attempt.\n *\n * @param domain - The domain name to query\n * @param type - DNS record type name (e.g. \"TXT\", \"MX\", \"A\")\n * @param dnssecCheck - If true, sets the CD=0 flag to request DNSSEC validation\n * @returns The full DoH JSON response\n */\nexport async function queryDns(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst cache = opts?.queryCache;\n\tif (!cache) {\n\t\treturn queryDnsUncached(domain, type, dnssecCheck, opts);\n\t}\n\n\tconst cacheKey = `${domain}:${type}:${dnssecCheck}`;\n\tconst existing = cache.get(cacheKey);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\n\tconst promise = queryDnsUncached(domain, type, dnssecCheck, opts);\n\tcache.set(cacheKey, promise);\n\tpromise.catch(() => cache.delete(cacheKey));\n\treturn promise;\n}\n\nasync function queryDnsUncached(domain: string, type: RecordTypeName, dnssecCheck = false, opts?: QueryDnsOptions): Promise<DohResponse> {\n\tconst timeoutMs = opts?.timeoutMs ?? DNS_TIMEOUT_MS;\n\tconst retries = opts?.retries ?? DNS_RETRIES;\n\tconst confirmWithSecondaryOnEmpty = opts?.confirmWithSecondaryOnEmpty ?? DNS_CONFIRM_WITH_SECONDARY_ON_EMPTY;\n\tconst url = buildDohUrl(DOH_ENDPOINT, domain, type, dnssecCheck);\n\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\t\tlet response: Response;\n\n\t\ttry {\n\t\t\tresponse = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/dns-json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tcf: { cacheTtl: DOH_EDGE_CACHE_TTL, cacheEverything: true },\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tclearTimeout(timeout);\n\t\t\tif (err instanceof DOMException && err.name === 'AbortError') {\n\t\t\t\tif (attempt < retries) {\n\t\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new DnsQueryError(`DNS query timed out after ${timeoutMs}ms`, domain, type);\n\t\t\t}\n\t\t\tif (attempt < retries) {\n\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DNS query failed: ${err instanceof Error ? err.message : String(err)}`, domain, type);\n\t\t}\n\n\t\tclearTimeout(timeout);\n\n\t\tif (!response.ok) {\n\t\t\tif (attempt < retries && response.status >= 500) {\n\t\t\t\tawait new Promise((r) => setTimeout(r, DNS_RETRY_BASE_DELAY_MS * (attempt + 1) + Math.random() * 50));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new DnsQueryError(`DoH returned HTTP ${response.status}`, domain, type, response.status);\n\t\t}\n\n\t\tconst raw = await response.json();\n\t\tif (typeof raw !== 'object' || raw === null || typeof (raw as DohResponse).Status !== 'number' || !Number.isFinite((raw as DohResponse).Status)) {\n\t\t\tthrow new DnsQueryError('Invalid DoH response format', domain, type);\n\t\t}\n\t\tconst data = raw as DohResponse;\n\n\t\tif (confirmWithSecondaryOnEmpty && !opts?.skipSecondaryConfirmation && !hasTypedAnswers(data, type)) {\n\t\t\t// Try custom secondary (bv-dns) first if configured\n\t\t\tif (opts?.secondaryDoh?.endpoint) {\n\t\t\t\tconst bvDns = await fetchDohWithAuth(\n\t\t\t\t\tbuildDohUrl(opts.secondaryDoh.endpoint, domain, type, dnssecCheck),\n\t\t\t\t\ttimeoutMs,\n\t\t\t\t\topts.secondaryDoh.token,\n\t\t\t\t);\n\t\t\t\tif (bvDns && hasTypedAnswers(bvDns, type)) {\n\t\t\t\t\treturn bvDns;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Google DoH as final fallback\n\t\t\tconst google = await queryDnsFromEndpoint(GOOGLE_DOH_ENDPOINT, domain, type, dnssecCheck, timeoutMs);\n\t\t\tif (google && hasTypedAnswers(google, type)) {\n\t\t\t\treturn google;\n\t\t\t}\n\t\t}\n\n\t\treturn data;\n\t}\n\n\tthrow new DnsQueryError('DNS query failed after retries', domain, type);\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryDns } from './dns-transport';\nimport { RecordType, type QueryDnsOptions, type RecordTypeName } from './dns-types';\n\n/** Parsed CAA record with flags, tag, and value */\nexport interface CaaRecord {\n\tflags: number;\n\ttag: string;\n\tvalue: string;\n}\n\n/** Parsed PTR record hostname */\nexport interface PtrRecord {\n\thostname: string;\n}\n\n/** Parsed SRV record with priority, weight, port, and target */\nexport interface SrvRecord {\n\tpriority: number;\n\tweight: number;\n\tport: number;\n\ttarget: string;\n}\n\n/** Parsed TLSA record with usage, selector, matching type, and certificate data */\nexport interface TlsaRecord {\n\tusage: number;\n\tselector: number;\n\tmatchingType: number;\n\tcertData: string;\n}\n\n/**\n * Query DNS and return just the answer data strings.\n * Returns an empty array if no answers are found.\n */\nexport async function queryDnsRecords(domain: string, type: RecordTypeName, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst resp = await queryDns(domain, type, false, opts);\n\treturn (resp.Answer ?? []).filter((answer) => answer.type === RecordType[type]).map((answer) => answer.data);\n}\n\n/**\n * Query TXT records, concatenate multi-string values, and unescape DNS\n * presentation-format backslash sequences.\n *\n * Cloudflare DoH returns TXT data with surrounding quotes and multiple\n * strings separated by `\" \"`. Per RFC 7208 §3.3, multi-string TXT records\n * MUST be concatenated without adding spaces. Some nameservers also emit\n * RFC 1035 §5.1 backslash escapes (e.g. `\\;` for a literal semicolon);\n * we unescape both `\\X` (single-char) and `\\DDD` (decimal octet) forms.\n */\nexport async function queryTxtRecords(domain: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst records = await queryDnsRecords(domain, 'TXT', opts);\n\treturn records.map((record) =>\n\t\tunescapeDnsTxt(\n\t\t\trecord\n\t\t\t\t.replace(/\" \"/g, '')\n\t\t\t\t.replace(/^\"|\"$/g, ''),\n\t\t),\n\t);\n}\n\n/**\n * Unescape DNS presentation-format backslash sequences in TXT record data.\n * Handles `\\DDD` (decimal octet 000–255) and `\\X` (literal character).\n *\n * Some DoH providers double-escape (e.g. `\\\\;` in the JS string for what\n * should be a plain `;`), so we loop until the string stabilises.\n */\nexport function unescapeDnsTxt(text: string): string {\n\tconst unescape = (s: string) =>\n\t\ts.replace(/\\\\(\\d{3})|\\\\(.)/g, (_, decimal, ch) => {\n\t\t\tif (decimal !== undefined) {\n\t\t\t\tconst code = parseInt(decimal, 10);\n\t\t\t\treturn code <= 255 ? String.fromCharCode(code) : `\\\\${decimal}`;\n\t\t\t}\n\t\t\treturn ch;\n\t\t});\n\n\tlet result = text;\n\tfor (let i = 0; i < 5; i++) {\n\t\tconst next = unescape(result);\n\t\tif (next === result) break;\n\t\tresult = next;\n\t}\n\treturn result;\n}\n\n/**\n * Check if a domain has valid DNSSEC by examining the AD (Authenticated Data) flag.\n * Returns true if the response was DNSSEC-validated.\n */\nexport async function checkDnssec(domain: string, opts?: QueryDnsOptions): Promise<boolean> {\n\tconst resp = await queryDns(domain, 'A', true, opts);\n\treturn resp.AD === true;\n}\n\n/**\n * Parse a single CAA record data string.\n * Handles both human-readable format (e.g. `0 issue \"letsencrypt.org\"`)\n * and Cloudflare DoH hex wire format (e.g. `\\# 19 00 05 69 73 73 75 65...`).\n *\n * Wire format bytes: flags(1) + tag_length(1) + tag(tag_length) + value(rest)\n */\nexport function parseCaaRecord(data: string): CaaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 3) return null;\n\n\t\tconst flags = parseInt(hexBytes[0], 16);\n\t\tconst tagLen = parseInt(hexBytes[1], 16);\n\t\tif (isNaN(flags) || isNaN(tagLen) || hexBytes.length < 2 + tagLen) return null;\n\n\t\tconst tag = hexBytes\n\t\t\t.slice(2, 2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\t\tconst value = hexBytes\n\t\t\t.slice(2 + tagLen)\n\t\t\t.map((hexByte) => String.fromCharCode(parseInt(hexByte, 16)))\n\t\t\t.join('');\n\n\t\treturn { flags, tag: tag.toLowerCase(), value };\n\t}\n\n\tconst match = data.match(/^(\\d+)\\s+(\\S+)\\s+\"?([^\"]*)\"?\\s*$/);\n\tif (match) {\n\t\treturn {\n\t\t\tflags: parseInt(match[1], 10),\n\t\t\ttag: match[2].toLowerCase(),\n\t\t\tvalue: match[3],\n\t\t};\n\t}\n\n\treturn null;\n}\n\n/**\n * Query CAA records and parse them into structured objects.\n * Handles both human-readable and hex wire format from DoH.\n */\nexport async function queryCaaRecords(domain: string, opts?: QueryDnsOptions): Promise<CaaRecord[]> {\n\tconst records = await queryDnsRecords(domain, 'CAA', opts);\n\treturn records.map(parseCaaRecord).filter((record): record is CaaRecord => record !== null);\n}\n\n/**\n * Query MX records and parse them into priority + exchange pairs.\n */\nexport async function queryMxRecords(domain: string, opts?: QueryDnsOptions): Promise<Array<{ priority: number; exchange: string }>> {\n\tconst records = await queryDnsRecords(domain, 'MX', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\texchange: parts.slice(1).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Query PTR records for an IP address by constructing the reverse DNS name.\n * For IPv4 address `192.0.2.1`, queries `1.2.0.192.in-addr.arpa`.\n * Returns an array of PTR hostnames with trailing dots stripped.\n */\nexport async function queryPtrRecords(ip: string, opts?: QueryDnsOptions): Promise<string[]> {\n\tconst reverseName = ip.split('.').reverse().join('.') + '.in-addr.arpa';\n\tconst records = await queryDnsRecords(reverseName, 'PTR', opts);\n\treturn records.map((record) => record.replace(/\\.$/, ''));\n}\n\n/**\n * Query SRV records and parse them into structured objects.\n * SRV data format: `priority weight port target`\n */\nexport async function querySrvRecords(\n\tname: string,\n\topts?: QueryDnsOptions,\n): Promise<Array<{ priority: number; weight: number; port: number; target: string }>> {\n\tconst records = await queryDnsRecords(name, 'SRV', opts);\n\treturn records.map((record) => {\n\t\tconst parts = record.split(' ');\n\t\treturn {\n\t\t\tpriority: parseInt(parts[0], 10),\n\t\t\tweight: parseInt(parts[1], 10),\n\t\t\tport: parseInt(parts[2], 10),\n\t\t\ttarget: parts.slice(3).join(' ').replace(/\\.$/, ''),\n\t\t};\n\t});\n}\n\n/**\n * Parse a TLSA record data string into structured fields.\n * Handles both human-readable format (`usage selector matchingType certData`)\n * and hex wire format (data starting with `\\#`).\n *\n * Returns null if the data cannot be parsed.\n */\nexport function parseTlsaRecord(data: string): TlsaRecord | null {\n\tif (data.startsWith('\\\\#') || data.startsWith('#')) {\n\t\tconst parts = data.trim().split(/\\s+/);\n\t\tconst hexStart = parts[0] === '\\\\#' || parts[0] === '#' ? 2 : 1;\n\t\tconst hexBytes = parts.slice(hexStart);\n\t\tif (hexBytes.length < 4) return null;\n\n\t\tconst usage = parseInt(hexBytes[0], 16);\n\t\tconst selector = parseInt(hexBytes[1], 16);\n\t\tconst matchingType = parseInt(hexBytes[2], 16);\n\t\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\t\tconst certData = hexBytes.slice(3).join('');\n\t\treturn { usage, selector, matchingType, certData };\n\t}\n\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 4) return null;\n\n\tconst usage = parseInt(parts[0], 10);\n\tconst selector = parseInt(parts[1], 10);\n\tconst matchingType = parseInt(parts[2], 10);\n\tif (isNaN(usage) || isNaN(selector) || isNaN(matchingType)) return null;\n\n\tconst certData = parts.slice(3).join('');\n\treturn { usage, selector, matchingType, certData };\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNS query library using Cloudflare DNS-over-HTTPS (DoH).\n * All queries go through https://cloudflare-dns.com/dns-query\n * using the JSON wire format (application/dns-json).\n *\n * Workers-compatible: uses only fetch API, no Node.js APIs.\n */\n\nexport * from './dns-types';\nexport { DnsQueryError, queryDns } from './dns-transport';\nexport {\n\ttype CaaRecord,\n\ttype PtrRecord,\n\ttype SrvRecord,\n\ttype TlsaRecord,\n\tcheckDnssec,\n\tparseCaaRecord,\n\tparseTlsaRecord,\n\tqueryCaaRecords,\n\tqueryDnsRecords,\n\tqueryMxRecords,\n\tqueryPtrRecords,\n\tquerySrvRecords,\n\tqueryTxtRecords,\n} from './dns-records';\n","// SPDX-License-Identifier: BUSL-1.1\n\nexport type Severity = 'critical' | 'high' | 'medium' | 'low' | 'info';\nexport type FindingConfidence = 'deterministic' | 'heuristic' | 'verified';\n\nexport type CheckCategory =\n\t| 'spf'\n\t| 'dmarc'\n\t| 'dkim'\n\t| 'dnssec'\n\t| 'ssl'\n\t| 'mta_sts'\n\t| 'ns'\n\t| 'caa'\n\t| 'subdomain_takeover'\n\t| 'mx'\n\t| 'bimi'\n\t| 'tlsrpt'\n\t| 'lookalikes'\n\t| 'shadow_domains'\n\t| 'txt_hygiene'\n\t| 'http_security'\n\t| 'dane'\n\t| 'mx_reputation'\n\t| 'srv'\n\t| 'zone_hygiene';\n\nexport interface Finding {\n\tcategory: CheckCategory;\n\ttitle: string;\n\tseverity: Severity;\n\tdetail: string;\n\tmetadata?: Record<string, unknown>;\n}\n\nexport interface CheckResult {\n\tcategory: CheckCategory;\n\tpassed: boolean;\n\tscore: number;\n\tfindings: Finding[];\n}\n\nexport interface ScanScore {\n\toverall: number;\n\tgrade: string;\n\tcategoryScores: Record<CheckCategory, number>;\n\tfindings: Finding[];\n\tsummary: string;\n}\n\n/** Display/UI weight distribution for categories. NOT used in scoring — see IMPORTANCE_WEIGHTS for actual scoring weights. Exists for category registry and display purposes only. */\nexport const CATEGORY_DISPLAY_WEIGHTS: Record<CheckCategory, number> = {\n\tspf: 0.15,\n\tdmarc: 0.15,\n\tdkim: 0.15,\n\tdnssec: 0.15,\n\tssl: 0.15,\n\tmta_sts: 0.05,\n\tns: 0.05,\n\tcaa: 0.05,\n\tsubdomain_takeover: 0.1,\n\tmx: 0,\n\tbimi: 0,\n\ttlsrpt: 0.02,\n\tlookalikes: 0,\n\tshadow_domains: 0,\n\ttxt_hygiene: 0,\n\thttp_security: 0.05,\n\tdane: 0,\n\tmx_reputation: 0,\n\tsrv: 0,\n\tzone_hygiene: 0,\n};\n\n/** Severity penalty multipliers applied to the category score */\nexport const SEVERITY_PENALTIES: Record<Severity, number> = {\n\tcritical: 40,\n\thigh: 25,\n\tmedium: 15,\n\tlow: 5,\n\tinfo: 0,\n};\n\nfunction isExplicitConfidence(value: unknown): value is FindingConfidence {\n\treturn value === 'deterministic' || value === 'heuristic' || value === 'verified';\n}\n\n/**\n * Infer how strongly a finding can be trusted based on available evidence.\n * - verified: explicit proof (currently only supported on takeover checks)\n * - heuristic: signal-based or partial-evidence checks\n * - deterministic: direct record/protocol validation\n */\nexport function inferFindingConfidence(finding: Finding): FindingConfidence {\n\tconst declared = finding.metadata?.confidence;\n\tif (isExplicitConfidence(declared)) return declared;\n\n\tif (finding.category === 'subdomain_takeover') {\n\t\tconst status = finding.metadata?.verificationStatus;\n\t\tif (status === 'verified') return 'verified';\n\t\treturn 'heuristic';\n\t}\n\n\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\tif (\n\t\ttext.includes('common selectors') ||\n\t\ttext.includes('among tested selectors') ||\n\t\ttext.includes('inferred') ||\n\t\ttext.includes('manual review') ||\n\t\ttext.includes('possible') ||\n\t\ttext.includes('potential') ||\n\t\ttext.includes('could indicate')\n\t) {\n\t\treturn 'heuristic';\n\t}\n\n\treturn 'deterministic';\n}\n\nfunction withConfidenceMetadata(finding: Finding): Finding {\n\tconst confidence = inferFindingConfidence(finding);\n\treturn {\n\t\t...finding,\n\t\tmetadata: {\n\t\t\t...(finding.metadata ?? {}),\n\t\t\tconfidence,\n\t\t},\n\t};\n}\n\n/**\n * Compute the score for a single check category based on its findings.\n * Starts at 100 and deducts points based on finding severities.\n */\nexport function computeCategoryScore(findings: Finding[]): number {\n\tlet score = 100;\n\tfor (const finding of findings) {\n\t\tscore -= SEVERITY_PENALTIES[finding.severity];\n\t}\n\treturn Math.max(0, Math.min(100, score));\n}\n\n/**\n * Build a CheckResult from a category and its findings.\n */\nexport function buildCheckResult(category: CheckCategory, findings: Finding[]): CheckResult {\n\tconst normalizedFindings = findings.map(withConfidenceMetadata);\n\tconst score = computeCategoryScore(normalizedFindings);\n\treturn {\n\t\tcategory,\n\t\tpassed: score >= 50,\n\t\tscore,\n\t\tfindings: normalizedFindings,\n\t};\n}\n\n/**\n * Create a finding object with the given parameters.\n */\nexport function createFinding(\n\tcategory: CheckCategory,\n\ttitle: string,\n\tseverity: Severity,\n\tdetail: string,\n\tmetadata?: Record<string, unknown>,\n): Finding {\n\treturn { category, title, severity, detail, ...(metadata ? { metadata } : {}) };\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Context-aware scoring profiles for scan_domain.\n *\n * Adapts importance weights based on detected domain purpose (mail-enabled,\n * enterprise mail, non-mail, web-only, minimal infrastructure).\n *\n * Phase 1: Auto-detection runs and reports the detected profile in the\n * structured result, but `auto` uses `mail_enabled` weights (identical to\n * today). Only explicit profile selection activates different weights.\n */\n\nimport type { CheckCategory, CheckResult } from './scoring-model';\n\nexport type DomainProfile = 'mail_enabled' | 'enterprise_mail' | 'non_mail' | 'web_only' | 'minimal';\n\nexport interface DomainContext {\n\tprofile: DomainProfile;\n\tsignals: string[];\n\tweights: Record<CheckCategory, ImportanceProfile>;\n\tdetectedProvider: string | null;\n}\n\ninterface ImportanceProfile {\n\timportance: number;\n}\n\n/** Per-profile importance weights. */\nexport const PROFILE_WEIGHTS: Record<DomainProfile, Record<CheckCategory, ImportanceProfile>> = {\n\tmail_enabled: {\n\t\tdmarc: { importance: 22 },\n\t\tdkim: { importance: 16 },\n\t\tspf: { importance: 10 },\n\t\tssl: { importance: 5 },\n\t\tsubdomain_takeover: { importance: 3 },\n\t\tdnssec: { importance: 2 },\n\t\tmta_sts: { importance: 2 },\n\t\tmx: { importance: 2 },\n\t\ttlsrpt: { importance: 1 },\n\t\tcaa: { importance: 0 },\n\t\tns: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\tlookalikes: { importance: 0 },\n\t\tshadow_domains: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\thttp_security: { importance: 3 },\n\t\tdane: { importance: 1 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tenterprise_mail: {\n\t\tdmarc: { importance: 24 },\n\t\tdkim: { importance: 18 },\n\t\tspf: { importance: 12 },\n\t\tssl: { importance: 5 },\n\t\tsubdomain_takeover: { importance: 3 },\n\t\tdnssec: { importance: 3 },\n\t\tmta_sts: { importance: 4 },\n\t\tmx: { importance: 2 },\n\t\ttlsrpt: { importance: 2 },\n\t\tcaa: { importance: 0 },\n\t\tns: { importance: 0 },\n\t\tbimi: { importance: 1 },\n\t\tlookalikes: { importance: 0 },\n\t\tshadow_domains: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\thttp_security: { importance: 3 },\n\t\tdane: { importance: 2 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tnon_mail: {\n\t\tssl: { importance: 8 },\n\t\tsubdomain_takeover: { importance: 5 },\n\t\tdnssec: { importance: 5 },\n\t\tcaa: { importance: 3 },\n\t\tdmarc: { importance: 2 },\n\t\tns: { importance: 2 },\n\t\tdkim: { importance: 1 },\n\t\tspf: { importance: 1 },\n\t\tmx: { importance: 0 },\n\t\tmta_sts: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\tlookalikes: { importance: 0 },\n\t\tshadow_domains: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\thttp_security: { importance: 5 },\n\t\tdane: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tweb_only: {\n\t\tssl: { importance: 12 },\n\t\tsubdomain_takeover: { importance: 5 },\n\t\tdnssec: { importance: 5 },\n\t\tcaa: { importance: 5 },\n\t\tdmarc: { importance: 2 },\n\t\tns: { importance: 2 },\n\t\tdkim: { importance: 1 },\n\t\tspf: { importance: 1 },\n\t\tmx: { importance: 0 },\n\t\tmta_sts: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\tlookalikes: { importance: 0 },\n\t\tshadow_domains: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\thttp_security: { importance: 5 },\n\t\tdane: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n\tminimal: {\n\t\tdmarc: { importance: 5 },\n\t\tssl: { importance: 5 },\n\t\tdnssec: { importance: 5 },\n\t\tdkim: { importance: 3 },\n\t\tspf: { importance: 3 },\n\t\tsubdomain_takeover: { importance: 3 },\n\t\tns: { importance: 2 },\n\t\tmx: { importance: 1 },\n\t\tcaa: { importance: 1 },\n\t\tmta_sts: { importance: 0 },\n\t\ttlsrpt: { importance: 0 },\n\t\tbimi: { importance: 0 },\n\t\tlookalikes: { importance: 0 },\n\t\tshadow_domains: { importance: 0 },\n\t\ttxt_hygiene: { importance: 0 },\n\t\thttp_security: { importance: 2 },\n\t\tdane: { importance: 0 },\n\t\tmx_reputation: { importance: 0 },\n\t\tsrv: { importance: 0 },\n\t\tzone_hygiene: { importance: 0 },\n\t},\n};\n\n/** Which categories trigger the critical gap ceiling per profile. */\nexport const PROFILE_CRITICAL_CATEGORIES: Record<DomainProfile, CheckCategory[]> = {\n\tmail_enabled: ['spf', 'dmarc', 'dkim', 'ssl', 'subdomain_takeover'],\n\tenterprise_mail: ['spf', 'dmarc', 'dkim', 'ssl', 'subdomain_takeover'],\n\tnon_mail: ['ssl', 'subdomain_takeover', 'http_security'],\n\tweb_only: ['ssl', 'subdomain_takeover', 'http_security'],\n\tminimal: ['ssl', 'subdomain_takeover'],\n};\n\n/** Whether a profile is eligible for the email bonus. */\nexport const PROFILE_EMAIL_BONUS_ELIGIBLE: Record<DomainProfile, boolean> = {\n\tmail_enabled: true,\n\tenterprise_mail: true,\n\tnon_mail: false,\n\tweb_only: false,\n\tminimal: false,\n};\n\n/** Known enterprise mail providers detected via MX record patterns. */\nconst ENTERPRISE_PROVIDERS = [\n\t'google workspace',\n\t'microsoft 365',\n\t'proofpoint',\n\t'mimecast',\n\t'barracuda',\n];\n\n/**\n * Detect domain context from completed check results.\n * Pure function — reads findings metadata only, no DNS queries.\n */\nexport function detectDomainContext(results: CheckResult[]): DomainContext {\n\tconst signals: string[] = [];\n\n\tconst mxResult = results.find((r) => r.category === 'mx');\n\tconst sslResult = results.find((r) => r.category === 'ssl');\n\tconst caaResult = results.find((r) => r.category === 'caa');\n\tconst dkimResult = results.find((r) => r.category === 'dkim');\n\tconst mtaStsResult = results.find((r) => r.category === 'mta_sts');\n\tconst bimiResult = results.find((r) => r.category === 'bimi');\n\n\t// Detect MX presence\n\tconst hasNoMx = mxResult\n\t\t? mxResult.findings.some((f) => {\n\t\t\t\tconst title = f.title.toLowerCase();\n\t\t\t\treturn title.includes('no mx records') || title.includes('null mx');\n\t\t\t})\n\t\t: false;\n\tconst hasMxUnknown = mxResult\n\t\t? mxResult.findings.some((f) => f.title.toLowerCase().includes('dns query failed'))\n\t\t: false;\n\tconst hasMx = mxResult && !hasNoMx && !hasMxUnknown;\n\n\tif (hasMx) signals.push('MX present');\n\tif (hasNoMx) signals.push('No MX records');\n\tif (hasMxUnknown) signals.push('MX status unknown');\n\n\t// Detect enterprise provider from MX findings\n\tlet hasEnterpriseProvider = false;\n\tlet detectedProviderName: string | null = null;\n\tif (mxResult) {\n\t\tfor (const finding of mxResult.findings) {\n\t\t\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\t\t\tconst providerName = finding.metadata?.provider;\n\t\t\tconst providerStr = typeof providerName === 'string' ? providerName.toLowerCase() : '';\n\t\t\tfor (const provider of ENTERPRISE_PROVIDERS) {\n\t\t\t\tif (text.includes(provider) || providerStr.includes(provider)) {\n\t\t\t\t\thasEnterpriseProvider = true;\n\t\t\t\t\tdetectedProviderName = provider;\n\t\t\t\t\tsignals.push(`${provider} provider`);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (hasEnterpriseProvider) break;\n\t\t}\n\t}\n\n\t// Detect hardening signals (DKIM present, MTA-STS present, BIMI present)\n\tconst dkimPresent = dkimResult\n\t\t? !dkimResult.findings.some((f) => {\n\t\t\t\tconst text = `${f.title} ${f.detail}`.toLowerCase();\n\t\t\t\treturn /(no\\s+dkim|not\\s+found|missing)/.test(text) && f.severity !== 'info';\n\t\t\t})\n\t\t: false;\n\tif (dkimPresent && hasMx) signals.push('DKIM present');\n\n\tconst mtaStsPresent = mtaStsResult ? mtaStsResult.passed : false;\n\tif (mtaStsPresent) signals.push('MTA-STS present');\n\n\tconst bimiPresent = bimiResult ? bimiResult.passed : false;\n\tif (bimiPresent) signals.push('BIMI present');\n\n\tconst hasHardeningSignal = dkimPresent || mtaStsPresent || bimiPresent;\n\n\t// Detect web indicators\n\tconst sslPass = sslResult ? sslResult.passed : false;\n\tconst caaPass = caaResult ? caaResult.passed : false;\n\tif (sslPass) signals.push('SSL valid');\n\tif (caaPass) signals.push('CAA present');\n\n\t// Count failed/timed-out checks\n\tconst totalChecks = results.length;\n\tconst failedChecks = results.filter((r) => !r.passed).length;\n\tconst failureRatio = totalChecks > 0 ? failedChecks / totalChecks : 0;\n\tif (failureRatio > 0.5) signals.push(`>${Math.round(failureRatio * 100)}% checks failed`);\n\n\t// Detection priority\n\tlet profile: DomainProfile;\n\n\tif (hasNoMx) {\n\t\t// Explicitly no MX (no records or null MX) → non-mail profiles\n\t\tif (caaPass || sslPass) {\n\t\t\tprofile = 'web_only';\n\t\t} else {\n\t\t\tprofile = 'non_mail';\n\t\t}\n\t} else if (hasMxUnknown || !hasMx) {\n\t\t// MX lookup failed or no MX result at all → default to mail_enabled (safe fallback)\n\t\tprofile = 'mail_enabled';\n\t} else if (hasMx && hasEnterpriseProvider && hasHardeningSignal) {\n\t\tprofile = 'enterprise_mail';\n\t} else {\n\t\tprofile = 'mail_enabled';\n\t}\n\n\t// Override to minimal if most checks failed\n\tif (failureRatio > 0.5) {\n\t\tprofile = 'minimal';\n\t}\n\n\treturn {\n\t\tprofile,\n\t\tsignals,\n\t\tweights: PROFILE_WEIGHTS[profile],\n\t\tdetectedProvider: detectedProviderName,\n\t};\n}\n\n/** Look up the weight table for a given profile, optionally from runtime config. */\nexport function getProfileWeights(\n\tprofile: DomainProfile,\n\tconfig?: import('./scoring-config').ScoringConfig,\n): Record<CheckCategory, ImportanceProfile> {\n\tif (config) {\n\t\tconst flat = config.profileWeights[profile];\n\t\tconst result = {} as Record<CheckCategory, ImportanceProfile>;\n\t\tfor (const key of Object.keys(flat) as CheckCategory[]) {\n\t\t\tresult[key] = { importance: flat[key] };\n\t\t}\n\t\treturn result;\n\t}\n\treturn PROFILE_WEIGHTS[profile];\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Runtime scoring configuration.\n *\n * All scoring weights, thresholds, and tuning constants are configurable\n * via the `SCORING_CONFIG` environment variable (JSON string). The open-source\n * codebase ships with reasonable defaults; production deployments can override\n * any subset of values.\n *\n * Parse once at request entry and thread through the call chain — never\n * re-parse per tool call.\n */\n\nimport type { CheckCategory } from './scoring-model';\nimport type { DomainProfile } from './context-profiles';\n\n/** All tunable scoring parameters. */\nexport interface ScoringConfig {\n\t/** Base importance weights per check category (used when no profile context). */\n\tweights: Record<CheckCategory, number>;\n\n\t/** Per-profile importance weights. */\n\tprofileWeights: Record<DomainProfile, Record<CheckCategory, number>>;\n\n\t/** Scoring thresholds and constants. */\n\tthresholds: {\n\t\temailBonusImportance: number;\n\t\tspfStrongThreshold: number;\n\t\tcriticalOverallPenalty: number;\n\t\tcriticalGapCeiling: number;\n\t};\n\n\t/** Grade boundaries (minimum score for each grade). */\n\tgrades: {\n\t\taPlus: number;\n\t\ta: number;\n\t\tbPlus: number;\n\t\tb: number;\n\t\tcPlus: number;\n\t\tc: number;\n\t\tdPlus: number;\n\t\td: number;\n\t\te: number;\n\t};\n\n\t/** Baseline failure rates for adaptive weight computation. */\n\tbaselineFailureRates: Record<string, number>;\n}\n\n/** Built-in defaults — used when `SCORING_CONFIG` env var is absent or partial. */\nexport const DEFAULT_SCORING_CONFIG: ScoringConfig = {\n\tweights: {\n\t\tspf: 10,\n\t\tdmarc: 22,\n\t\tdkim: 16,\n\t\tdnssec: 2,\n\t\tssl: 5,\n\t\tmta_sts: 2,\n\t\tns: 0,\n\t\tcaa: 0,\n\t\tsubdomain_takeover: 3,\n\t\tmx: 2,\n\t\tbimi: 0,\n\t\ttlsrpt: 1,\n\t\tlookalikes: 0,\n\t\tshadow_domains: 0,\n\t\ttxt_hygiene: 0,\n\t\thttp_security: 3,\n\t\tdane: 1,\n\t\tmx_reputation: 0,\n\t\tsrv: 0,\n\t\tzone_hygiene: 0,\n\t},\n\tprofileWeights: {\n\t\tmail_enabled: { dmarc: 22, dkim: 16, spf: 10, ssl: 5, subdomain_takeover: 3, dnssec: 2, mta_sts: 2, mx: 2, tlsrpt: 1, caa: 0, ns: 0, bimi: 0, lookalikes: 0, shadow_domains: 0, txt_hygiene: 0, http_security: 3, dane: 1, mx_reputation: 0, srv: 0, zone_hygiene: 0 },\n\t\tenterprise_mail: { dmarc: 24, dkim: 18, spf: 12, ssl: 5, subdomain_takeover: 3, dnssec: 3, mta_sts: 4, mx: 2, tlsrpt: 2, caa: 0, ns: 0, bimi: 1, lookalikes: 0, shadow_domains: 0, txt_hygiene: 0, http_security: 3, dane: 2, mx_reputation: 0, srv: 0, zone_hygiene: 0 },\n\t\tnon_mail: { ssl: 8, subdomain_takeover: 5, dnssec: 5, caa: 3, dmarc: 2, ns: 2, dkim: 1, spf: 1, mx: 0, mta_sts: 0, tlsrpt: 0, bimi: 0, lookalikes: 0, shadow_domains: 0, txt_hygiene: 0, http_security: 5, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0 },\n\t\tweb_only: { ssl: 12, subdomain_takeover: 5, dnssec: 5, caa: 5, dmarc: 2, ns: 2, dkim: 1, spf: 1, mx: 0, mta_sts: 0, tlsrpt: 0, bimi: 0, lookalikes: 0, shadow_domains: 0, txt_hygiene: 0, http_security: 5, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0 },\n\t\tminimal: { dmarc: 5, ssl: 5, dnssec: 5, dkim: 3, spf: 3, subdomain_takeover: 3, ns: 2, mx: 1, caa: 1, mta_sts: 0, tlsrpt: 0, bimi: 0, lookalikes: 0, shadow_domains: 0, txt_hygiene: 0, http_security: 2, dane: 0, mx_reputation: 0, srv: 0, zone_hygiene: 0 },\n\t},\n\tthresholds: {\n\t\temailBonusImportance: 8,\n\t\tspfStrongThreshold: 57,\n\t\tcriticalOverallPenalty: 15,\n\t\tcriticalGapCeiling: 64,\n\t},\n\tgrades: {\n\t\taPlus: 90,\n\t\ta: 85,\n\t\tbPlus: 80,\n\t\tb: 75,\n\t\tcPlus: 70,\n\t\tc: 65,\n\t\tdPlus: 60,\n\t\td: 55,\n\t\te: 50,\n\t},\n\tbaselineFailureRates: {\n\t\tdmarc: 0.40,\n\t\tspf: 0.25,\n\t\tdkim: 0.35,\n\t\tssl: 0.08,\n\t\tmta_sts: 0.85,\n\t\tdnssec: 0.80,\n\t\tmx: 0.05,\n\t\tcaa: 0.70,\n\t\tns: 0.03,\n\t\tbimi: 0.95,\n\t\ttlsrpt: 0.90,\n\t\tsubdomain_takeover: 0.10,\n\t\tlookalikes: 0.00,\n\t\tshadow_domains: 0.00,\n\t\ttxt_hygiene: 0.00,\n\t\thttp_security: 0.35,\n\t\tdane: 0.90,\n\t\tmx_reputation: 0.00,\n\t\tsrv: 0.00,\n\t\tzone_hygiene: 0.00,\n\t},\n};\n\n/**\n * Convert flat weight numbers to the `{ importance: number }` shape\n * used by the scoring engine and profile system.\n */\nexport function toImportanceRecord<K extends string>(\n\tweights: Record<K, number>,\n): Record<K, { importance: number }> {\n\tconst result = {} as Record<K, { importance: number }>;\n\tfor (const key of Object.keys(weights) as K[]) {\n\t\tresult[key] = { importance: weights[key] };\n\t}\n\treturn result;\n}\n\n/** Safely merge a partial weight record into defaults. */\nfunction mergeWeights(\n\tdefaults: Record<string, number>,\n\toverrides: Record<string, unknown> | undefined,\n): Record<string, number> {\n\tif (!overrides || typeof overrides !== 'object') return { ...defaults };\n\tconst result = { ...defaults };\n\tfor (const [key, value] of Object.entries(overrides)) {\n\t\tif (key in defaults && typeof value === 'number' && Number.isFinite(value)) {\n\t\t\tresult[key] = Math.max(0, value);\n\t\t}\n\t}\n\treturn result;\n}\n\n/**\n * Parse a `SCORING_CONFIG` env var string into a fully-populated `ScoringConfig`.\n *\n * Gracefully handles undefined, empty, invalid JSON, partial overrides,\n * and invalid value types. Always returns a complete config by merging\n * overrides into defaults.\n */\nexport function parseScoringConfig(raw: string | undefined): ScoringConfig {\n\tif (!raw || raw.trim().length === 0) return DEFAULT_SCORING_CONFIG;\n\n\tlet parsed: Record<string, unknown>;\n\ttry {\n\t\tparsed = JSON.parse(raw) as Record<string, unknown>;\n\t} catch {\n\t\treturn DEFAULT_SCORING_CONFIG;\n\t}\n\n\tif (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n\t\treturn DEFAULT_SCORING_CONFIG;\n\t}\n\n\t// Merge weights\n\tconst weights = mergeWeights(\n\t\tDEFAULT_SCORING_CONFIG.weights,\n\t\tparsed.weights as Record<string, unknown> | undefined,\n\t) as Record<CheckCategory, number>;\n\n\t// Merge profile weights\n\tconst profileWeights = { ...DEFAULT_SCORING_CONFIG.profileWeights } as Record<DomainProfile, Record<CheckCategory, number>>;\n\tconst rawProfileWeights = parsed.profileWeights as Record<string, Record<string, unknown>> | undefined;\n\tif (rawProfileWeights && typeof rawProfileWeights === 'object') {\n\t\tfor (const profile of Object.keys(DEFAULT_SCORING_CONFIG.profileWeights) as DomainProfile[]) {\n\t\t\tif (profile in rawProfileWeights) {\n\t\t\t\tprofileWeights[profile] = mergeWeights(\n\t\t\t\t\tDEFAULT_SCORING_CONFIG.profileWeights[profile],\n\t\t\t\t\trawProfileWeights[profile],\n\t\t\t\t) as Record<CheckCategory, number>;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge thresholds\n\tconst rawThresholds = parsed.thresholds as Record<string, unknown> | undefined;\n\tconst thresholds = { ...DEFAULT_SCORING_CONFIG.thresholds };\n\tif (rawThresholds && typeof rawThresholds === 'object') {\n\t\tfor (const key of Object.keys(thresholds) as Array<keyof typeof thresholds>) {\n\t\t\tif (key in rawThresholds && typeof rawThresholds[key] === 'number' && Number.isFinite(rawThresholds[key])) {\n\t\t\t\tthresholds[key] = rawThresholds[key] as number;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge grades\n\tconst rawGrades = parsed.grades as Record<string, unknown> | undefined;\n\tconst grades = { ...DEFAULT_SCORING_CONFIG.grades };\n\tif (rawGrades && typeof rawGrades === 'object') {\n\t\tfor (const key of Object.keys(grades) as Array<keyof typeof grades>) {\n\t\t\tif (key in rawGrades && typeof rawGrades[key] === 'number' && Number.isFinite(rawGrades[key])) {\n\t\t\t\tgrades[key] = rawGrades[key] as number;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Merge baseline failure rates\n\tconst baselineFailureRates = mergeWeights(\n\t\tDEFAULT_SCORING_CONFIG.baselineFailureRates,\n\t\tparsed.baselineFailureRates as Record<string, unknown> | undefined,\n\t);\n\n\treturn { weights, profileWeights, thresholds, grades, baselineFailureRates };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport {\n\tCATEGORY_DISPLAY_WEIGHTS,\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype Finding,\n\tinferFindingConfidence,\n\ttype ScanScore,\n} from './scoring-model';\nimport type { DomainContext } from './context-profiles';\nimport { PROFILE_CRITICAL_CATEGORIES, PROFILE_EMAIL_BONUS_ELIGIBLE } from './context-profiles';\nimport type { ScoringConfig } from './scoring-config';\nimport { DEFAULT_SCORING_CONFIG, toImportanceRecord } from './scoring-config';\n\ninterface ImportanceProfile {\n\timportance: number;\n}\n\n/**\n * Scanner-aligned importance weighting for the checks currently supported by this MCP server.\n * Values are sourced from blackveilsecurity.com score engine for overlapping checks.\n */\nexport const IMPORTANCE_WEIGHTS: Record<CheckCategory, ImportanceProfile> = {\n\tspf: { importance: 10 },\n\tdmarc: { importance: 22 },\n\tdkim: { importance: 16 },\n\tdnssec: { importance: 2 },\n\tssl: { importance: 5 },\n\tmta_sts: { importance: 2 },\n\tns: { importance: 0 },\n\tcaa: { importance: 0 },\n\tsubdomain_takeover: { importance: 3 },\n\tmx: { importance: 2 },\n\tbimi: { importance: 0 },\n\ttlsrpt: { importance: 1 },\n\tlookalikes: { importance: 0 },\n\tshadow_domains: { importance: 0 },\n\ttxt_hygiene: { importance: 0 },\n\thttp_security: { importance: 3 },\n\tdane: { importance: 1 },\n\tmx_reputation: { importance: 0 },\n\tsrv: { importance: 0 },\n\tzone_hygiene: { importance: 0 },\n};\n\nfunction scoreIndicatesMissingControl(findings: Finding[]): boolean {\n\treturn findings.some((finding) => {\n\t\tif (finding.severity !== 'critical' && finding.severity !== 'high') return false;\n\t\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\t\treturn /(no\\s+.+\\s+record|missing|required|not\\s+found)/.test(text);\n\t});\n}\n\nfunction clampPercent(score: number): number {\n\treturn Math.max(0, Math.min(100, score));\n}\n\nfunction computeProviderConfidenceModifier(findings: Finding[]): number {\n\tconst confidences: number[] = [];\n\n\tfor (const finding of findings) {\n\t\tconst confidence = finding.metadata?.providerConfidence;\n\t\tif (typeof confidence === 'number' && Number.isFinite(confidence)) {\n\t\t\tconfidences.push(Math.max(0, Math.min(1, confidence)));\n\t\t}\n\t}\n\n\tif (confidences.length === 0) return 0;\n\n\tconst avgConfidence = confidences.reduce((sum, value) => sum + value, 0) / confidences.length;\n\tconst centered = avgConfidence - 0.5;\n\treturn Math.round(centered * 10);\n}\n\n/** Map numeric score to letter grade */\nexport function scoreToGrade(score: number, config?: ScoringConfig): string {\n\tconst g = config?.grades ?? DEFAULT_SCORING_CONFIG.grades;\n\tif (score >= g.aPlus) return 'A+';\n\tif (score >= g.a) return 'A';\n\tif (score >= g.bPlus) return 'B+';\n\tif (score >= g.b) return 'B';\n\tif (score >= g.cPlus) return 'C+';\n\tif (score >= g.c) return 'C';\n\tif (score >= g.dPlus) return 'D+';\n\tif (score >= g.d) return 'D';\n\tif (score >= g.e) return 'E';\n\treturn 'F';\n}\n\n/** Default critical categories used when no context is provided.\n * DNSSEC is excluded: its importance weight (2) already reflects its proportional\n * impact, and only ~30% of domains deploy it — capping the entire score at 64\n * for missing DNSSEC produces misleading results for well-configured domains. */\nconst DEFAULT_CRITICAL_CATEGORIES: CheckCategory[] = ['spf', 'dmarc', 'dkim', 'ssl', 'subdomain_takeover'];\n\n/**\n * Compute the overall scan score from individual check results.\n * Uses weighted average of category scores.\n *\n * When a `DomainContext` is provided, uses profile-specific weights,\n * critical gap categories, and email bonus eligibility instead of defaults.\n */\nexport function computeScanScore(results: CheckResult[], context?: DomainContext, config?: ScoringConfig): ScanScore {\n\tconst partialScores: Partial<Record<CheckCategory, number>> = {};\n\tconst allFindings: Finding[] = [];\n\n\t// CATEGORY_DISPLAY_WEIGHTS is Record<CheckCategory, number> — Object.keys returns string[], cast is safe\n\tfor (const category of Object.keys(CATEGORY_DISPLAY_WEIGHTS) as CheckCategory[]) {\n\t\tpartialScores[category] = 100;\n\t}\n\n\t// All CheckCategory keys are populated above — safe to widen from Partial\n\tconst categoryScores = partialScores as Record<CheckCategory, number>;\n\n\tconst cfg = config ?? DEFAULT_SCORING_CONFIG;\n\tconst emailBonusImportance = cfg.thresholds.emailBonusImportance;\n\tconst spfStrongThreshold = cfg.thresholds.spfStrongThreshold;\n\tconst criticalOverallPenalty = cfg.thresholds.criticalOverallPenalty;\n\tconst criticalGapCeiling = cfg.thresholds.criticalGapCeiling;\n\n\tif (results.length === 0) {\n\t\treturn {\n\t\t\toverall: 100,\n\t\t\tgrade: scoreToGrade(100, config),\n\t\t\tcategoryScores,\n\t\t\tfindings: [],\n\t\t\tsummary: `Excellent! No security issues found. Grade: ${scoreToGrade(100, config)}`,\n\t\t};\n\t}\n\n\tfor (const result of results) {\n\t\tcategoryScores[result.category] = result.score;\n\t\tallFindings.push(...result.findings);\n\t}\n\n\tlet earnedPoints = 0;\n\tlet maxPoints = 0;\n\n\t// Use context-specific weights when provided, otherwise fall back to config defaults\n\tconst activeWeights = context ? context.weights : toImportanceRecord(cfg.weights);\n\n\t// activeWeights is Record<CheckCategory, ImportanceProfile> — Object.keys returns string[], cast is safe\n\tfor (const category of Object.keys(activeWeights) as CheckCategory[]) {\n\t\tconst { importance } = activeWeights[category];\n\t\tmaxPoints += importance;\n\t\tif (importance === 0) continue;\n\n\t\tconst result = results.find((entry) => entry.category === category);\n\t\tconst rawScore = result ? clampPercent(result.score) : 100;\n\t\tconst effectiveScore = result && scoreIndicatesMissingControl(result.findings) ? 0 : rawScore;\n\t\tearnedPoints += (effectiveScore / 100) * importance;\n\t}\n\n\t// Email bonus: only awarded for profiles that are eligible (or when no context is provided)\n\tconst emailBonusEligible = context ? PROFILE_EMAIL_BONUS_ELIGIBLE[context.profile] : true;\n\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst dkimResult = results.find((result) => result.category === 'dkim');\n\tconst dmarcResult = results.find((result) => result.category === 'dmarc');\n\tconst spfStrong = !!spfResult && !scoreIndicatesMissingControl(spfResult.findings) && spfResult.score >= spfStrongThreshold;\n\tconst dkimPresent = !!dkimResult && !scoreIndicatesMissingControl(dkimResult.findings);\n\tconst dmarcPresent = !!dmarcResult && !scoreIndicatesMissingControl(dmarcResult.findings);\n\n\tlet emailBonus = 0;\n\tif (emailBonusEligible && spfStrong && dkimPresent && dmarcPresent && dmarcResult) {\n\t\tif (dmarcResult.score >= 90) {\n\t\t\temailBonus = emailBonusImportance;\n\t\t} else if (dmarcResult.score >= 70) {\n\t\t\temailBonus = Math.ceil(emailBonusImportance * 0.6);\n\t\t} else {\n\t\t\temailBonus = Math.ceil(emailBonusImportance * 0.4);\n\t\t}\n\t}\n\n\tearnedPoints += emailBonus;\n\tif (emailBonus > 0) {\n\t\tmaxPoints += emailBonusImportance;\n\t}\n\n\tconst baseOverall = Math.round(maxPoints > 0 ? clampPercent((earnedPoints / maxPoints) * 100) : 0);\n\tconst providerModifier = computeProviderConfidenceModifier(allFindings);\n\tconst criticalCount = allFindings.filter((finding) => finding.severity === 'critical').length;\n\tconst verifiedCriticalCount = allFindings.filter(\n\t\t(finding) => finding.severity === 'critical' && inferFindingConfidence(finding) === 'verified',\n\t).length;\n\tconst criticalPenalty = verifiedCriticalCount > 0 ? criticalOverallPenalty : 0;\n\tconst preCeiling = clampPercent(baseOverall + providerModifier - criticalPenalty);\n\n\t// Critical gap ceiling: cap score when foundational controls are missing\n\tconst criticalCategories = context\n\t\t? PROFILE_CRITICAL_CATEGORIES[context.profile]\n\t\t: DEFAULT_CRITICAL_CATEGORIES;\n\tconst hasCriticalGap = criticalCategories.some((cat) => {\n\t\tconst result = results.find((r) => r.category === cat);\n\t\treturn result && scoreIndicatesMissingControl(result.findings);\n\t});\n\tconst overall = hasCriticalGap ? Math.min(preCeiling, criticalGapCeiling) : preCeiling;\n\n\tconst grade = scoreToGrade(overall, config);\n\n\tconst highCount = allFindings.filter((finding) => finding.severity === 'high').length;\n\tconst totalIssues = allFindings.filter((finding) => finding.severity !== 'info').length;\n\n\tlet summary: string;\n\tif (totalIssues === 0) {\n\t\tsummary = `Excellent! No security issues found. Grade: ${grade}`;\n\t} else if (criticalCount > 0) {\n\t\tsummary = `${criticalCount} critical issue(s) found requiring immediate attention. Grade: ${grade}`;\n\t} else if (highCount > 0) {\n\t\tsummary = `${highCount} high-severity issue(s) found. Grade: ${grade}`;\n\t} else {\n\t\tsummary = `${totalIssues} issue(s) found. Grade: ${grade}`;\n\t}\n\n\treturn {\n\t\toverall,\n\t\tgrade,\n\t\tcategoryScores,\n\t\tfindings: allFindings,\n\t\tsummary,\n\t};\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Adaptive weight computation for context-aware scoring.\n *\n * Uses exponential moving averages (EMA) of per-category failure rates,\n * collected by the ProfileAccumulator Durable Object, to adjust static\n * importance weights at scoring time. A maturity-gated blend ensures\n * weights stay close to static until enough telemetry has accumulated.\n */\n\nimport type { CheckCategory } from './scoring-model';\nimport type { DomainProfile } from './context-profiles';\nimport { PROFILE_WEIGHTS } from './context-profiles';\n\n// ─── Telemetry interfaces ──────────────────────────────────────────────\n\n/** A single scan's telemetry payload sent to the ProfileAccumulator DO. */\nexport interface ScanTelemetry {\n\tprofile: string;\n\tprovider: string | null;\n\tcategoryFindings: Array<{ category: string; score: number; passed: boolean }>;\n\ttimestamp: number;\n}\n\n/** Response from the adaptive weights endpoint. */\nexport interface AdaptiveWeightsResponse {\n\tprofile: string;\n\tprovider: string | null;\n\tsampleCount: number;\n\tblendFactor: number;\n\tweights: Record<string, number>;\n\tboundHits: string[];\n}\n\n/** Min/max bounds for an adaptive weight value. */\nexport interface WeightBound {\n\tmin: number;\n\tmax: number;\n}\n\n// ─── Constants ─────────────────────────────────────────────────────────\n\n/** How aggressively deviation from baseline adjusts the weight (0–1). */\nexport const SENSITIVITY = 0.5;\n\n/** Sample count at which blending reaches 100% adaptive. */\nexport const MATURITY_THRESHOLD = 200;\n\n/** EMA span (number of recent observations the average reflects). */\nexport const EMA_SPAN = 200;\n\n/** EMA smoothing factor derived from span. */\nexport const EMA_ALPHA = 2 / (EMA_SPAN + 1);\n\n/** Minimum |scoreDelta| before a scoring note is generated. */\nexport const SCORING_NOTE_DELTA_THRESHOLD = 3;\n\n/** Expected failure rate per category across all domains (prior). */\nexport const BASELINE_FAILURE_RATES: Record<string, number> = {\n\tdmarc: 0.40,\n\tspf: 0.25,\n\tdkim: 0.35,\n\tssl: 0.08,\n\tmta_sts: 0.85,\n\tdnssec: 0.80,\n\tmx: 0.05,\n\tcaa: 0.70,\n\tns: 0.03,\n\tbimi: 0.95,\n\ttlsrpt: 0.90,\n\tsubdomain_takeover: 0.10,\n\tlookalikes: 0.00,\n};\n\n// ─── Weight bounds ─────────────────────────────────────────────────────\n\n/** Categories treated as \"critical mail\" for bound computation in mail-centric profiles. */\nconst CRITICAL_MAIL_CATEGORIES = new Set<string>(['dmarc', 'spf', 'dkim', 'ssl']);\n\n/** Profiles where critical-mail floor applies. */\nconst CRITICAL_MAIL_PROFILES = new Set<string>(['mail_enabled', 'enterprise_mail']);\n\n/**\n * Compute default min/max bounds for an adaptive weight.\n *\n * Critical-mail categories get a higher floor (min 5) to prevent\n * important email-auth checks from being zeroed out.\n */\nexport function defaultBounds(staticWeight: number, isCriticalMail: boolean): WeightBound {\n\tconst minFloor = isCriticalMail ? 5 : 0;\n\treturn {\n\t\tmin: Math.max(minFloor, Math.floor(staticWeight * 0.5)),\n\t\tmax: Math.ceil(staticWeight * 2) + 3,\n\t};\n}\n\n/** Pre-computed bounds for every profile × category combination. */\nexport const WEIGHT_BOUNDS: Record<DomainProfile, Record<CheckCategory, WeightBound>> = (() => {\n\tconst profiles = Object.keys(PROFILE_WEIGHTS) as DomainProfile[];\n\tconst result = {} as Record<DomainProfile, Record<CheckCategory, WeightBound>>;\n\n\tfor (const profile of profiles) {\n\t\tconst weights = PROFILE_WEIGHTS[profile];\n\t\tconst categories = Object.keys(weights) as CheckCategory[];\n\t\tconst profileBounds = {} as Record<CheckCategory, WeightBound>;\n\n\t\tfor (const cat of categories) {\n\t\t\tconst isCritical = CRITICAL_MAIL_PROFILES.has(profile) && CRITICAL_MAIL_CATEGORIES.has(cat);\n\t\t\tprofileBounds[cat] = defaultBounds(weights[cat].importance, isCritical);\n\t\t}\n\n\t\tresult[profile] = profileBounds;\n\t}\n\n\treturn result;\n})();\n\n// ─── Computation functions ─────────────────────────────────────────────\n\n/**\n * Compute a single adaptive weight from EMA failure rate and baseline.\n *\n * @returns The clamped weight and whether a bound was hit ('min' | 'max' | null).\n */\nexport function computeAdaptiveWeight(params: {\n\tstaticWeight: number;\n\temaFailureRate: number;\n\tbaselineFailureRate: number;\n\tbounds: WeightBound;\n}): { weight: number; boundHit: 'min' | 'max' | null } {\n\tconst { staticWeight, emaFailureRate, baselineFailureRate, bounds } = params;\n\n\tconst deviation = emaFailureRate - baselineFailureRate;\n\tconst rawAdjustment = deviation * SENSITIVITY * staticWeight;\n\tconst adaptive = staticWeight + rawAdjustment;\n\tconst clamped = Math.max(bounds.min, Math.min(bounds.max, adaptive));\n\n\tlet boundHit: 'min' | 'max' | null = null;\n\tif (clamped <= bounds.min && adaptive < bounds.min) {\n\t\tboundHit = 'min';\n\t} else if (clamped >= bounds.max && adaptive > bounds.max) {\n\t\tboundHit = 'max';\n\t}\n\n\treturn { weight: clamped, boundHit };\n}\n\n/**\n * Blend static and adaptive weights based on sample maturity.\n *\n * Returns `(1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight`\n * where `blendFactor = min(1.0, sampleCount / MATURITY_THRESHOLD)`.\n */\nexport function blendWeights(staticWeight: number, adaptiveWeight: number, sampleCount: number): number {\n\tconst blendFactor = Math.min(1.0, sampleCount / MATURITY_THRESHOLD);\n\treturn (1 - blendFactor) * staticWeight + blendFactor * adaptiveWeight;\n}\n\n// ─── Type adapter ──────────────────────────────────────────────────────\n\n/**\n * Convert a DO-returned weight map to a CheckCategory-keyed importance record.\n *\n * Falls back to the static profile weight for any category not present in the\n * DO response. Returns `null` if any value is non-finite or negative.\n */\nexport function adaptiveWeightsToContext(\n\tdoWeights: Record<string, number>,\n\tprofile: DomainProfile,\n): Record<CheckCategory, { importance: number }> | null {\n\tconst staticWeights = PROFILE_WEIGHTS[profile];\n\tconst categories = Object.keys(staticWeights) as CheckCategory[];\n\tconst result = {} as Record<CheckCategory, { importance: number }>;\n\n\tfor (const cat of categories) {\n\t\tconst value = cat in doWeights ? doWeights[cat] : staticWeights[cat].importance;\n\t\tif (!isFinite(value) || value < 0) {\n\t\t\treturn null;\n\t\t}\n\t\tresult[cat] = { importance: value };\n\t}\n\n\treturn result;\n}\n\n// ─── Scoring note generation ───────────────────────────────────────────\n\n/**\n * Generate a human-readable note explaining adaptive weight shifts.\n *\n * Returns `null` if the absolute score delta is below the threshold.\n */\nexport function generateScoringNote(\n\tweightDeltas: Record<string, number>,\n\tscoreDelta: number,\n\tprovider: string | null,\n): string | null {\n\tif (Math.abs(scoreDelta) < SCORING_NOTE_DELTA_THRESHOLD) {\n\t\treturn null;\n\t}\n\n\t// Collect significant deltas (|delta| >= 2) sorted by magnitude descending\n\tconst significant = Object.entries(weightDeltas)\n\t\t.filter(([, d]) => Math.abs(d) >= 2)\n\t\t.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\n\tif (significant.length === 0) {\n\t\t// No individually significant deltas but overall threshold met — use the largest anyway\n\t\tconst all = Object.entries(weightDeltas).sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));\n\t\tif (all.length === 0) return null;\n\t\tconst [topCat, topDelta] = all[0];\n\t\treturn formatNote(topCat, topDelta, provider);\n\t}\n\n\tif (significant.length >= 3) {\n\t\tconst [topCat] = significant[0];\n\t\treturn `Several checks were weighted differently based on patterns seen across similar domains. The biggest shift was in ${topCat.toUpperCase()}.`;\n\t}\n\n\tconst [topCat, topDelta] = significant[0];\n\treturn formatNote(topCat, topDelta, provider);\n}\n\n/** Format a single-category scoring note. */\nfunction formatNote(category: string, delta: number, provider: string | null): string {\n\tconst cat = category.toUpperCase();\n\n\tif (delta > 0 && provider) {\n\t\tconst providerDisplay = capitalizeWords(provider);\n\t\treturn `${cat} carried more weight because domains using ${providerDisplay} frequently have issues in this area.`;\n\t}\n\n\tif (delta > 0) {\n\t\treturn `${cat} carried more weight in this scan because it is a common issue across similar domains.`;\n\t}\n\n\treturn `${cat} carried less weight because similar domains rarely have issues there.`;\n}\n\n/** Capitalize the first letter of each word. */\nfunction capitalizeWords(s: string): string {\n\treturn s.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNS Security Scoring Library\n *\n * Public scoring surface re-exporting the scoring model and scan aggregation engine.\n */\n\nexport {\n\tCATEGORY_DISPLAY_WEIGHTS,\n\tSEVERITY_PENALTIES,\n\tbuildCheckResult,\n\tcomputeCategoryScore,\n\tcreateFinding,\n\tinferFindingConfidence,\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype Finding,\n\ttype FindingConfidence,\n\ttype ScanScore,\n\ttype Severity,\n} from './scoring-model';\n\nexport { computeScanScore, scoreToGrade } from './scoring-engine';\n\nexport { detectDomainContext, getProfileWeights, type DomainContext, type DomainProfile } from './context-profiles';\n\nexport {\n\tadaptiveWeightsToContext,\n\tgenerateScoringNote,\n\tcomputeAdaptiveWeight,\n\tblendWeights,\n\ttype AdaptiveWeightsResponse,\n\ttype ScanTelemetry,\n\ttype WeightBound,\n} from './adaptive-weights';\n\nexport { parseScoringConfig, DEFAULT_SCORING_CONFIG, toImportanceRecord, type ScoringConfig } from './scoring-config';\n","// SPDX-License-Identifier: BUSL-1.1\n\nexport interface ProviderSignature {\n\tname: string;\n\tdomains: string[];\n\tselectorHints?: string[];\n}\n\nexport interface ProviderSignaturePayload {\n\tversion?: string;\n\tinbound?: ProviderSignature[];\n\toutbound?: ProviderSignature[];\n}\n\nexport interface ProviderSourceResult {\n\tversion: string;\n\tsource: 'runtime' | 'stale' | 'built-in';\n\tfetchedAt: string;\n\tdegraded: boolean;\n\tinbound: ProviderSignature[];\n\toutbound: ProviderSignature[];\n}\n\nexport interface LoadProviderSignaturesOptions {\n\tsourceUrl?: string;\n\tallowedHosts?: string[];\n\texpectedSha256?: string;\n\ttimeoutMs?: number;\n\tretries?: number;\n}\n\nexport const DEFAULT_TIMEOUT_MS = 2500;\nexport const DEFAULT_RETRIES = 1;\nexport const RUNTIME_SIGNATURE_CACHE_TTL_MS = 5 * 60 * 1000;\n\nexport const BUILT_IN_SIGNATURES: ProviderSignaturePayload = {\n\tversion: 'built-in-2026-03-04',\n\tinbound: [\n\t\t{ name: 'Google Workspace', domains: ['google.com', 'googlemail.com'], selectorHints: ['google'] },\n\t\t{ name: 'Microsoft 365', domains: ['outlook.com', 'protection.outlook.com'], selectorHints: ['selector1', 'selector2'] },\n\t\t{ name: 'Proofpoint', domains: ['pphosted.com'] },\n\t\t{ name: 'Mimecast', domains: ['mimecast.com'], selectorHints: ['mimecast'] },\n\t\t{ name: 'Mailgun', domains: ['mailgun.org'] },\n\t\t{ name: 'SendGrid', domains: ['sendgrid.net'] },\n\t\t{ name: 'Amazon SES', domains: ['amazonses.com'] },\n\t],\n\toutbound: [],\n};\n\nexport function normalizeSha256(value: string): string {\n\treturn value.trim().toLowerCase().replace(/^sha256:/, '');\n}\n\nexport function normalizeAllowedHosts(input: string[] | undefined): string[] {\n\tif (!Array.isArray(input)) return [];\n\treturn input.map((host) => host.trim().toLowerCase()).filter((host) => host.length > 0);\n}\n\nexport function validateRuntimeSourceUrl(sourceUrl: string, allowedHosts: string[]): URL {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(sourceUrl);\n\t} catch {\n\t\tthrow new Error('Invalid provider signature source URL');\n\t}\n\n\tif (url.protocol !== 'https:') {\n\t\tthrow new Error('Invalid provider signature source URL: HTTPS is required');\n\t}\n\n\tif (allowedHosts.length > 0 && !allowedHosts.includes(url.hostname.toLowerCase())) {\n\t\tthrow new Error('Invalid provider signature source URL: host is not allowlisted');\n\t}\n\n\treturn url;\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n\treturn Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, '0')).join('');\n}\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction normalizeProviderSignatures(input: ProviderSignature[] | undefined): ProviderSignature[] {\n\tif (!Array.isArray(input)) return [];\n\n\treturn input\n\t\t.map((provider) => {\n\t\t\tconst name = typeof provider?.name === 'string' ? provider.name.trim() : '';\n\t\t\tconst domains = Array.isArray(provider?.domains)\n\t\t\t\t? provider.domains.map((domain) => normalizeDomain(String(domain))).filter((domain) => domain.length > 0)\n\t\t\t\t: [];\n\t\t\tconst selectorHints = Array.isArray(provider?.selectorHints)\n\t\t\t\t? provider.selectorHints.map((selector) => String(selector).trim().toLowerCase()).filter((selector) => selector.length > 0)\n\t\t\t\t: [];\n\t\t\treturn { name, domains, ...(selectorHints.length > 0 ? { selectorHints } : {}) };\n\t\t})\n\t\t.filter((provider) => provider.name.length > 0 && provider.domains.length > 0);\n}\n\nexport function buildResult(\n\tpayload: ProviderSignaturePayload,\n\tsource: ProviderSourceResult['source'],\n\tdegraded: boolean,\n): ProviderSourceResult {\n\tconst inbound = normalizeProviderSignatures(payload.inbound);\n\tconst outbound = normalizeProviderSignatures(payload.outbound);\n\n\treturn {\n\t\tversion: payload.version?.trim() || BUILT_IN_SIGNATURES.version || 'unknown',\n\t\tsource,\n\t\tfetchedAt: new Date().toISOString(),\n\t\tdegraded,\n\t\tinbound,\n\t\toutbound,\n\t};\n}\n\nexport function isValidSignaturePayload(payload: unknown): payload is ProviderSignaturePayload {\n\tif (!payload || typeof payload !== 'object') return false;\n\tconst record = payload as Record<string, unknown>; // typeof payload === 'object' is checked above\n\tif (record.version !== undefined && typeof record.version !== 'string') return false;\n\tif (record.inbound !== undefined && !Array.isArray(record.inbound)) return false;\n\tif (record.outbound !== undefined && !Array.isArray(record.outbound)) return false;\n\treturn true;\n}\n\nexport async function fetchProviderPayload(\n\turl: string,\n\ttimeoutMs: number,\n\tretries: number,\n\texpectedSha256?: string,\n): Promise<ProviderSignaturePayload | null> {\n\tfor (let attempt = 0; attempt <= retries; attempt++) {\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\theaders: { Accept: 'application/json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tredirect: 'manual',\n\t\t\t});\n\t\t\tif (response.status >= 300 && response.status < 400) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!response.ok) {\n\t\t\t\tif (attempt < retries && response.status >= 500) continue;\n\t\t\t\tthrow new Error(`Provider signature source returned HTTP ${response.status}`);\n\t\t\t}\n\n\t\t\tconst rawPayload = await response.text();\n\t\t\tif (!expectedSha256) {\n\t\t\t\tthrow new Error('Provider signature source requires a pinned SHA-256 digest');\n\t\t\t}\n\n\t\t\tconst digest = await sha256Hex(rawPayload);\n\t\t\tif (digest !== normalizeSha256(expectedSha256)) {\n\t\t\t\tthrow new Error('Provider signature source failed SHA-256 verification');\n\t\t\t}\n\n\t\t\tconst payload = JSON.parse(rawPayload) as unknown;\n\t\t\tif (!isValidSignaturePayload(payload)) {\n\t\t\t\tthrow new Error('Provider signature source returned an invalid payload shape');\n\t\t\t}\n\n\t\t\treturn payload;\n\t\t} catch (error) {\n\t\t\tif (attempt < retries) continue;\n\t\t\tif (error instanceof DOMException && error.name === 'AbortError') {\n\t\t\t\tthrow new Error(`Provider signature source timed out after ${timeoutMs}ms`);\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\t}\n\n\tthrow new Error('Failed to load provider signatures');\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport {\n\tBUILT_IN_SIGNATURES,\n\tbuildResult,\n\tDEFAULT_RETRIES,\n\tDEFAULT_TIMEOUT_MS,\n\tfetchProviderPayload,\n\ttype LoadProviderSignaturesOptions,\n\tnormalizeAllowedHosts,\n\ttype ProviderSignature,\n\ttype ProviderSourceResult,\n\tRUNTIME_SIGNATURE_CACHE_TTL_MS,\n\tvalidateRuntimeSourceUrl,\n} from './provider-signature-source';\n\ninterface ProviderMatchEvidence {\n\tprovider: string;\n\tmatches: string[];\n}\n\nlet lastKnownGood: ProviderSourceResult | null = null;\nlet runtimeSignatureCache: {\n\tsourceUrl: string;\n\tresult: ProviderSourceResult;\n\texpiresAt: number;\n} | null = null;\n\nfunction normalizeDomain(value: string): string {\n\treturn value.trim().toLowerCase().replace(/\\.$/, '');\n}\n\nfunction boundarySuffixMatch(hostname: string, suffix: string): boolean {\n\tconst host = normalizeDomain(hostname);\n\tconst normalizedSuffix = normalizeDomain(suffix);\n\tif (!host || !normalizedSuffix) return false;\n\treturn host === normalizedSuffix || host.endsWith(`.${normalizedSuffix}`);\n}\n\n\nexport async function loadProviderSignatures(options?: LoadProviderSignaturesOptions): Promise<ProviderSourceResult> {\n\tconst timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tconst retries = options?.retries ?? DEFAULT_RETRIES;\n\tconst sourceUrl = options?.sourceUrl?.trim();\n\tconst allowedHosts = normalizeAllowedHosts(options?.allowedHosts);\n\tconst expectedSha256 = options?.expectedSha256?.trim();\n\n\tif (!sourceUrl) {\n\t\treturn buildResult(BUILT_IN_SIGNATURES, 'built-in', false);\n\t}\n\n\tconst now = Date.now();\n\tif (runtimeSignatureCache && runtimeSignatureCache.sourceUrl === sourceUrl && runtimeSignatureCache.expiresAt > now) {\n\t\treturn runtimeSignatureCache.result;\n\t}\n\n\ttry {\n\t\tconst validatedUrl = validateRuntimeSourceUrl(sourceUrl, allowedHosts);\n\t\tconst payload = await fetchProviderPayload(validatedUrl.toString(), timeoutMs, retries, expectedSha256);\n\t\tif (!payload) {\n\t\t\tthrow new Error('Provider signature source returned a redirect');\n\t\t}\n\t\tconst result = buildResult(payload, 'runtime', false);\n\t\tlastKnownGood = result;\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn result;\n\t} catch {\n\t\tif (lastKnownGood) {\n\t\t\tconst staleResult = { ...lastKnownGood, source: 'stale' as const, degraded: true, fetchedAt: new Date().toISOString() };\n\t\t\truntimeSignatureCache = {\n\t\t\t\tsourceUrl,\n\t\t\t\tresult: staleResult,\n\t\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t\t};\n\t\t\treturn staleResult;\n\t\t}\n\t\tconst fallbackResult = buildResult(BUILT_IN_SIGNATURES, 'built-in', true);\n\t\truntimeSignatureCache = {\n\t\t\tsourceUrl,\n\t\t\tresult: fallbackResult,\n\t\t\texpiresAt: now + RUNTIME_SIGNATURE_CACHE_TTL_MS,\n\t\t};\n\t\treturn fallbackResult;\n\t}\n}\n\n/**\n * Test helper to reset provider signature loader state between cases.\n * @internal Exported for test use only.\n */\nexport function resetProviderSignatureState(): void {\n\tlastKnownGood = null;\n\truntimeSignatureCache = null;\n}\n\nexport function detectProviderMatches(hosts: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedHosts = hosts.map((host) => normalizeDomain(host)).filter((host) => host.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst providerMatches = new Set<string>();\n\t\tfor (const host of normalizedHosts) {\n\t\t\tif (provider.domains.some((domain) => boundarySuffixMatch(host, domain))) {\n\t\t\t\tproviderMatches.add(host);\n\t\t\t}\n\t\t}\n\t\tif (providerMatches.size > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(providerMatches) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n\nexport function detectProviderMatchesBySelectors(selectors: string[], signatures: ProviderSignature[]): ProviderMatchEvidence[] {\n\tconst normalizedSelectors = selectors.map((selector) => selector.trim().toLowerCase()).filter((selector) => selector.length > 0);\n\tconst matches: ProviderMatchEvidence[] = [];\n\n\tfor (const provider of signatures) {\n\t\tconst hints = provider.selectorHints ?? [];\n\t\tif (hints.length === 0) continue;\n\n\t\tconst providerMatches = normalizedSelectors.filter((selector) => hints.includes(selector));\n\t\tif (providerMatches.length > 0) {\n\t\t\tmatches.push({ provider: provider.name, matches: Array.from(new Set(providerMatches)) });\n\t\t}\n\t}\n\n\treturn matches;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\nexport type ParsedMxRecord = {\n\tpriority: number;\n\texchange: string;\n\traw: string;\n};\n\nexport function parseMxRecords(answers: string[]): ParsedMxRecord[] {\n\treturn answers.map((answer) => {\n\t\tconst parts = answer.split(' ');\n\t\tconst priority = parseInt(parts[0], 10);\n\t\tconst exchange = (parts.slice(1).join(' ') || '').replace(/\\.$/, '').toLowerCase();\n\t\treturn { priority, exchange, raw: answer };\n\t});\n}\n\nexport function isNullMxRecord(record: ParsedMxRecord): boolean {\n\treturn record.exchange === '' || record.exchange === '.';\n}\n\nexport function getNullMxFinding(): Finding {\n\treturn createFinding('mx', 'Null MX record (RFC 7505)', 'info', 'Domain explicitly declares it does not accept email via null MX record.');\n}\n\nexport function getPresenceFinding(mxRecords: ParsedMxRecord[]): Finding {\n\treturn createFinding('mx', 'MX records found', 'info', `${mxRecords.length} mail exchange record(s) present.`);\n}\n\nexport function getIpTargetFindings(mxRecords: ParsedMxRecord[]): Finding[] {\n\tconst ipPattern = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\treturn mxRecords.flatMap((mxRecord) =>\n\t\tipPattern.test(mxRecord.exchange)\n\t\t\t? [\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx',\n\t\t\t\t\t\t'MX points to IP address',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`MX record \"${mxRecord.raw}\" points to an IP address. MX targets must be hostnames per RFC 5321.`,\n\t\t\t\t\t),\n\t\t\t\t]\n\t\t\t: [],\n\t);\n}\n\nexport function getSingleMxFinding(mxRecords: ParsedMxRecord[]): Finding | null {\n\tif (mxRecords.length !== 1) {\n\t\treturn null;\n\t}\n\n\treturn createFinding('mx', 'Single MX record', 'low', 'Only one MX record found. Consider adding a backup MX for redundancy.');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX record check tool for MCP server.\n * Validates presence and quality of MX records for a domain.\n * Returns CheckResult with findings including RFC compliance, redundancy, and provider detection.\n */\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { createFinding, buildCheckResult } from '../lib/scoring';\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { detectProviderMatches, loadProviderSignatures } from '../lib/provider-signatures';\nimport { getIpTargetFindings, getNullMxFinding, getPresenceFinding, getSingleMxFinding, isNullMxRecord, parseMxRecords } from './mx-analysis';\n\nexport interface CheckMxOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n}\n\n/** Check MX record configuration for a domain */\nexport async function checkMx(domain: string, options?: CheckMxOptions, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tlet answers;\n\ttry {\n\t\tanswers = await queryDnsRecords(domain, 'MX', dnsOptions);\n\t} catch {\n\t\treturn buildCheckResult('mx', [createFinding('mx', 'DNS query failed', 'medium', 'MX record lookup failed')]);\n\t}\n\n\tif (!answers || answers.length === 0) {\n\t\treturn buildCheckResult('mx', [\n\t\t\tcreateFinding(\n\t\t\t\t'mx',\n\t\t\t\t'No MX records found',\n\t\t\t\t'medium',\n\t\t\t\t'No mail exchange records present. If this domain does not handle email, consider publishing a null MX record (RFC 7505).',\n\t\t\t),\n\t\t]);\n\t}\n\n\tconst findings: Finding[] = [];\n\n\tconst mxRecords = parseMxRecords(answers);\n\n\t// Check for null MX (RFC 7505: priority 0, exchange \".\")\n\tconst nullMx = mxRecords.find(isNullMxRecord);\n\tif (nullMx) {\n\t\tfindings.push(getNullMxFinding());\n\t\treturn buildCheckResult('mx', findings);\n\t}\n\n\tfindings.push(getPresenceFinding(mxRecords));\n\n\tfindings.push(...getIpTargetFindings(mxRecords));\n\n\t// Check for dangling MX records (hostnames that don't resolve)\n\tconst ipPattern = /^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;\n\tconst hostnameRecords = mxRecords.filter((r) => !ipPattern.test(r.exchange));\n\tconst resolutions = await Promise.all(\n\t\thostnameRecords.map(async (r) => {\n\t\t\ttry {\n\t\t\t\tconst [a, aaaa] = await Promise.all([\n\t\t\t\t\tqueryDnsRecords(r.exchange, 'A', dnsOptions).catch(() => []),\n\t\t\t\t\tqueryDnsRecords(r.exchange, 'AAAA', dnsOptions).catch(() => []),\n\t\t\t\t]);\n\t\t\t\treturn { record: r, resolved: a.length > 0 || aaaa.length > 0 };\n\t\t\t} catch {\n\t\t\t\treturn { record: r, resolved: false };\n\t\t\t}\n\t\t}),\n\t);\n\tfor (const { record, resolved } of resolutions) {\n\t\tif (!resolved) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mx',\n\t\t\t\t\t'Dangling MX record',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`MX target \"${record.exchange}\" does not resolve to any A or AAAA record. Mail delivery to this host will fail.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for single MX (no redundancy)\n\tconst singleMxFinding = getSingleMxFinding(mxRecords);\n\tif (singleMxFinding) {\n\t\tfindings.push(singleMxFinding);\n\t}\n\n\t// Duplicate MX priorities are valid and commonly used for load balancing.\n\n\tconst mxTargets = mxRecords.map((r) => r.exchange);\n\tconst providerSignatures = await loadProviderSignatures({\n\t\tsourceUrl: options?.providerSignaturesUrl,\n\t\tallowedHosts: options?.providerSignaturesAllowedHosts,\n\t\texpectedSha256: options?.providerSignaturesSha256,\n\t});\n\tconst inboundMatches = detectProviderMatches(mxTargets, providerSignatures.inbound);\n\n\tif (inboundMatches.length > 0) {\n\t\tconst providerNames = inboundMatches.map((m) => m.provider).join(', ');\n\t\tconst evidence = inboundMatches.map((m) => `${m.provider}: ${m.matches.join(', ')}`).join('; ');\n\t\tconst providerConfidence = providerSignatures.source === 'runtime' ? 0.95 : providerSignatures.source === 'stale' ? 0.75 : 0.7;\n\n\t\tfindings.push(\n\t\t\tcreateFinding('mx', 'Managed email provider detected', 'info', `Inbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\t\tdetectionType: 'inbound',\n\t\t\t\tproviders: inboundMatches.map((m) => ({ name: m.provider, matches: m.matches })),\n\t\t\t\tproviderConfidence,\n\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (providerSignatures.degraded) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx',\n\t\t\t\t'Provider signature source unavailable',\n\t\t\t\t'info',\n\t\t\t\t`Provider detection used ${providerSignatures.source === 'stale' ? 'stale cached' : 'built-in fallback'} signatures.`,\n\t\t\t\t{\n\t\t\t\t\tdetectionType: 'inbound',\n\t\t\t\t\tproviderConfidence: providerSignatures.source === 'stale' ? 0.55 : 0.45,\n\t\t\t\t\tsignatureSource: providerSignatures.source,\n\t\t\t\t\tsignatureVersion: providerSignatures.version,\n\t\t\t\t\tsignatureFetchedAt: providerSignatures.fetchedAt,\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('mx', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * JSON-RPC 2.0 Protocol Utilities\n *\n * Shared types and helpers for constructing JSON-RPC 2.0\n * request/response/error objects used throughout the MCP server.\n */\n\n/** JSON-RPC 2.0 request shape */\nexport interface JsonRpcRequest {\n\tjsonrpc: string;\n\tid?: string | number | null;\n\tmethod: string;\n\tparams?: Record<string, unknown>;\n}\n\n/** JSON-RPC 2.0 error codes */\nexport const JSON_RPC_ERRORS = {\n\tPARSE_ERROR: -32700,\n\tINVALID_REQUEST: -32600,\n\tMETHOD_NOT_FOUND: -32601,\n\tINVALID_PARAMS: -32602,\n\tINTERNAL_ERROR: -32603,\n\tUNAUTHORIZED: -32001,\n\tRATE_LIMITED: -32029,\n} as const;\n\n/** Build a JSON-RPC 2.0 error response object */\nexport function jsonRpcError(id: string | number | null | undefined, code: number, message: string) {\n\treturn {\n\t\tjsonrpc: '2.0' as const,\n\t\tid: id ?? null,\n\t\terror: { code, message },\n\t};\n}\n\n/** Known safe error message prefixes that may be passed through to clients */\nconst SAFE_ERROR_PREFIXES = ['Missing required', 'Invalid', 'Domain ', 'Resource not found', 'Rate limit exceeded'];\n\n/**\n * Sanitize an error for client-facing responses.\n * Returns the original message if it starts with a known safe prefix,\n * otherwise returns the generic fallback to prevent information leaks.\n *\n * @param error - The caught error (unknown type from catch blocks)\n * @param fallback - Generic message to return for unexpected errors\n */\nexport function sanitizeErrorMessage(error: unknown, fallback: string): string {\n\tif (error instanceof Error) {\n\t\tfor (const prefix of SAFE_ERROR_PREFIXES) {\n\t\t\tif (error.message.startsWith(prefix)) {\n\t\t\t\treturn error.message;\n\t\t\t}\n\t\t}\n\t}\n\treturn fallback;\n}\n\n/** Build a JSON-RPC 2.0 success response object */\nexport function jsonRpcSuccess(id: string | number | null | undefined, result: unknown) {\n\treturn {\n\t\tjsonrpc: '2.0' as const,\n\t\tid: id ?? null,\n\t\tresult,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { JSON_RPC_ERRORS, jsonRpcError } from '../lib/json-rpc';\nimport type { JsonRpcRequest } from '../lib/json-rpc';\n\ntype RequestErrorStatus = 400 | 413;\n\nexport interface ParsedJsonRpcRequestResult {\n\tok: boolean;\n\tbody?: JsonRpcRequest | unknown[];\n\tisBatch?: boolean;\n\tstatus?: RequestErrorStatus;\n\tpayload?: ReturnType<typeof jsonRpcError>;\n}\n\nexport interface RequestBodyReadResult {\n\tok: boolean;\n\trawBody?: string;\n\tstatus?: RequestErrorStatus;\n\tpayload?: ReturnType<typeof jsonRpcError>;\n}\n\nexport function parseAllowedHosts(raw: string | undefined): string[] | undefined {\n\tconst trimmed = raw?.trim();\n\tif (!trimmed) return undefined;\n\treturn trimmed\n\t\t.split(',')\n\t\t.map((host) => host.trim().toLowerCase())\n\t\t.filter((host) => host.length > 0);\n}\n\nexport function summarizeParamsForLog(params: unknown): Record<string, unknown> | undefined {\n\tif (!params || typeof params !== 'object' || Array.isArray(params)) return undefined;\n\treturn {\n\t\tkeys: Object.keys(params).sort().slice(0, 25),\n\t};\n}\n\nexport function normalizeHeaders(headers: Headers): Record<string, string> {\n\tconst normalized: Record<string, string> = {};\n\theaders.forEach((value, key) => {\n\t\tnormalized[key.toLowerCase()] = value;\n\t});\n\treturn normalized;\n}\n\nexport async function readRequestBody(request: Request, maxBytes: number): Promise<RequestBodyReadResult> {\n\tlet rawBody = '';\n\tconst reader = request.body?.getReader();\n\tif (reader) {\n\t\tlet total = 0;\n\t\tconst decoder = new TextDecoder();\n\t\twhile (true) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\t\t\ttotal += value.length;\n\t\t\tif (total > maxBytes) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tstatus: 413,\n\t\t\t\t\tpayload: jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Request body too large'),\n\t\t\t\t};\n\t\t\t}\n\t\t\trawBody += decoder.decode(value, { stream: true });\n\t\t}\n\t\trawBody += decoder.decode(); // flush any remaining buffered bytes\n\t} else {\n\t\trawBody = await request.text();\n\t\tif (rawBody.length > maxBytes) {\n\t\t\treturn {\n\t\t\t\tok: false,\n\t\t\t\tstatus: 413,\n\t\t\t\tpayload: jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Request body too large'),\n\t\t\t};\n\t\t}\n\t}\n\n\treturn {\n\t\tok: true,\n\t\trawBody,\n\t};\n}\n\nexport function parseJsonRpcRequest(rawBody: string): ParsedJsonRpcRequestResult {\n\ttry {\n\t\tconst parsed = JSON.parse(rawBody);\n\t\tif (Array.isArray(parsed)) {\n\t\t\tif (parsed.length === 0) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tpayload: jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC batch request: empty array'),\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tok: true,\n\t\t\t\tbody: parsed,\n\t\t\t\tisBatch: true,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tok: true,\n\t\t\tbody: parsed as JsonRpcRequest, // validated by validateJsonRpcRequest above\n\t\t\tisBatch: false,\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tok: false,\n\t\t\tstatus: 400,\n\t\t\tpayload: jsonRpcError(null, JSON_RPC_ERRORS.PARSE_ERROR, 'Parse error: invalid JSON'),\n\t\t};\n\t}\n}\n\nexport function validateJsonRpcRequest(body: JsonRpcRequest): { status: 400; payload: ReturnType<typeof jsonRpcError> } | undefined {\n\tif (body.jsonrpc !== '2.0' || typeof body.method !== 'string') {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tpayload: jsonRpcError(body.id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC 2.0 request'),\n\t\t};\n\t}\n\n\tif (body.id !== undefined && body.id !== null && typeof body.id !== 'string' && typeof body.id !== 'number') {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tpayload: jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC id: must be string, number, or null'),\n\t\t};\n\t}\n\n\treturn undefined;\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { RateLimitResult, ToolDailyRateLimitResult } from './rate-limiter';\n\ninterface RateLimitWindow {\n\ttimestamps: number[];\n}\n\ninterface RateLimitEntry {\n\tminute: RateLimitWindow;\n\thour: RateLimitWindow;\n}\n\ninterface ToolDailyRateLimitEntry {\n\ttimestamps: number[];\n}\n\nexport type RateLimitScope = 'tools' | 'control';\n\nconst MINUTE_MS = 60_000;\nconst HOUR_MS = 3_600_000;\nconst DAY_MS = 86_400_000;\nconst CLEANUP_INTERVAL_MS = 300_000;\n\nconst RATE_LIMIT_ENTRIES = new Map<string, RateLimitEntry>();\nconst TOOL_DAILY_ENTRIES = new Map<string, ToolDailyRateLimitEntry>();\nlet lastCleanup = Date.now();\n\n/** Prune timestamps that fall outside a sliding window. */\nexport function pruneTimestamps(timestamps: number[], windowMs: number, now: number): number[] {\n\tconst cutoff = now - windowMs;\n\tlet index = 0;\n\twhile (index < timestamps.length && timestamps[index] <= cutoff) {\n\t\tindex++;\n\t}\n\treturn index > 0 ? timestamps.slice(index) : timestamps;\n}\n\nfunction cleanupExpiredEntries(now: number): void {\n\tif (now - lastCleanup < CLEANUP_INTERVAL_MS) return;\n\tlastCleanup = now;\n\n\tconst hourCutoff = now - HOUR_MS;\n\tfor (const [key, entry] of RATE_LIMIT_ENTRIES) {\n\t\tif (entry.hour.timestamps.length === 0 || entry.hour.timestamps[entry.hour.timestamps.length - 1] <= hourCutoff) {\n\t\t\tRATE_LIMIT_ENTRIES.delete(key);\n\t\t}\n\t}\n\n\tconst dayCutoff = now - DAY_MS;\n\tfor (const [key, entry] of TOOL_DAILY_ENTRIES) {\n\t\tif (entry.timestamps.length === 0 || entry.timestamps[entry.timestamps.length - 1] <= dayCutoff) {\n\t\t\tTOOL_DAILY_ENTRIES.delete(key);\n\t\t}\n\t}\n}\n\nfunction getOrCreateEntry(key: string): RateLimitEntry {\n\tlet entry = RATE_LIMIT_ENTRIES.get(key);\n\tif (!entry) {\n\t\tentry = {\n\t\t\tminute: { timestamps: [] },\n\t\t\thour: { timestamps: [] },\n\t\t};\n\t\tRATE_LIMIT_ENTRIES.set(key, entry);\n\t}\n\treturn entry;\n}\n\nfunction buildScopedEntryKey(ip: string, scope: RateLimitScope): string {\n\treturn `${scope}:${ip}`;\n}\n\nfunction getOrCreateToolDailyEntry(key: string): ToolDailyRateLimitEntry {\n\tlet entry = TOOL_DAILY_ENTRIES.get(key);\n\tif (!entry) {\n\t\tentry = { timestamps: [] };\n\t\tTOOL_DAILY_ENTRIES.set(key, entry);\n\t}\n\treturn entry;\n}\n\nexport function checkScopedRateLimitInMemory(ip: string, scope: RateLimitScope, minuteLimit: number, hourLimit: number): RateLimitResult {\n\tconst now = Date.now();\n\tcleanupExpiredEntries(now);\n\n\tconst entry = getOrCreateEntry(buildScopedEntryKey(ip, scope));\n\tentry.minute.timestamps = pruneTimestamps(entry.minute.timestamps, MINUTE_MS, now);\n\tentry.hour.timestamps = pruneTimestamps(entry.hour.timestamps, HOUR_MS, now);\n\n\tconst minuteCount = entry.minute.timestamps.length;\n\tconst hourCount = entry.hour.timestamps.length;\n\n\tif (minuteCount >= minuteLimit) {\n\t\tconst oldestInWindow = entry.minute.timestamps[0];\n\t\tconst retryAfterMs = oldestInWindow + MINUTE_MS - now;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(retryAfterMs, 0),\n\t\t\tminuteRemaining: 0,\n\t\t\thourRemaining: Math.max(hourLimit - hourCount, 0),\n\t\t};\n\t}\n\n\tif (hourCount >= hourLimit) {\n\t\tconst oldestInWindow = entry.hour.timestamps[0];\n\t\tconst retryAfterMs = oldestInWindow + HOUR_MS - now;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(retryAfterMs, 0),\n\t\t\tminuteRemaining: Math.max(minuteLimit - minuteCount, 0),\n\t\t\thourRemaining: 0,\n\t\t};\n\t}\n\n\tentry.minute.timestamps.push(now);\n\tentry.hour.timestamps.push(now);\n\n\treturn {\n\t\tallowed: true,\n\t\tminuteRemaining: minuteLimit - minuteCount - 1,\n\t\thourRemaining: hourLimit - hourCount - 1,\n\t};\n}\n\nexport function checkToolDailyRateLimitInMemory(principalId: string, toolName: string, limit: number): ToolDailyRateLimitResult {\n\tconst now = Date.now();\n\tcleanupExpiredEntries(now);\n\n\tconst key = `${principalId}:${toolName.trim().toLowerCase()}`;\n\tconst entry = getOrCreateToolDailyEntry(key);\n\tentry.timestamps = pruneTimestamps(entry.timestamps, DAY_MS, now);\n\n\tconst count = entry.timestamps.length;\n\tif (count >= limit) {\n\t\tconst oldestInWindow = entry.timestamps[0];\n\t\tconst retryAfterMs = oldestInWindow + DAY_MS - now;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(retryAfterMs, 0),\n\t\t\tremaining: 0,\n\t\t\tlimit,\n\t\t};\n\t}\n\n\tentry.timestamps.push(now);\n\treturn {\n\t\tallowed: true,\n\t\tremaining: Math.max(limit - entry.timestamps.length, 0),\n\t\tlimit,\n\t};\n}\n\nexport function resetRateLimit(ip: string): void {\n\tRATE_LIMIT_ENTRIES.delete(buildScopedEntryKey(ip, 'tools'));\n\tRATE_LIMIT_ENTRIES.delete(buildScopedEntryKey(ip, 'control'));\n}\n\nexport function resetAllRateLimits(): void {\n\tRATE_LIMIT_ENTRIES.clear();\n\tTOOL_DAILY_ENTRIES.clear();\n\tlastCleanup = Date.now();\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { DurableObject } from 'cloudflare:workers';\n\nconst COORDINATOR_NAME = 'global-quota-coordinator';\nconst CLEANUP_ALARM_INTERVAL_MS = 15 * 60 * 1000;\nconst KEY_PREFIX = 'quota:';\n\ntype ScopedQuotaScope = 'tools' | 'control';\n\ninterface CounterRecord {\n\tcount: number;\n\texpiresAt: number;\n}\n\ninterface RateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tminuteRemaining: number;\n\thourRemaining: number;\n}\n\ninterface ToolDailyRateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n\tlimit: number;\n}\n\ninterface GlobalRateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n\tlimit: number;\n}\n\ninterface SessionCreateRateResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n}\n\ntype QuotaCoordinatorRequest =\n\t| {\n\t\t\tkind: 'scoped-rate';\n\t\t\tscope: ScopedQuotaScope;\n\t\t\tip: string;\n\t\t\tminuteLimit: number;\n\t\t\thourLimit: number;\n\t }\n\t| {\n\t\t\tkind: 'tool-daily';\n\t\t\tprincipalId: string;\n\t\t\ttoolName: string;\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tkind: 'global-daily';\n\t\t\tlimit: number;\n\t }\n\t| {\n\t\t\tkind: 'session-create';\n\t\t\tip: string;\n\t\t\tlimit: number;\n\t\t\twindowMs: number;\n\t }\n\t| {\n\t\t\tkind: 'reset';\n\t };\n\nfunction getCoordinatorStub(namespace: DurableObjectNamespace | undefined): DurableObjectStub | undefined {\n\tif (!namespace) return undefined;\n\treturn namespace.getByName(COORDINATOR_NAME);\n}\n\nasync function callCoordinator<T>(\n\tnamespace: DurableObjectNamespace | undefined,\n\tpayload: QuotaCoordinatorRequest,\n): Promise<T | undefined> {\n\tconst stub = getCoordinatorStub(namespace);\n\tif (!stub) return undefined;\n\n\tconst response = await stub.fetch('https://quota.internal/', {\n\t\tmethod: 'POST',\n\t\theaders: { 'content-type': 'application/json' },\n\t\tbody: JSON.stringify(payload),\n\t});\n\n\tif (!response.ok) {\n\t\tthrow new Error(`Quota coordinator returned HTTP ${response.status}`);\n\t}\n\n\tif (payload.kind === 'reset') {\n\t\treturn undefined;\n\t}\n\n\treturn (await response.json()) as T; // response shape matches the generic T per handler contract\n}\n\nexport async function checkScopedRateLimitWithCoordinator(\n\tip: string,\n\tscope: ScopedQuotaScope,\n\tminuteLimit: number,\n\thourLimit: number,\n\tnamespace?: DurableObjectNamespace,\n): Promise<RateLimitResult | undefined> {\n\treturn callCoordinator<RateLimitResult>(namespace, {\n\t\tkind: 'scoped-rate',\n\t\tscope,\n\t\tip,\n\t\tminuteLimit,\n\t\thourLimit,\n\t});\n}\n\nexport async function checkToolDailyRateLimitWithCoordinator(\n\tprincipalId: string,\n\ttoolName: string,\n\tlimit: number,\n\tnamespace?: DurableObjectNamespace,\n): Promise<ToolDailyRateLimitResult | undefined> {\n\treturn callCoordinator<ToolDailyRateLimitResult>(namespace, {\n\t\tkind: 'tool-daily',\n\t\tprincipalId,\n\t\ttoolName,\n\t\tlimit,\n\t});\n}\n\nexport async function checkGlobalDailyLimitWithCoordinator(\n\tlimit: number,\n\tnamespace?: DurableObjectNamespace,\n): Promise<GlobalRateLimitResult | undefined> {\n\treturn callCoordinator<GlobalRateLimitResult>(namespace, {\n\t\tkind: 'global-daily',\n\t\tlimit,\n\t});\n}\n\nexport async function checkSessionCreateRateLimitWithCoordinator(\n\tip: string,\n\tlimit: number,\n\twindowMs: number,\n\tnamespace?: DurableObjectNamespace,\n): Promise<SessionCreateRateResult | undefined> {\n\treturn callCoordinator<SessionCreateRateResult>(namespace, {\n\t\tkind: 'session-create',\n\t\tip,\n\t\tlimit,\n\t\twindowMs,\n\t});\n}\n\nexport async function resetQuotaCoordinatorState(namespace?: DurableObjectNamespace): Promise<void> {\n\tawait callCoordinator(namespace, { kind: 'reset' });\n}\n\nfunction normalizeRecord(record: unknown, now: number): CounterRecord | undefined {\n\tif (!record || typeof record !== 'object') return undefined;\n\tconst candidate = record as Partial<CounterRecord>; // typeof record === 'object' checked above; fields validated below\n\tif (typeof candidate.count !== 'number' || typeof candidate.expiresAt !== 'number') return undefined;\n\tif (candidate.expiresAt <= now) return undefined;\n\treturn { count: candidate.count, expiresAt: candidate.expiresAt };\n}\n\nfunction minuteWindowEnd(now: number): number {\n\treturn (Math.floor(now / 60_000) + 1) * 60_000;\n}\n\nfunction hourWindowEnd(now: number): number {\n\treturn (Math.floor(now / 3_600_000) + 1) * 3_600_000;\n}\n\nfunction dayWindowEnd(now: number): number {\n\treturn (Math.floor(now / 86_400_000) + 1) * 86_400_000;\n}\n\nfunction scopedMinuteKey(scope: ScopedQuotaScope, ip: string, now: number): string {\n\tconst prefix = scope === 'tools' ? 'tools:min' : 'control:min';\n\treturn `${KEY_PREFIX}${prefix}:${ip}:${Math.floor(now / 60_000)}`;\n}\n\nfunction scopedHourKey(scope: ScopedQuotaScope, ip: string, now: number): string {\n\tconst prefix = scope === 'tools' ? 'tools:hr' : 'control:hr';\n\treturn `${KEY_PREFIX}${prefix}:${ip}:${Math.floor(now / 3_600_000)}`;\n}\n\nfunction toolDailyKey(principalId: string, toolName: string, now: number): string {\n\treturn `${KEY_PREFIX}tool:day:${toolName.trim().toLowerCase()}:${principalId}:${Math.floor(now / 86_400_000)}`;\n}\n\nfunction globalDailyKey(now: number): string {\n\treturn `${KEY_PREFIX}global:day:${Math.floor(now / 86_400_000)}`;\n}\n\nfunction sessionCreateKey(ip: string, windowMs: number, now: number): string {\n\treturn `${KEY_PREFIX}session:create:${ip}:${Math.floor(now / windowMs)}`;\n}\n\nconst VALID_KINDS = new Set<string>(['scoped-rate', 'tool-daily', 'global-daily', 'session-create', 'reset']);\n\n/** Validate a raw JSON payload against the QuotaCoordinatorRequest discriminated union */\nexport function validateQuotaPayload(\n\traw: unknown,\n): { valid: true; payload: QuotaCoordinatorRequest } | { valid: false; error: string } {\n\tif (!raw || typeof raw !== 'object' || !('kind' in raw)) {\n\t\treturn { valid: false, error: 'Invalid payload: missing kind' };\n\t}\n\n\tconst { kind } = raw as { kind: unknown }; // safe: 'kind' in raw is checked above\n\tif (typeof kind !== 'string' || !VALID_KINDS.has(kind)) {\n\t\treturn { valid: false, error: `Invalid payload: unknown kind \"${String(kind)}\"` };\n\t}\n\n\t// Validate string field lengths to prevent storage exhaustion\n\tconst obj = raw as Record<string, unknown>;\n\tif ('ip' in obj && (typeof obj.ip !== 'string' || obj.ip.length > 50)) {\n\t\treturn { valid: false, error: 'Invalid ip: must be string <= 50 chars' };\n\t}\n\tif ('principalId' in obj && (typeof obj.principalId !== 'string' || obj.principalId.length > 100)) {\n\t\treturn { valid: false, error: 'Invalid principalId: must be string <= 100 chars' };\n\t}\n\tif ('scope' in obj && (typeof obj.scope !== 'string' || obj.scope.length > 30)) {\n\t\treturn { valid: false, error: 'Invalid scope' };\n\t}\n\n\t// Validate numeric fields to prevent NaN/Infinity propagation\n\tfor (const numField of ['minuteLimit', 'hourLimit', 'limit', 'windowMs'] as const) {\n\t\tif (numField in obj) {\n\t\t\tconst val = obj[numField];\n\t\t\tif (typeof val !== 'number' || !Number.isFinite(val) || val < 0) {\n\t\t\t\treturn { valid: false, error: `Invalid ${numField}: must be a non-negative finite number` };\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { valid: true, payload: raw as QuotaCoordinatorRequest };\n}\n\nexport class QuotaCoordinator extends DurableObject<Env> {\n\tprivate async ensureCleanupAlarm(): Promise<void> {\n\t\tconst currentAlarm = await this.ctx.storage.getAlarm();\n\t\tif (currentAlarm !== null) return;\n\t\tawait this.ctx.storage.setAlarm(Date.now() + CLEANUP_ALARM_INTERVAL_MS);\n\t}\n\n\tprivate async getCounter(txn: DurableObjectTransaction, key: string, now: number): Promise<CounterRecord | undefined> {\n\t\tconst record = normalizeRecord(await txn.get<CounterRecord>(key), now);\n\t\tif (!record) {\n\t\t\tawait txn.delete(key);\n\t\t}\n\t\treturn record;\n\t}\n\n\tprivate async handleScopedRateLimit(payload: Extract<QuotaCoordinatorRequest, { kind: 'scoped-rate' }>): Promise<RateLimitResult> {\n\t\tconst now = Date.now();\n\t\tconst minuteKey = scopedMinuteKey(payload.scope, payload.ip, now);\n\t\tconst hourKey = scopedHourKey(payload.scope, payload.ip, now);\n\n\t\tconst result = await this.ctx.storage.transaction(async (txn: DurableObjectTransaction) => {\n\t\t\tconst [minuteRecord, hourRecord] = await Promise.all([\n\t\t\t\tthis.getCounter(txn, minuteKey, now),\n\t\t\t\tthis.getCounter(txn, hourKey, now),\n\t\t\t]);\n\t\t\tconst minuteCount = minuteRecord?.count ?? 0;\n\t\t\tconst hourCount = hourRecord?.count ?? 0;\n\n\t\t\tif (minuteCount >= payload.minuteLimit) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(minuteWindowEnd(now) - now, 0),\n\t\t\t\t\tminuteRemaining: 0,\n\t\t\t\t\thourRemaining: Math.max(payload.hourLimit - hourCount, 0),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (hourCount >= payload.hourLimit) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(hourWindowEnd(now) - now, 0),\n\t\t\t\t\tminuteRemaining: Math.max(payload.minuteLimit - minuteCount, 0),\n\t\t\t\t\thourRemaining: 0,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst newMinute = minuteCount + 1;\n\t\t\tconst newHour = hourCount + 1;\n\t\t\tawait txn.put({\n\t\t\t\t[minuteKey]: { count: newMinute, expiresAt: minuteWindowEnd(now) },\n\t\t\t\t[hourKey]: { count: newHour, expiresAt: hourWindowEnd(now) },\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tallowed: true,\n\t\t\t\tminuteRemaining: payload.minuteLimit - newMinute,\n\t\t\t\thourRemaining: payload.hourLimit - newHour,\n\t\t\t};\n\t\t});\n\n\t\tawait this.ensureCleanupAlarm();\n\t\treturn result;\n\t}\n\n\tprivate async handleToolDailyRateLimit(\n\t\tpayload: Extract<QuotaCoordinatorRequest, { kind: 'tool-daily' }>,\n\t): Promise<ToolDailyRateLimitResult> {\n\t\tconst now = Date.now();\n\t\tconst key = toolDailyKey(payload.principalId, payload.toolName, now);\n\n\t\tconst result = await this.ctx.storage.transaction(async (txn: DurableObjectTransaction) => {\n\t\t\tconst record = await this.getCounter(txn, key, now);\n\t\t\tconst currentCount = record?.count ?? 0;\n\n\t\t\tif (currentCount >= payload.limit) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(dayWindowEnd(now) - now, 0),\n\t\t\t\t\tremaining: 0,\n\t\t\t\t\tlimit: payload.limit,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextCount = currentCount + 1;\n\t\t\tawait txn.put(key, { count: nextCount, expiresAt: dayWindowEnd(now) });\n\n\t\t\treturn {\n\t\t\t\tallowed: true,\n\t\t\t\tremaining: Math.max(payload.limit - nextCount, 0),\n\t\t\t\tlimit: payload.limit,\n\t\t\t};\n\t\t});\n\n\t\tawait this.ensureCleanupAlarm();\n\t\treturn result;\n\t}\n\n\tprivate async handleGlobalDailyLimit(payload: Extract<QuotaCoordinatorRequest, { kind: 'global-daily' }>): Promise<GlobalRateLimitResult> {\n\t\tconst now = Date.now();\n\t\tconst key = globalDailyKey(now);\n\n\t\tconst result = await this.ctx.storage.transaction(async (txn: DurableObjectTransaction) => {\n\t\t\tconst record = await this.getCounter(txn, key, now);\n\t\t\tconst currentCount = record?.count ?? 0;\n\n\t\t\tif (currentCount >= payload.limit) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(dayWindowEnd(now) - now, 0),\n\t\t\t\t\tremaining: 0,\n\t\t\t\t\tlimit: payload.limit,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextCount = currentCount + 1;\n\t\t\tawait txn.put(key, { count: nextCount, expiresAt: dayWindowEnd(now) });\n\n\t\t\treturn {\n\t\t\t\tallowed: true,\n\t\t\t\tremaining: Math.max(payload.limit - nextCount, 0),\n\t\t\t\tlimit: payload.limit,\n\t\t\t};\n\t\t});\n\n\t\tawait this.ensureCleanupAlarm();\n\t\treturn result;\n\t}\n\n\tprivate async handleSessionCreate(payload: Extract<QuotaCoordinatorRequest, { kind: 'session-create' }>): Promise<SessionCreateRateResult> {\n\t\tconst now = Date.now();\n\t\tconst key = sessionCreateKey(payload.ip, payload.windowMs, now);\n\t\tconst windowEnd = (Math.floor(now / payload.windowMs) + 1) * payload.windowMs;\n\n\t\tconst result = await this.ctx.storage.transaction(async (txn: DurableObjectTransaction) => {\n\t\t\tconst record = await this.getCounter(txn, key, now);\n\t\t\tconst currentCount = record?.count ?? 0;\n\n\t\t\tif (currentCount >= payload.limit) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(windowEnd - now, 0),\n\t\t\t\t\tremaining: 0,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextCount = currentCount + 1;\n\t\t\tawait txn.put(key, { count: nextCount, expiresAt: windowEnd });\n\n\t\t\treturn {\n\t\t\t\tallowed: true,\n\t\t\t\tremaining: Math.max(payload.limit - nextCount, 0),\n\t\t\t};\n\t\t});\n\n\t\tawait this.ensureCleanupAlarm();\n\t\treturn result;\n\t}\n\n\tasync fetch(request: Request): Promise<Response> {\n\t\tif (request.method !== 'POST') {\n\t\t\treturn new Response('Method Not Allowed', { status: 405 });\n\t\t}\n\n\t\tconst raw: unknown = await request.json();\n\t\tconst validation = validateQuotaPayload(raw);\n\t\tif (!validation.valid) {\n\t\t\treturn new Response(validation.error, { status: 400 });\n\t\t}\n\n\t\tconst payload = validation.payload;\n\t\tswitch (payload.kind) {\n\t\t\tcase 'scoped-rate':\n\t\t\t\treturn Response.json(await this.handleScopedRateLimit(payload));\n\t\t\tcase 'tool-daily':\n\t\t\t\treturn Response.json(await this.handleToolDailyRateLimit(payload));\n\t\t\tcase 'global-daily':\n\t\t\t\treturn Response.json(await this.handleGlobalDailyLimit(payload));\n\t\t\tcase 'session-create':\n\t\t\t\treturn Response.json(await this.handleSessionCreate(payload));\n\t\t\tcase 'reset':\n\t\t\t\tawait this.ctx.storage.deleteAll();\n\t\t\t\tawait this.ctx.storage.deleteAlarm();\n\t\t\t\treturn new Response(null, { status: 204 });\n\t\t\tdefault:\n\t\t\t\t// Unreachable — validateQuotaPayload ensures kind is valid\n\t\t\t\treturn new Response('Invalid payload', { status: 400 });\n\t\t}\n\t}\n\n\tasync alarm(): Promise<void> {\n\t\tconst now = Date.now();\n\t\tconst records = await this.ctx.storage.list<CounterRecord>({ prefix: KEY_PREFIX });\n\t\tconst expiredKeys: string[] = [];\n\t\tfor (const [key, value] of records.entries()) {\n\t\t\tif (!normalizeRecord(value, now)) {\n\t\t\t\texpiredKeys.push(key);\n\t\t\t}\n\t\t}\n\t\tif (expiredKeys.length > 0) {\n\t\t\tawait this.ctx.storage.delete(expiredKeys);\n\t\t}\n\n\t\tif (records.size > expiredKeys.length) {\n\t\t\tawait this.ctx.storage.setAlarm(now + CLEANUP_ALARM_INTERVAL_MS);\n\t\t}\n\t}\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Rate limiter for the DNS Security MCP Server.\n * Enforces per-IP limits: 50 requests/minute, 300 requests/hour.\n * Also enforces a global daily cap across all IPs as a cost ceiling.\n *\n * Uses Cloudflare KV for distributed rate limiting when available,\n * with in-memory fallback when KV is not configured.\n *\n * KV strategy: fixed-window counters with expirationTtl for automatic cleanup.\n * Key format: rl:min:{ip}:{windowId} (minute), rl:hr:{ip}:{windowId} (hour)\n *\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nimport {\n\tcheckScopedRateLimitInMemory,\n\tcheckToolDailyRateLimitInMemory,\n\tpruneTimestamps,\n\tresetAllRateLimits,\n\tresetRateLimit,\n\ttype RateLimitScope,\n} from './rate-limiter-memory';\nimport {\n\tcheckGlobalDailyLimitWithCoordinator,\n\tcheckScopedRateLimitWithCoordinator,\n\tcheckToolDailyRateLimitWithCoordinator,\n} from './quota-coordinator';\n\nexport interface RateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tminuteRemaining: number;\n\thourRemaining: number;\n}\n\nexport interface ToolDailyRateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n\tlimit: number;\n}\n\nexport interface GlobalRateLimitResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n\tlimit: number;\n}\n\nconst MINUTE_LIMIT = 50;\nconst HOUR_LIMIT = 300;\nconst CONTROL_PLANE_MINUTE_LIMIT = 60;\nconst CONTROL_PLANE_HOUR_LIMIT = 600;\nconst MINUTE_MS = 60_000;\nconst HOUR_MS = 3_600_000;\nconst DAY_MS = 86_400_000;\n\n// Best-effort per-IP serialization for KV updates inside a single isolate.\n// This does not provide cross-isolate atomicity, but it prevents local races.\nconst KV_IP_LOCK_TAILS = new Map<string, Promise<void>>();\n\nfunction checkRateLimitInMemory(ip: string): RateLimitResult {\n\treturn checkScopedRateLimitInMemory(ip, 'tools', MINUTE_LIMIT, HOUR_LIMIT);\n}\n\nfunction checkControlPlaneRateLimitInMemory(ip: string): RateLimitResult {\n\treturn checkScopedRateLimitInMemory(ip, 'control', CONTROL_PLANE_MINUTE_LIMIT, CONTROL_PLANE_HOUR_LIMIT);\n}\n\n/** Parse a KV counter value, returning 0 for NaN/corrupt values. */\nfunction parseKvCounter(val: string | null): number {\n\tif (!val) return 0;\n\tconst n = parseInt(val, 10);\n\treturn Number.isFinite(n) && n >= 0 ? n : 0;\n}\n\n// ---------------------------------------------------------------------------\n// KV-backed rate limiting (fixed-window counters)\n// ---------------------------------------------------------------------------\n\nasync function checkScopedRateLimitKV(\n\tip: string,\n\tscope: RateLimitScope,\n\tminuteLimit: number,\n\thourLimit: number,\n\tkv: KVNamespace,\n): Promise<RateLimitResult> {\n\treturn withIpKvLock(ip, async () => {\n\tconst now = Date.now();\n\tconst minuteWindow = Math.floor(now / MINUTE_MS);\n\tconst hourWindow = Math.floor(now / HOUR_MS);\n\n\tconst minuteKey = scope === 'tools' ? `rl:min:${ip}:${minuteWindow}` : `rl:ctl:min:${ip}:${minuteWindow}`;\n\tconst hourKey = scope === 'tools' ? `rl:hr:${ip}:${hourWindow}` : `rl:ctl:hr:${ip}:${hourWindow}`;\n\n\t// Read both counters in parallel\n\tconst [minuteVal, hourVal] = await Promise.all([kv.get(minuteKey), kv.get(hourKey)]);\n\n\tconst minuteCount = parseKvCounter(minuteVal);\n\tconst hourCount = parseKvCounter(hourVal);\n\n\t// Check minute limit\n\tif (minuteCount >= minuteLimit) {\n\t\tconst windowEnd = (minuteWindow + 1) * MINUTE_MS;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(windowEnd - now, 0),\n\t\t\tminuteRemaining: 0,\n\t\t\thourRemaining: Math.max(hourLimit - hourCount, 0),\n\t\t};\n\t}\n\n\t// Check hour limit\n\tif (hourCount >= hourLimit) {\n\t\tconst windowEnd = (hourWindow + 1) * HOUR_MS;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(windowEnd - now, 0),\n\t\t\tminuteRemaining: Math.max(minuteLimit - minuteCount, 0),\n\t\t\thourRemaining: 0,\n\t\t};\n\t}\n\n\t// Allowed — increment both counters (write in parallel)\n\tconst newMinute = minuteCount + 1;\n\tconst newHour = hourCount + 1;\n\tawait Promise.all([\n\t\tkv.put(minuteKey, String(newMinute), { expirationTtl: 60 }),\n\t\tkv.put(hourKey, String(newHour), { expirationTtl: 3600 }),\n\t]);\n\n\treturn {\n\t\tallowed: true,\n\t\tminuteRemaining: minuteLimit - newMinute,\n\t\thourRemaining: hourLimit - newHour,\n\t};\n\t});\n}\n\nasync function checkRateLimitKV(ip: string, kv: KVNamespace): Promise<RateLimitResult> {\n\treturn checkScopedRateLimitKV(ip, 'tools', MINUTE_LIMIT, HOUR_LIMIT, kv);\n}\n\nasync function checkControlPlaneRateLimitKV(ip: string, kv: KVNamespace): Promise<RateLimitResult> {\n\treturn checkScopedRateLimitKV(ip, 'control', CONTROL_PLANE_MINUTE_LIMIT, CONTROL_PLANE_HOUR_LIMIT, kv);\n}\n\nasync function withIpKvLock<T>(ip: string, work: () => Promise<T>): Promise<T> {\n\tconst prevTail = KV_IP_LOCK_TAILS.get(ip) ?? Promise.resolve();\n\tlet release: (() => void) | undefined;\n\tconst current = new Promise<void>((resolve) => {\n\t\trelease = resolve;\n\t});\n\tconst tail = prevTail.then(() => current);\n\tKV_IP_LOCK_TAILS.set(ip, tail);\n\n\tawait prevTail;\n\ttry {\n\t\treturn await work();\n\t} finally {\n\t\trelease?.();\n\t\tif (KV_IP_LOCK_TAILS.get(ip) === tail) {\n\t\t\tKV_IP_LOCK_TAILS.delete(ip);\n\t\t}\n\t}\n}\n\nasync function checkToolDailyRateLimitKV(\n\tprincipalId: string,\n\ttoolName: string,\n\tlimit: number,\n\tkv: KVNamespace,\n): Promise<ToolDailyRateLimitResult> {\n\treturn withIpKvLock(`tool:${principalId}:${toolName}`, async () => {\n\t\tconst now = Date.now();\n\t\tconst dayWindow = Math.floor(now / DAY_MS);\n\t\tconst toolKey = toolName.trim().toLowerCase();\n\t\tconst key = `rl:day:tool:${toolKey}:${principalId}:${dayWindow}`;\n\n\t\tconst currentVal = await kv.get(key);\n\t\tconst currentCount = parseKvCounter(currentVal);\n\n\t\tif (currentCount >= limit) {\n\t\t\tconst windowEnd = (dayWindow + 1) * DAY_MS;\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\tretryAfterMs: Math.max(windowEnd - now, 0),\n\t\t\t\tremaining: 0,\n\t\t\t\tlimit,\n\t\t\t};\n\t\t}\n\n\t\tconst nextCount = currentCount + 1;\n\t\tawait kv.put(key, String(nextCount), { expirationTtl: 86_400 });\n\n\t\treturn {\n\t\t\tallowed: true,\n\t\t\tremaining: Math.max(limit - nextCount, 0),\n\t\t\tlimit,\n\t\t};\n\t});\n}\n\n// ---------------------------------------------------------------------------\n// Global daily cap (cost ceiling across all IPs)\n// ---------------------------------------------------------------------------\n\nlet globalDayWindow = 0;\nlet globalDayCount = 0;\n\nfunction checkGlobalDailyLimitInMemory(limit: number): GlobalRateLimitResult {\n\tconst now = Date.now();\n\tconst currentWindow = Math.floor(now / DAY_MS);\n\tif (currentWindow !== globalDayWindow) {\n\t\tglobalDayWindow = currentWindow;\n\t\tglobalDayCount = 0;\n\t}\n\tif (globalDayCount >= limit) {\n\t\tconst windowEnd = (currentWindow + 1) * DAY_MS;\n\t\treturn { allowed: false, retryAfterMs: Math.max(windowEnd - now, 0), remaining: 0, limit };\n\t}\n\tglobalDayCount++;\n\treturn { allowed: true, remaining: Math.max(limit - globalDayCount, 0), limit };\n}\n\nasync function checkGlobalDailyLimitKV(limit: number, kv: KVNamespace): Promise<GlobalRateLimitResult> {\n\tconst now = Date.now();\n\tconst currentWindow = Math.floor(now / DAY_MS);\n\tconst key = `rl:global:day:${currentWindow}`;\n\n\tconst currentVal = await kv.get(key);\n\tconst currentCount = parseKvCounter(currentVal);\n\n\tif (currentCount >= limit) {\n\t\tconst windowEnd = (currentWindow + 1) * DAY_MS;\n\t\treturn { allowed: false, retryAfterMs: Math.max(windowEnd - now, 0), remaining: 0, limit };\n\t}\n\n\tconst nextCount = currentCount + 1;\n\tawait kv.put(key, String(nextCount), { expirationTtl: 86_400 });\n\n\treturn { allowed: true, remaining: Math.max(limit - nextCount, 0), limit };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Check if a request from the given IP is allowed under rate limits.\n * If allowed, the request is counted. If not, returns retry-after info.\n *\n * @param ip - Client IP address\n * @param kv - Optional KV namespace for distributed rate limiting.\n * Falls back to in-memory when not provided or on KV errors.\n */\nexport async function checkRateLimit(ip: string, kv?: KVNamespace, quotaCoordinator?: DurableObjectNamespace): Promise<RateLimitResult> {\n\tif (quotaCoordinator) {\n\t\ttry {\n\t\t\tconst coordinated = await checkScopedRateLimitWithCoordinator(ip, 'tools', MINUTE_LIMIT, HOUR_LIMIT, quotaCoordinator);\n\t\t\tif (coordinated) return coordinated;\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] quota coordinator error, falling back to KV/in-memory');\n\t\t}\n\t}\n if (kv) {\n\t try {\n\t\t return await checkRateLimitKV(ip, kv);\n\t } catch {\n\t\t // KV error — log warning and fall back to in-memory\n\t\t console.warn('[rate-limiter] KV error, falling back to in-memory');\n\t }\n }\n return checkRateLimitInMemory(ip);\n}\n\n/**\n * Check if a request from the given IP is allowed under lower-cost control-plane limits.\n * Uses KV when available, with in-memory fallback on failure.\n */\nexport async function checkControlPlaneRateLimit(\n\tip: string,\n\tkv?: KVNamespace,\n\tquotaCoordinator?: DurableObjectNamespace,\n): Promise<RateLimitResult> {\n\tif (quotaCoordinator) {\n\t\ttry {\n\t\t\tconst coordinated = await checkScopedRateLimitWithCoordinator(ip, 'control', CONTROL_PLANE_MINUTE_LIMIT, CONTROL_PLANE_HOUR_LIMIT, quotaCoordinator);\n\t\t\tif (coordinated) return coordinated;\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] quota coordinator control-plane error, falling back to KV/in-memory');\n\t\t}\n\t}\n\tif (kv) {\n\t\ttry {\n\t\t\treturn await checkControlPlaneRateLimitKV(ip, kv);\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] KV control-plane error, falling back to in-memory');\n\t\t}\n\t}\n\treturn checkControlPlaneRateLimitInMemory(ip);\n}\n\n/**\n * Check a per-principal daily quota for a specific tool.\n * Uses KV when available, with in-memory fallback on failure.\n */\nexport async function checkToolDailyRateLimit(\n\tprincipalId: string,\n\ttoolName: string,\n\tlimit: number,\n\tkv?: KVNamespace,\n\tquotaCoordinator?: DurableObjectNamespace,\n): Promise<ToolDailyRateLimitResult> {\n\tif (quotaCoordinator) {\n\t\ttry {\n\t\t\tconst coordinated = await checkToolDailyRateLimitWithCoordinator(principalId, toolName, limit, quotaCoordinator);\n\t\t\tif (coordinated) return coordinated;\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] quota coordinator tool quota error, falling back to KV/in-memory');\n\t\t}\n\t}\n\tif (kv) {\n\t\ttry {\n\t\t\treturn await checkToolDailyRateLimitKV(principalId, toolName, limit, kv);\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] KV tool quota error, falling back to in-memory');\n\t\t}\n\t}\n\treturn checkToolDailyRateLimitInMemory(principalId, toolName, limit);\n}\n\n/**\n * Check if the global daily tool call budget has been exhausted.\n * Uses KV when available, with in-memory fallback on failure.\n */\nexport async function checkGlobalDailyLimit(\n\tlimit: number,\n\tkv?: KVNamespace,\n\tquotaCoordinator?: DurableObjectNamespace,\n): Promise<GlobalRateLimitResult> {\n\tif (quotaCoordinator) {\n\t\ttry {\n\t\t\tconst coordinated = await checkGlobalDailyLimitWithCoordinator(limit, quotaCoordinator);\n\t\t\tif (coordinated) return coordinated;\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] quota coordinator global cap error, falling back to KV/in-memory');\n\t\t}\n\t}\n\tif (kv) {\n\t\ttry {\n\t\t\treturn await checkGlobalDailyLimitKV(limit, kv);\n\t\t} catch {\n\t\t\tconsole.warn('[rate-limiter] KV global cap error, falling back to in-memory');\n\t\t}\n\t}\n\treturn checkGlobalDailyLimitInMemory(limit);\n}\n\n/**\n * Reset rate limit state for an IP (useful for testing).\n * @internal Exported for test use only.\n */\nexport { pruneTimestamps, resetRateLimit, resetAllRateLimits };\n\n/** @internal Reset global daily counter (test use only). */\nexport function resetGlobalDailyLimit(): void {\n\tglobalDayWindow = 0;\n\tglobalDayCount = 0;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Structured logging utility for Cloudflare Worker (MCP server)\n * Logs JSON objects with request, tool, result, and error metadata\n * Usage: logEvent({ ... })\n */\n\nexport type LogEvent = {\n\ttimestamp: string;\n\trequestId?: string;\n\tip?: string;\n\ttool?: string;\n\tdomain?: string;\n\tseverity?: 'info' | 'warn' | 'error';\n\tcategory?: string;\n\tresult?: string;\n\tdetails?: unknown;\n\terror?: string;\n\tdurationMs?: number;\n\tuserAgent?: string;\n};\n\nconst REDACTED = '[redacted]';\nconst MAX_LOG_STRING_LENGTH = 256;\nconst SENSITIVE_KEY_PATTERN = /(authorization|mcp-session-id|session|token|api[-_]?key|secret|password|cookie|rawbody)/i;\n\nfunction isSensitiveKey(key: string): boolean {\n\treturn !/^has[A-Z]/.test(key) && SENSITIVE_KEY_PATTERN.test(key);\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction sanitizeString(value: string): string {\n\treturn value.length > MAX_LOG_STRING_LENGTH ? `${value.slice(0, MAX_LOG_STRING_LENGTH)}...` : value;\n}\n\nexport function sanitizeLogValue(value: unknown, key?: string): unknown {\n\tif (key && isSensitiveKey(key)) {\n\t\treturn REDACTED;\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn sanitizeString(value);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item) => sanitizeLogValue(item));\n\t}\n\n\tif (isPlainObject(value)) {\n\t\tconst sanitized: Record<string, unknown> = {};\n\t\tfor (const [entryKey, entryValue] of Object.entries(value)) {\n\t\t\tsanitized[entryKey] = sanitizeLogValue(entryValue, entryKey);\n\t\t}\n\t\treturn sanitized;\n\t}\n\n\treturn value;\n}\n\nexport function sanitizeHeadersForLog(headers: Headers | Record<string, string>): Record<string, string> {\n\tconst sanitized: Record<string, string> = {};\n\tif (headers instanceof Headers) {\n\t\theaders.forEach((value, rawKey) => {\n\t\t\tconst key = rawKey.toLowerCase();\n\t\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t\t});\n\t\treturn sanitized;\n\t}\n\n\tfor (const [rawKey, value] of Object.entries(headers)) {\n\t\tconst key = rawKey.toLowerCase();\n\t\tsanitized[key] = isSensitiveKey(key) ? REDACTED : sanitizeString(value);\n\t}\n\treturn sanitized;\n}\n\n/**\n * Emit a structured log event (console.log as JSON)\n */\nexport function logEvent(event: LogEvent): void {\n\tconst log = {\n\t\t...event,\n\t\ttimestamp: event.timestamp || new Date().toISOString(),\n\t\tdetails: sanitizeLogValue(event.details),\n\t\terror: typeof event.error === 'string' ? sanitizeString(event.error) : event.error,\n\t};\n\tconsole.log(JSON.stringify(log));\n}\n\n/**\n * Helper for error logging\n */\nexport function logError(error: Error | string, context?: Partial<LogEvent>): void {\n\tlogEvent({\n\t\ttimestamp: new Date().toISOString(),\n\t\tseverity: 'error',\n\t\terror: typeof error === 'string' ? error : error.message,\n\t\t...context,\n\t});\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { pruneTimestamps } from './rate-limiter';\n\nexport interface SessionRecord {\n\tcreatedAt: number;\n\tlastAccessedAt: number;\n}\n\nexport interface SessionCreateRateResult {\n\tallowed: boolean;\n\tretryAfterMs?: number;\n\tremaining: number;\n}\n\n/** Active sessions keyed by session ID */\nexport const ACTIVE_SESSIONS = new Map<string, SessionRecord>();\n\n/** Session idle TTL (30 minutes) */\nexport const SESSION_TTL_MS = 30 * 60 * 1000;\nexport const SESSION_REFRESH_INTERVAL_MS = 5 * 60 * 1000;\n\nconst SESSION_CREATE_WINDOW_MS = 60_000;\nconst SESSION_CREATE_LIMIT_PER_MINUTE = 30;\nconst MAX_IN_MEMORY_SESSIONS = 2000;\nconst SESSION_CLEANUP_INTERVAL_MS = 5 * 60 * 1000;\n\nlet lastCleanupAt = 0;\nconst SESSION_CREATE_BY_IP = new Map<string, number[]>();\n\nfunction isExpired(lastAccessedAt: number, now: number): boolean {\n\treturn now - lastAccessedAt > SESSION_TTL_MS;\n}\n\nfunction maybeCleanupSessions(now: number): void {\n\tif (now - lastCleanupAt < SESSION_CLEANUP_INTERVAL_MS) return;\n\tlastCleanupAt = now;\n\n\tfor (const [id, session] of ACTIVE_SESSIONS.entries()) {\n\t\tif (isExpired(session.lastAccessedAt, now)) {\n\t\t\tACTIVE_SESSIONS.delete(id);\n\t\t}\n\t}\n}\n\nfunction evictLeastRecentlyUsedSession(): void {\n\tlet oldestId: string | undefined;\n\tlet oldestAccess = Number.POSITIVE_INFINITY;\n\n\tfor (const [id, session] of ACTIVE_SESSIONS.entries()) {\n\t\tif (session.lastAccessedAt < oldestAccess) {\n\t\t\toldestAccess = session.lastAccessedAt;\n\t\t\toldestId = id;\n\t\t}\n\t}\n\n\tif (oldestId) {\n\t\tACTIVE_SESSIONS.delete(oldestId);\n\t}\n}\n\nexport function checkSessionCreateRateLimitInMemory(ip: string): SessionCreateRateResult {\n\tconst now = Date.now();\n\tconst key = ip || 'unknown';\n\tconst existing = SESSION_CREATE_BY_IP.get(key) ?? [];\n\tconst recent = pruneTimestamps(existing, SESSION_CREATE_WINDOW_MS, now);\n\n\tif (recent.length >= SESSION_CREATE_LIMIT_PER_MINUTE) {\n\t\tconst oldest = recent[0];\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tretryAfterMs: Math.max(oldest + SESSION_CREATE_WINDOW_MS - now, 0),\n\t\t\tremaining: 0,\n\t\t};\n\t}\n\n\trecent.push(now);\n\tSESSION_CREATE_BY_IP.set(key, recent);\n\treturn {\n\t\tallowed: true,\n\t\tremaining: SESSION_CREATE_LIMIT_PER_MINUTE - recent.length,\n\t};\n}\n\nexport function createSessionInMemory(id: string): void {\n\tconst now = Date.now();\n\tconst record: SessionRecord = { createdAt: now, lastAccessedAt: now };\n\tACTIVE_SESSIONS.set(id, record);\n\tmaybeCleanupSessions(now);\n\tif (ACTIVE_SESSIONS.size > MAX_IN_MEMORY_SESSIONS) {\n\t\tevictLeastRecentlyUsedSession();\n\t}\n}\n\nexport function validateSessionInMemory(id: string): boolean {\n\tconst now = Date.now();\n\tmaybeCleanupSessions(now);\n\n\tconst session = ACTIVE_SESSIONS.get(id);\n\tif (!session) return false;\n\n\tif (isExpired(session.lastAccessedAt, now)) {\n\t\tACTIVE_SESSIONS.delete(id);\n\t\treturn false;\n\t}\n\n\tif (now - session.lastAccessedAt >= SESSION_REFRESH_INTERVAL_MS) {\n\t\tsession.lastAccessedAt = now;\n\t}\n\treturn true;\n}\n\nexport function deleteSessionInMemory(id: string): boolean {\n\treturn ACTIVE_SESSIONS.delete(id);\n}\n\nexport function resetSessions(): void {\n\tACTIVE_SESSIONS.clear();\n\tSESSION_CREATE_BY_IP.clear();\n\tlastCleanupAt = 0;\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Session Management\n *\n * KV-backed (when configured) or in-memory (fallback) session store.\n * Sessions are created\n * on `initialize`, refreshed on successful validation, and removed\n * on `DELETE /mcp` or when expired.\n */\n\nimport {\n\tACTIVE_SESSIONS,\n\tcheckSessionCreateRateLimitInMemory,\n\tcreateSessionInMemory,\n\tdeleteSessionInMemory,\n\tresetSessions,\n\tSESSION_REFRESH_INTERVAL_MS,\n\tSESSION_TTL_MS,\n\ttype SessionCreateRateResult,\n\ttype SessionRecord,\n\tvalidateSessionInMemory,\n} from './session-memory';\nimport { checkSessionCreateRateLimitWithCoordinator } from './quota-coordinator';\n\nexport { ACTIVE_SESSIONS, resetSessions, SESSION_REFRESH_INTERVAL_MS, SESSION_TTL_MS };\n\nconst SESSION_TTL_SECONDS = Math.ceil(SESSION_TTL_MS / 1000);\nconst SESSION_CREATE_WINDOW_MS = 60_000;\nconst SESSION_CREATE_LIMIT_PER_MINUTE = 30;\n\nconst SESSION_KEY_PREFIX = 'session:';\nconst SESSION_CREATE_RATE_KEY_PREFIX = 'rl:session-create';\n\n/** Cleanup cadence for lazy background pruning (5 minutes) */\nfunction sessionKey(id: string): string {\n\treturn `${SESSION_KEY_PREFIX}${id}`;\n}\n\nexport async function checkSessionCreateRateLimit(\n\tip: string,\n\tkv?: KVNamespace,\n\tquotaCoordinator?: DurableObjectNamespace,\n): Promise<SessionCreateRateResult> {\n\tif (quotaCoordinator) {\n\t\ttry {\n\t\t\tconst coordinated = await checkSessionCreateRateLimitWithCoordinator(\n\t\t\t\tip,\n\t\t\t\tSESSION_CREATE_LIMIT_PER_MINUTE,\n\t\t\t\tSESSION_CREATE_WINDOW_MS,\n\t\t\t\tquotaCoordinator,\n\t\t\t);\n\t\t\tif (coordinated) return coordinated;\n\t\t} catch {\n\t\t\tconsole.warn('[session] quota coordinator create limiter failed, falling back to KV/in-memory');\n\t\t}\n\t}\n\tif (kv) {\n\t\ttry {\n\t\t\tconst now = Date.now();\n\t\t\tconst keyIp = ip || 'unknown';\n\t\t\tconst minuteWindow = Math.floor(now / SESSION_CREATE_WINDOW_MS);\n\t\t\tconst key = `${SESSION_CREATE_RATE_KEY_PREFIX}:${keyIp}:${minuteWindow}`;\n\t\t\tconst currentVal = await kv.get(key);\n\t\t\tconst parsed = currentVal ? parseInt(currentVal, 10) : 0;\n\t\t\tconst currentCount = Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n\n\t\t\tif (currentCount >= SESSION_CREATE_LIMIT_PER_MINUTE) {\n\t\t\t\tconst windowEnd = (minuteWindow + 1) * SESSION_CREATE_WINDOW_MS;\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tretryAfterMs: Math.max(windowEnd - now, 0),\n\t\t\t\t\tremaining: 0,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst nextCount = currentCount + 1;\n\t\t\tawait kv.put(key, String(nextCount), { expirationTtl: 60 });\n\t\t\treturn {\n\t\t\t\tallowed: true,\n\t\t\t\tremaining: SESSION_CREATE_LIMIT_PER_MINUTE - nextCount,\n\t\t\t};\n\t\t} catch {\n\t\t\tconsole.warn('[session] KV create limiter failed, falling back to in-memory');\n\t\t}\n\t}\n\n\treturn checkSessionCreateRateLimitInMemory(ip);\n}\n\nasync function createSessionKVRecord(id: string, kv: KVNamespace, record: SessionRecord): Promise<void> {\n\tawait kv.put(sessionKey(id), JSON.stringify(record), { expirationTtl: SESSION_TTL_SECONDS });\n}\n\nasync function readSessionKVRecord(id: string, kv: KVNamespace): Promise<SessionRecord | undefined> {\n\tconst record = await kv.get(sessionKey(id), 'json');\n\tif (!record || typeof record !== 'object') return undefined;\n\n\tconst candidate = record as Partial<SessionRecord>; // KV returns unknown; fields are validated below\n\tif (typeof candidate.createdAt !== 'number' || typeof candidate.lastAccessedAt !== 'number') {\n\t\treturn undefined;\n\t}\n\n\treturn {\n\t\tcreatedAt: candidate.createdAt,\n\t\tlastAccessedAt: candidate.lastAccessedAt,\n\t};\n}\n\n/** Generate a cryptographically secure session ID (hex, visible ASCII) */\nexport function generateSessionId(): string {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n}\n\n/** Create a new session and return its ID */\nexport async function createSession(kv?: KVNamespace): Promise<string> {\n\tconst id = generateSessionId();\n\tconst now = Date.now();\n\tconst record: SessionRecord = { createdAt: now, lastAccessedAt: now };\n\n\tif (kv) {\n\t\ttry {\n\t\t\tawait createSessionKVRecord(id, kv, record);\n\t\t\treturn id;\n\t\t} catch {\n\t\t\tconsole.warn('[session] KV create failed, falling back to in-memory');\n\t\t}\n\t}\n\n\tcreateSessionInMemory(id);\n\treturn id;\n}\n\n/** Check whether a session ID exists in the active sessions store */\nexport async function validateSession(id: string, kv?: KVNamespace): Promise<boolean> {\n\tif (kv) {\n\t\ttry {\n\t\t\tconst now = Date.now();\n\t\t\tconst record = await readSessionKVRecord(id, kv);\n\t\t\tif (!record) return false;\n\n\t\t\tif (now - record.lastAccessedAt > SESSION_TTL_MS) {\n\t\t\t\tawait kv.delete(sessionKey(id));\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (now - record.lastAccessedAt >= SESSION_REFRESH_INTERVAL_MS) {\n\t\t\t\trecord.lastAccessedAt = now;\n\t\t\t\ttry {\n\t\t\t\t\tawait createSessionKVRecord(id, kv, record);\n\t\t\t\t} catch {\n\t\t\t\t\t// Session is valid — refresh write failure is non-fatal\n\t\t\t\t\tconsole.warn('[session] KV refresh write failed (session still valid)');\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tconsole.warn('[session] KV validate failed, falling back to in-memory');\n\t\t}\n\t}\n\n\treturn validateSessionInMemory(id);\n}\n\n/** Remove a session from the store. Returns true if the session existed. */\nexport async function deleteSession(id: string, kv?: KVNamespace): Promise<boolean> {\n\tif (kv) {\n\t\ttry {\n\t\t\tconst existing = await readSessionKVRecord(id, kv);\n\t\t\tif (!existing) return false;\n\t\t\tawait kv.delete(sessionKey(id));\n\t\t\treturn true;\n\t\t} catch {\n\t\t\tconsole.warn('[session] KV delete failed, falling back to in-memory');\n\t\t}\n\t}\n\n\treturn deleteSessionInMemory(id);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSE Transport Helpers\n *\n * Utilities for Server-Sent Events (SSE) formatting used by the\n * MCP Streamable HTTP transport layer.\n */\n\nimport { sanitizeErrorMessage } from './json-rpc';\n\n/** Format a JSON-RPC message as an SSE `message` event */\nexport function sseEvent(data: unknown, eventId?: string): string {\n\tlet event = '';\n\tif (eventId) {\n\t\tevent += `id: ${eventId}\\n`;\n\t}\n\tevent += `event: message\\ndata: ${JSON.stringify(data)}\\n\\n`;\n\treturn event;\n}\n\n/** Check whether the Accept header includes text/event-stream */\nexport function acceptsSSE(accept: string | undefined): boolean {\n\treturn !!accept && accept.includes('text/event-stream');\n}\n\n/**\n * Build a Response for an error payload, using SSE format when the client\n * sent `Accept: text/event-stream` so that SSE-only transports (e.g. mcp-remote)\n * receive the error instead of hanging.\n *\n * Uses the actual HTTP status code so MCP clients can detect session expiry (404)\n * and other errors at the HTTP level, as required by the MCP spec.\n */\nexport function sseErrorResponse(\n\tpayload: unknown,\n\tstatus: number,\n\taccept: string | undefined,\n\textraHeaders?: Record<string, string>,\n\teventId?: string,\n): Response {\n\tif (acceptsSSE(accept)) {\n\t\tconst body = sseEvent(payload, eventId);\n\t\treturn new Response(body, {\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t\t'Cache-Control': 'no-cache',\n\t\t\t\t'Content-Length': String(new TextEncoder().encode(body).byteLength),\n\t\t\t\t...extraHeaders,\n\t\t\t},\n\t\t});\n\t}\n\treturn Response.json(payload, { status, headers: extraHeaders });\n}\n\n/** Create a ReadableStream that emits pre-formatted SSE text and then closes */\nexport function createSseStream(events: string): ReadableStream<Uint8Array> {\n\treturn new ReadableStream({\n\t\tstart(controller) {\n\t\t\tcontroller.enqueue(new TextEncoder().encode(events));\n\t\t\tcontroller.close();\n\t\t},\n\t});\n}\n\n/** Interval between SSE heartbeat comments (ms). */\nconst HEARTBEAT_INTERVAL_MS = 5_000;\n\n/**\n * Create a streaming SSE Response that sends heartbeat comments while\n * a long-running operation executes. This keeps the TCP connection alive\n * and prevents proxy/client-side idle timeouts (e.g. mcp-remote / Claude Desktop).\n *\n * The stream emits `: heartbeat\\n\\n` comments (ignored by SSE EventSource\n * listeners per spec) every HEARTBEAT_INTERVAL_MS until the operation\n * resolves, then sends the result as a final `message` event and closes.\n */\nexport function createStreamingSseResponse<T>(\n\toperation: Promise<T>,\n\tformatResult: (result: T) => string,\n\theaders: Record<string, string>,\n): Response {\n\tconst encoder = new TextEncoder();\n\tconst stream = new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tlet closed = false;\n\n\t\t\tconst heartbeat = setInterval(() => {\n\t\t\t\tif (closed) return;\n\t\t\t\ttry {\n\t\t\t\t\tcontroller.enqueue(encoder.encode(': heartbeat\\n\\n'));\n\t\t\t\t} catch {\n\t\t\t\t\t// Stream already closed/errored — clean up\n\t\t\t\t\tclearInterval(heartbeat);\n\t\t\t\t}\n\t\t\t}, HEARTBEAT_INTERVAL_MS);\n\n\t\t\toperation\n\t\t\t\t.then((result) => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tclosed = true;\n\t\t\t\t\tclearInterval(heartbeat);\n\t\t\t\t\tcontroller.enqueue(encoder.encode(formatResult(result)));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tif (closed) return;\n\t\t\t\t\tclosed = true;\n\t\t\t\t\tclearInterval(heartbeat);\n\t\t\t\t\t// Emit error as a proper JSON-RPC error SSE event so MCP clients can parse it\n\t\t\t\t\tconst message = sanitizeErrorMessage(err, 'Internal error');\n\t\t\t\t\tconst jsonRpcErr = { jsonrpc: '2.0', id: null, error: { code: -32603, message } };\n\t\t\t\t\tcontroller.enqueue(encoder.encode(`event: message\\ndata: ${JSON.stringify(jsonRpcErr)}\\n\\n`));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t});\n\t\t},\n\t});\n\n\treturn new Response(stream, {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t'Content-Type': 'text/event-stream',\n\t\t\t'Cache-Control': 'no-cache',\n\t\t\t...headers,\n\t\t},\n\t});\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { checkControlPlaneRateLimit } from '../lib/rate-limiter';\nimport { validateSession } from '../lib/session';\nimport { JSON_RPC_ERRORS, jsonRpcError } from '../lib/json-rpc';\nimport { sseErrorResponse } from '../lib/sse';\n\nexport async function buildControlPlaneRateLimitResponse(\n\tip: string,\n\tkv: KVNamespace | undefined,\n\tmethod: string,\n\tisAuthenticated: boolean,\n\tid: string | number | null | undefined,\n\taccept?: string,\n\tquotaCoordinator?: DurableObjectNamespace,\n): Promise<Response | undefined> {\n\tif (isAuthenticated || method === 'tools/call' || method.startsWith('notifications/')) return undefined;\n\n\tconst rateResult = await checkControlPlaneRateLimit(ip, kv, quotaCoordinator);\n\tif (rateResult.allowed) return undefined;\n\n\tconst headers: Record<string, string> = {\n\t\t'x-ratelimit-limit': '60',\n\t\t'x-ratelimit-remaining': String(rateResult.minuteRemaining),\n\t};\n\tif (rateResult.retryAfterMs !== undefined) {\n\t\theaders['retry-after'] = String(Math.ceil(rateResult.retryAfterMs / 1000));\n\t}\n\n\treturn sseErrorResponse(\n\t\tjsonRpcError(\n\t\t\tid,\n\t\t\tJSON_RPC_ERRORS.RATE_LIMITED,\n\t\t\t`Rate limit exceeded. Retry after ${Math.ceil((rateResult.retryAfterMs ?? 0) / 1000)}s`,\n\t\t),\n\t\t429,\n\t\taccept,\n\t\theaders,\n\t\tid != null ? String(id) : undefined,\n\t);\n}\n\nexport interface SessionValidationError {\n\tstatus: 400 | 404;\n\tpayload: ReturnType<typeof jsonRpcError>;\n}\n\n/**\n * Validate session for non-initialize requests.\n * Returns 400 for missing session header, 404 for expired/terminated sessions.\n */\nexport async function validateSessionRequest(\n\tsessionId: string | undefined,\n\tsessionStore: KVNamespace | undefined,\n\tid: string | number | null | undefined,\n\tmessage: string,\n): Promise<SessionValidationError | undefined> {\n\tif (!sessionId) {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tpayload: jsonRpcError(id, JSON_RPC_ERRORS.INVALID_REQUEST, message),\n\t\t};\n\t}\n\tif (!(await validateSession(sessionId, sessionStore))) {\n\t\treturn {\n\t\t\tstatus: 404,\n\t\t\tpayload: jsonRpcError(id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Not Found: session expired or terminated'),\n\t\t};\n\t}\n\treturn undefined;\n}\n\n/**\n * Resolve session for GET /mcp SSE stream.\n * Requires an existing valid session — does not create sessions (use POST initialize for that).\n */\nexport async function resolveSseSession(options: {\n\tsessionId: string | undefined;\n\tip: string;\n\trateLimitKv?: KVNamespace;\n\tsessionStore?: KVNamespace;\n}): Promise<{ response?: Response; sessionId?: string }> {\n\tif (!options.sessionId) {\n\t\treturn {\n\t\t\tresponse: Response.json(\n\t\t\t\tjsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Bad Request: missing session'),\n\t\t\t\t{ status: 400 },\n\t\t\t),\n\t\t};\n\t}\n\n\tif (!(await validateSession(options.sessionId, options.sessionStore))) {\n\t\treturn {\n\t\t\tresponse: Response.json(\n\t\t\t\tjsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Not Found: session expired or terminated'),\n\t\t\t\t{ status: 404 },\n\t\t\t),\n\t\t};\n\t}\n\n\treturn { sessionId: options.sessionId };\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { checkRateLimit, checkToolDailyRateLimit, checkGlobalDailyLimit } from '../lib/rate-limiter';\nimport { logEvent, logError } from '../lib/log';\nimport { jsonRpcError, JSON_RPC_ERRORS, sanitizeErrorMessage } from '../lib/json-rpc';\nimport { buildControlPlaneRateLimitResponse, validateSessionRequest } from './route-gates';\nimport { FREE_TOOL_DAILY_LIMITS, GLOBAL_DAILY_TOOL_LIMIT, TIER_DAILY_LIMITS, TIER_TOOL_DAILY_LIMITS } from '../lib/config';\nimport { normalizeToolName } from '../handlers/tool-args';\nimport { acceptsSSE } from '../lib/sse';\nimport { dispatchMcpMethod } from './dispatch';\nimport { validateJsonRpcRequest } from './request';\nimport type { JsonRpcRequest } from '../lib/json-rpc';\nimport type { AnalyticsClient } from '../lib/analytics';\n\nexport type ProcessedRequestResult =\n\t| {\n\t\t\tkind: 'notification';\n\t }\n\t| {\n\t\t\tkind: 'response';\n\t\t\tpayload: unknown;\n\t\t\theaders: Record<string, string>;\n\t\t\thttpStatus: number;\n\t\t\tuseErrorEnvelope: boolean;\n\t\t\teventId?: string;\n\t\t\tstreamOperation?: Promise<unknown>;\n\t };\n\nexport interface ExecuteMcpRequestOptions {\n\tbody: JsonRpcRequest;\n\taccept?: string;\n\tallowStreaming: boolean;\n\tbatchMode: boolean;\n\tbatchSize: number;\n\tresponseTransport: 'json' | 'sse';\n\tstartTime: number;\n\tip: string;\n\tisAuthenticated: boolean;\n\ttierAuthResult?: import('../lib/tier-auth').TierAuthResult;\n\tuserAgent?: string;\n\tsessionId?: string;\n\tvalidateSession: boolean;\n\tsessionErrorMessage?: string;\n\tcreateSessionOnInitialize?: boolean;\n\texistingSessionId?: string;\n\tserverVersion: string;\n\trateLimitKv?: KVNamespace;\n\tquotaCoordinator?: DurableObjectNamespace;\n\tsessionStore?: KVNamespace;\n\tscanCache?: KVNamespace;\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string;\n\tproviderSignaturesSha256?: string;\n\tanalytics?: AnalyticsClient;\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tscoringConfig?: import('../lib/scoring-config').ScoringConfig;\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH endpoint URL (bv-dns). */\n\tsecondaryDohEndpoint?: string;\n\t/** Auth token for custom secondary DoH. */\n\tsecondaryDohToken?: string;\n\tcountry?: string;\n\tclientType?: string;\n\tauthTier?: string;\n\tsessionHash?: string;\n}\n\nfunction getDomainFromParams(params: Record<string, unknown> | undefined): string | undefined {\n\treturn typeof params === 'object' && params && 'domain' in params ? String(params.domain) : undefined;\n}\n\nfunction extractHeaders(response: Response): Record<string, string> {\n\tconst headers: Record<string, string> = {};\n\tresponse.headers.forEach((value, key) => {\n\t\tconst lower = key.toLowerCase();\n\t\tif (lower === 'content-type' || lower === 'cache-control' || lower === 'content-length') return;\n\t\theaders[key] = value;\n\t});\n\treturn headers;\n}\n\nasync function readJsonRpcPayload(response: Response): Promise<ReturnType<typeof jsonRpcError>> {\n\tconst contentType = response.headers.get('content-type')?.toLowerCase() ?? '';\n\tif (contentType.includes('text/event-stream')) {\n\t\tconst text = await response.text();\n\t\tconst dataLine = text\n\t\t\t.split('\\n')\n\t\t\t.find((line) => line.startsWith('data: '));\n\t\tif (!dataLine) {\n\t\t\treturn jsonRpcError(null, JSON_RPC_ERRORS.INTERNAL_ERROR, 'Internal server error');\n\t\t}\n\t\treturn JSON.parse(dataLine.slice('data: '.length)) as ReturnType<typeof jsonRpcError>;\n\t}\n\n\treturn (await response.json()) as ReturnType<typeof jsonRpcError>;\n}\n\nfunction emitRequestAnalytics(\n\toptions: ExecuteMcpRequestOptions,\n\tmethod: string,\n\tstatus: 'ok' | 'error',\n\thasJsonRpcError: boolean,\n): void {\n\toptions.analytics?.emitRequestEvent({\n\t\tmethod,\n\t\tstatus,\n\t\tdurationMs: Date.now() - options.startTime,\n\t\tisAuthenticated: options.isAuthenticated,\n\t\thasJsonRpcError,\n\t\ttransport: options.responseTransport,\n\t\tcountry: options.country,\n\t\tclientType: options.clientType as import('../lib/client-detection').McpClientType,\n\t\tauthTier: options.authTier,\n\t\tsessionHash: options.sessionHash,\n\t});\n}\n\nexport async function executeMcpRequest(options: ExecuteMcpRequestOptions): Promise<ProcessedRequestResult> {\n\tconst validationError = validateJsonRpcRequest(options.body);\n\tif (validationError) {\n\t\temitRequestAnalytics(\n\t\t\toptions,\n\t\t\ttypeof options.body?.method === 'string' ? options.body.method : 'invalid',\n\t\t\t'error',\n\t\t\ttrue,\n\t\t);\n\t\treturn {\n\t\t\tkind: 'response',\n\t\t\tpayload: validationError.payload,\n\t\t\theaders: {},\n\t\t\thttpStatus: validationError.status,\n\t\t\tuseErrorEnvelope: true,\n\t\t\teventId: options.body.id != null ? String(options.body.id) : undefined,\n\t\t};\n\t}\n\n\tconst { id, method, params } = options.body;\n\tconst eventId = id != null ? String(id) : undefined;\n\n\tif (options.batchMode && options.batchSize > 1 && method === 'initialize') {\n\t\temitRequestAnalytics(options, method, 'error', true);\n\t\treturn {\n\t\t\tkind: 'response',\n\t\t\tpayload: jsonRpcError(id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC batch request: initialize cannot be batched with other messages'),\n\t\t\theaders: {},\n\t\t\thttpStatus: 400,\n\t\t\tuseErrorEnvelope: true,\n\t\t\teventId,\n\t\t};\n\t}\n\n\tlet rateHeaders: Record<string, string> = {};\n\tif (!options.isAuthenticated && method === 'tools/call') {\n\t\tconst globalResult = await checkGlobalDailyLimit(GLOBAL_DAILY_TOOL_LIMIT, options.rateLimitKv, options.quotaCoordinator);\n\t\tif (!globalResult.allowed) {\n\t\t\tconst globalHeaders: Record<string, string> = {};\n\t\t\tif (globalResult.retryAfterMs !== undefined) {\n\t\t\t\tglobalHeaders['retry-after'] = String(Math.ceil(globalResult.retryAfterMs / 1000));\n\t\t\t}\n\t\t\toptions.analytics?.emitRateLimitEvent({\n\t\t\t\tlimitType: 'daily_global',\n\t\t\t\ttoolName: 'n/a',\n\t\t\t\tlimit: GLOBAL_DAILY_TOOL_LIMIT,\n\t\t\t\tremaining: 0,\n\t\t\t\tcountry: options.country,\n\t\t\t\tauthTier: options.authTier,\n\t\t\t});\n\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: jsonRpcError(\n\t\t\t\t\tid,\n\t\t\t\t\tJSON_RPC_ERRORS.RATE_LIMITED,\n\t\t\t\t\t'Service capacity reached for today. Please try again tomorrow or deploy your own instance.',\n\t\t\t\t),\n\t\t\t\theaders: globalHeaders,\n\t\t\t\thttpStatus: 429,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\n\t\tconst rateResult = await checkRateLimit(options.ip, options.rateLimitKv, options.quotaCoordinator);\n\t\trateHeaders = {\n\t\t\t'x-ratelimit-limit': '50',\n\t\t\t'x-ratelimit-remaining': String(rateResult.minuteRemaining),\n\t\t};\n\t\tif (!rateResult.allowed) {\n\t\t\tif (rateResult.retryAfterMs !== undefined) {\n\t\t\t\trateHeaders['retry-after'] = String(Math.ceil(rateResult.retryAfterMs / 1000));\n\t\t\t}\n\t\t\toptions.analytics?.emitRateLimitEvent({\n\t\t\t\tlimitType: 'minute',\n\t\t\t\ttoolName: 'n/a',\n\t\t\t\tlimit: 50,\n\t\t\t\tremaining: rateResult.minuteRemaining,\n\t\t\t\tcountry: options.country,\n\t\t\t\tauthTier: options.authTier,\n\t\t\t});\n\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: jsonRpcError(\n\t\t\t\t\tid,\n\t\t\t\t\tJSON_RPC_ERRORS.RATE_LIMITED,\n\t\t\t\t\t`Rate limit exceeded. Retry after ${Math.ceil((rateResult.retryAfterMs ?? 0) / 1000)}s`,\n\t\t\t\t),\n\t\t\t\theaders: rateHeaders,\n\t\t\t\thttpStatus: 429,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\n\t\tconst toolNameRaw = typeof params === 'object' && params !== null && 'name' in params ? (params as Record<string, unknown>).name : undefined;\n\t\tconst toolName = typeof toolNameRaw === 'string' ? normalizeToolName(toolNameRaw) : '';\n\t\tconst toolDailyLimit = toolName ? FREE_TOOL_DAILY_LIMITS[toolName] : undefined;\n\t\tif (toolDailyLimit !== undefined) {\n\t\t\tconst toolQuotaResult = await checkToolDailyRateLimit(\n\t\t\t\toptions.ip,\n\t\t\t\ttoolName,\n\t\t\t\ttoolDailyLimit,\n\t\t\t\toptions.rateLimitKv,\n\t\t\t\toptions.quotaCoordinator,\n\t\t\t);\n\t\t\trateHeaders['x-quota-limit'] = String(toolQuotaResult.limit);\n\t\t\trateHeaders['x-quota-remaining'] = String(toolQuotaResult.remaining);\n\t\t\tif (!toolQuotaResult.allowed) {\n\t\t\t\tif (toolQuotaResult.retryAfterMs !== undefined) {\n\t\t\t\t\trateHeaders['retry-after'] = String(Math.ceil(toolQuotaResult.retryAfterMs / 1000));\n\t\t\t\t}\n\t\t\t\toptions.analytics?.emitRateLimitEvent({\n\t\t\t\t\tlimitType: 'daily_tool',\n\t\t\t\t\ttoolName,\n\t\t\t\t\tlimit: toolDailyLimit,\n\t\t\t\t\tremaining: 0,\n\t\t\t\t\tcountry: options.country,\n\t\t\t\t\tauthTier: options.authTier ?? 'anon',\n\t\t\t\t});\n\t\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\t\treturn {\n\t\t\t\t\tkind: 'response',\n\t\t\t\t\tpayload: jsonRpcError(\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tJSON_RPC_ERRORS.RATE_LIMITED,\n\t\t\t\t\t\t`Rate limit exceeded. ${toolName} is limited to ${toolDailyLimit} requests per day for free tier users.`,\n\t\t\t\t\t),\n\t\t\t\t\theaders: rateHeaders,\n\t\t\t\t\thttpStatus: 429,\n\t\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\t\teventId,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} else if (options.tierAuthResult?.authenticated && options.tierAuthResult.tier && method === 'tools/call') {\n\t\t// Authenticated tier-based rate limiting (keyed by API key hash, not IP)\n\t\tconst tier = options.tierAuthResult.tier;\n\t\tconst principalId = options.tierAuthResult.keyHash ?? options.ip;\n\n\t\tconst toolNameRaw = typeof params === 'object' && params !== null && 'name' in params ? (params as Record<string, unknown>).name : undefined;\n\t\tconst toolName = typeof toolNameRaw === 'string' ? normalizeToolName(toolNameRaw) : 'unknown';\n\n\t\t// Per-tool tier override takes precedence over flat tier limit\n\t\tconst dailyLimit = TIER_TOOL_DAILY_LIMITS[tier]?.[toolName] ?? TIER_DAILY_LIMITS[tier];\n\n\t\tconst tierQuotaResult = await checkToolDailyRateLimit(\n\t\t\tprincipalId,\n\t\t\ttoolName,\n\t\t\tdailyLimit,\n\t\t\toptions.rateLimitKv,\n\t\t\toptions.quotaCoordinator,\n\t\t);\n\t\trateHeaders['x-quota-limit'] = String(tierQuotaResult.limit);\n\t\trateHeaders['x-quota-remaining'] = String(tierQuotaResult.remaining);\n\t\trateHeaders['x-quota-tier'] = tier;\n\t\tif (!tierQuotaResult.allowed) {\n\t\t\tif (tierQuotaResult.retryAfterMs !== undefined) {\n\t\t\t\trateHeaders['retry-after'] = String(Math.ceil(tierQuotaResult.retryAfterMs / 1000));\n\t\t\t}\n\t\t\toptions.analytics?.emitRateLimitEvent({\n\t\t\t\tlimitType: 'daily_tool',\n\t\t\t\ttoolName,\n\t\t\t\tlimit: dailyLimit,\n\t\t\t\tremaining: 0,\n\t\t\t\tcountry: options.country,\n\t\t\t\tauthTier: tier,\n\t\t\t});\n\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: jsonRpcError(\n\t\t\t\t\tid,\n\t\t\t\t\tJSON_RPC_ERRORS.RATE_LIMITED,\n\t\t\t\t\t`Rate limit exceeded. ${tier} tier is limited to ${dailyLimit} requests per day.`,\n\t\t\t\t),\n\t\t\t\theaders: rateHeaders,\n\t\t\t\thttpStatus: 429,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (method !== 'tools/call') {\n\t\tconst controlPlaneLimited = await buildControlPlaneRateLimitResponse(\n\t\t\toptions.ip,\n\t\t\toptions.rateLimitKv,\n\t\t\tmethod,\n\t\t\toptions.isAuthenticated,\n\t\t\tid,\n\t\t\toptions.accept,\n\t\t\toptions.quotaCoordinator,\n\t\t);\n\t\tif (controlPlaneLimited) {\n\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: await readJsonRpcPayload(controlPlaneLimited),\n\t\t\t\theaders: extractHeaders(controlPlaneLimited),\n\t\t\t\thttpStatus: controlPlaneLimited.status,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (options.validateSession && method !== 'initialize' && !method.startsWith('notifications/')) {\n\t\tconst sessionError = await validateSessionRequest(\n\t\t\toptions.sessionId,\n\t\t\toptions.sessionStore,\n\t\t\tid,\n\t\t\toptions.sessionErrorMessage ?? 'Bad Request: missing session',\n\t\t);\n\t\tif (sessionError) {\n\t\t\temitRequestAnalytics(options, method, 'error', true);\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: sessionError.payload,\n\t\t\t\theaders: {},\n\t\t\t\thttpStatus: sessionError.status,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\t}\n\n\tconst isNotification = id === undefined || id === null;\n\tif (isNotification && method !== 'initialize') {\n\t\temitRequestAnalytics(options, method, 'ok', false);\n\t\treturn { kind: 'notification' };\n\t}\n\n\tif (options.allowStreaming && method === 'tools/call' && options.responseTransport === 'sse' && acceptsSSE(options.accept)) {\n\t\tconst dispatchPromise = dispatchMcpMethod({\n\t\t\tid,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t\tip: options.ip,\n\t\t\tisAuthenticated: options.isAuthenticated,\n\t\t\trateHeaders,\n\t\t\tserverVersion: options.serverVersion,\n\t\t\trateLimitKv: options.rateLimitKv,\n\t\t\tquotaCoordinator: options.quotaCoordinator,\n\t\t\tsessionStore: options.sessionStore,\n\t\t\tscanCache: options.scanCache,\n\t\t\tproviderSignaturesUrl: options.providerSignaturesUrl,\n\t\t\tproviderSignaturesAllowedHosts: options.providerSignaturesAllowedHosts,\n\t\t\tproviderSignaturesSha256: options.providerSignaturesSha256,\n\t\t\tanalytics: options.analytics,\n\t\t\tprofileAccumulator: options.profileAccumulator,\n\t\t\twaitUntil: options.waitUntil,\n\t\t\tcreateSessionOnInitialize: options.createSessionOnInitialize,\n\t\t\texistingSessionId: options.existingSessionId,\n\t\t\tscoringConfig: options.scoringConfig,\n\t\t\tcacheTtlSeconds: options.cacheTtlSeconds,\n\t\t\tsecondaryDohEndpoint: options.secondaryDohEndpoint,\n\t\t\tsecondaryDohToken: options.secondaryDohToken,\n\t\t\tcountry: options.country,\n\t\t\tclientType: options.clientType,\n\t\t\tauthTier: options.authTier,\n\t\t}).then((dispatchResult) => {\n\t\t\tif (dispatchResult.kind === 'early-error') {\n\t\t\t\treturn dispatchResult.payload;\n\t\t\t}\n\n\t\t\tlogEvent({\n\t\t\t\ttimestamp: new Date().toISOString(),\n\t\t\t\trequestId: typeof id === 'string' ? id : undefined,\n\t\t\t\tip: options.ip,\n\t\t\t\ttool: dispatchResult.logTool,\n\t\t\t\tcategory: dispatchResult.logCategory,\n\t\t\t\tresult: dispatchResult.logResult,\n\t\t\t\tdetails: dispatchResult.logDetails,\n\t\t\t\tdurationMs: Date.now() - options.startTime,\n\t\t\t\tuserAgent: options.userAgent,\n\t\t\t\tseverity: dispatchResult.logCategory === 'error' ? 'error' : 'info',\n\t\t\t\tdomain: getDomainFromParams(params),\n\t\t\t});\n\n\t\t\tconst hasJsonRpcError = typeof dispatchResult.payload === 'object' && dispatchResult.payload !== null && 'error' in dispatchResult.payload;\n\t\t\temitRequestAnalytics(options, method, hasJsonRpcError ? 'error' : 'ok', hasJsonRpcError);\n\t\t\treturn dispatchResult.payload;\n\t\t});\n\n\t\treturn {\n\t\t\tkind: 'response',\n\t\t\tpayload: null,\n\t\t\theaders: { ...rateHeaders },\n\t\t\thttpStatus: 200,\n\t\t\tuseErrorEnvelope: false,\n\t\t\teventId,\n\t\t\tstreamOperation: dispatchPromise,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst dispatchResult = await dispatchMcpMethod({\n\t\t\tid,\n\t\t\tmethod,\n\t\t\tparams,\n\t\t\tip: options.ip,\n\t\t\tisAuthenticated: options.isAuthenticated,\n\t\t\trateHeaders,\n\t\t\tserverVersion: options.serverVersion,\n\t\t\trateLimitKv: options.rateLimitKv,\n\t\t\tquotaCoordinator: options.quotaCoordinator,\n\t\t\tsessionStore: options.sessionStore,\n\t\t\tscanCache: options.scanCache,\n\t\t\tproviderSignaturesUrl: options.providerSignaturesUrl,\n\t\t\tproviderSignaturesAllowedHosts: options.providerSignaturesAllowedHosts,\n\t\t\tproviderSignaturesSha256: options.providerSignaturesSha256,\n\t\t\tanalytics: options.analytics,\n\t\t\tprofileAccumulator: options.profileAccumulator,\n\t\t\twaitUntil: options.waitUntil,\n\t\t\tcreateSessionOnInitialize: options.createSessionOnInitialize,\n\t\t\texistingSessionId: options.existingSessionId,\n\t\t\tscoringConfig: options.scoringConfig,\n\t\t\tcacheTtlSeconds: options.cacheTtlSeconds,\n\t\t\tsecondaryDohEndpoint: options.secondaryDohEndpoint,\n\t\t\tsecondaryDohToken: options.secondaryDohToken,\n\t\t\tcountry: options.country,\n\t\t\tclientType: options.clientType,\n\t\t\tauthTier: options.authTier,\n\t\t});\n\n\t\tif (dispatchResult.kind === 'early-error') {\n\t\t\treturn {\n\t\t\t\tkind: 'response',\n\t\t\t\tpayload: dispatchResult.payload,\n\t\t\t\theaders: dispatchResult.headers,\n\t\t\t\thttpStatus: dispatchResult.status,\n\t\t\t\tuseErrorEnvelope: true,\n\t\t\t\teventId,\n\t\t\t};\n\t\t}\n\n\t\tconst headers: Record<string, string> = {};\n\t\tif (dispatchResult.newSessionId) {\n\t\t\theaders['mcp-session-id'] = dispatchResult.newSessionId;\n\t\t}\n\t\tObject.assign(headers, rateHeaders);\n\n\t\tlogEvent({\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\trequestId: typeof id === 'string' ? id : undefined,\n\t\t\tip: options.ip,\n\t\t\ttool: dispatchResult.logTool,\n\t\t\tcategory: dispatchResult.logCategory,\n\t\t\tresult: dispatchResult.logResult,\n\t\t\tdetails: dispatchResult.logDetails,\n\t\t\tdurationMs: Date.now() - options.startTime,\n\t\t\tuserAgent: options.userAgent,\n\t\t\tseverity: dispatchResult.logCategory === 'error' ? 'error' : 'info',\n\t\t\tdomain: getDomainFromParams(params),\n\t\t});\n\n\t\tconst hasJsonRpcError = typeof dispatchResult.payload === 'object' && dispatchResult.payload !== null && 'error' in dispatchResult.payload;\n\t\temitRequestAnalytics(options, method, hasJsonRpcError ? 'error' : 'ok', hasJsonRpcError);\n\n\t\treturn {\n\t\t\tkind: 'response',\n\t\t\tpayload: dispatchResult.payload,\n\t\t\theaders,\n\t\t\thttpStatus: 200,\n\t\t\tuseErrorEnvelope: false,\n\t\t\teventId,\n\t\t};\n\t} catch (err) {\n\t\temitRequestAnalytics(options, method, 'error', true);\n\t\tlogError(err instanceof Error ? err : String(err), {\n\t\t\tseverity: 'error',\n\t\t\tip: options.ip,\n\t\t\trequestId: typeof options.body?.id === 'string' ? options.body.id : undefined,\n\t\t\ttool: typeof options.body?.method === 'string' ? options.body.method : undefined,\n\t\t\tdetails: { params: options.body?.params && typeof options.body.params === 'object' ? { keys: Object.keys(options.body.params).sort().slice(0, 25) } : undefined },\n\t\t\tdurationMs: Date.now() - options.startTime,\n\t\t\tuserAgent: options.userAgent,\n\t\t});\n\t\treturn {\n\t\t\tkind: 'response',\n\t\t\tpayload: jsonRpcError(id, JSON_RPC_ERRORS.INTERNAL_ERROR, sanitizeErrorMessage(err, 'Internal server error')),\n\t\t\theaders: {},\n\t\t\thttpStatus: 500,\n\t\t\tuseErrorEnvelope: true,\n\t\t\teventId,\n\t\t};\n\t}\n}","// SPDX-License-Identifier: BUSL-1.1\n\n// For IDN/Unicode normalization\nimport * as punycode from 'punycode/';\n// Centralized normalization config\nimport {\n\tBLOCKED_SUFFIXES,\n\tBLOCKED_HOSTS,\n\tBLOCKED_IP_PATTERNS,\n\tBLOCKED_DNS_REBINDING,\n\tMAX_DOMAIN_LENGTH,\n\tMAX_LABEL_LENGTH,\n\tLABEL_REGEX,\n} from './config';\n/**\n * Input sanitization and validation utilities for the DNS Security MCP Server.\n * Handles domain validation, input cleaning, and MCP error response helpers.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nexport interface ValidationResult {\n\tvalid: boolean;\n\terror?: string;\n}\n\n/**\n * Parse a numeric IPv4 segment using decimal, octal, or hex notation.\n * Returns null when the token is not a numeric IP segment.\n */\nfunction parseIpv4NumberToken(token: string): number | null {\n\tif (!token) return null;\n\n\tlet radix = 10;\n\tlet digits = token;\n\tif (/^0x[0-9a-f]+$/i.test(token)) {\n\t\tradix = 16;\n\t\tdigits = token.slice(2);\n\t} else if (/^0[0-7]+$/.test(token) && token.length > 1) {\n\t\tradix = 8;\n\t}\n\n\tif (digits.length === 0) return null;\n\tconst value = Number.parseInt(digits, radix);\n\tif (!Number.isFinite(value) || value < 0) return null;\n\treturn value;\n}\n\n/**\n * Canonicalize IPv4 literals that may use short/octal/hex forms.\n * Returns null when input is not an IPv4 host literal candidate.\n */\nfunction canonicalizeIpv4Literal(input: string): string | null {\n\tif (!/^[0-9a-fx.]+$/i.test(input)) return null;\n\n\tconst parts = input.split('.');\n\tif (parts.length < 1 || parts.length > 4) return null;\n\tif (parts.some((part) => part.length === 0)) return null;\n\n\tconst values: number[] = [];\n\tfor (const part of parts) {\n\t\tconst parsed = parseIpv4NumberToken(part);\n\t\tif (parsed === null) return null;\n\t\tvalues.push(parsed);\n\t}\n\n\tlet ipAsUint32 = 0;\n\tif (values.length === 1) {\n\t\tif (values[0] > 0xffffffff) return null;\n\t\tipAsUint32 = values[0] >>> 0;\n\t} else if (values.length === 2) {\n\t\tif (values[0] > 0xff || values[1] > 0xffffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | values[1]) >>> 0;\n\t} else if (values.length === 3) {\n\t\tif (values[0] > 0xff || values[1] > 0xff || values[2] > 0xffff) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | values[2]) >>> 0;\n\t} else {\n\t\tif (values.some((value) => value > 0xff)) return null;\n\t\tipAsUint32 = ((values[0] << 24) | (values[1] << 16) | (values[2] << 8) | values[3]) >>> 0;\n\t}\n\n\tconst oct1 = (ipAsUint32 >>> 24) & 0xff;\n\tconst oct2 = (ipAsUint32 >>> 16) & 0xff;\n\tconst oct3 = (ipAsUint32 >>> 8) & 0xff;\n\tconst oct4 = ipAsUint32 & 0xff;\n\treturn `${oct1}.${oct2}.${oct3}.${oct4}`;\n}\n\n/**\n * Validate and sanitize a domain name for DNS queries.\n * Rejects localhost, private/reserved TLDs, IP addresses, and malformed domains.\n */\n\nexport function validateDomain(input: string): ValidationResult {\n\tif (!input || typeof input !== 'string') {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Check for invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst invisiblePattern = /[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu;\n\tif (invisiblePattern.test(input)) {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\tconst cleaned = input.replace(invisiblePattern, '').trim();\n\tif (cleaned.length === 0) {\n\t\treturn { valid: false, error: 'Domain name is required' };\n\t}\n\n\t// Normalize Unicode to NFC, lowercase, remove trailing dot\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\n\t// Convert Unicode/emoji/IDN to punycode for validation\n\tlet asciiDomain: string;\n\ttry {\n\t\tasciiDomain = punycode.toASCII(domain);\n\t} catch {\n\t\treturn { valid: false, error: 'Domain contains invalid Unicode or cannot be converted to ASCII' };\n\t}\n\n\tif (asciiDomain.length > MAX_DOMAIN_LENGTH) {\n\t\treturn { valid: false, error: `Domain exceeds maximum length of ${MAX_DOMAIN_LENGTH} characters` };\n\t}\n\n\t// Check blocked exact hostnames\n\tif (BLOCKED_HOSTS.includes(asciiDomain)) {\n\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved hostname` };\n\t}\n\n\t// Check blocked suffixes\n\tfor (const suffix of BLOCKED_SUFFIXES) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: `Domain \"${asciiDomain}\" is not allowed: reserved TLD \"${suffix}\"` };\n\t\t}\n\t}\n\n\t// Canonicalize non-standard IPv4 literals (e.g. 127.1, 0177.0.0.1)\n\t// and reject all IP literal forms (public, private, and special).\n\tconst canonicalIpv4 = canonicalizeIpv4Literal(asciiDomain);\n\tif (canonicalIpv4) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Reject dotted numeric host literals that are IPv4-like but malformed/out-of-range.\n\tif (/^\\d+(?:\\.\\d+){1,3}$/.test(asciiDomain)) {\n\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t}\n\n\t// Check if it looks like an IP address (blocked)\n\tfor (const pattern of BLOCKED_IP_PATTERNS) {\n\t\tif (pattern.test(asciiDomain)) {\n\t\t\treturn { valid: false, error: `IP addresses are not allowed: \"${asciiDomain}\"` };\n\t\t}\n\t}\n\n\t// Check for DNS rebinding services\n\tfor (const suffix of BLOCKED_DNS_REBINDING) {\n\t\tif (asciiDomain === suffix.slice(1) || asciiDomain.endsWith(suffix)) {\n\t\t\treturn { valid: false, error: 'Domain uses a DNS rebinding service and is not allowed' };\n\t\t}\n\t}\n\n\t// Validate domain label structure (punycode labels)\n\tconst labels = asciiDomain.split('.');\n\tif (labels.length < 2) {\n\t\treturn { valid: false, error: 'Domain must have at least two labels (e.g., example.com)' };\n\t}\n\tfor (const label of labels) {\n\t\tif (label.length === 0) {\n\t\t\treturn { valid: false, error: 'Domain contains empty label (consecutive dots)' };\n\t\t}\n\t\tif (label.length > MAX_LABEL_LENGTH) {\n\t\t\treturn { valid: false, error: `Label \"${label}\" exceeds maximum length of ${MAX_LABEL_LENGTH} characters` };\n\t\t}\n\t\tif (!LABEL_REGEX.test(label)) {\n\t\t\treturn { valid: false, error: `Label \"${label}\" contains invalid characters` };\n\t\t}\n\t}\n\n\treturn { valid: true };\n}\n\n/**\n * Sanitize a domain string: trim, lowercase, remove trailing dot.\n * Call validateDomain first to ensure the domain is valid.\n */\nexport function sanitizeDomain(input: string): string {\n\t// Remove invisible/non-printable Unicode (except space, dot, hyphen)\n\tconst cleaned = input.replace(/[\\p{C}\\p{Zl}\\p{Zp}\\u200B-\\u200D\\uFEFF]/gu, '').trim();\n\tif (cleaned.length === 0) return '';\n\tlet domain = cleaned.normalize('NFC').toLowerCase();\n\tif (domain.endsWith('.')) domain = domain.slice(0, -1);\n\t// Convert Unicode/emoji/IDN to punycode for DNS queries\n\ttry {\n\t\treturn punycode.toASCII(domain);\n\t} catch {\n\t\treturn '';\n\t}\n}\n\n/**\n * Sanitize arbitrary text input for safe logging/display.\n * Removes control characters except newlines and tabs, and truncates length.\n */\nexport function sanitizeInput(input: string, maxLength = 500): string {\n\tif (typeof input !== 'string') return '';\n\tconst sanitized = input.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '');\n\treturn sanitized.slice(0, maxLength);\n}\n\n\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { validateDomain, sanitizeDomain } from '../lib/sanitize';\n\nconst TOOL_ALIASES: Record<string, string> = {\n\tscan: 'scan_domain',\n};\n\nexport function normalizeToolName(name: string): string {\n\tconst normalized = name.trim().toLowerCase();\n\treturn TOOL_ALIASES[normalized] ?? normalized;\n}\n\nexport function extractAndValidateDomain(args: Record<string, unknown>): string {\n\tconst domain = args.domain;\n\tif (typeof domain !== 'string' || domain.trim().length === 0) {\n\t\tthrow new Error('Missing required parameter: domain');\n\t}\n\tconst validation = validateDomain(domain);\n\tif (!validation.valid) {\n\t\tthrow new Error(validation.error ?? 'Invalid domain');\n\t}\n\tconst sanitized = sanitizeDomain(domain);\n\tif (!sanitized) {\n\t\tthrow new Error('Domain validation failed: could not normalize domain');\n\t}\n\treturn sanitized;\n}\n\nexport function extractDkimSelector(args: Record<string, unknown>): string | undefined {\n\tif (typeof args.selector !== 'string' || args.selector.trim().length === 0) {\n\t\treturn undefined;\n\t}\n\tconst selector = args.selector.trim().toLowerCase();\n\tif (!/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/.test(selector) || selector.length > 63) {\n\t\tthrow new Error('Invalid DKIM selector: must be a valid DNS label (alphanumeric and hyphens, max 63 chars)');\n\t}\n\treturn selector;\n}\n\nconst VALID_PROFILES = ['auto', 'mail_enabled', 'enterprise_mail', 'non_mail', 'web_only', 'minimal'] as const;\n\n/** Extract and validate the optional scoring profile parameter. */\nexport function extractScanProfile(args: Record<string, unknown>): typeof VALID_PROFILES[number] | undefined {\n\tconst profile = args.profile;\n\tif (profile === undefined || profile === null) return undefined;\n\tif (typeof profile !== 'string') {\n\t\tthrow new Error('Invalid profile: must be a string');\n\t}\n\tconst normalized = profile.trim().toLowerCase();\n\tif (!(VALID_PROFILES as readonly string[]).includes(normalized)) {\n\t\tthrow new Error(`Invalid profile: must be one of ${VALID_PROFILES.join(', ')}`);\n\t}\n\treturn normalized as typeof VALID_PROFILES[number];\n}\n\nconst VALID_GRADES = new Set(['A+', 'A', 'B+', 'B', 'C+', 'C', 'D+', 'D', 'E', 'F']);\n\n/** Extract and validate the optional baseline parameter for compare_baseline. */\nexport function extractBaseline(args: Record<string, unknown>): Record<string, unknown> {\n\tconst raw = args.baseline;\n\tif (raw === undefined || raw === null) return {};\n\tif (typeof raw !== 'object' || Array.isArray(raw)) {\n\t\tthrow new Error('Invalid baseline: must be an object');\n\t}\n\tconst b = raw as Record<string, unknown>;\n\tconst result: Record<string, unknown> = {};\n\tif (b.grade !== undefined) {\n\t\tif (typeof b.grade !== 'string' || !VALID_GRADES.has(b.grade.toUpperCase())) {\n\t\t\tthrow new Error('Invalid baseline grade');\n\t\t}\n\t\tresult.grade = b.grade;\n\t}\n\tif (b.score !== undefined) {\n\t\tif (typeof b.score !== 'number' || b.score < 0 || b.score > 100) {\n\t\t\tthrow new Error('Invalid baseline score: must be 0-100');\n\t\t}\n\t\tresult.score = b.score;\n\t}\n\tfor (const key of ['require_dmarc_enforce', 'require_spf', 'require_dkim', 'require_dnssec', 'require_mta_sts', 'require_caa'] as const) {\n\t\tif (b[key] !== undefined) {\n\t\t\tif (typeof b[key] !== 'boolean') {\n\t\t\t\tthrow new Error(`Invalid baseline ${key}: must be boolean`);\n\t\t\t}\n\t\t\tresult[key] = b[key];\n\t\t}\n\t}\n\tfor (const key of ['max_critical_findings', 'max_high_findings'] as const) {\n\t\tif (b[key] !== undefined) {\n\t\t\tif (typeof b[key] !== 'number' || b[key]! < 0 || !Number.isInteger(b[key])) {\n\t\t\t\tthrow new Error(`Invalid baseline ${key}: must be a non-negative integer`);\n\t\t\t}\n\t\t\tresult[key] = b[key];\n\t\t}\n\t}\n\treturn result;\n}\n\nexport function extractExplainFindingArgs(args: Record<string, unknown>): {\n\tcheckType: string;\n\tstatus: string;\n\tdetails?: string;\n} {\n\tconst checkType = args.checkType;\n\tconst status = args.status;\n\tif (typeof checkType !== 'string' || typeof status !== 'string') {\n\t\tthrow new Error('Missing required parameters: checkType and status');\n\t}\n\tif (checkType.length > 100) {\n\t\tthrow new Error('Invalid checkType: must be <= 100 characters');\n\t}\n\tif (status.length > 500) {\n\t\tthrow new Error('Invalid status: must be <= 500 characters');\n\t}\n\tconst details = typeof args.details === 'string' ? args.details : undefined;\n\tif (details && details.length > 2000) {\n\t\tthrow new Error('Invalid details: must be <= 2000 characters');\n\t}\n\treturn { checkType, status, details };\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { INFLIGHT_CLEANUP_MS } from './config';\n\n/**\n * TTL cache for DNS scan results.\n *\n * Uses Cloudflare KV for persistent caching when available,\n * with in-memory fallback when KV is not configured.\n *\n * Cloudflare Workers compatible - no Node.js APIs.\n */\n\ninterface CacheEntry<T> {\n\tvalue: T;\n\texpiresAt: number;\n}\n\ninterface CacheOptions {\n\t/** Time-to-live in milliseconds. Default: 5 minutes (300_000ms) */\n\tttlMs?: number;\n\t/** Maximum number of entries. Default: 1000 */\n\tmaxEntries?: number;\n}\n\nconst DEFAULT_TTL_MS = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_TTL_SECONDS = 300; // 5 minutes in seconds (for KV expirationTtl)\nconst DEFAULT_MAX_ENTRIES = 1000;\n\nexport class TTLCache<T = unknown> {\n\tprivate readonly store = new Map<string, CacheEntry<T>>();\n\tprivate readonly ttlMs: number;\n\tprivate readonly maxEntries: number;\n\n\tconstructor(options: CacheOptions = {}) {\n\t\tthis.ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;\n\t\tthis.maxEntries = options.maxEntries ?? DEFAULT_MAX_ENTRIES;\n\t}\n\n\t/**\n\t * Get a cached value by key. Returns undefined if not found or expired.\n\t */\n\tget(key: string): T | undefined {\n\t\tconst entry = this.store.get(key);\n\t\tif (!entry) {\n\t\t\treturn undefined;\n\t\t}\n\t\tif (Date.now() > entry.expiresAt) {\n\t\t\tthis.store.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\treturn entry.value;\n\t}\n\n\t/**\n\t * Set a value in the cache with optional custom TTL.\n\t */\n\tset(key: string, value: T, ttlMs?: number): void {\n\t\t// Evict expired entries if at capacity\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tthis.evictExpired();\n\t\t}\n\t\t// If still at capacity after eviction, remove oldest entry\n\t\tif (this.store.size >= this.maxEntries && !this.store.has(key)) {\n\t\t\tconst firstKey = this.store.keys().next().value;\n\t\t\tif (firstKey !== undefined) {\n\t\t\t\tthis.store.delete(firstKey);\n\t\t\t}\n\t\t}\n\t\tthis.store.set(key, {\n\t\t\tvalue,\n\t\t\texpiresAt: Date.now() + (ttlMs ?? this.ttlMs),\n\t\t});\n\t}\n\n\t/**\n\t * Check if a key exists and is not expired.\n\t */\n\thas(key: string): boolean {\n\t\treturn this.get(key) !== undefined;\n\t}\n\n\t/**\n\t * Delete a specific key from the cache.\n\t */\n\tdelete(key: string): boolean {\n\t\treturn this.store.delete(key);\n\t}\n\n\t/**\n\t * Remove all entries from the cache.\n\t */\n\tclear(): void {\n\t\tthis.store.clear();\n\t}\n\n\t/**\n\t * Get the number of entries (including potentially expired ones).\n\t */\n\tget size(): number {\n\t\treturn this.store.size;\n\t}\n\n\t/**\n\t * Remove all expired entries from the cache.\n\t */\n\tevictExpired(): number {\n\t\tconst now = Date.now();\n\t\tlet evicted = 0;\n\t\tfor (const [key, entry] of this.store) {\n\t\t\tif (now > entry.expiresAt) {\n\t\t\t\tthis.store.delete(key);\n\t\t\t\tevicted++;\n\t\t\t}\n\t\t}\n\t\treturn evicted;\n\t}\n}\n\n/** In-flight promise map for cache stampede (thundering herd) protection */\nconst INFLIGHT = new Map<string, Promise<unknown>>();\n\n/** In-memory cache instance used as fallback when KV is unavailable */\nexport const IN_MEMORY_CACHE = new TTLCache<unknown>({\n\tttlMs: DEFAULT_TTL_MS,\n\tmaxEntries: DEFAULT_MAX_ENTRIES,\n});\n\n// ---------------------------------------------------------------------------\n// KV-backed cache functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get a cached value by key.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param kv - Optional KV namespace for persistent caching\n */\nexport async function cacheGet<T>(key: string, kv?: KVNamespace): Promise<T | undefined> {\n if (kv) {\n\t try {\n\t\t const val = await kv.get(key, 'json');\n\t\t return (val ?? undefined) as T | undefined; // KV.get('json') returns unknown; generic T is caller-enforced\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t console.warn('[cache] KV get failed, falling back to in-memory');\n\t }\n }\n return IN_MEMORY_CACHE.get(key) as T | undefined;\n}\n\n/**\n * Set a cached value with configurable TTL.\n * Uses KV when available, falls back to in-memory.\n *\n * @param key - Cache key\n * @param value - Value to cache (must be JSON-serializable for KV)\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n */\n/**\n * Set a cached value, deferring the KV write via ctx.waitUntil() to avoid blocking the response.\n * Falls back to synchronous cacheSet when no ExecutionContext is provided.\n */\nexport function cacheSetDeferred(key: string, value: unknown, ctx: ExecutionContext, kv?: KVNamespace, ttlSeconds?: number): void {\n\tctx.waitUntil(cacheSet(key, value, kv, ttlSeconds));\n}\n\nexport async function cacheSet(key: string, value: unknown, kv?: KVNamespace, ttlSeconds?: number): Promise<void> {\n const ttl = ttlSeconds ?? DEFAULT_TTL_SECONDS;\n if (kv) {\n\t try {\n\t\t await kv.put(key, JSON.stringify(value), { expirationTtl: ttl });\n\t\t return;\n\t } catch {\n\t\t // KV error — log warning and fall through to in-memory\n\t\t console.warn('[cache] KV put failed, falling back to in-memory');\n\t }\n }\n IN_MEMORY_CACHE.set(key, value, ttl * 1000);\n}\n\n/**\n * Run a function with cache-aside logic: returns cached value if available,\n * otherwise executes the function and caches the result.\n * Includes in-flight deduplication to prevent cache stampedes.\n *\n * @param key - Cache key\n * @param run - Async function to execute on cache miss\n * @param kv - Optional KV namespace for persistent caching\n * @param ttlSeconds - Cache TTL in seconds (default: 300 = 5 minutes)\n * @returns The cached or freshly computed result\n */\nexport async function runWithCache<T>(key: string, run: () => Promise<T>, kv?: KVNamespace, ttlSeconds?: number): Promise<T> {\n\tconst cached = await cacheGet<T>(key, kv);\n\tif (cached !== undefined) return cached;\n\n\tconst existing = INFLIGHT.get(key);\n\tif (existing) return existing as Promise<T>; // INFLIGHT map stores Promise<unknown>; keyed by same cache key ensures type match\n\n\tconst cleanup = setTimeout(() => INFLIGHT.delete(key), INFLIGHT_CLEANUP_MS);\n\tconst promise = run()\n\t\t.then(async (result) => {\n\t\t\tawait cacheSet(key, result, kv, ttlSeconds);\n\t\t\treturn result;\n\t\t})\n\t\t.finally(() => {\n\t\t\tclearTimeout(cleanup);\n\t\t\tINFLIGHT.delete(key);\n\t\t});\n\n\tINFLIGHT.set(key, promise);\n\treturn promise;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF (Sender Policy Framework) check tool.\n * Queries TXT records for SPF and validates the policy.\n * Implements recursive include expansion per RFC 7208 §4.6.4.\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport { parseDmarcTags } from './dmarc-utils';\nimport {\n\tRISKY_MECHANISMS,\n\tcheckBroadIpRanges,\n\tcountRecursiveLookups,\n\textractSpfSignalDomains,\n\ttype RecursiveState,\n} from './spf-analysis';\nimport { analyzeTrustSurface } from './spf-trust-surface';\n\ninterface TrustSurfaceDmarcContext {\n\tcorroboratedByWeakDmarc: boolean;\n\tdmarcPolicy?: string;\n\tdmarcAlignmentMode?: string;\n}\n\nasync function getTrustSurfaceDmarcContext(domain: string, dnsOptions?: QueryDnsOptions): Promise<TrustSurfaceDmarcContext> {\n\ttry {\n\t\tconst dmarcRecords = await queryTxtRecords(`_dmarc.${domain}`, dnsOptions);\n\t\tconst dmarcRecord = dmarcRecords.find((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\n\t\tif (!dmarcRecord) {\n\t\t\treturn {\n\t\t\t\tcorroboratedByWeakDmarc: true,\n\t\t\t\tdmarcPolicy: 'missing',\n\t\t\t\tdmarcAlignmentMode: 'missing',\n\t\t\t};\n\t\t}\n\n\t\tconst tags = parseDmarcTags(dmarcRecord);\n\t\tconst policy = tags.get('p') ?? 'none';\n\t\tconst pct = tags.get('pct') ?? '100';\n\t\tconst aspf = tags.get('aspf') ?? 'r';\n\t\tconst adkim = tags.get('adkim') ?? 'r';\n\t\tconst enforcementWeak = policy !== 'reject' || pct !== '100';\n\t\tconst alignmentWeak = aspf !== 's' || adkim !== 's';\n\t\tconst alignmentMode = aspf === 's' && adkim === 's' ? 'strict' : 'relaxed';\n\n\t\treturn {\n\t\t\tcorroboratedByWeakDmarc: enforcementWeak && alignmentWeak,\n\t\t\tdmarcPolicy: pct === '100' ? policy : `${policy}; pct=${pct}`,\n\t\t\tdmarcAlignmentMode: alignmentMode,\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tcorroboratedByWeakDmarc: false,\n\t\t\tdmarcPolicy: 'unknown',\n\t\t\tdmarcAlignmentMode: 'unknown',\n\t\t};\n\t}\n}\n\n/**\n * Check SPF records for a domain.\n * Looks for v=spf1 TXT records and validates their configuration.\n * Recursively expands include chains to compute true DNS lookup count.\n */\nexport async function checkSpf(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst txtRecords = await queryTxtRecords(domain, dnsOptions);\n\n\t// Filter for SPF records\n\tconst spfRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=spf1'));\n\n\tif (spfRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'No SPF record found',\n\t\t\t\t'critical',\n\t\t\t\t`No SPF (v=spf1) TXT record found for ${domain}. Without SPF, any server can send email claiming to be from your domain.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('spf', findings);\n\t}\n\n\tif (spfRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Multiple SPF records',\n\t\t\t\t'high',\n\t\t\t\t`Found ${spfRecords.length} SPF records. RFC 7208 requires exactly one SPF record per domain. Multiple records cause unpredictable behavior.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst spf = spfRecords[0];\n\tconst spfSignals = extractSpfSignalDomains(spf);\n\tconst spfMetadata = {\n\t\tsignalType: 'spf',\n\t\tincludeDomains: spfSignals.includeDomains,\n\t\t...(spfSignals.redirectDomain ? { redirectDomain: spfSignals.redirectDomain } : {}),\n\t};\n\n\t// Check for redirect= — determines whether missing 'all' is an issue\n\tconst hasRedirect = /\\bredirect=/i.test(spf);\n\n\t// Check for overly permissive +all or ?all\n\tconst allMechanism = spf.match(/[+?~-]all/i);\n\tif (allMechanism) {\n\t\tconst qualifier = allMechanism[0];\n\t\tif (RISKY_MECHANISMS.includes(qualifier.toLowerCase())) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t`Permissive SPF: ${qualifier}`,\n\t\t\t\t\t'critical',\n\t\t\t\t\t`SPF record uses \"${qualifier}\" which allows any server to send email as ${domain}. Use \"-all\" (hard fail) or \"~all\" (soft fail) instead.`,\n\t\t\t\t\tspfMetadata,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (qualifier.toLowerCase() === '~all') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t'SPF soft fail (~all)',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SPF record uses \"~all\" (soft fail). Consider upgrading to \"-all\" (hard fail) for stricter enforcement once you've verified all legitimate senders are included.`,\n\t\t\t\t\tspfMetadata,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\t// -all is the recommended setting, no finding needed\n\t} else if (!hasRedirect) {\n\t\t// RFC 7208 §6.1: redirect= replaces the entire record, making 'all' irrelevant\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t\"No 'all' mechanism\",\n\t\t\t\t'medium',\n\t\t\t\t`SPF record does not end with an \"all\" mechanism. Without it, the default behavior is neutral, which provides weak protection.`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for overly broad IP ranges\n\tfindings.push(...checkBroadIpRanges(spf, spfMetadata));\n\n\t// Recursive DNS lookup budget (RFC 7208 §4.6.4)\n\tconst state: RecursiveState = {\n\t\ttotalQueries: 0,\n\t\tvisited: new Set([domain]),\n\t\tcache: new Map(),\n\t\tfindings: [],\n\t\tcircularDetected: false,\n\t};\n\tconst recursiveLookupCount = await countRecursiveLookups(spf, 0, state, dnsOptions);\n\n\t// Add any circular-include findings from recursive expansion\n\tfindings.push(...state.findings);\n\n\tif (recursiveLookupCount > 10) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Too many DNS lookups',\n\t\t\t\t'critical',\n\t\t\t\t`SPF record requires ${recursiveLookupCount} DNS lookups (limit: 10). Receivers may return PermError and reject legitimate mail.`,\n\t\t\t\t{ ...spfMetadata, lookupCount: recursiveLookupCount },\n\t\t\t),\n\t\t);\n\t} else if (recursiveLookupCount >= 9) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'SPF lookup budget near limit',\n\t\t\t\t'high',\n\t\t\t\t`SPF record requires ${recursiveLookupCount}/10 DNS lookups. Any future sender additions may push this domain into permanent SPF failures.`,\n\t\t\t\t{ ...spfMetadata, lookupCount: recursiveLookupCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for deprecated ptr mechanism\n\tif (/\\bptr\\b/i.test(spf)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'Deprecated ptr mechanism',\n\t\t\t\t'medium',\n\t\t\t\t`SPF record uses the \"ptr\" mechanism which is deprecated in RFC 7208 due to performance and reliability issues.`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Trust surface analysis — flag multi-tenant SaaS platform includes\n\tconst trustSurfaceContext = await getTrustSurfaceDmarcContext(domain, dnsOptions);\n\tconst trustSurfaceFindings = analyzeTrustSurface(spf, trustSurfaceContext);\n\tfindings.push(...trustSurfaceFindings);\n\n\t// Informational trust-surface findings should not suppress the clean SPF status.\n\tconst issueFindings = findings.filter((f) => !(f.metadata?.trustSurface && f.severity === 'info'));\n\tif (issueFindings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t'SPF record configured',\n\t\t\t\t'info',\n\t\t\t\t`SPF record found and properly configured: ${spf.substring(0, 100)}${spf.length > 100 ? '...' : ''}`,\n\t\t\t\tspfMetadata,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('spf', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { createFinding } from '../lib/scoring';\nimport type { Finding } from '../lib/scoring';\n\n/** Parse DMARC tag-value pairs from a DMARC record string. */\nexport function parseDmarcTags(record: string): Map<string, string> {\n\tconst tags = new Map<string, string>();\n\tconst parts = record.split(';');\n\tfor (const part of parts) {\n\t\tconst trimmed = part.trim();\n\t\tconst eqIndex = trimmed.indexOf('=');\n\t\tif (eqIndex > 0) {\n\t\t\tconst key = trimmed.substring(0, eqIndex).trim().toLowerCase();\n\t\t\tconst value = trimmed.substring(eqIndex + 1).trim().toLowerCase();\n\t\t\ttags.set(key, value);\n\t\t}\n\t}\n\treturn tags;\n}\n\n/** Extract the domain part from a mailto: URI, stripping optional size suffix. */\nexport function extractDomainFromMailto(uri: string): string | null {\n\tconst trimmed = uri.trim().toLowerCase();\n\tif (!trimmed.startsWith('mailto:')) return null;\n\tlet email = trimmed.substring(7).trim();\n\temail = email.replace(/![0-9]+[kmgt]?$/i, '');\n\tconst atIndex = email.lastIndexOf('@');\n\tif (atIndex < 0) return null;\n\treturn email.substring(atIndex + 1);\n}\n\n/**\n * Validate DMARC URI format (must be mailto: scheme).\n * Strips the optional RFC 7489 §6.2 size limit suffix before checking.\n */\nexport function isValidDmarcUri(uri: string): boolean {\n\tconst trimmed = uri.trim().toLowerCase();\n\tif (!trimmed.startsWith('mailto:')) {\n\t\treturn false;\n\t}\n\tlet email = trimmed.substring(7).trim();\n\temail = email.replace(/![0-9]+[kmgt]?$/i, '');\n\treturn /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n}\n\n/** Detect known third-party DMARC aggregator services. */\nexport function detectThirdPartyAggregators(uris: string[]): string[] {\n\tconst knownAggregators = [\n\t\t'dmarcian.com',\n\t\t'agari.com',\n\t\t'valimail.com',\n\t\t'returnpath.com',\n\t\t'postmarkapp.com',\n\t\t'dmarcanalyzer.com',\n\t\t'mimecast.com',\n\t\t'proofpoint.com',\n\t\t'250ok.com',\n\t\t'easydmarc.com',\n\t\t'sendmarc.com',\n\t\t'ondmarc.com',\n\t\t'dmarcdigest.com',\n\t\t'dmarcly.com',\n\t\t'powerdmarc.com',\n\t\t'redsift.com',\n\t];\n\n\tconst detected: string[] = [];\n\tfor (const uri of uris) {\n\t\tconst lower = uri.toLowerCase();\n\t\tfor (const aggregator of knownAggregators) {\n\t\t\tif (lower.includes(aggregator) && !detected.includes(aggregator)) {\n\t\t\t\tdetected.push(aggregator);\n\t\t\t}\n\t\t}\n\t}\n\treturn detected;\n}\n\n/**\n * Check cross-domain RUA authorization per RFC 7489 §7.1.\n * When rua= points to a third-party domain, verify authorization TXT records.\n */\nexport async function checkRuaAuthorization(domain: string, ruaUris: string[], dnsOptions?: QueryDnsOptions): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\tconst checkedDomains = new Set<string>();\n\n\tfor (const uri of ruaUris) {\n\t\tconst targetDomain = extractDomainFromMailto(uri);\n\t\tif (!targetDomain || targetDomain === domain || checkedDomains.has(targetDomain)) continue;\n\t\tcheckedDomains.add(targetDomain);\n\n\t\ttry {\n\t\t\tconst authRecords = await queryTxtRecords(`${domain}._report._dmarc.${targetDomain}`, dnsOptions);\n\t\t\tconst hasAuth = authRecords.some((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\t\t\tif (!hasAuth) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'dmarc',\n\t\t\t\t\t\t'Third-party aggregate reporting not authorized',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`Aggregate reports sent to ${targetDomain} will be silently discarded. The authorization record ${domain}._report._dmarc.${targetDomain} must contain a TXT record with \"v=DMARC1\" (RFC 7489 §7.1).`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} catch {\n\t\t\t// DNS query failed — don't produce a finding for transient errors.\n\t\t}\n\t}\n\n\treturn findings;\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\n/** Known risky SPF mechanisms that allow broad sending. */\nexport const RISKY_MECHANISMS = ['+all', '?all'];\n\n/** Maximum recursion depth for SPF include expansion. */\nexport const MAX_RECURSION_DEPTH = 10;\n\n/** Maximum total DNS queries during recursive expansion. */\nexport const MAX_RECURSIVE_QUERIES = 10;\n\nexport type SpfLookupAnalysis = {\n\tcount: number;\n\tmechanisms: string[];\n};\n\nexport type RecursiveState = {\n\ttotalQueries: number;\n\tvisited: Set<string>;\n\tcache: Map<string, SpfLookupAnalysis>;\n\tfindings: Finding[];\n\tcircularDetected: boolean;\n};\n\n/**\n * Count SPF mechanisms that consume DNS lookups in a single record (non-recursive).\n * RFC 7208 limits evaluation to 10 DNS-mechanism lookups.\n */\nexport function analyzeSpfLookupBudget(spfRecord: string): SpfLookupAnalysis {\n\tconst mechanisms: string[] = [];\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\t\tif (normalized.startsWith('include:')) mechanisms.push('include');\n\t\telse if (normalized === 'a' || normalized.startsWith('a:') || normalized.startsWith('a/')) mechanisms.push('a');\n\t\telse if (normalized === 'mx' || normalized.startsWith('mx:') || normalized.startsWith('mx/')) mechanisms.push('mx');\n\t\telse if (normalized === 'ptr' || normalized.startsWith('ptr:')) mechanisms.push('ptr');\n\t\telse if (normalized.startsWith('exists:')) mechanisms.push('exists');\n\t\t// Note: redirect= is a modifier (RFC 7208 §6.1), not a mechanism.\n\t\t// It does not consume a DNS lookup slot itself — the target record's\n\t\t// mechanisms are counted when countRecursiveLookups recurses into it.\n\t}\n\n\treturn { count: mechanisms.length, mechanisms };\n}\n\n/**\n * Extract include domains and redirect domain from an SPF record.\n * Used by scan-domain provider inference — do not change the return shape.\n */\nexport function extractSpfSignalDomains(spfRecord: string): { includeDomains: string[]; redirectDomain?: string } {\n\tconst includeDomains = Array.from(spfRecord.matchAll(/\\binclude:([^\\s]+)/gi))\n\t\t.map((match) => match[1].trim().toLowerCase())\n\t\t.filter((domain) => domain.length > 0);\n\n\tconst redirectMatch = spfRecord.match(/\\bredirect=([^\\s]+)/i);\n\tconst redirectDomain = redirectMatch?.[1]?.trim().toLowerCase();\n\n\treturn {\n\t\tincludeDomains,\n\t\t...(redirectDomain ? { redirectDomain } : {}),\n\t};\n}\n\n/** Extract domains referenced by include: and redirect= mechanisms. */\nexport function extractLookupDomains(spfRecord: string): { includes: string[]; redirect?: string } {\n\tconst includes: string[] = [];\n\tlet redirect: string | undefined;\n\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\t\tif (normalized.startsWith('include:')) {\n\t\t\tconst domain = normalized.slice('include:'.length);\n\t\t\tif (domain) includes.push(domain);\n\t\t} else if (normalized.startsWith('redirect=')) {\n\t\t\tconst domain = normalized.slice('redirect='.length);\n\t\t\tif (domain) redirect = domain;\n\t\t}\n\t}\n\n\treturn { includes, redirect };\n}\n\n/**\n * Recursively count all DNS-lookup-generating mechanisms across SPF include chains.\n * Tracks visited domains to detect circular includes.\n */\nexport async function countRecursiveLookups(\n\tspfRecord: string,\n\tdepth: number,\n\tstate: RecursiveState,\n\tdnsOptions?: QueryDnsOptions,\n): Promise<number> {\n\tconst local = analyzeSpfLookupBudget(spfRecord);\n\tlet totalCount = local.count;\n\n\tif (depth >= MAX_RECURSION_DEPTH) {\n\t\treturn totalCount;\n\t}\n\n\tconst { includes, redirect } = extractLookupDomains(spfRecord);\n\tconst domainsToResolve = [...includes];\n\tif (redirect) domainsToResolve.push(redirect);\n\n\tfor (const targetDomain of domainsToResolve) {\n\t\tif (state.visited.has(targetDomain)) {\n\t\t\tif (!state.circularDetected) {\n\t\t\t\tstate.circularDetected = true;\n\t\t\t\tstate.findings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Circular SPF include detected',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF include chain contains a circular reference involving ${targetDomain}. This will cause SPF evaluation to fail.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (state.cache.has(targetDomain)) {\n\t\t\ttotalCount += state.cache.get(targetDomain)!.count;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (state.totalQueries >= MAX_RECURSIVE_QUERIES) {\n\t\t\tbreak;\n\t\t}\n\n\t\tstate.visited.add(targetDomain);\n\t\tstate.totalQueries++;\n\n\t\ttry {\n\t\t\tconst txtRecords = await queryTxtRecords(targetDomain, dnsOptions);\n\t\t\tconst nestedSpf = txtRecords.find((record) => record.toLowerCase().startsWith('v=spf1'));\n\n\t\t\tif (nestedSpf) {\n\t\t\t\tconst nestedCount = await countRecursiveLookups(nestedSpf, depth + 1, state, dnsOptions);\n\t\t\t\tstate.cache.set(targetDomain, { count: nestedCount, mechanisms: [] });\n\t\t\t\ttotalCount += nestedCount;\n\t\t\t}\n\t\t} catch {\n\t\t\t// DNS query failed for nested domain — local mechanism count already includes the lookup.\n\t\t}\n\n\t\tstate.visited.delete(targetDomain);\n\t}\n\n\treturn totalCount;\n}\n\n/**\n * Check for overly broad IP ranges in SPF record.\n * Returns findings for ip4 prefixes <= /8 and ip6 prefixes <= /16.\n */\nexport function checkBroadIpRanges(spfRecord: string, metadata: Record<string, unknown>): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tfor (const token of spfRecord.split(/\\s+/)) {\n\t\tif (!token) continue;\n\t\tconst normalized = token.replace(/^[+\\-~?]/, '').toLowerCase();\n\n\t\tconst ip4Match = normalized.match(/^ip4:([^/]+)(?:\\/(\\d+))?$/);\n\t\tif (ip4Match) {\n\t\t\tconst prefix = ip4Match[2] ? parseInt(ip4Match[2], 10) : 32;\n\t\t\tif (prefix <= 8) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Overly broad IP range',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF record contains \"${token}\" which authorizes an extremely large IP range (/${prefix}). This undermines SPF protection by allowing too many servers to send mail.`,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst ip6Match = normalized.match(/^ip6:([^/]+)(?:\\/(\\d+))?$/);\n\t\tif (ip6Match) {\n\t\t\tconst prefix = ip6Match[2] ? parseInt(ip6Match[2], 10) : 128;\n\t\t\tif (prefix <= 16) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'spf',\n\t\t\t\t\t\t'Overly broad IPv6 range',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`SPF record contains \"${token}\" which authorizes an extremely large IPv6 range (/${prefix}). This undermines SPF protection by allowing too many servers to send mail.`,\n\t\t\t\t\t\tmetadata,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn findings;\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SPF Trust Surface Analysis.\n * Identifies when SPF include: or redirect= directives delegate sending\n * authority to multi-tenant SaaS platforms, expanding the domain's trust surface.\n */\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\ninterface PlatformInfo {\n\tname: string;\n\trisk: string;\n}\n\nexport interface TrustSurfaceContext {\n\tcorroboratedByWeakDmarc?: boolean;\n\tdmarcPolicy?: string;\n\tdmarcAlignmentMode?: string;\n}\n\n/** Known multi-tenant SaaS platforms whose shared SPF includes widen the trust surface. */\nconst MULTI_TENANT_PLATFORMS: ReadonlyMap<string, PlatformInfo> = new Map([\n\t['_spf.salesforce.com', { name: 'Salesforce', risk: 'Any Salesforce customer can send as your domain' }],\n\t[\n\t\t'spf.protection.outlook.com',\n\t\t{ name: 'Microsoft 365', risk: 'Any M365 tenant can send as your domain without DKIM/DMARC enforcement' },\n\t],\n\t['_spf.google.com', { name: 'Google Workspace', risk: 'Any Google Workspace customer can send as your domain' }],\n\t['sendgrid.net', { name: 'SendGrid', risk: 'Any SendGrid customer can send as your domain' }],\n\t['spf.mandrillapp.com', { name: 'Mailchimp/Mandrill', risk: 'Any Mailchimp customer can send as your domain' }],\n\t['mail.zendesk.com', { name: 'Zendesk', risk: 'Any Zendesk customer can send as your domain' }],\n\t['stspg-customer.com', { name: 'Postmark', risk: 'Any Postmark customer can send as your domain' }],\n\t['spf.brevo.com', { name: 'Brevo (Sendinblue)', risk: 'Any Brevo customer can send as your domain' }],\n\t['amazonses.com', { name: 'Amazon SES', risk: 'Any SES customer can send as your domain' }],\n\t['servers.mcsv.net', { name: 'Mailchimp', risk: 'Any Mailchimp customer can send as your domain' }],\n\t['hubspotemail.net', { name: 'HubSpot', risk: 'Any HubSpot customer can send as your domain' }],\n\t['mktomail.com', { name: 'Marketo', risk: 'Any Marketo customer can send as your domain' }],\n\t['pphosted.com', { name: 'Proofpoint', risk: 'Any Proofpoint customer can send as your domain' }],\n\t['firebasemail.com', { name: 'Firebase', risk: 'Any Firebase project can send as your domain' }],\n\t['freshdesk.com', { name: 'Freshdesk', risk: 'Any Freshdesk customer can send as your domain' }],\n\t['spf.messagelabs.com', { name: 'Symantec/Broadcom', risk: 'Shared sending infrastructure' }],\n\t['_spf.atlassian.net', { name: 'Atlassian', risk: 'Any Atlassian customer can send as your domain' }],\n\t['xero.com', { name: 'Xero', risk: 'Any Xero customer can send as your domain' }],\n]);\n\n/**\n * Check whether a domain matches or is a subdomain of a known multi-tenant platform.\n */\nfunction matchPlatform(domain: string): { key: string; info: PlatformInfo } | undefined {\n\tconst lower = domain.toLowerCase();\n\tfor (const [key, info] of MULTI_TENANT_PLATFORMS) {\n\t\tif (lower === key || lower.endsWith(`.${key}`)) {\n\t\t\treturn { key, info };\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Extract include: and redirect= domains from an SPF record string.\n */\nfunction extractIncludeAndRedirectDomains(spfRecord: string): string[] {\n\tconst domains: string[] = [];\n\tconst includeRegex = /\\binclude:([^\\s]+)/gi;\n\tconst redirectRegex = /\\bredirect=([^\\s]+)/gi;\n\n\tlet match: RegExpExecArray | null;\n\twhile ((match = includeRegex.exec(spfRecord)) !== null) {\n\t\tdomains.push(match[1]);\n\t}\n\twhile ((match = redirectRegex.exec(spfRecord)) !== null) {\n\t\tdomains.push(match[1]);\n\t}\n\treturn domains;\n}\n\n/**\n * Analyze an SPF record for trust surface exposure from multi-tenant SaaS platform includes.\n * Returns findings for each shared platform detected, plus a summary finding when multiple are found.\n */\nexport function analyzeTrustSurface(spfRecord: string, context: TrustSurfaceContext = {}): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst domains = extractIncludeAndRedirectDomains(spfRecord);\n\tconst matchedPlatforms: { name: string; includeDomain: string }[] = [];\n\tconst corroboratedByWeakDmarc = context.corroboratedByWeakDmarc === true;\n\tconst findingSeverity = corroboratedByWeakDmarc ? 'medium' : 'info';\n\tconst summarySeverity = corroboratedByWeakDmarc ? 'high' : 'info';\n\tconst detailSuffix = corroboratedByWeakDmarc\n\t\t? 'Weak DMARC enforcement and relaxed alignment corroborate this exposure, so a provider misconfiguration or abuse case would be more likely to pass policy checks.'\n\t\t: 'This is common and not inherently a misconfiguration, but it expands the sending infrastructure you rely on. The risk becomes more material when DMARC enforcement and alignment are weak.';\n\n\tfor (const domain of domains) {\n\t\tconst result = matchPlatform(domain);\n\t\tif (result) {\n\t\t\tmatchedPlatforms.push({ name: result.info.name, includeDomain: domain });\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'spf',\n\t\t\t\t\t`SPF delegates to shared platform: ${result.info.name}`,\n\t\t\t\t\tfindingSeverity,\n\t\t\t\t\t`SPF include:${domain} authorizes ${result.info.name}. ${result.info.risk}. ${detailSuffix}`,\n\t\t\t\t\t{\n\t\t\t\t\t\ttrustSurface: true,\n\t\t\t\t\t\tplatform: result.info.name,\n\t\t\t\t\t\tincludeDomain: domain,\n\t\t\t\t\t\tdmarcCorroborated: corroboratedByWeakDmarc,\n\t\t\t\t\t\t...(context.dmarcPolicy ? { dmarcPolicy: context.dmarcPolicy } : {}),\n\t\t\t\t\t\t...(context.dmarcAlignmentMode ? { dmarcAlignmentMode: context.dmarcAlignmentMode } : {}),\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (matchedPlatforms.length > 1) {\n\t\tconst platformNames = matchedPlatforms.map((p) => p.name).join(', ');\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'spf',\n\t\t\t\t`SPF trust surface: ${matchedPlatforms.length} shared platforms`,\n\t\t\t\tsummarySeverity,\n\t\t\t\t`SPF record delegates sending authority to ${matchedPlatforms.length} multi-tenant platforms (${platformNames}). Audit each include to confirm it is still needed, configure provider-specific DKIM, and keep DMARC enforcement and alignment strong across every authorized sender.`,\n\t\t\t\t{\n\t\t\t\t\ttrustSurface: true,\n\t\t\t\t\tplatformCount: matchedPlatforms.length,\n\t\t\t\t\tplatforms: platformNames,\n\t\t\t\t\tdmarcCorroborated: corroboratedByWeakDmarc,\n\t\t\t\t\t...(context.dmarcPolicy ? { dmarcPolicy: context.dmarcPolicy } : {}),\n\t\t\t\t\t...(context.dmarcAlignmentMode ? { dmarcAlignmentMode: context.dmarcAlignmentMode } : {}),\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DMARC (Domain-based Message Authentication, Reporting & Conformance) check tool.\n * Queries _dmarc TXT records and validates the policy.\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { checkRuaAuthorization, detectThirdPartyAggregators, isValidDmarcUri, parseDmarcTags } from './dmarc-utils';\n\nexport { parseDmarcTags } from './dmarc-utils';\n\n/**\n * Check DMARC records for a domain.\n * Queries _dmarc.<domain> TXT records and validates policy configuration.\n */\nexport async function checkDmarc(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst txtRecords = await queryTxtRecords(`_dmarc.${domain}`, dnsOptions);\n\n\t// Filter for DMARC records\n\tconst dmarcRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\n\tif (dmarcRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No DMARC record found',\n\t\t\t\t'critical',\n\t\t\t\t`No DMARC record found at _dmarc.${domain}. Without DMARC, receivers cannot verify email authentication and spoofing is easier.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('dmarc', findings);\n\t}\n\n\tif (dmarcRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Multiple DMARC records',\n\t\t\t\t'high',\n\t\t\t\t`Found ${dmarcRecords.length} DMARC records. Only one DMARC record should exist per domain.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst dmarc = dmarcRecords[0];\n\tconst tags = parseDmarcTags(dmarc);\n\tconst validPolicies = new Set(['none', 'quarantine', 'reject']);\n\n\t// Check policy (p= tag)\n\tconst policy = tags.get('p');\n\tif (!policy) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Missing DMARC policy',\n\t\t\t\t'critical',\n\t\t\t\t`DMARC record is missing the required \"p=\" tag. Without a policy, DMARC provides no protection.`,\n\t\t\t),\n\t\t);\n\t} else if (!validPolicies.has(policy)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid DMARC policy value',\n\t\t\t\t'high',\n\t\t\t\t`DMARC policy value \"${policy}\" is invalid. Allowed values are none, quarantine, or reject.`,\n\t\t\t),\n\t\t);\n\t} else if (policy === 'none') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC policy set to none',\n\t\t\t\t'high',\n\t\t\t\t`DMARC policy is \"none\" which only monitors but does not reject or quarantine spoofed emails. Consider upgrading to \"quarantine\" or \"reject\".`,\n\t\t\t),\n\t\t);\n\t} else if (policy === 'quarantine') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC policy set to quarantine',\n\t\t\t\t'low',\n\t\t\t\t`DMARC policy is \"quarantine\". Consider upgrading to \"reject\" for maximum protection once you've verified legitimate email flows.`,\n\t\t\t),\n\t\t);\n\t}\n\t// \"reject\" is the strongest setting - no finding needed\n\n\t// Check subdomain policy (sp= tag)\n\tconst sp = tags.get('sp');\n\tif (!sp && policy === 'reject') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No subdomain policy',\n\t\t\t\t'low',\n\t\t\t\t`No subdomain policy (sp=) specified. Subdomains inherit the main policy (\"${policy}\"), but explicitly setting sp= is recommended.`,\n\t\t\t),\n\t\t);\n\t} else if (!sp && policy === 'none') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Subdomains inherit p=none policy',\n\t\t\t\t'info',\n\t\t\t\t'No subdomain policy (sp=) specified. Subdomains inherit the \"none\" policy, which provides no protection against spoofing.',\n\t\t\t),\n\t\t);\n\t} else if (sp) {\n\t\tif (!validPolicies.has(sp)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid subdomain policy value',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC subdomain policy value \"${sp}\" is invalid. Allowed values are none, quarantine, or reject.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'reject' && sp === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than parent policy',\n\t\t\t\t\t'high',\n\t\t\t\t\t'Subdomain policy is set to \"none\" while parent policy is \"reject\". This leaves subdomains vulnerable to spoofing.',\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'reject' && sp === 'quarantine') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than parent policy',\n\t\t\t\t\t'low',\n\t\t\t\t\t'Subdomain policy is \"quarantine\" while parent policy is \"reject\". Consider using sp=reject for consistent enforcement.',\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (policy === 'quarantine' && sp === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Subdomain policy weaker than domain policy',\n\t\t\t\t\t'medium',\n\t\t\t\t\t'Subdomain policy is set to \"none\" while domain policy is \"quarantine\". Subdomains are unprotected against spoofing.',\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check percentage (pct= tag)\n\tconst pct = tags.get('pct');\n\tif (pct) {\n\t\tconst pctValue = Number.parseInt(pct, 10);\n\t\tif (!Number.isFinite(pctValue) || Number.isNaN(pctValue) || pctValue < 0 || pctValue > 100) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid DMARC percentage value',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC pct value \"${pct}\" is invalid. Allowed range is 0-100.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (pctValue < 100) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC not applied to all emails',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC pct=${pctValue} means the policy only applies to ${pctValue}% of emails. Set pct=100 for full coverage.`,\n\t\t\t),\n\t\t);\n\t\t}\n\t}\n\n\t// Check forensic failure reporting options (fo=)\n\tconst fo = tags.get('fo');\n\tif (fo) {\n\t\tconst allowedFoValues = new Set(['0', '1', 'd', 's']);\n\t\tconst foValues = fo\n\t\t\t.split(':')\n\t\t\t.map((v) => v.trim())\n\t\t\t.filter((v) => v.length > 0);\n\n\t\tconst invalidFo = foValues.filter((v) => !allowedFoValues.has(v));\n\t\tif (foValues.length === 0 || invalidFo.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid DMARC failure reporting options',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC fo value \"${fo}\" contains unsupported option(s): ${invalidFo.join(', ') || 'none'}. Allowed values: 0, 1, d, s.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (foValues.length === 1 && foValues[0] === '0') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Limited DMARC failure reporting coverage',\n\t\t\t\t\t'low',\n\t\t\t\t\t'DMARC fo=0 only generates forensic reports when both SPF and DKIM fail. Consider fo=1 for broader failure visibility.',\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for reporting (rua= tag)\n\tconst rua = tags.get('rua');\n\tif (!rua) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No aggregate reporting',\n\t\t\t\t'medium',\n\t\t\t\t`No aggregate report URI (rua=) specified. Without reporting, you cannot monitor DMARC authentication results.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// Validate rua= URI format\n\t\tconst ruaUris = rua.split(',').map((u) => u.trim());\n\t\tconst invalidRuaUris = ruaUris.filter((uri) => !isValidDmarcUri(uri));\n\t\tif (invalidRuaUris.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid aggregate report URI format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC aggregate report URI(s) invalid: ${invalidRuaUris.join(', ')}. Must use mailto: scheme.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Check for third-party aggregator services\n\t\tconst aggregators = detectThirdPartyAggregators(ruaUris);\n\t\tif (aggregators.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Third-party DMARC aggregator detected',\n\t\t\t\t\t'info',\n\t\t\t\t\t`Using third-party aggregator(s): ${aggregators.join(', ')}. Ensure these services are authorized to receive your DMARC reports.`,\n\t\t\t\t\t{ aggregators },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Cross-domain RUA authorization check (RFC 7489 §7.1)\n\t\tconst ruaAuthFindings = await checkRuaAuthorization(domain, ruaUris, dnsOptions);\n\t\tfindings.push(...ruaAuthFindings);\n\t}\n\n\t// Check forensic reporting (ruf= tag)\n\tconst ruf = tags.get('ruf');\n\tif (ruf) {\n\t\tconst rufUris = ruf.split(',').map((u) => u.trim());\n\t\tconst invalidRufUris = rufUris.filter((uri) => !isValidDmarcUri(uri));\n\t\tif (invalidRufUris.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dmarc',\n\t\t\t\t\t'Invalid forensic report URI format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`DMARC forensic report URI(s) invalid: ${invalidRufUris.join(', ')}. Must use mailto: scheme.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} else if (rua) {\n\t\t// rua= is present but ruf= is not\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'No forensic reporting configured (ruf= absent)',\n\t\t\t\t'low',\n\t\t\t\t'Aggregate reporting (rua=) is configured but forensic reporting (ruf=) is not. Forensic reports provide detailed failure information useful for troubleshooting.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check DKIM alignment mode (adkim= tag)\n\tconst adkim = tags.get('adkim');\n\tif (adkim && adkim !== 'r' && adkim !== 's') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid DKIM alignment mode',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC adkim value \"${adkim}\" is invalid. Allowed values are \"r\" (relaxed) or \"s\" (strict).`,\n\t\t\t),\n\t\t);\n\t} else if (!adkim || adkim === 'r') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Relaxed DKIM alignment',\n\t\t\t\t'low',\n\t\t\t\t`DKIM alignment mode is relaxed (adkim=r or unset). Consider adkim=s (strict) for stronger authentication.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check SPF alignment mode (aspf= tag)\n\tconst aspf = tags.get('aspf');\n\tif (aspf && aspf !== 'r' && aspf !== 's') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Invalid SPF alignment mode',\n\t\t\t\t'medium',\n\t\t\t\t`DMARC aspf value \"${aspf}\" is invalid. Allowed values are \"r\" (relaxed) or \"s\" (strict).`,\n\t\t\t),\n\t\t);\n\t} else if (!aspf || aspf === 'r') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'Relaxed SPF alignment',\n\t\t\t\t'low',\n\t\t\t\t`SPF alignment mode is relaxed (aspf=r or unset). Consider aspf=s (strict) for stronger authentication.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no critical, high, or medium issues found, add info\n\tconst hasSignificantIssues = findings.some((f) => f.severity === 'critical' || f.severity === 'high' || f.severity === 'medium');\n\tif (!hasSignificantIssues) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dmarc',\n\t\t\t\t'DMARC properly configured',\n\t\t\t\t'info',\n\t\t\t\t`DMARC record found with policy \"${policy}\" and valid core tags.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dmarc', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DKIM (DomainKeys Identified Mail) check tool.\n * Queries common DKIM selector TXT records and validates configuration.\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { analyzeKeyStrength, consolidateSelectorProbeKeyStrengthFindings, getDkimTagValue } from './dkim-analysis';\n\n/** Common DKIM selectors used by major email providers */\nconst COMMON_SELECTORS = [\n\t'default',\n\t'google',\n\t'20230601', // Google Workspace\n\t'selector1', // Microsoft 365\n\t'selector2', // Microsoft 365\n\t'k1', // Mailchimp\n\t's1',\n\t's2',\n\t'mail',\n\t'dkim',\n\t'amazonses', // Amazon SES\n\t'zoho', // Zoho Mail\n];\n\n/**\n * Check DKIM records for a domain.\n * Probes common selectors at <selector>._domainkey.<domain>.\n * Optionally accepts a specific selector to check.\n */\nexport async function checkDkim(domain: string, selector?: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst selectorsToCheck = selector ? [selector] : COMMON_SELECTORS;\n\tconst foundSelectors: string[] = [];\n\tlet hasValidKey = false;\n\n\t// Check each selector in parallel\n\tconst results = await Promise.all(\n\t\tselectorsToCheck.map(async (sel) => {\n\t\t\ttry {\n\t\t\t\tconst records = await queryTxtRecords(`${sel}._domainkey.${domain}`, dnsOptions);\n\t\t\t\tconst dkimRecords = records.filter((r) => r.toLowerCase().includes('v=dkim1') || r.includes('p='));\n\t\t\t\treturn { selector: sel, records: dkimRecords };\n\t\t\t} catch {\n\t\t\t\treturn { selector: sel, records: [] };\n\t\t\t}\n\t\t}),\n\t);\n\n\tfor (const result of results) {\n\t\tif (result.records.length > 0) {\n\t\t\tfoundSelectors.push(result.selector);\n\n\t\t\t// Validate each DKIM record\n\t\t\tfor (const record of result.records) {\n\t\t\t\tconst isRevoked = /p=\\s*;/i.test(record) || /p=\\s*$/i.test(record);\n\t\t\t\tconst publicKey = getDkimTagValue(record, 'p');\n\n\t\t\t\t// Check for empty public key (revoked)\n\t\t\t\tif (isRevoked) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Revoked DKIM key: ${result.selector}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" has an empty public key (p=), indicating the key has been revoked.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\thasValidKey = true;\n\t\t\t\t}\n\n\t\t\t\t// Check key type (should be rsa or ed25519)\n\t\t\t\tconst keyTypeMatch = record.match(/k=([^;\\s]+)/i);\n\t\t\t\tconst parsedKeyType = keyTypeMatch ? keyTypeMatch[1].toLowerCase() : null;\n\t\t\t\tif (keyTypeMatch && !['rsa', 'ed25519'].includes(parsedKeyType!)) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Unknown DKIM key type: ${keyTypeMatch[1]}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" uses unknown key type \"${keyTypeMatch[1]}\". Expected \"rsa\" or \"ed25519\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Check for testing mode\n\t\t\t\tif (/t=y/i.test(record)) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`DKIM in testing mode: ${result.selector}`,\n\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" is in testing mode (t=y). Verifiers may treat failures as non-fatal.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Analyze key strength (only if key is valid/not revoked)\n\t\t\t\t// Use 'rsa-default' when no k= tag is present (RFC 6376 defaults to rsa)\n\t\t\t\t// to distinguish from an explicit k=rsa declaration\n\t\t\t\tif (!isRevoked && publicKey) {\n\t\t\t\t\tconst declaredKeyType = parsedKeyType ?? 'rsa-default';\n\t\t\t\t\tconst keyAnalysis = analyzeKeyStrength(publicKey, declaredKeyType);\n\n\t\t\t\t\tif (keyAnalysis.keyType === 'ed25519') {\n\t\t\t\t\t\t// Ed25519 is always strong — emit an info finding\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t`Ed25519 key detected: ${result.selector}`,\n\t\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" uses Ed25519, a strong elliptic-curve key type.`,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tkeyType: 'ed25519',\n\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (keyAnalysis.keyType === 'unknown') {\n\t\t\t\t\t\t// Short key with no k= tag — could be Ed25519 without the tag\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t`Short key material: ${result.selector}`,\n\t\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" has very short key material without a k= tag. Consider adding \"k=ed25519\" or \"k=rsa\" for clarity.`,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t} else if (keyAnalysis.keyType === 'rsa') {\n\t\t\t\t\t\tconst severityMsg =\n\t\t\t\t\t\t\tkeyAnalysis.strength === 'critical'\n\t\t\t\t\t\t\t\t? 'weak'\n\t\t\t\t\t\t\t\t: keyAnalysis.strength === 'high'\n\t\t\t\t\t\t\t\t\t? 'legacy'\n\t\t\t\t\t\t\t\t\t: keyAnalysis.strength === 'medium'\n\t\t\t\t\t\t\t\t\t\t? 'below recommended'\n\t\t\t\t\t\t\t\t\t\t: 'strong';\n\t\t\t\t\t\tconst descriptions: Record<string, string> = {\n\t\t\t\t\t\t\tcritical:\n\t\t\t\t\t\t\t\t`DKIM RSA key for \"${result.selector}\" is ${severityMsg} (~${keyAnalysis.bits} bits). Upgrade to 2048-bit RSA or use Ed25519 for better security.`,\n\t\t\t\t\t\t\thigh: `DKIM RSA key for \"${result.selector}\" is ${severityMsg} (${keyAnalysis.bits} bits). Consider upgrading to 2048-bit RSA or Ed25519.`,\n\t\t\t\t\t\t\tmedium: `DKIM RSA key for \"${result.selector}\" is ${severityMsg} (${keyAnalysis.bits} bits). Major providers recommend 4096-bit RSA or Ed25519.`,\n\t\t\t\t\t\t\tinfo: `DKIM RSA key for \"${result.selector}\" is strong (${keyAnalysis.bits} bits).`,\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tif (keyAnalysis.strength !== 'info') {\n\t\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t\t\t`${severityMsg.charAt(0).toUpperCase() + severityMsg.slice(1)} RSA key: ${result.selector}`,\n\t\t\t\t\t\t\t\t\tkeyAnalysis.strength,\n\t\t\t\t\t\t\t\t\tdescriptions[keyAnalysis.strength],\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\testimatedBits: keyAnalysis.bits,\n\t\t\t\t\t\t\t\t\t\tkeyType: keyAnalysis.keyType,\n\t\t\t\t\t\t\t\t\t\tselector: result.selector,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Check for missing v= tag (should be v=DKIM1)\n\t\t\t\tconst versionTag = getDkimTagValue(record, 'v');\n\t\t\t\tif (!versionTag) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'dkim',\n\t\t\t\t\t\t\t`Missing DKIM version tag: ${result.selector}`,\n\t\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t\t`DKIM selector \"${result.selector}\" is missing the v= tag. Should be set to v=DKIM1.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// If multiple found selectors are ALL revoked and none have valid keys,\n\t// this is a non-sending domain posture — downgrade to info\n\tif (foundSelectors.length > 1 && !hasValidKey) {\n\t\tconst revokedCount = findings.filter((f) => f.title.startsWith('Revoked DKIM key:')).length;\n\t\t// Remove individual revoked findings\n\t\tfor (let i = findings.length - 1; i >= 0; i--) {\n\t\t\tif (findings[i].title.startsWith('Revoked DKIM key:')) {\n\t\t\t\tfindings.splice(i, 1);\n\t\t\t}\n\t\t}\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'DKIM keys revoked (non-sending)',\n\t\t\t\t'info',\n\t\t\t\t`All ${revokedCount} DKIM selector(s) have revoked keys (empty p= tag). This is expected for domains that do not send email.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// In selector-probing mode, multiple selectors can expose identical key profiles.\n\t// Consolidate duplicate key-strength findings to avoid over-penalizing the same issue pattern.\n\tif (!selector && foundSelectors.length > 1) {\n\t\tconsolidateSelectorProbeKeyStrengthFindings(findings);\n\t}\n\n\tif (foundSelectors.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'No DKIM records found among tested selectors',\n\t\t\t\t'high',\n\t\t\t\t`No DKIM records were found for ${domain} among the tested selector set (${selectorsToCheck.join(', ')}). This result is based on selector probing and may miss custom selector names. DKIM helps verify email authenticity and integrity.`,\n\t\t\t\t{\n\t\t\t\t\tsignalType: 'dkim',\n\t\t\t\t\tdetectionMethod: 'selector-probing',\n\t\t\t\t\tselectorsChecked: selectorsToCheck,\n\t\t\t\t\tselectorsFound: [],\n\t\t\t\t},\n\t\t\t),\n\t\t);\n\t} else if (foundSelectors.length > 0 && hasValidKey && findings.every((f) => f.severity === 'info')) {\n\t\t// Emit selectorsFound metadata even when info-level findings exist (e.g., Ed25519 detection)\n\t\t// Skip when all keys are revoked (non-sending) — that case already has its own consolidated finding\n\t\tfindings.push(\n\t\t\tcreateFinding('dkim', 'DKIM configured', 'info', `DKIM records found for selectors: ${foundSelectors.join(', ')}`, {\n\t\t\t\tsignalType: 'dkim',\n\t\t\t\tselectorsChecked: selectorsToCheck,\n\t\t\t\tselectorsFound: foundSelectors,\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dkim', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type Finding, createFinding } from '../lib/scoring';\n\nexport type DkimKeyStrength = 'critical' | 'high' | 'medium' | 'info';\n\nexport type DkimKeyAnalysis = {\n\tbits: number | null;\n\tstrength: DkimKeyStrength;\n\tkeyType: 'rsa' | 'ed25519' | 'unknown';\n};\n\nexport function getDkimTagValue(record: string, tag: string): string | undefined {\n\tconst match = record.match(new RegExp(`(?:^|;)\\\\s*${tag}=([^;]*)`, 'i'));\n\treturn match?.[1]?.trim();\n}\n\n/**\n * Analyze key strength based on key type and base64 character count.\n * For RSA keys, estimates bit-length from base64 character count.\n * For Ed25519 keys, always returns info (strong by design).\n */\nexport function analyzeKeyStrength(publicKeyBase64: string | undefined, declaredKeyType: string): DkimKeyAnalysis {\n\tif (!publicKeyBase64) {\n\t\treturn { bits: null, strength: 'info', keyType: 'unknown' };\n\t}\n\n\tif (declaredKeyType === 'ed25519') {\n\t\treturn { bits: 256, strength: 'info', keyType: 'ed25519' };\n\t}\n\n\tconst cleanKey = publicKeyBase64.replace(/\\s/g, '');\n\tconst charCount = cleanKey.length;\n\n\tif (declaredKeyType === 'rsa-default' && charCount < 50) {\n\t\treturn { bits: null, strength: 'medium', keyType: 'unknown' };\n\t}\n\n\tif (charCount < 150) {\n\t\treturn { bits: 512, strength: 'critical', keyType: 'rsa' };\n\t}\n\n\tif (charCount < 230) {\n\t\treturn { bits: 1024, strength: 'high', keyType: 'rsa' };\n\t}\n\n\tif (charCount < 550) {\n\t\treturn { bits: 2048, strength: 'medium', keyType: 'rsa' };\n\t}\n\n\treturn { bits: 4096, strength: 'info', keyType: 'rsa' };\n}\n\nexport function consolidateSelectorProbeKeyStrengthFindings(findings: Finding[]): void {\n\tconst seen = new Set<string>();\n\tlet removed = 0;\n\n\tfor (let index = findings.length - 1; index >= 0; index--) {\n\t\tconst finding = findings[index];\n\t\tif (!/rsa key:/i.test(finding.title)) continue;\n\t\tif (!['critical', 'high', 'medium'].includes(finding.severity)) continue;\n\t\tconst estimatedBits = finding.metadata?.estimatedBits;\n\t\tconst keyType = finding.metadata?.keyType;\n\t\tif (typeof estimatedBits !== 'number' || keyType !== 'rsa') continue;\n\n\t\tconst key = `${finding.severity}:${estimatedBits}:${keyType}`;\n\t\tif (seen.has(key)) {\n\t\t\tfindings.splice(index, 1);\n\t\t\tremoved += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tseen.add(key);\n\t}\n\n\tif (removed > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dkim',\n\t\t\t\t'Similar DKIM key-strength findings consolidated',\n\t\t\t\t'info',\n\t\t\t\t`Consolidated ${removed} duplicate selector-probe key-strength finding(s) to reduce repeated penalty for identical key profiles across selectors.`,\n\t\t\t),\n\t\t);\n\t}\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DNSSEC (DNS Security Extensions) check tool.\n * Validates DNSSEC by checking the AD flag, querying for DNSKEY/DS records,\n * and auditing algorithm and digest type security.\n */\n\nimport { checkDnssec as dnsCheckDnssec, queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { auditDnskeyAlgorithms, auditDsDigestTypes, parseDnskeyAlgorithm, parseDsRecord } from './dnssec-analysis';\n\nexport { parseDnskeyAlgorithm, parseDsRecord };\n\n/**\n * Check DNSSEC configuration for a domain.\n * Verifies the AD (Authenticated Data) flag, checks for DNSKEY/DS records,\n * and audits algorithm and digest type security.\n */\nexport async function checkDnssec(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\t// Check AD flag via DoH\n\tlet adFlag = false;\n\ttry {\n\t\tadFlag = await dnsCheckDnssec(domain, dnsOptions);\n\t} catch {\n\t\tfindings.push(\n\t\t\tcreateFinding('dnssec', 'DNSSEC check failed', 'medium', `Could not verify DNSSEC status for ${domain}. The DNS query failed.`),\n\t\t);\n\t\treturn buildCheckResult('dnssec', findings);\n\t}\n\n\tif (!adFlag) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC not validated',\n\t\t\t\t'high',\n\t\t\t\t`DNSSEC validation failed for ${domain}. The AD (Authenticated Data) flag is not set, meaning DNS responses are not cryptographically verified.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for DNSKEY records and audit algorithms\n\ttry {\n\t\tconst dnskeyRecords = await queryDnsRecords(domain, 'DNSKEY', dnsOptions);\n\t\tif (dnskeyRecords.length === 0 && !adFlag) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t'No DNSKEY records',\n\t\t\t\t\t'high',\n\t\t\t\t\t`No DNSKEY records found for ${domain}. DNSSEC requires DNSKEY records to be published in the zone.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (dnskeyRecords.length > 0) {\n\t\t\tfindings.push(...auditDnskeyAlgorithms(domain, dnskeyRecords));\n\t\t}\n\t} catch {\n\t\t// Non-critical: DNSKEY query failure\n\t}\n\n\t// Check for DS records and audit digest types\n\ttry {\n\t\tconst dsRecords = await queryDnsRecords(domain, 'DS', dnsOptions);\n\t\tif (dsRecords.length === 0 && !adFlag) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t'No DS records',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`No DS (Delegation Signer) records found for ${domain}. DS records in the parent zone are needed to establish the DNSSEC chain of trust.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (dsRecords.length > 0) {\n\t\t\tfindings.push(...auditDsDigestTypes(domain, dsRecords));\n\t\t}\n\t} catch {\n\t\t// Non-critical: DS query failure\n\t}\n\n\t// If DNSSEC is valid and no issues found (only info findings at most)\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dnssec',\n\t\t\t\t'DNSSEC enabled and validated',\n\t\t\t\t'info',\n\t\t\t\t`DNSSEC is properly configured for ${domain}. DNS responses are cryptographically verified.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dnssec', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type Finding, createFinding } from '../lib/scoring';\n\n/** DNSKEY algorithm number to human-readable name and security status */\nconst DNSKEY_ALGORITHMS: Record<number, { name: string; deprecated: boolean }> = {\n\t5: { name: 'RSA/SHA-1', deprecated: true },\n\t7: { name: 'RSASHA1-NSEC3', deprecated: true },\n\t8: { name: 'RSA/SHA-256', deprecated: false },\n\t10: { name: 'RSA/SHA-512', deprecated: false },\n\t13: { name: 'ECDSA P-256', deprecated: false },\n\t14: { name: 'ECDSA P-384', deprecated: false },\n\t15: { name: 'Ed25519', deprecated: false },\n};\n\n/** Modern algorithm numbers that warrant a positive info finding */\nconst MODERN_ALGORITHMS = new Set([13, 14, 15]);\n\n/** DS digest types considered deprecated */\nconst DEPRECATED_DS_DIGESTS: Record<number, string> = {\n\t1: 'SHA-1',\n};\n\n/**\n * Parse the algorithm number from a DNSKEY record data string.\n * Format: \"flags protocol algorithm <base64key>\" e.g. \"257 3 13 mdsswUyr3DPW...\"\n */\nexport function parseDnskeyAlgorithm(data: string): number | null {\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 3) return null;\n\tconst algorithm = parseInt(parts[2], 10);\n\treturn isNaN(algorithm) ? null : algorithm;\n}\n\n/**\n * Parse algorithm and digest type from a DS record data string.\n * Format: \"keytag algorithm digesttype <hex-digest>\" e.g. \"12345 13 2 abc123...\"\n */\nexport function parseDsRecord(data: string): { algorithm: number; digestType: number } | null {\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 3) return null;\n\tconst algorithm = parseInt(parts[1], 10);\n\tconst digestType = parseInt(parts[2], 10);\n\tif (isNaN(algorithm) || isNaN(digestType)) return null;\n\treturn { algorithm, digestType };\n}\n\n/**\n * Audit DNSKEY algorithm numbers and produce findings for deprecated or modern algorithms.\n */\nexport function auditDnskeyAlgorithms(domain: string, dnskeyRecords: string[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst seenAlgorithms = new Set<number>();\n\n\tfor (const record of dnskeyRecords) {\n\t\tconst algorithm = parseDnskeyAlgorithm(record);\n\t\tif (algorithm === null || seenAlgorithms.has(algorithm)) continue;\n\t\tseenAlgorithms.add(algorithm);\n\n\t\tconst known = DNSKEY_ALGORITHMS[algorithm];\n\t\tif (known?.deprecated) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Deprecated DNSKEY algorithm (${known.name})`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm} (${known.name}), which is deprecated and may be vulnerable to collision attacks. Upgrade to ECDSA (algorithm 13/14) or Ed25519 (algorithm 15).`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (MODERN_ALGORITHMS.has(algorithm)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Modern DNSSEC algorithm (${known!.name})`,\n\t\t\t\t\t'info',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm} (${known!.name}), which is a modern and secure choice.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (!known) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Unknown DNSKEY algorithm (${algorithm})`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${domain} uses DNSKEY algorithm ${algorithm}, which is not a commonly recognized DNSSEC algorithm. Verify this is intentional.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn findings;\n}\n\n/**\n * Audit DS digest types and produce findings for deprecated digests.\n */\nexport function auditDsDigestTypes(domain: string, dsRecords: string[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst seenDigestTypes = new Set<number>();\n\n\tfor (const record of dsRecords) {\n\t\tconst parsed = parseDsRecord(record);\n\t\tif (parsed === null) continue;\n\n\t\tconst { digestType } = parsed;\n\t\tif (seenDigestTypes.has(digestType)) continue;\n\t\tseenDigestTypes.add(digestType);\n\n\t\tconst deprecatedName = DEPRECATED_DS_DIGESTS[digestType];\n\t\tif (deprecatedName) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dnssec',\n\t\t\t\t\t`Deprecated DS digest type (${deprecatedName})`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${domain} uses DS digest type ${digestType} (${deprecatedName}), which is deprecated. Use SHA-256 (type 2) or SHA-384 (type 4) instead.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn findings;\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SSL/TLS certificate check tool.\n * Validates SSL certificate by attempting HTTPS connection,\n * checks HSTS configuration,\n * and verifies HTTP→HTTPS redirect.\n * Workers-compatible: uses fetch API only (cert expiry/chain require external APIs).\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\nimport { getHttpRedirectFindings, getHttpsErrorFinding, getHttpsFindings } from './ssl-analysis';\n\n/**\n * Check SSL/TLS configuration for a domain.\n * Validates HTTPS connectivity, HSTS headers, and HTTP→HTTPS redirect.\n */\nexport async function checkSsl(domain: string): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\tconst httpsResult = await checkHttps(domain);\n\tfindings.push(...httpsResult);\n\n\t// Only check HTTP redirect if HTTPS is working (no critical findings)\n\tconst hasCritical = findings.some((f) => f.severity === 'critical');\n\tif (!hasCritical) {\n\t\tconst redirectResult = await checkHttpRedirect(domain);\n\t\tfindings.push(...redirectResult);\n\t}\n\n\tif (findings.length === 0) {\n\t\tfindings.push(createFinding('ssl', 'HTTPS and HSTS properly configured', 'info', `HTTPS connection succeeded and HSTS header is properly configured for ${domain}. Note: This check verifies HTTPS reachability and HSTS policy. Certificate expiry, TLS version, and cipher suite analysis require a dedicated TLS scanner.`));\n\t}\n\n\treturn buildCheckResult('ssl', findings);\n}\n\n/** Check HTTPS connectivity by attempting a fetch */\nasync function checkHttps(domain: string): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst response = await fetch(`https://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t});\n\n\t\tconst isRedirect = response.status >= 300 && response.status < 400;\n\t\tconst location = isRedirect ? response.headers.get('location') : null;\n\t\tconst isDowngrade = location?.startsWith('http://') ?? false;\n\t\tconst isHttpsRedirect = isRedirect && !isDowngrade;\n\n\t\t// For HTTPS-to-HTTPS redirects: skip — no downgrade and can't check final page HSTS\n\t\t// For HTTP downgrade: report critical + check HSTS on the HTTPS redirect response\n\t\t// For non-redirects: check HSTS normally\n\t\tif (!isHttpsRedirect) {\n\t\t\tconst redirectTarget = isDowngrade ? (location ?? undefined) : undefined;\n\t\t\tfindings.push(...getHttpsFindings(domain, redirectTarget, response.headers.get('strict-transport-security')));\n\t\t}\n\n\t} catch (err) {\n\t\tconst message = err instanceof Error && (err.message.includes('timeout') || err.message.includes('abort'))\n\t\t\t? err.message\n\t\t\t: 'Connection failed';\n\t\tfindings.push(getHttpsErrorFinding(domain, message));\n\t}\n\n\treturn findings;\n}\n\n/** Check if HTTP redirects to HTTPS */\nasync function checkHttpRedirect(domain: string): Promise<Finding[]> {\n\tconst findings: Finding[] = [];\n\ttry {\n\t\tconst response = await fetch(`http://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t});\n\t\tfindings.push(...getHttpRedirectFindings(domain, response.status, response.headers.get('location')));\n\t} catch {\n\t\t// HTTP not available or blocked — not necessarily an issue, skip silently\n\t}\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type Finding, createFinding } from '../lib/scoring';\n\nexport function getHttpsFindings(domain: string, responseUrl: string | undefined, hstsHeader: string | null): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (responseUrl && responseUrl.startsWith('http://')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HTTPS redirects to HTTP',\n\t\t\t\t'critical',\n\t\t\t\t`${domain} redirects HTTPS requests to HTTP, exposing traffic to interception.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!hstsHeader) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'No HSTS header',\n\t\t\t\t'medium',\n\t\t\t\t`${domain} does not set a Strict-Transport-Security header. HSTS prevents browsers from connecting over plain HTTP.`,\n\t\t\t),\n\t\t);\n\t\treturn findings;\n\t}\n\n\tconst maxAgeMatch = hstsHeader.match(/max-age=(\\d+)/i);\n\tif (maxAgeMatch) {\n\t\tconst maxAge = parseInt(maxAgeMatch[1], 10);\n\t\tif (maxAge < 31536000) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ssl',\n\t\t\t\t\t'HSTS max-age too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`HSTS max-age is ${maxAge} seconds (${Math.round(maxAge / 86400)} days). Recommended minimum is 31536000 (1 year).`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (!/includeSubDomains/i.test(hstsHeader)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HSTS missing includeSubDomains',\n\t\t\t\t'low',\n\t\t\t\t'HSTS header does not include the includeSubDomains directive. Subdomains are not protected by HSTS.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getHttpsErrorFinding(domain: string, message: string): Finding {\n\tif (message.includes('timeout') || message.includes('abort')) {\n\t\treturn createFinding(\n\t\t\t'ssl',\n\t\t\t'HTTPS connection timeout',\n\t\t\t'high',\n\t\t\t`Could not establish HTTPS connection to ${domain} within 10 seconds. The server may not support HTTPS.`,\n\t\t);\n\t}\n\n\treturn createFinding(\n\t\t'ssl',\n\t\t'HTTPS connection failed',\n\t\t'critical',\n\t\t`Failed to connect to ${domain} over HTTPS: ${message}. The domain may not have a valid SSL certificate.`,\n\t);\n}\n\nexport function getHttpRedirectFindings(domain: string, status: number, location: string | null): Finding[] {\n\tif (status >= 300 && status < 400 && location?.startsWith('https://')) {\n\t\treturn [];\n\t}\n\n\tif (status >= 300 && status < 400 && location && !location.startsWith('https://')) {\n\t\treturn [\n\t\t\tcreateFinding(\n\t\t\t\t'ssl',\n\t\t\t\t'HTTP does not redirect to HTTPS',\n\t\t\t\t'medium',\n\t\t\t\t`HTTP requests to ${domain} redirect to ${location} instead of HTTPS.`,\n\t\t\t),\n\t\t];\n\t}\n\n\treturn [\n\t\tcreateFinding(\n\t\t\t'ssl',\n\t\t\t'No HTTP to HTTPS redirect',\n\t\t\t'medium',\n\t\t\t`HTTP requests to ${domain} are not redirected to HTTPS (status ${status}).`,\n\t\t),\n\t];\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MTA-STS (Mail Transfer Agent Strict Transport Security) check tool.\n * Queries _mta-sts TXT records and validates the MTA-STS policy.\n */\n\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\nimport { queryMxRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport {\n\tfinalizeMissingMtaStsRecordFinding,\n\tfinalizeMissingTlsRptRecordFinding,\n\textractPolicyMxPatterns,\n\tgetMtaStsPolicyFindings,\n\tgetMtaStsTxtFindings,\n\tgetTlsRptRecordFindings,\n\tgetUncoveredMxHostFindings,\n\tshouldSummarizeMissingMailProtections,\n} from './mta-sts-analysis';\n\n/**\n * Check MTA-STS configuration for a domain.\n * Queries _mta-sts.<domain> TXT records and optionally fetches the policy file.\n */\nexport async function checkMtaSts(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tlet findings: Finding[] = [];\n\n\t// Check for _mta-sts TXT record\n\tlet hasTxtRecord = false;\n\ttry {\n\t\tconst txtRecords = await queryTxtRecords(`_mta-sts.${domain}`, dnsOptions);\n\t\tconst txtAnalysis = getMtaStsTxtFindings(txtRecords);\n\t\thasTxtRecord = txtAnalysis.hasTxtRecord;\n\t\tfindings.push(...finalizeMissingMtaStsRecordFinding(txtAnalysis.findings, domain));\n\t} catch {\n\t\tfindings = [];\n\t\tfindings.push(createFinding('mta_sts', 'MTA-STS DNS query failed', 'low', `Could not query MTA-STS TXT record for ${domain}.`));\n\t}\n\n\t// Try to fetch the MTA-STS policy file\n\tif (hasTxtRecord) {\n\t\ttry {\n\t\t\tconst policyUrl = `https://mta-sts.${domain}/.well-known/mta-sts.txt`;\n\t\t\tconst response = await fetch(policyUrl, {\n\t\t\t\tmethod: 'GET',\n\t\t\t\tredirect: 'manual',\n\t\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t\t});\n\n\t\t\tif ([301, 302, 303, 307, 308].includes(response.status)) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t'MTA-STS policy redirects',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} returned HTTP ${response.status} redirect. The policy must be served directly at the well-known URL without redirects.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else if (!response.ok) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mta_sts',\n\t\t\t\t\t\t'MTA-STS policy file not accessible',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`MTA-STS policy file at ${policyUrl} returned HTTP ${response.status}. The policy file must be accessible over HTTPS.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tfindings.push(...getMtaStsPolicyFindings(body, policyUrl));\n\n\t\t\t\tconst policyMxPatterns = extractPolicyMxPatterns(body);\n\t\t\t\tconst modeMatch = body.match(/mode:\\s*(enforce|testing|none)/i);\n\t\t\t\tconst policyMode = modeMatch ? modeMatch[1].toLowerCase() : '';\n\t\t\t\tif (policyMxPatterns.length > 0 && (policyMode === 'enforce' || policyMode === 'testing')) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst mxRecords = await queryMxRecords(domain, dnsOptions);\n\t\t\t\t\t\tfindings.push(...getUncoveredMxHostFindings(mxRecords.map((mx) => mx.exchange), policyMxPatterns));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// MX query failed; skip coverage cross-check.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS policy fetch failed',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Could not fetch MTA-STS policy file from https://mta-sts.${domain}/.well-known/mta-sts.txt`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Check for TLSRPT record\n\tlet hasTlsRptRecord = false;\n\tlet tlsRptChecked = false;\n\ttry {\n\t\tconst tlsrptRecords = await queryTxtRecords(`_smtp._tls.${domain}`, dnsOptions);\n\t\ttlsRptChecked = true;\n\t\tconst tlsRptAnalysis = getTlsRptRecordFindings(tlsrptRecords);\n\t\thasTlsRptRecord = tlsRptAnalysis.hasTlsRptRecord;\n\t\tfindings.push(...finalizeMissingTlsRptRecordFinding(tlsRptAnalysis.findings, domain));\n\t} catch {\n\t\ttlsRptChecked = true;\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'TLS-RPT DNS query failed',\n\t\t\t\t'low',\n\t\t\t\t`Could not query TLS-RPT TXT record for ${domain}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS properly configured',\n\t\t\t\t'info',\n\t\t\t\t`MTA-STS is properly configured for ${domain} with an accessible policy file.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If both records are missing, add a clear summary and suppress duplicate findings\n\t// But preserve DNS error findings so they are not masked\n\tif (shouldSummarizeMissingMailProtections(findings, hasTxtRecord, tlsRptChecked, hasTlsRptRecord)) {\n\t\tfindings = [];\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'No MTA-STS or TLS-RPT records found',\n\t\t\t\t'medium',\n\t\t\t\t`Neither MTA-STS nor TLS-RPT records are present for ${domain}. This is normal for domains that do not accept inbound email, but consider adding these records if you operate a mail server.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('mta_sts', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type Finding, createFinding } from '../lib/scoring';\n\nexport function getMtaStsTxtFindings(records: string[]): { findings: Finding[]; hasTxtRecord: boolean } {\n\tconst findings: Finding[] = [];\n\tconst mtaStsRecords = records.filter((record) => /^v=stsv1[;\\s]/i.test(record));\n\n\tif (mtaStsRecords.length === 0) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'No MTA-STS record found',\n\t\t\t\t\t'medium',\n\t\t\t\t\t'',\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTxtRecord: false,\n\t\t};\n\t}\n\n\tif (mtaStsRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding('mta_sts', 'Multiple MTA-STS records', 'medium', `Found ${mtaStsRecords.length} MTA-STS records. Only one should exist.`),\n\t\t);\n\t}\n\n\tif (!mtaStsRecords[0].includes('id=')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS missing id tag',\n\t\t\t\t'medium',\n\t\t\t\t'MTA-STS record is missing the \"id=\" tag. This tag is required for policy versioning.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn { findings, hasTxtRecord: true };\n}\n\nexport function finalizeMissingMtaStsRecordFinding(findings: Finding[], domain: string): Finding[] {\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'No MTA-STS record found'\n\t\t\t? createFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'No MTA-STS record found',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`No MTA-STS TXT record found at _mta-sts.${domain}. MTA-STS enforces TLS for incoming email, preventing downgrade attacks.`,\n\t\t\t\t)\n\t\t\t: finding,\n\t);\n}\n\nexport function getMtaStsPolicyFindings(body: string, policyUrl: string): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst versionMatch = body.match(/version:\\s*(\\S+)/i);\n\tif (!versionMatch || versionMatch[1] !== 'STSv1') {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing or invalid version',\n\t\t\t\t'high',\n\t\t\t\t'The MTA-STS policy must contain \"version: STSv1\" as required by RFC 8461.',\n\t\t\t),\n\t\t);\n\t}\n\n\tconst modeMatch = body.match(/mode:\\s*(enforce|testing|none)/i);\n\n\tif (!modeMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding('mta_sts', 'MTA-STS policy missing mode', 'high', 'MTA-STS policy file does not contain a valid \"mode:\" directive.'),\n\t\t);\n\t} else {\n\t\tconst mode = modeMatch[1].toLowerCase();\n\t\tif (mode === 'testing') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding('mta_sts', 'MTA-STS in testing mode', 'low', 'MTA-STS policy is in \"testing\" mode. Consider switching to \"enforce\" once verified.'),\n\t\t\t);\n\t\t} else if (mode === 'none') {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding('mta_sts', 'MTA-STS policy disabled', 'medium', 'MTA-STS policy mode is \"none\", effectively disabling MTA-STS protection.'),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (!body.includes('mx:')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing MX entries',\n\t\t\t\t'high',\n\t\t\t\t'MTA-STS policy file does not contain any \"mx:\" entries. At least one MX pattern is required.',\n\t\t\t),\n\t\t);\n\t}\n\n\tconst maxAgeMatch = body.match(/max_age:\\s*(\\d+)/i);\n\tif (!maxAgeMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t'MTA-STS policy missing max_age',\n\t\t\t\t'high',\n\t\t\t\t'The max_age directive is required by RFC 8461. Without it, the policy is technically invalid.',\n\t\t\t),\n\t\t);\n\t} else {\n\t\tconst maxAge = parseInt(maxAgeMatch[1], 10);\n\t\tif (maxAge < 86400) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS max_age too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`MTA-STS max_age is ${maxAge} seconds (less than 1 day). A short max_age reduces the effectiveness of MTA-STS protection.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (maxAge > 31557600) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'MTA-STS max_age exceeds one year',\n\t\t\t\t\t'info',\n\t\t\t\t\t`MTA-STS max_age is ${maxAge} seconds (more than 1 year). This is acceptable but noted.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (findings.length === 0) {\n\t\treturn [];\n\t}\n\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'MTA-STS policy missing mode' || finding.title === 'MTA-STS policy missing MX entries'\n\t\t\t? createFinding('mta_sts', finding.title, finding.severity, finding.detail.replace('MTA-STS policy file', `MTA-STS policy file at ${policyUrl}`))\n\t\t\t: finding,\n\t);\n}\n\nexport function extractPolicyMxPatterns(body: string): string[] {\n\treturn [...body.matchAll(/mx:\\s*(\\S+)/gi)].map((match) => match[1].toLowerCase());\n}\n\nexport function matchesMxPattern(hostname: string, pattern: string): boolean {\n\tif (pattern.startsWith('*.')) {\n\t\tconst suffix = pattern.slice(1);\n\t\treturn hostname.endsWith(suffix) || hostname === pattern.slice(2);\n\t}\n\n\treturn hostname === pattern;\n}\n\nexport function getUncoveredMxHostFindings(mxHosts: string[], policyMxPatterns: string[]): Finding[] {\n\treturn mxHosts.flatMap((mxHost) => {\n\t\tconst hostname = mxHost.toLowerCase();\n\t\tconst covered = policyMxPatterns.some((pattern) => matchesMxPattern(hostname, pattern));\n\t\tif (covered) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn [\n\t\t\tcreateFinding(\n\t\t\t\t'mta_sts',\n\t\t\t\t`MTA-STS policy does not cover MX host ${mxHost}`,\n\t\t\t\t'high',\n\t\t\t\t`The MX host ${mxHost} is not matched by any mx: entry in the MTA-STS policy. Mail delivered to this MX will fail MTA-STS validation.`,\n\t\t\t),\n\t\t];\n\t});\n}\n\nexport function hasValidTlsRptRecord(records: string[]): boolean {\n\treturn records.some((record) => record.toLowerCase().startsWith('v=tlsrptv1'));\n}\n\nexport function getTlsRptRecordFindings(records: string[]): { findings: Finding[]; hasTlsRptRecord: boolean } {\n\tconst validRecords = records.filter((record) => record.toLowerCase().startsWith('v=tlsrptv1'));\n\tif (validRecords.length === 0) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT record missing',\n\t\t\t\t\t'low',\n\t\t\t\t\t'',\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: false,\n\t\t};\n\t}\n\n\tconst tlsrptRecord = validRecords[0];\n\tconst ruaMatch = tlsrptRecord.match(/rua\\s*=\\s*([^;\\s]+)/i);\n\tif (!ruaMatch) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT missing rua directive',\n\t\t\t\t\t'low',\n\t\t\t\t\t'TLS-RPT record does not contain a \"rua=\" directive. The rua URI is needed to receive TLS failure reports.',\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: true,\n\t\t};\n\t}\n\n\tconst ruaValue = ruaMatch[1];\n\tconst isValidMailto = /^mailto:[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(ruaValue);\n\tconst isValidHttps = /^https:\\/\\/.+/.test(ruaValue);\n\tif (!isValidMailto && !isValidHttps) {\n\t\treturn {\n\t\t\tfindings: [\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT invalid rua format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLS-RPT rua value \"${ruaValue}\" is not a valid mailto: or https: URI.`,\n\t\t\t\t),\n\t\t\t],\n\t\t\thasTlsRptRecord: true,\n\t\t};\n\t}\n\n\treturn { findings: [], hasTlsRptRecord: true };\n}\n\nexport function finalizeMissingTlsRptRecordFinding(findings: Finding[], domain: string): Finding[] {\n\treturn findings.map((finding) =>\n\t\tfinding.title === 'TLS-RPT record missing'\n\t\t\t? createFinding(\n\t\t\t\t\t'mta_sts',\n\t\t\t\t\t'TLS-RPT record missing',\n\t\t\t\t\t'low',\n\t\t\t\t\t`No TLS-RPT record found at _smtp._tls.${domain}. Consider adding a TLS-RPT record for reporting SMTP TLS issues.`,\n\t\t\t\t)\n\t\t\t: finding,\n\t);\n}\n\nexport function shouldSummarizeMissingMailProtections(findings: Finding[], hasTxtRecord: boolean, tlsRptChecked: boolean, hasTlsRptRecord: boolean): boolean {\n\tconst hasDnsErrorFindings = findings.some((finding) => finding.title.includes('DNS query failed'));\n\treturn !hasTxtRecord && tlsRptChecked && !hasTlsRptRecord && !hasDnsErrorFindings;\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * NS (Name Server) check tool.\n * Validates nameserver configuration for a domain.\n */\n\nimport { queryDnsRecords, queryDns } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport {\n\tgetNameserverDiversityFinding,\n\tgetNsConfiguredFinding,\n\tgetNsVisibilityFinding,\n\tgetSingleNsFinding,\n\tgetSoaValidationFindings,\n\tnormalizeNsRecords,\n\tparseSoaValues,\n} from './ns-analysis';\n\n/**\n * Check nameserver configuration for a domain.\n * Validates NS records exist, checks for diversity, and verifies responsiveness.\n */\nexport async function checkNs(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\tlet nsRecords: string[] = [];\n\ttry {\n\t\tnsRecords = normalizeNsRecords(await queryDnsRecords(domain, 'NS', dnsOptions));\n\t} catch {\n\t\tfindings.push(createFinding('ns', 'NS query failed', 'critical', `Could not query nameserver records for ${domain}.`));\n\t\treturn buildCheckResult('ns', findings);\n\t}\n\n\tif (nsRecords.length === 0) {\n\t\t// Check if domain still resolves (e.g. delegation-only zones like govt.nz)\n\t\tlet domainResolves = false;\n\t\ttry {\n\t\t\tconst aResp = await queryDns(domain, 'A', false, dnsOptions);\n\t\t\tdomainResolves = (aResp.Answer ?? []).length > 0;\n\t\t} catch {\n\t\t\t/* ignore */\n\t\t}\n\n\t\tfindings.push(getNsVisibilityFinding(domain, domainResolves));\n\t\treturn buildCheckResult('ns', findings);\n\t}\n\n\t// Check for single nameserver (no redundancy) — RFC 1035 §2.2 mandates at least two\n\tconst singleNsFinding = getSingleNsFinding(nsRecords);\n\tif (singleNsFinding) {\n\t\tfindings.push(singleNsFinding);\n\t}\n\n\tconst diversityFinding = getNameserverDiversityFinding(nsRecords);\n\tif (diversityFinding) {\n\t\tfindings.push(diversityFinding);\n\t}\n\n\t// Check SOA record exists and validate parameters\n\ttry {\n\t\tconst soaResp = await queryDns(domain, 'SOA', false, dnsOptions);\n\t\tconst soaRecords = (soaResp.Answer ?? []).filter((a) => a.type === 6);\n\t\tif (soaRecords.length === 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'No SOA record',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`No SOA (Start of Authority) record found for ${domain}. SOA records are required for proper DNS zone configuration.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tconst soaValues = parseSoaValues(soaRecords[0].data);\n\t\t\tif (soaValues) {\n\t\t\t\tfindings.push(...getSoaValidationFindings(soaValues));\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Non-critical\n\t}\n\n\t// Wildcard DNS detection — probe a random subdomain\n\ttry {\n\t\tconst probeFqdn = `_bv-probe-${crypto.randomUUID().slice(0, 8)}.${domain}`;\n\t\tconst probeRecords = await queryDnsRecords(probeFqdn, 'A', dnsOptions);\n\t\tif (probeRecords.length > 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'Wildcard DNS detected',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Domain responds to arbitrary subdomains, indicating a wildcard DNS record (*.${domain}). Wildcard records can mask dangling CNAMEs, complicate subdomain enumeration defences, and make subdomain takeover detection unreliable.`,\n\t\t\t\t\t{ wildcardDetected: true, probeSubdomain: probeFqdn },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} catch {\n\t\t// Non-critical — wildcard detection failure should not affect NS check\n\t}\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(getNsConfiguredFinding(nsRecords));\n\t}\n\n\treturn buildCheckResult('ns', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\nconst RESILIENT_NS_PROVIDERS: Record<string, string> = {\n\t'cloudflare.com':\n\t\t\"Cloudflare's anycast network provides built-in geographic redundancy, so this is lower risk than single-provider setups on traditional DNS hosts.\",\n\t'awsdns.com': \"AWS Route 53's anycast network provides built-in geographic redundancy, so this is lower risk than single-provider setups on traditional DNS hosts.\",\n\t'google.com':\n\t\t'Google Cloud DNS uses globally distributed authoritative infrastructure, so this is lower risk than single-provider setups on traditional DNS hosts.',\n};\n\nexport type ParsedSoaValues = {\n\trefresh: number | null;\n\tretry: number | null;\n\texpire: number | null;\n\tminimum: number | null;\n};\n\nexport function normalizeNsRecords(nsRecords: string[]): string[] {\n\treturn nsRecords.map((record) => record.replace(/\\.$/, '').toLowerCase());\n}\n\nexport function getNsVisibilityFinding(domain: string, domainResolves: boolean): Finding {\n\tif (domainResolves) {\n\t\treturn createFinding(\n\t\t\t'ns',\n\t\t\t'NS records not directly visible',\n\t\t\t'low',\n\t\t\t`No NS records returned for ${domain} directly, but the domain resolves. NS records may be managed at a parent zone.`,\n\t\t);\n\t}\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'No NS records found',\n\t\t'critical',\n\t\t`No nameserver records found for ${domain}. Without NS records, the domain cannot resolve.`,\n\t);\n}\n\nexport function getSingleNsFinding(nsRecords: string[]): Finding | null {\n\tif (nsRecords.length !== 1) {\n\t\treturn null;\n\t}\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'Single nameserver (violates RFC 1035 §2.2)',\n\t\t'high',\n\t\t`Only one nameserver found (${nsRecords[0]}). RFC 1035 §2.2 mandates at least two nameservers for every zone to ensure redundancy and availability.`,\n\t);\n}\n\nexport function getNameserverDiversityFinding(nsRecords: string[]): Finding | null {\n\tconst providerDomains = new Set(\n\t\tnsRecords.map((record) => {\n\t\t\tconst parts = record.split('.');\n\t\t\treturn parts.slice(-2).join('.');\n\t\t}),\n\t);\n\n\tif (providerDomains.size !== 1 || nsRecords.length <= 1) {\n\t\treturn null;\n\t}\n\n\tconst providerDomain = [...providerDomains][0];\n\tconst providerContext =\n\t\tRESILIENT_NS_PROVIDERS[providerDomain] ?? 'Consider using nameservers from different providers for better resilience.';\n\n\treturn createFinding(\n\t\t'ns',\n\t\t'Low nameserver diversity',\n\t\t'low',\n\t\t`All nameservers are under ${providerDomain}. ${providerContext} For maximum independence, a secondary DNS provider can be added.`,\n\t);\n}\n\nexport function parseSoaValues(soaData: string): ParsedSoaValues | null {\n\tconst soaParts = soaData.trim().split(/\\s+/);\n\tif (soaParts.length < 7) {\n\t\treturn null;\n\t}\n\n\tconst refresh = parseInt(soaParts[3], 10);\n\tconst retry = parseInt(soaParts[4], 10);\n\tconst expire = parseInt(soaParts[5], 10);\n\tconst minimum = parseInt(soaParts[6], 10);\n\n\treturn {\n\t\trefresh: Number.isNaN(refresh) ? null : refresh,\n\t\tretry: Number.isNaN(retry) ? null : retry,\n\t\texpire: Number.isNaN(expire) ? null : expire,\n\t\tminimum: Number.isNaN(minimum) ? null : minimum,\n\t};\n}\n\nexport function getSoaValidationFindings(soaValues: ParsedSoaValues): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (soaValues.refresh !== null) {\n\t\tif (soaValues.refresh < 300) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'SOA refresh interval too short',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SOA refresh interval is ${soaValues.refresh}s (< 300s / 5 min). Very short refresh intervals increase DNS traffic and load on nameservers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (soaValues.refresh > 86400) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'ns',\n\t\t\t\t\t'SOA refresh interval too long',\n\t\t\t\t\t'low',\n\t\t\t\t\t`SOA refresh interval is ${soaValues.refresh}s (> 86400s / 1 day). Long refresh intervals delay propagation of zone changes to secondary nameservers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (soaValues.retry !== null && soaValues.refresh !== null && soaValues.retry > soaValues.refresh) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA retry exceeds refresh interval',\n\t\t\t\t'low',\n\t\t\t\t`SOA retry interval (${soaValues.retry}s) exceeds refresh interval (${soaValues.refresh}s). Retry should be shorter than refresh to allow timely recovery after failed zone transfers.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (soaValues.expire !== null && soaValues.expire < 604800) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA expire too short',\n\t\t\t\t'medium',\n\t\t\t\t`SOA expire value is ${soaValues.expire}s (< 604800s / 1 week). If secondary nameservers cannot reach the primary for this duration, they will stop serving the zone.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tif (soaValues.minimum !== null && soaValues.minimum > 86400) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'ns',\n\t\t\t\t'SOA negative cache TTL too long',\n\t\t\t\t'low',\n\t\t\t\t`SOA minimum (negative cache TTL) is ${soaValues.minimum}s (> 86400s / 1 day). This means NXDOMAIN responses will be cached for extended periods, delaying visibility of new records.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getNsConfiguredFinding(nsRecords: string[]): Finding {\n\treturn createFinding('ns', 'Nameservers properly configured', 'info', `${nsRecords.length} nameservers found: ${nsRecords.join(', ')}`);\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * CAA (Certificate Authority Authorization) check tool.\n * Validates CAA DNS records that restrict which CAs can issue certificates.\n */\n\nimport { queryCaaRecords, type CaaRecord } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { getCaaConfiguredFinding, getCaaValidationFindings, summarizeCaaTags } from './caa-analysis';\n\n/**\n * Check CAA records for a domain.\n * Validates that CAA records exist and are properly configured.\n */\nexport async function checkCaa(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\tlet caaRecords: CaaRecord[] = [];\n\ttry {\n\t\tcaaRecords = await queryCaaRecords(domain, dnsOptions);\n\t} catch {\n\t\tfindings.push(createFinding('caa', 'CAA query failed', 'medium', `Could not query CAA records for ${domain}.`));\n\t\treturn buildCheckResult('caa', findings);\n\t}\n\n\tif (caaRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA records',\n\t\t\t\t'medium',\n\t\t\t\t`No CAA records found for ${domain}. CAA records restrict which Certificate Authorities can issue certificates for your domain, preventing unauthorized issuance.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('caa', findings);\n\t}\n\n\tfindings.push(...getCaaValidationFindings(summarizeCaaTags(caaRecords)));\n\n\t// If no issues found\n\tif (findings.length === 0) {\n\t\tfindings.push(getCaaConfiguredFinding());\n\t}\n\n\treturn buildCheckResult('caa', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { CaaRecord } from '../lib/dns';\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\nexport function summarizeCaaTags(caaRecords: CaaRecord[]): {\n\thasIssue: boolean;\n\thasIssuewild: boolean;\n\thasIodef: boolean;\n} {\n\tlet hasIssue = false;\n\tlet hasIssuewild = false;\n\tlet hasIodef = false;\n\n\tfor (const record of caaRecords) {\n\t\tif (record.tag === 'issue') {\n\t\t\thasIssue = true;\n\t\t}\n\t\tif (record.tag === 'issuewild') {\n\t\t\thasIssuewild = true;\n\t\t}\n\t\tif (record.tag === 'iodef') {\n\t\t\thasIodef = true;\n\t\t}\n\t}\n\n\treturn { hasIssue, hasIssuewild, hasIodef };\n}\n\nexport function getCaaValidationFindings(tagSummary: { hasIssue: boolean; hasIssuewild: boolean; hasIodef: boolean }): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (!tagSummary.hasIssue) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA issue tag',\n\t\t\t\t'medium',\n\t\t\t\t'CAA records exist but no \"issue\" tag found. The \"issue\" tag specifies which CAs are authorized to issue certificates.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!tagSummary.hasIssuewild) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA issuewild tag',\n\t\t\t\t'low',\n\t\t\t\t'No \"issuewild\" CAA tag found. Consider adding one to control wildcard certificate issuance separately.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!tagSummary.hasIodef) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'caa',\n\t\t\t\t'No CAA iodef tag',\n\t\t\t\t'low',\n\t\t\t\t'No \"iodef\" CAA tag found. The iodef tag specifies where CAs should report policy violations.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\nexport function getCaaConfiguredFinding(): Finding {\n\treturn createFinding('caa', 'CAA properly configured', 'info', 'CAA records found with issue, issuewild, and iodef tags configured.');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * BIMI (Brand Indicators for Message Identification) check tool.\n * Queries TXT records at default._bimi.<domain> and validates\n * logo URL and authority evidence configuration.\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\n\n/**\n * Check BIMI records for a domain.\n * Validates the presence and configuration of BIMI TXT records,\n * including logo URL format and VMC authority evidence.\n */\nexport async function checkBimi(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst bimiDomain = `default._bimi.${domain}`;\n\tconst txtRecords = await queryTxtRecords(bimiDomain, dnsOptions);\n\n\tconst bimiRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=bimi1'));\n\n\tif (bimiRecords.length === 0) {\n\t\t// Check DMARC enforcement status to provide context\n\t\tconst dmarcRecords = await queryTxtRecords(`_dmarc.${domain}`, dnsOptions);\n\t\tconst dmarcRecord = dmarcRecords.find((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\t\tconst isEnforcing =\n\t\t\tdmarcRecord && (/\\bp=reject\\b/i.test(dmarcRecord) || /\\bp=quarantine\\b/i.test(dmarcRecord));\n\n\t\tif (!isEnforcing) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'No BIMI record (DMARC not enforcing)',\n\t\t\t\t\t'info',\n\t\t\t\t\t`No BIMI record found at ${bimiDomain}. BIMI requires DMARC enforcement (p=quarantine or p=reject) before a BIMI record can be validated by mail clients. Set up DMARC enforcement first.`,\n\t\t\t\t),\n\t\t\t);\n\t\t} else {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'No BIMI record found',\n\t\t\t\t\t'low',\n\t\t\t\t\t`No BIMI record found at ${bimiDomain}. This domain has DMARC enforcement and is eligible for BIMI. Publishing a BIMI record allows email clients like Gmail and Apple Mail to display your brand logo next to your emails.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t\treturn buildCheckResult('bimi', findings);\n\t}\n\n\tif (bimiRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'Multiple BIMI records',\n\t\t\t\t'medium',\n\t\t\t\t`Found ${bimiRecords.length} BIMI records at ${bimiDomain}. There should be exactly one BIMI record.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst bimi = bimiRecords[0];\n\n\t// Extract l= tag (logo URL)\n\tconst logoMatch = bimi.match(/\\bl=([^\\s;]+)/i);\n\tconst logoUrl = logoMatch?.[1];\n\n\tif (!logoUrl) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI record missing logo URL',\n\t\t\t\t'medium',\n\t\t\t\t`BIMI record at ${bimiDomain} does not contain a logo URL (l= tag). The logo URL is required for email clients to display your brand indicator.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// Validate logo URL format\n\t\tconst isHttps = logoUrl.toLowerCase().startsWith('https://');\n\t\tconst isSvg = logoUrl.toLowerCase().endsWith('.svg');\n\n\t\tif (!isHttps || !isSvg) {\n\t\t\tconst issues: string[] = [];\n\t\t\tif (!isHttps) issues.push('must use HTTPS');\n\t\t\tif (!isSvg) issues.push('must be an SVG file (SVG Tiny PS format)');\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'bimi',\n\t\t\t\t\t'BIMI logo URL invalid format',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`BIMI logo URL \"${logoUrl}\" is invalid: ${issues.join(' and ')}. BIMI requires an HTTPS URL pointing to an SVG Tiny PS image.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Extract a= tag (VMC/authority evidence URL)\n\tconst authMatch = bimi.match(/\\ba=([^\\s;]+)/i);\n\tconst authUrl = authMatch?.[1];\n\n\tif (!authUrl) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'No BIMI authority evidence (VMC)',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record at ${bimiDomain} does not include an authority evidence URL (a= tag). A Verified Mark Certificate (VMC) is optional but required by Gmail to display your logo. Consider obtaining a VMC from a certificate authority like DigiCert or Entrust.`,\n\t\t\t),\n\t\t);\n\t} else {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI authority evidence present',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record includes a Verified Mark Certificate (VMC) reference: ${authUrl}`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If logo URL is valid and present, add a positive finding\n\tif (logoUrl && logoUrl.toLowerCase().startsWith('https://') && logoUrl.toLowerCase().endsWith('.svg')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'bimi',\n\t\t\t\t'BIMI record configured',\n\t\t\t\t'info',\n\t\t\t\t`BIMI record found and configured at ${bimiDomain} with a valid HTTPS SVG logo reference.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('bimi', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * TLS-RPT (SMTP TLS Reporting) check tool.\n * Queries TXT records at _smtp._tls.<domain> and validates\n * reporting configuration per RFC 8460.\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\n\n/**\n * Check TLS-RPT records for a domain.\n * Validates the presence and configuration of SMTP TLS Reporting records.\n */\nexport async function checkTlsrpt(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst tlsrptDomain = `_smtp._tls.${domain}`;\n\tconst txtRecords = await queryTxtRecords(tlsrptDomain, dnsOptions);\n\n\tconst tlsrptRecords = txtRecords.filter((r) => r.toLowerCase().startsWith('v=tlsrptv1'));\n\n\tif (tlsrptRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'No TLS-RPT record found',\n\t\t\t\t'low',\n\t\t\t\t`No TLS-RPT (v=TLSRPTv1) record found at ${tlsrptDomain}. TLS-RPT enables your domain to receive reports about SMTP TLS failures, complementing MTA-STS. Without it, you have no visibility into email delivery security issues.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('tlsrpt', findings);\n\t}\n\n\tif (tlsrptRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'Multiple TLS-RPT records',\n\t\t\t\t'medium',\n\t\t\t\t`Found ${tlsrptRecords.length} TLS-RPT records at ${tlsrptDomain}. There should be exactly one TLS-RPT record per domain.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tconst record = tlsrptRecords[0];\n\n\t// Check for rua= tag\n\tconst ruaMatch = record.match(/\\brua=([^\\s;]+)/i);\n\tif (!ruaMatch) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT record missing reporting URI',\n\t\t\t\t'medium',\n\t\t\t\t`TLS-RPT record at ${tlsrptDomain} does not contain a reporting URI (rua= tag). Without a reporting destination, TLS failure reports cannot be delivered.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('tlsrpt', findings);\n\t}\n\n\tconst ruaValue = ruaMatch[1];\n\t// Split comma-separated URIs and validate each\n\tconst uris = ruaValue.split(',').map((u) => u.trim());\n\tconst invalidUris: string[] = [];\n\n\tfor (const uri of uris) {\n\t\tif (!uri.toLowerCase().startsWith('mailto:') && !uri.toLowerCase().startsWith('https://')) {\n\t\t\tinvalidUris.push(uri);\n\t\t}\n\t}\n\n\tif (invalidUris.length > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT invalid reporting URI scheme',\n\t\t\t\t'medium',\n\t\t\t\t`TLS-RPT reporting URI(s) use invalid scheme: ${invalidUris.join(', ')}. Only mailto: and https:// schemes are supported per RFC 8460.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// If record is valid\n\tif (invalidUris.length === 0 && tlsrptRecords.length <= 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'tlsrpt',\n\t\t\t\t'TLS-RPT record configured',\n\t\t\t\t'info',\n\t\t\t\t`TLS-RPT record found and configured at ${tlsrptDomain}: ${record.substring(0, 120)}${record.length > 120 ? '...' : ''}`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('tlsrpt', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain detection tool.\n * Generates typosquat/lookalike domain permutations and checks for\n * active DNS registrations and mail infrastructure.\n * Standalone check — not included in scan_domain due to query volume.\n */\n\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport { generateLookalikes } from './lookalike-analysis';\n\n/** Default and minimum batch sizes for adaptive batching */\nexport const INITIAL_BATCH_SIZE = 10;\nexport const MIN_BATCH_SIZE = 3;\nexport const BACKOFF_DELAY_MS = 500;\nexport const FAILURE_THRESHOLD = 2;\n\n/** Maximum wall-clock time for the entire lookalike check (ms). */\nconst LOOKALIKE_TIMEOUT_MS = 20_000;\n\n/** Canary label used for wildcard detection on parent domains */\nexport const WILDCARD_CANARY_LABEL = '_bv-wc-probe';\n\n/** Lean DNS options for Phase 1 existence checks — fast, no retries, no secondary confirmation. */\nexport const PHASE1_DNS_OPTS: QueryDnsOptions = {\n\ttimeoutMs: 2000,\n\tretries: 0,\n\tskipSecondaryConfirmation: true,\n};\n\ninterface LookalikeResult {\n\tdomain: string;\n\thasA: boolean;\n\thasMX: boolean;\n}\n\n/**\n * Check whether an MX record represents real mail infrastructure.\n * RFC 7505 null MX (\"0 .\") explicitly means \"no mail accepted\" and must be excluded.\n */\nfunction isRealMxRecord(data: string): boolean {\n\t// Null MX: priority 0, exchange \".\" — RFC 7505\n\tconst trimmed = data.trim();\n\treturn trimmed !== '0 .' && trimmed !== '0\\t.';\n}\n\n/**\n * Check a single lookalike domain for DNS and MX records.\n * Filters out null MX records (RFC 7505) to avoid false positives.\n */\nasync function probeLookalike(domain: string): Promise<LookalikeResult> {\n\tconst [aRecords, mxRecords] = await Promise.allSettled([\n\t\tqueryDnsRecords(domain, 'A'),\n\t\tqueryDnsRecords(domain, 'MX'),\n\t]);\n\n\tconst realMxRecords =\n\t\tmxRecords.status === 'fulfilled' ? mxRecords.value.filter(isRealMxRecord) : [];\n\n\treturn {\n\t\tdomain,\n\t\thasA: aRecords.status === 'fulfilled' && aRecords.value.length > 0,\n\t\thasMX: realMxRecords.length > 0,\n\t};\n}\n\n/**\n * Count the number of labels (dot-separated segments) in a domain.\n */\nfunction labelCount(domain: string): number {\n\treturn domain.split('.').length;\n}\n\n/**\n * Extract the parent domain from a dot-insertion permutation.\n * E.g., \"blackve.ilsecurity.com\" → \"ilsecurity.com\"\n */\nfunction getParentDomain(domain: string): string {\n\tconst parts = domain.split('.');\n\treturn parts.slice(1).join('.');\n}\n\n/**\n * Detect wildcard DNS on a set of parent domains by probing a canary subdomain.\n * Returns a Set of parent domains that have wildcard A records.\n */\nasync function detectWildcardParents(parentDomains: string[]): Promise<Set<string>> {\n\tconst wildcardParents = new Set<string>();\n\tconst probes = parentDomains.map(async (parent) => {\n\t\ttry {\n\t\t\tconst canary = `${WILDCARD_CANARY_LABEL}.${parent}`;\n\t\t\tconst records = await queryDnsRecords(canary, 'A');\n\t\t\tif (records.length > 0) {\n\t\t\t\twildcardParents.add(parent);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Query failed — not a wildcard\n\t\t}\n\t});\n\tawait Promise.allSettled(probes);\n\treturn wildcardParents;\n}\n\n/**\n * Phase 1: Fast NS existence check for all domains in parallel.\n * Returns only domains that have NS records (i.e., are registered).\n */\nasync function filterByNsExistence(domains: string[]): Promise<string[]> {\n\tconst results = await Promise.allSettled(\n\t\tdomains.map(async (domain) => {\n\t\t\tconst ns = await queryDnsRecords(domain, 'NS', PHASE1_DNS_OPTS);\n\t\t\treturn { domain, hasNs: ns.length > 0 };\n\t\t}),\n\t);\n\treturn results\n\t\t.filter(\n\t\t\t(r): r is PromiseFulfilledResult<{ domain: string; hasNs: boolean }> =>\n\t\t\t\tr.status === 'fulfilled' && r.value.hasNs,\n\t\t)\n\t\t.map((r) => r.value.domain);\n}\n\n/**\n * Run permutation probes with adaptive batch sizing and backoff.\n * Starts at INITIAL_BATCH_SIZE, halves on repeated failures (floor at MIN_BATCH_SIZE),\n * recovers on clean batches.\n */\nasync function probeWithAdaptiveBatching(\n\tpermutations: string[],\n): Promise<PromiseSettledResult<LookalikeResult>[]> {\n\tconst allResults: PromiseSettledResult<LookalikeResult>[] = [];\n\tlet batchSize = INITIAL_BATCH_SIZE;\n\tlet delayMs = 0;\n\n\tfor (let i = 0; i < permutations.length; i += batchSize) {\n\t\tif (delayMs > 0) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\n\t\tconst batch = permutations.slice(i, i + batchSize);\n\t\tconst batchResults = await Promise.allSettled(batch.map((d) => probeLookalike(d)));\n\t\tallResults.push(...batchResults);\n\n\t\t// Count failures in this batch\n\t\tconst failures = batchResults.filter((r) => r.status === 'rejected').length;\n\t\tif (failures > FAILURE_THRESHOLD) {\n\t\t\t// Back off: halve batch size (floor to MIN_BATCH_SIZE) and add delay\n\t\t\tbatchSize = Math.max(MIN_BATCH_SIZE, Math.floor(batchSize / 2));\n\t\t\tdelayMs = BACKOFF_DELAY_MS;\n\t\t} else if (delayMs > 0 && failures === 0) {\n\t\t\t// Recover: if a clean batch after backoff, try increasing again\n\t\t\tbatchSize = Math.min(INITIAL_BATCH_SIZE, batchSize + 2);\n\t\t\tdelayMs = 0;\n\t\t}\n\t}\n\n\treturn allResults;\n}\n\n/**\n * Detect registered lookalike/typosquat domains with DNS or mail infrastructure.\n * Generates domain permutations and checks for active registrations using adaptive batching.\n * Filters out false positives from wildcard DNS on parent domains and null MX records.\n */\nexport async function checkLookalikes(domain: string): Promise<CheckResult> {\n\treturn Promise.race([\n\t\tcheckLookalikesCore(domain),\n\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Lookalike check timed out')), LOOKALIKE_TIMEOUT_MS)),\n\t]).catch(() => {\n\t\treturn buildCheckResult('lookalikes', [\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'Lookalike check incomplete',\n\t\t\t\t'info',\n\t\t\t\t'Lookalike check did not complete. This check generates many DNS queries — try again shortly, as partial results are cached.',\n\t\t\t),\n\t\t]);\n\t});\n}\n\nasync function checkLookalikesCore(domain: string): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst permutations = generateLookalikes(domain);\n\n\tif (permutations.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`No lookalike domain permutations could be generated for ${domain}.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Identify dot-insertion permutations (they have more labels than the original domain)\n\tconst originalLabelCount = labelCount(domain);\n\tconst dotInsertionParents = new Map<string, string[]>(); // parent → [permutations]\n\tconst nonDotInsertionPerms: string[] = [];\n\n\tfor (const perm of permutations) {\n\t\tif (labelCount(perm) > originalLabelCount) {\n\t\t\tconst parent = getParentDomain(perm);\n\t\t\tconst existing = dotInsertionParents.get(parent);\n\t\t\tif (existing) {\n\t\t\t\texisting.push(perm);\n\t\t\t} else {\n\t\t\t\tdotInsertionParents.set(parent, [perm]);\n\t\t\t}\n\t\t} else {\n\t\t\tnonDotInsertionPerms.push(perm);\n\t\t}\n\t}\n\n\t// Detect wildcard DNS on parent domains of dot-insertion permutations\n\tconst wildcardParents = dotInsertionParents.size > 0\n\t\t? await detectWildcardParents([...dotInsertionParents.keys()])\n\t\t: new Set<string>();\n\n\t// Filter out permutations whose parent has wildcard DNS\n\tconst filteredDotInsertionPerms: string[] = [];\n\tfor (const [parent, perms] of dotInsertionParents) {\n\t\tif (!wildcardParents.has(parent)) {\n\t\t\tfilteredDotInsertionPerms.push(...perms);\n\t\t}\n\t}\n\n\tconst permsToProbe = [...nonDotInsertionPerms, ...filteredDotInsertionPerms];\n\n\t// Phase 1: Fast NS existence check — filter out unregistered domains\n\tconst registeredPerms = await filterByNsExistence(permsToProbe);\n\n\tif (registeredPerms.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations detected.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('lookalikes', findings);\n\t}\n\n\t// Phase 2: Detail probe only registered domains\n\tconst probeResults = await probeWithAdaptiveBatching(registeredPerms);\n\tconst results: LookalikeResult[] = [];\n\tfor (const result of probeResults) {\n\t\tif (result.status === 'fulfilled') {\n\t\t\tresults.push(result.value);\n\t\t}\n\t}\n\n\t// Classify results\n\tlet highCount = 0;\n\tfor (const result of results) {\n\t\tif (result.hasMX) {\n\t\t\thighCount++;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain with mail infrastructure: ${result.domain}`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`The domain ${result.domain} is registered with active mail servers (MX records), which could be used for phishing or email spoofing targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t} else if (result.hasA) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'lookalikes',\n\t\t\t\t\t`Lookalike domain registered: ${result.domain}`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`The domain ${result.domain} is registered (has web presence) but no mail infrastructure detected. It could still be used for phishing websites targeting ${domain}.`,\n\t\t\t\t\t{ lookalikeDomain: result.domain, hasA: result.hasA, hasMX: result.hasMX },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Summary finding for high-severity lookalikes\n\tif (highCount > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} with mail capability detected`,\n\t\t\t\t'high',\n\t\t\t\t`${highCount} lookalike domain${highCount > 1 ? 's' : ''} of ${domain} ${highCount > 1 ? 'have' : 'has'} active mail infrastructure, presenting a phishing risk. Consider monitoring these domains and implementing DMARC with p=reject to protect your brand.`,\n\t\t\t\t{ lookalikeDomainCount: highCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// If no active lookalikes found\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'lookalikes',\n\t\t\t\t'No active lookalike domains detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${permutations.length} domain permutations of ${domain}. No active registrations with DNS or mail infrastructure detected.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('lookalikes', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Lookalike domain generation utilities.\n * Generates typosquat/lookalike domain permutations using multiple strategies:\n * adjacent key swaps, character omission, character duplication, dot insertion,\n * common TLD swaps, and homoglyph substitution.\n */\n\nimport { LABEL_REGEX, MAX_DOMAIN_LENGTH, MAX_LABEL_LENGTH } from '../lib/config';\n\n/** QWERTY keyboard adjacency map for typosquat detection */\nconst QWERTY_ADJACENT: Record<string, string[]> = {\n\tq: ['w', 'a'],\n\tw: ['q', 'e', 's', 'a'],\n\te: ['w', 'r', 'd', 's'],\n\tr: ['e', 't', 'f', 'd'],\n\tt: ['r', 'y', 'g', 'f'],\n\ty: ['t', 'u', 'h', 'g'],\n\tu: ['y', 'i', 'j', 'h'],\n\ti: ['u', 'o', 'k', 'j'],\n\to: ['i', 'p', 'l', 'k'],\n\tp: ['o', 'l'],\n\ta: ['q', 'w', 's', 'z'],\n\ts: ['a', 'w', 'e', 'd', 'z', 'x'],\n\td: ['s', 'e', 'r', 'f', 'x', 'c'],\n\tf: ['d', 'r', 't', 'g', 'c', 'v'],\n\tg: ['f', 't', 'y', 'h', 'v', 'b'],\n\th: ['g', 'y', 'u', 'j', 'b', 'n'],\n\tj: ['h', 'u', 'i', 'k', 'n', 'm'],\n\tk: ['j', 'i', 'o', 'l', 'm'],\n\tl: ['k', 'o', 'p'],\n\tz: ['a', 's', 'x'],\n\tx: ['z', 's', 'd', 'c'],\n\tc: ['x', 'd', 'f', 'v'],\n\tv: ['c', 'f', 'g', 'b'],\n\tb: ['v', 'g', 'h', 'n'],\n\tn: ['b', 'h', 'j', 'm'],\n\tm: ['n', 'j', 'k'],\n};\n\n/** Homoglyph substitution pairs (one substitution at a time) */\nconst HOMOGLYPHS: Array<[string, string]> = [\n\t['o', '0'],\n\t['0', 'o'],\n\t['l', '1'],\n\t['1', 'l'],\n\t['i', '1'],\n\t['1', 'i'],\n\t['l', 'i'],\n\t['i', 'l'],\n\t['rn', 'm'],\n\t['m', 'rn'],\n\t['vv', 'w'],\n\t['w', 'vv'],\n];\n\n/** Common TLD swap pairs */\nconst TLD_SWAPS: Array<[string, string]> = [\n\t['.com', '.co'],\n\t['.com', '.net'],\n\t['.com', '.org'],\n\t['.com', '.io'],\n\t['.co.nz', '.com'],\n\t['.com.au', '.com'],\n];\n\n/** Maximum number of permutations to return */\nconst MAX_PERMUTATIONS = 50;\n\n/**\n * Split a domain into base (before TLD) and TLD parts.\n * Handles multi-part TLDs like .co.nz and .com.au.\n */\nfunction splitDomainTld(domain: string): { base: string; tld: string } {\n\tconst multiPartTlds = ['.co.nz', '.com.au', '.co.uk', '.org.uk', '.net.au', '.org.au'];\n\tfor (const multiTld of multiPartTlds) {\n\t\tif (domain.endsWith(multiTld)) {\n\t\t\treturn { base: domain.slice(0, -multiTld.length), tld: multiTld };\n\t\t}\n\t}\n\tconst lastDot = domain.lastIndexOf('.');\n\tif (lastDot === -1) return { base: domain, tld: '' };\n\treturn { base: domain.slice(0, lastDot), tld: domain.slice(lastDot) };\n}\n\n/**\n * Check whether a domain string is structurally valid.\n * Labels must be 1-63 chars, alphanumeric + hyphens, total <= 253 chars.\n */\nfunction isDomainValid(domain: string): boolean {\n\tif (domain.length > MAX_DOMAIN_LENGTH) return false;\n\tconst labels = domain.split('.');\n\tif (labels.length < 2) return false;\n\tfor (const label of labels) {\n\t\tif (label.length === 0 || label.length > MAX_LABEL_LENGTH) return false;\n\t\tif (!LABEL_REGEX.test(label)) return false;\n\t}\n\treturn true;\n}\n\n/**\n * Generate lookalike/typosquat domain permutations for a given domain.\n * Applies six strategies: adjacent key swaps, character omission, character duplication,\n * dot insertion, common TLD swaps, and homoglyph substitution.\n *\n * Returns up to 50 unique, valid, alphabetically sorted permutations.\n */\nexport function generateLookalikes(domain: string): string[] {\n\tconst normalizedDomain = domain.toLowerCase();\n\tconst { base, tld } = splitDomainTld(normalizedDomain);\n\tconst candidates = new Set<string>();\n\n\t// 1. Adjacent key swaps — swap each char in base with QWERTY adjacent keys\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst ch = base[i];\n\t\tconst adjacent = QWERTY_ADJACENT[ch];\n\t\tif (adjacent) {\n\t\t\tfor (const adj of adjacent) {\n\t\t\t\tconst permuted = base.slice(0, i) + adj + base.slice(i + 1);\n\t\t\t\tcandidates.add(permuted + tld);\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Character omission — remove one char at a time from base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base.slice(i + 1);\n\t\tif (permuted.length > 0) {\n\t\t\tcandidates.add(permuted + tld);\n\t\t}\n\t}\n\n\t// 3. Character duplication — double one char at a time in base\n\tfor (let i = 0; i < base.length; i++) {\n\t\tconst permuted = base.slice(0, i) + base[i] + base[i] + base.slice(i + 1);\n\t\tcandidates.add(permuted + tld);\n\t}\n\n\t// 4. Dot insertion — insert dots between chars in base (both parts must be >= 2 chars)\n\tfor (let i = 1; i < base.length; i++) {\n\t\tconst left = base.slice(0, i);\n\t\tconst right = base.slice(i);\n\t\tif (left.length >= 2 && right.length >= 2) {\n\t\t\tcandidates.add(left + '.' + right + tld);\n\t\t}\n\t}\n\n\t// 5. Common TLD swaps — swap to different TLD if original matches\n\tfor (const [fromTld, toTld] of TLD_SWAPS) {\n\t\tif (tld === fromTld) {\n\t\t\tcandidates.add(base + toTld);\n\t\t} else if (tld === toTld) {\n\t\t\tcandidates.add(base + fromTld);\n\t\t}\n\t}\n\n\t// 6. Homoglyph substitution — one substitution at a time in base\n\tfor (const [from, to] of HOMOGLYPHS) {\n\t\tlet searchIdx = 0;\n\t\twhile (searchIdx <= base.length - from.length) {\n\t\t\tconst idx = base.indexOf(from, searchIdx);\n\t\t\tif (idx === -1) break;\n\t\t\tconst permuted = base.slice(0, idx) + to + base.slice(idx + from.length);\n\t\t\tcandidates.add(permuted + tld);\n\t\t\tsearchIdx = idx + 1;\n\t\t}\n\t}\n\n\t// Filter, dedup, and cap\n\tconst results = Array.from(candidates)\n\t\t.filter((candidate) => candidate !== normalizedDomain && isDomainValid(candidate))\n\t\t.sort();\n\n\treturn results.slice(0, MAX_PERMUTATIONS);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Shadow domain detection tool.\n * Discovers alternate-TLD variants of a domain and assesses email spoofing risk.\n * For each variant, probes NS, A, MX, SPF, and DMARC records to classify risk.\n */\n\nimport { queryDnsRecords, queryMxRecords, queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\nimport { extractBrandName, getEffectiveTld } from '../lib/public-suffix';\nimport { validateDomain } from '../lib/sanitize';\n\n/** Wall-clock timeout for the entire shadow domain check (ms). */\nconst SHADOW_TIMEOUT_MS = 20_000;\n\n/** Batch size for adaptive batching. */\nconst INITIAL_BATCH_SIZE = 4;\nconst MIN_BATCH_SIZE = 2;\nconst BACKOFF_DELAY_MS = 500;\n\nexport const FAILURE_THRESHOLD = 0;\n\n/** Lean DNS options for Phase 1 existence checks. */\nexport const PHASE1_DNS_OPTS: QueryDnsOptions = {\n\ttimeoutMs: 2000,\n\tretries: 0,\n\tskipSecondaryConfirmation: true,\n};\n\n/** Global ccTLD set always appended. */\nconst GLOBAL_TLDS = [\n\t'.com', '.net', '.org', '.io', '.ai', '.co',\n\t'.de', '.fr', '.nl', '.eu', '.co.uk', '.com.au',\n\t'.ca', '.jp', '.in', '.sg', '.za',\n];\n\n/** Regional variant TLD sets by TLD family. */\nconst NZ_REGIONAL = ['.nz', '.co.nz', '.org.nz', '.net.nz', '.govt.nz', '.ac.nz', '.school.nz', '.gen.nz', '.kiwi'];\nconst UK_REGIONAL = ['.co.uk', '.org.uk', '.uk'];\nconst AU_REGIONAL = ['.com.au', '.org.au', '.net.au', '.gov.au'];\nconst GENERIC_EXTRA = ['.dev', '.app'];\n\n/** Generic TLD family members. */\nconst GENERIC_TLDS = new Set(['.com', '.org', '.net', '.io', '.dev', '.app', '.co', '.ai']);\n\n/** Probe result for a single variant domain. */\ninterface VariantProbeResult {\n\tvariant: string;\n\tns: string[];\n\thasA: boolean;\n\tmx: string[];\n\thasSpf: boolean;\n\tdmarcPolicy: string | null;\n}\n\n/**\n * Generate alternate-TLD variants for a given brand name and effective TLD.\n * Excludes the primary domain from the result.\n */\nexport function generateVariants(brand: string, effectiveTld: string, primaryDomain: string): string[] {\n\tconst rawTld = effectiveTld.toLowerCase();\n\t// Normalize: getEffectiveTld() returns without leading dot (e.g. 'com', 'co.nz'),\n\t// but the constant sets use leading dots. Ensure consistent format for comparison.\n\tconst tldLower = rawTld.startsWith('.') ? rawTld : '.' + rawTld;\n\tconst primaryLower = primaryDomain.toLowerCase();\n\tconst allTlds = new Set<string>();\n\n\t// Add global TLDs\n\tfor (const tld of GLOBAL_TLDS) {\n\t\tallTlds.add(tld);\n\t}\n\n\t// Add regional variants based on TLD family\n\tif (tldLower.endsWith('.nz') || tldLower === '.kiwi') {\n\t\tfor (const tld of NZ_REGIONAL) allTlds.add(tld);\n\t} else if (tldLower === '.co.uk' || tldLower === '.org.uk' || tldLower === '.uk') {\n\t\tfor (const tld of UK_REGIONAL) allTlds.add(tld);\n\t} else if (tldLower.endsWith('.au')) {\n\t\tfor (const tld of AU_REGIONAL) allTlds.add(tld);\n\t} else if (GENERIC_TLDS.has(tldLower)) {\n\t\tfor (const tld of GENERIC_EXTRA) allTlds.add(tld);\n\t}\n\n\tconst variants: string[] = [];\n\tfor (const tld of allTlds) {\n\t\tconst candidate = `${brand}${tld}`;\n\t\tif (candidate.toLowerCase() === primaryLower) continue;\n\n\t\tconst validation = validateDomain(candidate);\n\t\tif (validation.valid) {\n\t\t\tvariants.push(candidate);\n\t\t}\n\t}\n\n\treturn variants.sort();\n}\n\n/**\n * Probe a single variant domain for NS, A, MX, SPF, and DMARC records.\n * All 5 DNS queries run in parallel with skipSecondaryConfirmation.\n */\nasync function probeVariant(\n\tvariant: string,\n\tdnsOpts: QueryDnsOptions,\n\tprefetchedNs?: string[],\n): Promise<VariantProbeResult> {\n\tconst nsPromise: Promise<string[]> =\n\t\tprefetchedNs !== undefined ? Promise.resolve(prefetchedNs) : queryDnsRecords(variant, 'NS', dnsOpts);\n\n\tconst [nsResult, aResult, mxResult, txtResult, dmarcResult] = await Promise.allSettled([\n\t\tnsPromise,\n\t\tqueryDnsRecords(variant, 'A', dnsOpts),\n\t\tqueryMxRecords(variant, dnsOpts),\n\t\tqueryTxtRecords(variant, dnsOpts),\n\t\tqueryTxtRecords(`_dmarc.${variant}`, dnsOpts),\n\t]);\n\n\tconst ns = nsResult.status === 'fulfilled' ? nsResult.value : [];\n\tconst hasA = aResult.status === 'fulfilled' && aResult.value.length > 0;\n\tconst mx = mxResult.status === 'fulfilled' ? mxResult.value.map((r) => r.exchange) : [];\n\n\t// Check for SPF\n\tconst txtValues = txtResult.status === 'fulfilled' ? txtResult.value : [];\n\tconst hasSpf = txtValues.some((r) => r.toLowerCase().startsWith('v=spf1'));\n\n\t// Parse DMARC policy\n\tlet dmarcPolicy: string | null = null;\n\tconst dmarcValues = dmarcResult.status === 'fulfilled' ? dmarcResult.value : [];\n\tconst dmarcRecord = dmarcValues.find((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\tif (dmarcRecord) {\n\t\tconst pMatch = dmarcRecord.match(/;\\s*p=([^;\\s]+)/i);\n\t\tdmarcPolicy = pMatch ? pMatch[1].toLowerCase() : 'none';\n\t}\n\n\treturn { variant, ns, hasA, mx, hasSpf, dmarcPolicy };\n}\n\n/**\n * Phase 1: Fast NS existence check for all variants in parallel.\n * Returns a Map of variant -> NS records for registered domains.\n */\nasync function filterByNsExistence(\n\tvariants: string[],\n\tdnsOpts: QueryDnsOptions,\n): Promise<Map<string, string[]>> {\n\tconst registered = new Map<string, string[]>();\n\tconst results = await Promise.allSettled(\n\t\tvariants.map(async (variant) => {\n\t\t\tconst ns = await queryDnsRecords(variant, 'NS', { ...dnsOpts, ...PHASE1_DNS_OPTS });\n\t\t\treturn { variant, ns };\n\t\t}),\n\t);\n\tfor (const result of results) {\n\t\tif (result.status === 'fulfilled' && result.value.ns.length > 0) {\n\t\t\tregistered.set(result.value.variant, result.value.ns);\n\t\t}\n\t}\n\treturn registered;\n}\n\n/**\n * Check whether the variant MX set is a subset of the primary MX set.\n * Compares sorted exchange hostnames (case-insensitive).\n */\nfunction isSameMxInfra(variantMx: string[], primaryMx: string[]): boolean {\n\tif (variantMx.length === 0) return false;\n\tconst primarySet = new Set(primaryMx.map((h) => h.toLowerCase().replace(/\\.$/, '')));\n\treturn variantMx.every((h) => primarySet.has(h.toLowerCase().replace(/\\.$/, '')));\n}\n\n/**\n * Classify a probed variant into a finding based on risk.\n */\nfunction classifyVariant(probe: VariantProbeResult, primaryMx: string[]): Finding {\n\tconst { variant, ns, mx, hasSpf, dmarcPolicy } = probe;\n\tconst hasMx = mx.length > 0;\n\tconst hasNs = ns.length > 0;\n\tconst meta = { variant, ns, mx, hasSpf, dmarcPolicy };\n\n\tif (hasMx) {\n\t\tif (!hasSpf && dmarcPolicy === null) {\n\t\t\t// MX present, no SPF AND no DMARC → critical\n\t\t\treturn createFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain fully spoofable',\n\t\t\t\t'critical',\n\t\t\t\t`${variant} has mail servers but no SPF or DMARC records. Any sender can forge email from this domain.`,\n\t\t\t\tmeta,\n\t\t\t);\n\t\t}\n\n\t\tif (hasSpf && dmarcPolicy === null) {\n\t\t\t// MX present, SPF but no DMARC → high\n\t\t\treturn createFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain lacks DMARC',\n\t\t\t\t'high',\n\t\t\t\t`${variant} has mail servers and SPF but no DMARC record. Without DMARC, SPF alone cannot prevent spoofing.`,\n\t\t\t\tmeta,\n\t\t\t);\n\t\t}\n\n\t\tif (dmarcPolicy === 'none') {\n\t\t\t// MX present, DMARC p=none → high\n\t\t\treturn createFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain DMARC not enforcing',\n\t\t\t\t'high',\n\t\t\t\t`${variant} has mail servers with DMARC policy set to \"none\" — spoofed emails are monitored but not blocked.`,\n\t\t\t\tmeta,\n\t\t\t);\n\t\t}\n\n\t\t// DMARC is quarantine or reject — check MX infrastructure match\n\t\tif (dmarcPolicy === 'quarantine' || dmarcPolicy === 'reject') {\n\t\t\tif (!isSameMxInfra(mx, primaryMx)) {\n\t\t\t\t// Divergent MX infrastructure → medium\n\t\t\t\treturn createFinding(\n\t\t\t\t\t'shadow_domains',\n\t\t\t\t\t'Shadow domain divergent mail infrastructure',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${variant} uses different mail servers than the primary domain despite having enforcing DMARC. This may indicate separate management.`,\n\t\t\t\t\tmeta,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Same MX infra, properly authenticated → low\n\t\t\treturn createFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain well-managed',\n\t\t\t\t'low',\n\t\t\t\t`${variant} has matching mail infrastructure and enforcing DMARC — properly managed shadow domain.`,\n\t\t\t\tmeta,\n\t\t\t);\n\t\t}\n\n\t\t// DMARC present with unknown policy — treat as high-ish (SPF but unclear DMARC)\n\t\tif (!isSameMxInfra(mx, primaryMx)) {\n\t\t\treturn createFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain divergent mail infrastructure',\n\t\t\t\t'medium',\n\t\t\t\t`${variant} uses different mail servers than the primary domain.`,\n\t\t\t\tmeta,\n\t\t\t);\n\t\t}\n\n\t\treturn createFinding(\n\t\t\t'shadow_domains',\n\t\t\t'Shadow domain well-managed',\n\t\t\t'low',\n\t\t\t`${variant} has matching mail infrastructure and DMARC configured.`,\n\t\t\tmeta,\n\t\t);\n\t}\n\n\tif (hasNs) {\n\t\t// Registered but no MX → info\n\t\treturn createFinding(\n\t\t\t'shadow_domains',\n\t\t\t'Shadow domain registered, no mail',\n\t\t\t'info',\n\t\t\t`${variant} is registered (has NS records) but has no mail infrastructure configured.`,\n\t\t\tmeta,\n\t\t);\n\t}\n\n\t// Not registered → info\n\treturn createFinding(\n\t\t'shadow_domains',\n\t\t'Brand variant unregistered',\n\t\t'info',\n\t\t`${variant} does not appear to be registered. Consider defensive registration to prevent brand abuse.`,\n\t\tmeta,\n\t);\n}\n\n/**\n * Detect shared NS pairs across registered variants.\n * Returns info findings for groups of 2+ variants sharing the same NS pair.\n */\nfunction detectSharedNs(probes: VariantProbeResult[]): Finding[] {\n\tconst nsMap = new Map<string, string[]>();\n\n\tfor (const probe of probes) {\n\t\tif (probe.ns.length < 2) continue;\n\t\tconst nsKey = probe.ns\n\t\t\t.map((n) => n.toLowerCase().replace(/\\.$/, ''))\n\t\t\t.sort()\n\t\t\t.join(',');\n\t\tconst existing = nsMap.get(nsKey);\n\t\tif (existing) {\n\t\t\texisting.push(probe.variant);\n\t\t} else {\n\t\t\tnsMap.set(nsKey, [probe.variant]);\n\t\t}\n\t}\n\n\tconst findings: Finding[] = [];\n\tfor (const [nsKey, variants] of nsMap) {\n\t\tif (variants.length >= 2) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'shadow_domains',\n\t\t\t\t\t'Shared NS across shadow domains',\n\t\t\t\t\t'info',\n\t\t\t\t\t`${variants.join(', ')} share the same nameserver pair (${nsKey}), suggesting common ownership or registrar.`,\n\t\t\t\t\t{ variants, nameservers: nsKey },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\treturn findings;\n}\n\n/** Severity order for sorting findings (critical first). */\nconst SEVERITY_ORDER: Record<string, number> = {\n\tcritical: 0,\n\thigh: 1,\n\tmedium: 2,\n\tlow: 3,\n\tinfo: 4,\n};\n\n/**\n * Check shadow domains for a given domain.\n * Discovers alternate-TLD variants and assesses email spoofing risk.\n * Uses cooperative timeout with partial result preservation.\n */\nexport async function checkShadowDomains(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tconst startTime = Date.now();\n\tconst deadline = startTime + SHADOW_TIMEOUT_MS;\n\n\tconst brand = extractBrandName(domain);\n\tconst effectiveTld = getEffectiveTld(domain);\n\n\tif (!brand || !effectiveTld) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Unable to extract brand name',\n\t\t\t\t'info',\n\t\t\t\t`Could not determine the registrable brand name from \\`${domain}\\`.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('shadow_domains', findings);\n\t}\n\n\tconst variants = generateVariants(brand, effectiveTld, domain);\n\n\tif (variants.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'No shadow domain variants generated',\n\t\t\t\t'info',\n\t\t\t\t`No alternate-TLD variants could be generated for ${domain}.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('shadow_domains', findings);\n\t}\n\n\t// Query primary domain MX for comparison\n\tconst dnsOpts: QueryDnsOptions = { ...dnsOptions, skipSecondaryConfirmation: true };\n\tlet primaryMx: string[] = [];\n\ttry {\n\t\tconst mxResult = await queryMxRecords(domain, dnsOpts);\n\t\tprimaryMx = mxResult.map((r) => r.exchange);\n\t} catch {\n\t\t// Primary MX query failure — continue with empty set\n\t}\n\n\t// Phase 1: Fast NS existence check — filter out unregistered variants\n\tconst registeredVariants = await filterByNsExistence(variants, dnsOpts);\n\n\t// Classify unregistered variants immediately as info findings\n\tfor (const variant of variants) {\n\t\tif (!registeredVariants.has(variant)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'shadow_domains',\n\t\t\t\t\t'Brand variant unregistered',\n\t\t\t\t\t'info',\n\t\t\t\t\t`${variant} does not appear to be registered. Consider defensive registration to prevent brand abuse.`,\n\t\t\t\t\t{ variant, ns: [], mx: [], hasSpf: false, dmarcPolicy: null },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Phase 2: Detail probe only registered variants with NS passthrough\n\tconst registeredList = [...registeredVariants.entries()];\n\tlet batchSize = INITIAL_BATCH_SIZE;\n\tlet delayMs = 0;\n\tconst completedProbes: VariantProbeResult[] = [];\n\tconst variantsChecked = registeredList.length;\n\tlet timedOut = false;\n\n\tfor (let i = 0; i < registeredList.length; i += batchSize) {\n\t\tif (Date.now() >= deadline) {\n\t\t\ttimedOut = true;\n\t\t\tbreak;\n\t\t}\n\n\t\tif (delayMs > 0) {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\n\t\tconst batch = registeredList.slice(i, i + batchSize);\n\t\tconst batchResults = await Promise.allSettled(\n\t\t\tbatch.map(([variant, ns]) => probeVariant(variant, dnsOpts, ns)),\n\t\t);\n\n\t\tlet failures = 0;\n\t\tfor (const result of batchResults) {\n\t\t\tif (result.status === 'fulfilled') {\n\t\t\t\tcompletedProbes.push(result.value);\n\t\t\t} else {\n\t\t\t\tfailures++;\n\t\t\t}\n\t\t}\n\n\t\t// Adaptive batch sizing\n\t\tif (failures > FAILURE_THRESHOLD) {\n\t\t\tbatchSize = Math.max(MIN_BATCH_SIZE, Math.floor(batchSize / 2));\n\t\t\tdelayMs = BACKOFF_DELAY_MS;\n\t\t} else if (delayMs > 0) {\n\t\t\tbatchSize = Math.min(INITIAL_BATCH_SIZE, batchSize + 1);\n\t\t\tdelayMs = 0;\n\t\t}\n\t}\n\n\t// Classify each completed probe\n\tfor (const probe of completedProbes) {\n\t\tfindings.push(classifyVariant(probe, primaryMx));\n\t}\n\n\t// Detect shared NS pairs\n\tfindings.push(...detectSharedNs(completedProbes));\n\n\t// Add timeout finding if we didn't finish\n\tif (timedOut) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'Shadow domain check timed out',\n\t\t\t\t'info',\n\t\t\t\t`Shadow domain check timed out — ${variantsChecked} of ${variants.length} variants were checked.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Sort findings by severity (critical first)\n\tfindings.sort((a, b) => (SEVERITY_ORDER[a.severity] ?? 4) - (SEVERITY_ORDER[b.severity] ?? 4));\n\n\t// If no findings at all (shouldn't happen, but safeguard)\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'shadow_domains',\n\t\t\t\t'No shadow domain issues detected',\n\t\t\t\t'info',\n\t\t\t\t`Checked ${variants.length} alternate-TLD variants of ${domain}. No email spoofing risks detected.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('shadow_domains', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Curated public suffix list subset for multi-level TLD matching.\n * Used to extract the registrable brand name from a domain.\n *\n * Stored as a Set of dot-joined suffixes for O(1) lookup.\n */\nconst MULTI_LEVEL_SUFFIXES = new Set([\n\t// NZ\n\t'co.nz',\n\t'govt.nz',\n\t'org.nz',\n\t'net.nz',\n\t'ac.nz',\n\t'school.nz',\n\t'gen.nz',\n\t// UK\n\t'co.uk',\n\t'org.uk',\n\t'me.uk',\n\t'net.uk',\n\t'gov.uk',\n\t'ac.uk',\n\t// AU\n\t'com.au',\n\t'org.au',\n\t'net.au',\n\t'gov.au',\n\t'edu.au',\n\t// JP\n\t'co.jp',\n\t'or.jp',\n\t'ne.jp',\n\t'go.jp',\n\t'ac.jp',\n\t// ZA\n\t'co.za',\n\t'org.za',\n\t'gov.za',\n\t'net.za',\n\t// IN\n\t'co.in',\n\t'org.in',\n\t'net.in',\n\t'gov.in',\n\t// SG\n\t'com.sg',\n\t'org.sg',\n\t'gov.sg',\n]);\n\n/**\n * Determine the effective TLD for a domain by matching against\n * the curated multi-level suffix list.\n *\n * Walk domain labels right-to-left, checking progressively longer\n * suffixes against the PSL set. If a multi-level match is found,\n * that is the effective TLD. Otherwise the rightmost label is the TLD.\n *\n * Returns `null` if the input is empty, single-label, or is itself\n * a TLD suffix (i.e., there is no registrable label to the left).\n */\nexport function getEffectiveTld(domain: string): string | null {\n\tif (!domain) return null;\n\n\t// Strip trailing dot (e.g., \"example.com.\" → \"example.com\")\n\tconst normalized = domain.endsWith('.') ? domain.slice(0, -1) : domain;\n\tif (!normalized) return null;\n\n\tconst labels = normalized.toLowerCase().split('.');\n\tif (labels.length < 2) return null;\n\n\t// Walk from rightmost label, building candidate suffixes\n\t// and checking for multi-level matches (longest match wins).\n\tlet effectiveTld: string | null = null;\n\n\tfor (let i = labels.length - 2; i >= 0; i--) {\n\t\tconst candidate = labels.slice(i).join('.');\n\t\tif (MULTI_LEVEL_SUFFIXES.has(candidate)) {\n\t\t\teffectiveTld = candidate;\n\t\t\t// Keep checking for even longer matches (though unlikely with current data)\n\t\t} else {\n\t\t\t// No longer suffix can match if this intermediate one didn't\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// If no multi-level match, the rightmost label is the TLD\n\tif (!effectiveTld) {\n\t\teffectiveTld = labels[labels.length - 1];\n\t}\n\n\t// The effective TLD must leave at least one label to the left (the brand)\n\tconst tldLabels = effectiveTld.split('.');\n\tif (tldLabels.length >= labels.length) {\n\t\t// The input IS the TLD suffix itself — no registrable domain\n\t\treturn null;\n\t}\n\n\treturn effectiveTld;\n}\n\n/**\n * Extract the registrable brand name from a domain.\n *\n * The brand name is the label immediately to the left of the effective TLD.\n * Subdomains further to the left are stripped.\n *\n * @example\n * extractBrandName('tewhatuora.govt.nz') // => 'tewhatuora'\n * extractBrandName('sub.example.co.nz') // => 'example'\n * extractBrandName('blackveil.nz') // => 'blackveil'\n * extractBrandName('co.nz') // => null (bare TLD suffix)\n * extractBrandName('com') // => null (single label)\n */\nexport function extractBrandName(domain: string): string | null {\n\tconst tld = getEffectiveTld(domain);\n\tif (!tld) return null;\n\n\t// Strip trailing dot to match getEffectiveTld normalization\n\tconst normalized = domain.endsWith('.') ? domain.slice(0, -1) : domain;\n\tconst labels = normalized.toLowerCase().split('.');\n\tconst tldLabels = tld.split('.');\n\n\t// The brand label is at position (total labels - TLD labels - 1)\n\tconst brandIndex = labels.length - tldLabels.length - 1;\n\tif (brandIndex < 0) return null;\n\n\treturn labels[brandIndex];\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * TXT Record Hygiene check tool.\n *\n * Audits TXT records for governance and security concerns including:\n * - Geopolitical jurisdiction risks (Yandex/Baidu on government domains)\n * - Record accumulation and clutter\n * - Stale service integrations\n * - Misplaced DMARC records\n * - Cross-domain trust delegation\n */\n\nimport { queryTxtRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { getEffectiveTld } from '../lib/public-suffix';\nimport { validateDomain } from '../lib/sanitize';\nimport type { CheckResult, Finding } from '../lib/scoring';\nimport { buildCheckResult, createFinding } from '../lib/scoring';\n\n// ─── Verification pattern definitions ────────────────────────────────────────\n\ntype VerificationCategory = 'search_engine' | 'identity_auth' | 'collaboration' | 'security' | 'marketing' | 'infrastructure' | 'email_auth';\n\ninterface VerificationPattern {\n\tprefix: string;\n\tservice: string;\n\tcategory: VerificationCategory;\n\tjurisdiction?: string;\n}\n\nconst VERIFICATION_PATTERNS: VerificationPattern[] = [\n\t// Search engines\n\t{ prefix: 'google-site-verification=', service: 'Google Search Console', category: 'search_engine' },\n\t{ prefix: 'yandex-verification:', service: 'Yandex', category: 'search_engine', jurisdiction: 'RU' },\n\t{ prefix: 'msvalidate.01=', service: 'Bing', category: 'search_engine' },\n\t{ prefix: 'baidu-site-verification=', service: 'Baidu', category: 'search_engine', jurisdiction: 'CN' },\n\t{ prefix: 'naver-site-verification=', service: 'Naver', category: 'search_engine' },\n\n\t// Identity & auth\n\t{ prefix: 'MS=', service: 'Microsoft 365', category: 'identity_auth' },\n\t{ prefix: 'apple-domain-verification=', service: 'Apple', category: 'identity_auth' },\n\t{ prefix: 'facebook-domain-verification=', service: 'Facebook', category: 'identity_auth' },\n\t{ prefix: 'atlassian-domain-verification=', service: 'Atlassian', category: 'identity_auth' },\n\t{ prefix: 'adobe-idp-site-verification=', service: 'Adobe', category: 'identity_auth' },\n\t{ prefix: 'docusign=', service: 'DocuSign', category: 'identity_auth' },\n\t{ prefix: 'cisco-ci-domain-verification=', service: 'Cisco', category: 'identity_auth' },\n\t{ prefix: 'teamviewer-sso-verification=', service: 'TeamViewer', category: 'identity_auth' },\n\t{ prefix: 'zoom-domain-verification=', service: 'Zoom', category: 'identity_auth' },\n\n\t// Collaboration\n\t{ prefix: 'miro-verification=', service: 'Miro', category: 'collaboration' },\n\t{ prefix: 'figma-domain-verification=', service: 'Figma', category: 'collaboration' },\n\t{ prefix: 'slack-domain-verification=', service: 'Slack', category: 'collaboration' },\n\t{ prefix: 'asana-domain-verification=', service: 'Asana', category: 'collaboration' },\n\t{ prefix: 'notion-domain-verification=', service: 'Notion', category: 'collaboration' },\n\t{ prefix: 'canva-domain-verification=', service: 'Canva', category: 'collaboration' },\n\t{ prefix: 'monday-domain-verification=', service: 'Monday.com', category: 'collaboration' },\n\n\t// Security\n\t{ prefix: 'onetrust-domain-verification=', service: 'OneTrust', category: 'security' },\n\t{ prefix: 'knowbe4-site-verification=', service: 'KnowBe4', category: 'security' },\n\t{ prefix: 'sophos-domain-verification=', service: 'Sophos', category: 'security' },\n\t{ prefix: 'crowdstrike-domain-verification=', service: 'CrowdStrike', category: 'security' },\n\n\t// Marketing\n\t{ prefix: 'google-gws-recovery-domain-verification=', service: 'Google Workspace Recovery', category: 'marketing' },\n\t{ prefix: 'hubspot-developer-verification=', service: 'HubSpot', category: 'marketing' },\n\t{ prefix: 'pardot_', service: 'Salesforce Pardot', category: 'marketing' },\n\t{ prefix: 'mailchimp-domain-verification=', service: 'Mailchimp', category: 'marketing' },\n\t{ prefix: 'sendgrid-verification=', service: 'SendGrid', category: 'marketing' },\n\n\t// Infrastructure\n\t{ prefix: 'barco-verification=', service: 'Barco', category: 'infrastructure' },\n\t{ prefix: 'TrustedForDomainSharing=', service: 'TrustedForDomainSharing', category: 'infrastructure' },\n\t{ prefix: 'have-i-been-pwned-verification=', service: 'Have I Been Pwned', category: 'infrastructure' },\n\t{ prefix: 'stripe-verification=', service: 'Stripe', category: 'infrastructure' },\n\t{ prefix: 'globalsign-domain-verification=', service: 'GlobalSign', category: 'infrastructure' },\n\t{ prefix: '_github-pages-challenge-', service: 'GitHub Pages', category: 'infrastructure' },\n\t{ prefix: '_gitlab-pages-verification-code', service: 'GitLab Pages', category: 'infrastructure' },\n\t{ prefix: 'loaderio-', service: 'Loader.io', category: 'infrastructure' },\n\n\t// Email auth (v=spf1 is expected and not flagged as verification)\n\t{ prefix: 'v=DMARC1', service: 'DMARC', category: 'email_auth' },\n];\n\n// ─── SPF cross-reference for staleness detection ─────────────────────────────\n\nconst SERVICE_SPF_DOMAINS: Record<string, string[]> = {\n\t'Google Search Console': ['_spf.google.com', 'google.com'],\n\t'Microsoft 365': ['spf.protection.outlook.com', 'outlook.com'],\n\t'SendGrid': ['sendgrid.net'],\n\t'Mailchimp': ['mandrillapp.com', 'mailchimp.com'],\n\t'HubSpot': ['hubspotemail.net'],\n\t'Salesforce Pardot': ['salesforce.com'],\n\t'Zoho': ['zoho.com', 'zoho.eu'],\n\t'Freshdesk': ['freshdesk.com'],\n\t'Zendesk': ['zendesk.com'],\n};\n\n// ─── Government TLD detection ────────────────────────────────────────────────\n\nconst GOVERNMENT_TLDS = new Set([\n\t'govt.nz',\n\t'gov.au',\n\t'gov.uk',\n\t'gov.za',\n\t'gov.in',\n\t'go.jp',\n\t'gov.sg',\n\t'gov',\n\t'mil',\n\t'edu',\n\t'ac.nz',\n\t'ac.uk',\n\t'ac.jp',\n]);\n\nfunction isGovernmentDomain(domain: string): boolean {\n\tconst tld = getEffectiveTld(domain);\n\tif (!tld) return false;\n\treturn GOVERNMENT_TLDS.has(tld);\n}\n\n// ─── SPF include extraction ─────────────────────────────────────────────────\n\nfunction extractSpfIncludes(txtRecords: string[]): string[] {\n\tconst spfRecord = txtRecords.find((r) => r.toLowerCase().startsWith('v=spf1'));\n\tif (!spfRecord) return [];\n\tconst includes: string[] = [];\n\tconst regex = /\\binclude:(\\S+)/gi;\n\tlet match: RegExpExecArray | null;\n\twhile ((match = regex.exec(spfRecord)) !== null) {\n\t\tincludes.push(match[1].toLowerCase());\n\t}\n\treturn includes;\n}\n\n// ─── Hygiene rating ──────────────────────────────────────────────────────────\n\nfunction getHygieneRating(recordCount: number): string {\n\tif (recordCount >= 15) return 'Excessive';\n\tif (recordCount >= 10) return 'Cluttered';\n\tif (recordCount >= 5) return 'Moderate';\n\treturn 'Clean';\n}\n\n// ─── Main check function ─────────────────────────────────────────────────────\n\n/**\n * Check TXT record hygiene for a domain.\n *\n * Audits root TXT records for governance concerns including jurisdiction\n * risks, record accumulation, stale integrations, and misplaced records.\n */\nexport async function checkTxtHygiene(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\t// Defense-in-depth: validate domain even though upstream dispatch already validates\n\tconst validation = validateDomain(domain);\n\tif (!validation.valid) {\n\t\treturn buildCheckResult('txt_hygiene', [\n\t\t\tcreateFinding('txt_hygiene', 'Invalid domain', 'info', `Domain validation failed: ${validation.error ?? 'invalid input'}.`),\n\t\t]);\n\t}\n\n\t// Step 1: Fetch root TXT and _dmarc TXT in parallel (allSettled to tolerate partial failure)\n\tconst [rootResult, dmarcResult] = await Promise.allSettled([\n\t\tqueryTxtRecords(domain, dnsOptions),\n\t\tqueryTxtRecords(`_dmarc.${domain}`, dnsOptions),\n\t]);\n\tconst rootTxtRecords = rootResult.status === 'fulfilled' ? rootResult.value : [];\n\tconst dmarcTxtRecords = dmarcResult.status === 'fulfilled' ? dmarcResult.value : [];\n\n\t// Handle no TXT records\n\tif (rootTxtRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'No TXT records found',\n\t\t\t\t'info',\n\t\t\t\t`No TXT records found for ${domain}. This is unusual but not necessarily a problem.`,\n\t\t\t),\n\t\t);\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'TXT record hygiene summary',\n\t\t\t\t'info',\n\t\t\t\t`TXT record hygiene rating: Clean (0 records). No governance concerns detected.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('txt_hygiene', findings);\n\t}\n\n\t// Step 2: Pattern match TXT records\n\tinterface MatchedService {\n\t\tservice: string;\n\t\tcategory: VerificationCategory;\n\t\tjurisdiction?: string;\n\t\tprefix: string;\n\t\trecord: string;\n\t}\n\n\tconst matchedServices: MatchedService[] = [];\n\n\tfor (const record of rootTxtRecords) {\n\t\t// Skip SPF records — they are expected, not verification\n\t\tif (record.toLowerCase().startsWith('v=spf1')) continue;\n\n\t\tfor (const pattern of VERIFICATION_PATTERNS) {\n\t\t\tif (record.startsWith(pattern.prefix) || record.toLowerCase().startsWith(pattern.prefix.toLowerCase())) {\n\t\t\t\tmatchedServices.push({\n\t\t\t\t\tservice: pattern.service,\n\t\t\t\t\tcategory: pattern.category,\n\t\t\t\t\tjurisdiction: pattern.jurisdiction,\n\t\t\t\t\tprefix: pattern.prefix,\n\t\t\t\t\trecord,\n\t\t\t\t});\n\t\t\t\tbreak; // Only match first pattern per record\n\t\t\t}\n\t\t}\n\t}\n\n\t// Step 3: Generate findings\n\n\t// --- Geopolitical jurisdiction findings ---\n\tconst govDomain = isGovernmentDomain(domain);\n\tconst domainTld = getEffectiveTld(domain);\n\n\tfor (const match of matchedServices) {\n\t\tif (match.jurisdiction === 'RU') {\n\t\t\t// Don't flag on native .ru domains\n\t\t\tif (domainTld === 'ru') continue;\n\n\t\t\tif (govDomain) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t\t'Russian jurisdiction service on government domain',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`${match.service} verification record found on government domain ${domain}. This service operates under Russian jurisdiction and may pose data sovereignty concerns.`,\n\t\t\t\t\t\t{ service: match.service, jurisdiction: 'RU', category: match.category },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t\t'Russian jurisdiction service verification detected',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`${match.service} verification record found for ${domain}. This service operates under Russian jurisdiction. Consider whether this aligns with your organization's data governance policies.`,\n\t\t\t\t\t\t{ service: match.service, jurisdiction: 'RU', category: match.category },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (match.jurisdiction === 'CN') {\n\t\t\t// Don't flag on native .cn domains\n\t\t\tif (domainTld === 'cn') continue;\n\n\t\t\tif (govDomain) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t\t'Chinese jurisdiction service on government domain',\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`${match.service} verification record found on government domain ${domain}. This service operates under Chinese jurisdiction and may pose data sovereignty concerns.`,\n\t\t\t\t\t\t{ service: match.service, jurisdiction: 'CN', category: match.category },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t\t'Chinese jurisdiction service verification detected',\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`${match.service} verification record found for ${domain}. This service operates under Chinese jurisdiction. Consider whether this aligns with your organization's data governance policies.`,\n\t\t\t\t\t\t{ service: match.service, jurisdiction: 'CN', category: match.category },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Record accumulation ---\n\tconst recordCount = rootTxtRecords.length;\n\tif (recordCount >= 15) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'Excessive TXT record accumulation',\n\t\t\t\t'high',\n\t\t\t\t`Found ${recordCount} TXT records for ${domain}. Excessive records increase DNS response size, risk UDP truncation, and suggest poor lifecycle management. Review and remove unused verification records.`,\n\t\t\t\t{ recordCount },\n\t\t\t),\n\t\t);\n\t} else if (recordCount >= 10) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'TXT record accumulation',\n\t\t\t\t'medium',\n\t\t\t\t`Found ${recordCount} TXT records for ${domain}. Consider auditing for stale or unnecessary records to prevent future DNS response size issues.`,\n\t\t\t\t{ recordCount },\n\t\t\t),\n\t\t);\n\t}\n\n\t// --- Duplicate verification records ---\n\tconst prefixCounts = new Map<string, { service: string; count: number }>();\n\tfor (const match of matchedServices) {\n\t\tconst existing = prefixCounts.get(match.prefix);\n\t\tif (existing) {\n\t\t\texisting.count++;\n\t\t} else {\n\t\t\tprefixCounts.set(match.prefix, { service: match.service, count: 1 });\n\t\t}\n\t}\n\tfor (const [, { service, count }] of prefixCounts) {\n\t\tif (count >= 2) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t`Duplicate verification records: ${service}`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Found ${count} verification records for ${service}. Duplicate verification records are unnecessary and may indicate incomplete migrations or stale configurations.`,\n\t\t\t\t\t{ service, duplicateCount: count },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// --- DMARC misplaced at root ---\n\tconst dmarcAtRoot = rootTxtRecords.some((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\tif (dmarcAtRoot) {\n\t\tconst dmarcAtSubdomain = dmarcTxtRecords.some((r) => r.toLowerCase().startsWith('v=dmarc1'));\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'DMARC record misplaced at root',\n\t\t\t\t'medium',\n\t\t\t\t`A DMARC record (v=DMARC1) was found at the root domain instead of the correct location (_dmarc.${domain}). ${dmarcAtSubdomain ? 'A properly placed record also exists at _dmarc — the root record is redundant and should be removed.' : 'Mail receivers query _dmarc.${domain}, so a root-level DMARC record has no effect.'}`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// --- TrustedForDomainSharing ---\n\tconst hasTrustedSharing = matchedServices.some((m) => m.prefix === 'TrustedForDomainSharing=');\n\tif (hasTrustedSharing) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'Cross-domain trust delegation detected',\n\t\t\t\t'medium',\n\t\t\t\t`TrustedForDomainSharing record found for ${domain}. This delegates trust across domains and could be exploited if the trusted domain is compromised. Verify this delegation is intentional and actively needed.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// --- Stale integration detection (SPF cross-reference) ---\n\tconst spfIncludes = extractSpfIncludes(rootTxtRecords);\n\tfor (const match of matchedServices) {\n\t\tconst spfDomains = SERVICE_SPF_DOMAINS[match.service];\n\t\tif (!spfDomains) continue;\n\n\t\tconst hasSpfInclude = spfDomains.some((spfDomain) =>\n\t\t\tspfIncludes.some((include) => include.includes(spfDomain.toLowerCase())),\n\t\t);\n\n\t\tif (!hasSpfInclude) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'txt_hygiene',\n\t\t\t\t\t`Possible stale service integration: ${match.service}`,\n\t\t\t\t\t'low',\n\t\t\t\t\t`${match.service} verification record found but no corresponding SPF include detected. This may indicate the service is no longer actively used for email sending. Review and remove if the integration has been decommissioned.`,\n\t\t\t\t\t{ service: match.service, category: match.category },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// --- Multiple MS= records (tenant migration residue) ---\n\tconst msRecords = rootTxtRecords.filter((r) => r.startsWith('MS='));\n\tif (msRecords.length > 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t'Possible Microsoft tenant migration residue',\n\t\t\t\t'low',\n\t\t\t\t`Found ${msRecords.length} MS= verification records. Multiple MS= records typically indicate incomplete Microsoft 365 tenant migrations. Only the current tenant's record is needed.`,\n\t\t\t\t{ msRecordCount: msRecords.length },\n\t\t\t),\n\t\t);\n\t}\n\n\t// --- Info findings for each detected platform ---\n\tfor (const match of matchedServices) {\n\t\t// Skip DMARC at root — already flagged above\n\t\tif (match.category === 'email_auth' && match.service === 'DMARC') continue;\n\t\t// Skip TrustedForDomainSharing — already flagged above\n\t\tif (match.prefix === 'TrustedForDomainSharing=') continue;\n\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'txt_hygiene',\n\t\t\t\t`Service verification detected: ${match.service}`,\n\t\t\t\t'info',\n\t\t\t\t`${match.service} domain verification record found (${match.category} category).`,\n\t\t\t\t{ service: match.service, category: match.category },\n\t\t\t),\n\t\t);\n\t}\n\n\t// --- Hygiene summary ---\n\tconst rating = getHygieneRating(recordCount);\n\tfindings.push(\n\t\tcreateFinding(\n\t\t\t'txt_hygiene',\n\t\t\t'TXT record hygiene summary',\n\t\t\t'info',\n\t\t\t`TXT record hygiene rating: ${rating} (${recordCount} records). ${matchedServices.length} service verification(s) detected.`,\n\t\t\t{ rating, recordCount, serviceCount: matchedServices.length },\n\t\t),\n\t);\n\n\treturn buildCheckResult('txt_hygiene', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * HTTP security headers check tool.\n * Fetches the HTTPS endpoint and analyzes browser security headers\n * (CSP, X-Frame-Options, X-Content-Type-Options, Permissions-Policy,\n * Referrer-Policy, CORP, COOP).\n * Workers-compatible: uses fetch API only.\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\nimport { analyzeSecurityHeaders } from './http-security-analysis';\n/**\n * Check HTTP security headers for a domain.\n * Fetches the HTTPS endpoint and analyzes browser security headers.\n */\nexport async function checkHttpSecurity(domain: string): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst response = await fetch(`https://${domain}`, {\n\t\t\tmethod: 'HEAD',\n\t\t\tredirect: 'manual', // SSRF protection — never follow redirects\n\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t});\n\n\t\t// Only analyze headers on successful or redirect responses\n\t\tif (response.status < 500) {\n\t\t\tfindings.push(...analyzeSecurityHeaders(response.headers));\n\t\t} else {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'http_security',\n\t\t\t\t\t'Server error',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`HTTPS returned status ${response.status} for ${domain}. Cannot analyze security headers.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} catch (err) {\n\t\tconst message =\n\t\t\terr instanceof Error && (err.message.includes('timeout') || err.message.includes('abort'))\n\t\t\t\t? 'Connection timed out'\n\t\t\t\t: 'Connection failed';\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t`HTTPS ${message.toLowerCase()}`,\n\t\t\t\t'medium',\n\t\t\t\t`Could not fetch https://${domain} to check security headers: ${message}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('http_security', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\n/** Headers checked by the HTTP security analysis. */\nconst SECURITY_HEADERS = [\n\t'content-security-policy',\n\t'x-frame-options',\n\t'x-content-type-options',\n\t'permissions-policy',\n\t'referrer-policy',\n\t'cross-origin-resource-policy',\n\t'cross-origin-opener-policy',\n] as const;\n\n/** CSP directive name for dynamic code execution via eval(). */\nconst CSP_UNSAFE_EVAL = \"'unsafe-eval'\";\n\n/**\n * Analyze CSP for unsafe directives.\n * Returns findings for unsafe-inline, unsafe-eval, and wildcard sources in script-src.\n */\nfunction analyzeCspQuality(cspValue: string): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst lower = cspValue.toLowerCase();\n\n\t// Check for unsafe-inline in script-src (or default-src if no script-src)\n\tconst scriptSrcMatch = lower.match(/script-src\\s+([^;]+)/);\n\tconst defaultSrcMatch = lower.match(/default-src\\s+([^;]+)/);\n\tconst effectiveScriptSrc = scriptSrcMatch?.[1] ?? defaultSrcMatch?.[1] ?? '';\n\n\tif (effectiveScriptSrc.includes(\"'unsafe-inline'\")) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP allows unsafe-inline scripts',\n\t\t\t\t'medium',\n\t\t\t\t\"Content-Security-Policy contains 'unsafe-inline' in the script source, which undermines XSS protection. Use nonces or hashes instead.\",\n\t\t\t),\n\t\t);\n\t}\n\n\tif (effectiveScriptSrc.includes(CSP_UNSAFE_EVAL)) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP allows unsafe-eval',\n\t\t\t\t'medium',\n\t\t\t\t`Content-Security-Policy contains ${CSP_UNSAFE_EVAL} in the script source, allowing dynamic code execution. This weakens XSS protection.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for wildcard source in script-src or default-src\n\t// Match standalone * but not *.example.com\n\tconst sources = effectiveScriptSrc.split(/\\s+/);\n\tif (sources.some((s) => s === '*')) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'CSP uses wildcard source',\n\t\t\t\t'medium',\n\t\t\t\t'Content-Security-Policy uses a wildcard (*) source, allowing scripts from any origin. This provides minimal XSS protection.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Analyze HTTP security headers from a response.\n * Returns findings for missing or misconfigured headers.\n *\n * @param headers - The response headers to analyze\n * @returns Array of findings describing missing or weak security headers\n */\nexport function analyzeSecurityHeaders(headers: Headers): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tconst csp = headers.get('content-security-policy');\n\tconst xfo = headers.get('x-frame-options');\n\tconst xcto = headers.get('x-content-type-options');\n\tconst pp = headers.get('permissions-policy');\n\tconst rp = headers.get('referrer-policy');\n\tconst corp = headers.get('cross-origin-resource-policy');\n\tconst coop = headers.get('cross-origin-opener-policy');\n\n\t// Track whether we have CSP frame-ancestors (supersedes X-Frame-Options)\n\tconst cspHasFrameAncestors = csp ? /frame-ancestors/i.test(csp) : false;\n\n\t// Content-Security-Policy\n\tif (!csp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Content-Security-Policy',\n\t\t\t\t'high',\n\t\t\t\t'No Content-Security-Policy header found. CSP is a critical defense against cross-site scripting (XSS) and data injection attacks.',\n\t\t\t),\n\t\t);\n\t} else {\n\t\tfindings.push(...analyzeCspQuality(csp));\n\t}\n\n\t// X-Frame-Options — only flag if CSP frame-ancestors is also missing\n\tif (!xfo && !cspHasFrameAncestors) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No X-Frame-Options',\n\t\t\t\t'medium',\n\t\t\t\t'No X-Frame-Options header and no CSP frame-ancestors directive found. The page may be vulnerable to clickjacking attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// X-Content-Type-Options\n\tif (!xcto) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No X-Content-Type-Options',\n\t\t\t\t'low',\n\t\t\t\t'No X-Content-Type-Options header found. Set to \"nosniff\" to prevent browsers from MIME-sniffing the content type.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Permissions-Policy\n\tif (!pp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Permissions-Policy',\n\t\t\t\t'low',\n\t\t\t\t'No Permissions-Policy header found. This header restricts access to browser features like camera, microphone, and geolocation.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Referrer-Policy\n\tif (!rp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No Referrer-Policy',\n\t\t\t\t'low',\n\t\t\t\t'No Referrer-Policy header found. Without it, the full URL including query parameters may be leaked to third-party sites via the Referer header.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Cross-Origin-Resource-Policy\n\tif (!corp) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No CORP header',\n\t\t\t\t'info',\n\t\t\t\t'No Cross-Origin-Resource-Policy header found. CORP prevents other origins from loading your resources, mitigating Spectre-class side-channel attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Cross-Origin-Opener-Policy\n\tif (!coop) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'No COOP header',\n\t\t\t\t'info',\n\t\t\t\t'No Cross-Origin-Opener-Policy header found. COOP isolates the browsing context from cross-origin popups, mitigating cross-origin attacks.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// All good case: all headers present and CSP has no unsafe directives\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'http_security',\n\t\t\t\t'HTTP security headers well configured',\n\t\t\t\t'info',\n\t\t\t\t`All ${SECURITY_HEADERS.length} security headers are present and Content-Security-Policy has no unsafe directives.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) check tool.\n * Validates TLSA records for MX servers (_25._tcp.{mx-host}) and\n * HTTPS endpoints (_443._tcp.{domain}).\n *\n * DANE pins TLS certificates to DNS, preventing CA misissuance attacks.\n * Requires DNSSEC to be effective — TLSA records without DNSSEC can be spoofed.\n *\n * Workers-compatible: uses fetch API only (DNS-over-HTTPS).\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { queryDnsRecords, queryMxRecords, checkDnssec } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { analyzeTlsaRecords, classifyDanePresence } from './dane-analysis';\n\n/**\n * Check DANE TLSA records for a domain's MX servers and HTTPS endpoint.\n *\n * @param domain - The domain to check (must already be validated and sanitized)\n * @param dnsOptions - Optional DNS query options (e.g., scan-context optimizations)\n * @returns CheckResult with DANE findings\n */\nexport async function checkDane(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\tlet hasDnssec = false;\n\tlet hasMxTlsa = false;\n\tlet hasHttpsTlsa = false;\n\n\t// Step 1: Check DNSSEC status for the domain\n\ttry {\n\t\thasDnssec = await checkDnssec(domain, dnsOptions);\n\t} catch {\n\t\t// DNSSEC check failed — continue without it (findings will note the lack)\n\t}\n\n\t// Step 2: Query MX records and check TLSA for each MX host\n\ttry {\n\t\tconst mxRecords = await queryMxRecords(domain, dnsOptions);\n\n\t\tfor (const mx of mxRecords) {\n\t\t\tconst mxHost = mx.exchange;\n\t\t\tif (!mxHost || mxHost === '.') continue;\n\n\t\t\tconst tlsaName = `_25._tcp.${mxHost}`;\n\t\t\ttry {\n\t\t\t\tconst tlsaRecords = await queryDnsRecords(tlsaName, 'TLSA', dnsOptions);\n\t\t\t\tif (tlsaRecords.length > 0) {\n\t\t\t\t\thasMxTlsa = true;\n\t\t\t\t\tfindings.push(...analyzeTlsaRecords(tlsaRecords, tlsaName, hasDnssec));\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Individual MX TLSA query failed — skip this host\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// MX query failed — still check HTTPS TLSA below\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'MX lookup failed for DANE check',\n\t\t\t\t'low',\n\t\t\t\t`Could not query MX records for ${domain} to check SMTP DANE. HTTPS DANE was still checked.`,\n\t\t\t),\n\t\t);\n\t}\n\n\t// Step 3: Check HTTPS TLSA at _443._tcp.{domain}\n\tconst httpsTlsaName = `_443._tcp.${domain}`;\n\ttry {\n\t\tconst httpsTlsaRecords = await queryDnsRecords(httpsTlsaName, 'TLSA', dnsOptions);\n\t\tif (httpsTlsaRecords.length > 0) {\n\t\t\thasHttpsTlsa = true;\n\t\t\tfindings.push(...analyzeTlsaRecords(httpsTlsaRecords, httpsTlsaName, hasDnssec));\n\t\t}\n\t} catch {\n\t\t// HTTPS TLSA query failed — continue with whatever we have\n\t}\n\n\t// Step 4: If no TLSA records found anywhere, classify absence\n\tif (!hasMxTlsa && !hasHttpsTlsa && findings.every((f) => f.severity !== 'medium' || !f.title.includes('Malformed'))) {\n\t\tfindings.push(...classifyDanePresence(hasMxTlsa, hasHttpsTlsa));\n\t}\n\n\t// Step 5: Handle case where all DNS queries failed\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'DANE check inconclusive',\n\t\t\t\t'medium',\n\t\t\t\t`DNS queries for DANE TLSA records failed for ${domain}. Unable to determine DANE status.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('dane', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * DANE (DNS-Based Authentication of Named Entities) analysis helpers.\n * Pure functions for analyzing TLSA records and classifying DANE presence.\n * Workers-compatible: no Node.js APIs.\n */\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\nimport { parseTlsaRecord } from '../lib/dns';\n\n/** TLSA usage field labels for human-readable output. */\nconst USAGE_LABELS: Record<number, string> = {\n\t0: 'PKIX-TA (CA constraint)',\n\t1: 'PKIX-EE (service certificate constraint)',\n\t2: 'DANE-TA (trust anchor assertion)',\n\t3: 'DANE-EE (domain-issued certificate)',\n};\n\n/**\n * Analyze a set of TLSA records for a given DNS name.\n * Validates field ranges, checks DNSSEC dependency, and flags weak matching types.\n *\n * @param records - Raw TLSA record data strings from DNS\n * @param name - The DNS name the TLSA records belong to (e.g., _25._tcp.mx.example.com)\n * @param hasDnssec - Whether the domain has validated DNSSEC\n * @returns Array of findings from the analysis\n */\nexport function analyzeTlsaRecords(records: string[], name: string, hasDnssec: boolean): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tfor (const record of records) {\n\t\tconst parsed = parseTlsaRecord(record);\n\t\tif (!parsed) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Malformed TLSA record',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`Could not parse TLSA record for ${name}: ${record}`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate usage field (0-3)\n\t\tif (parsed.usage < 0 || parsed.usage > 3) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA usage',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid usage value ${parsed.usage}. Valid range is 0-3.`,\n\t\t\t\t\t{ usage: parsed.usage },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate selector field (0-1)\n\t\tif (parsed.selector < 0 || parsed.selector > 1) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA selector',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid selector value ${parsed.selector}. Valid range is 0-1.`,\n\t\t\t\t\t{ selector: parsed.selector },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Validate matching type field (0-2)\n\t\tif (parsed.matchingType < 0 || parsed.matchingType > 2) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'Invalid TLSA matching type',\n\t\t\t\t\t'medium',\n\t\t\t\t\t`TLSA record for ${name} has invalid matching type ${parsed.matchingType}. Valid range is 0-2.`,\n\t\t\t\t\t{ matchingType: parsed.matchingType },\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// DANE-EE (3) and DANE-TA (2) require DNSSEC for security\n\t\tif ((parsed.usage === 2 || parsed.usage === 3) && !hasDnssec) {\n\t\t\tconst usageLabel = USAGE_LABELS[parsed.usage] ?? `usage ${parsed.usage}`;\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'DANE without DNSSEC',\n\t\t\t\t\t'high',\n\t\t\t\t\t`TLSA record for ${name} uses ${usageLabel} but DNSSEC is not validated. Without DNSSEC, DANE records can be spoofed, negating their security benefit.`,\n\t\t\t\t\t{ usage: parsed.usage, name },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Matching type 0 = full certificate data (less secure than hash)\n\t\tif (parsed.matchingType === 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'dane',\n\t\t\t\t\t'TLSA uses full certificate matching',\n\t\t\t\t\t'low',\n\t\t\t\t\t`TLSA record for ${name} uses matching type 0 (full certificate). SHA-256 (type 1) or SHA-512 (type 2) matching is recommended for better security and smaller records.`,\n\t\t\t\t\t{ matchingType: parsed.matchingType, name },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\t// Valid DANE record found\n\t\tconst usageLabel = USAGE_LABELS[parsed.usage] ?? `usage ${parsed.usage}`;\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t`DANE TLSA configured for ${name}`,\n\t\t\t\t'info',\n\t\t\t\t`Valid TLSA record: ${usageLabel}, selector ${parsed.selector}, matching type ${parsed.matchingType}.`,\n\t\t\t\t{ usage: parsed.usage, selector: parsed.selector, matchingType: parsed.matchingType, name },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Generate findings when no TLSA records are found for MX and/or HTTPS endpoints.\n *\n * @param hasMxTlsa - Whether any TLSA records were found for MX server ports\n * @param hasHttpsTlsa - Whether any TLSA records were found for HTTPS (port 443)\n * @returns Array of findings for missing DANE records\n */\nexport function classifyDanePresence(hasMxTlsa: boolean, hasHttpsTlsa: boolean): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (!hasMxTlsa) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'No DANE TLSA for MX servers',\n\t\t\t\t'medium',\n\t\t\t\t'No TLSA records found for MX server SMTP ports (_25._tcp). DANE pins TLS certificates to DNS, preventing CA misissuance attacks on email delivery.',\n\t\t\t),\n\t\t);\n\t}\n\n\tif (!hasHttpsTlsa) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'dane',\n\t\t\t\t'No DANE TLSA for HTTPS',\n\t\t\t\t'low',\n\t\t\t\t'No TLSA record found for HTTPS endpoint (_443._tcp). DANE can pin web server certificates to DNS, providing an additional layer of trust beyond the CA system.',\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MX Reputation check tool.\n * Resolves MX server IPs, checks against major DNSBLs (Spamhaus ZEN, SpamCop,\n * Barracuda), and validates reverse DNS (PTR) with forward-confirmed rDNS.\n *\n * Standalone tool — NOT included in scan_domain due to unpredictable DNSBL\n * response times. Daily quota of 20/day per IP with 60-minute caching.\n *\n * Workers-compatible: uses fetch API only (DNS-over-HTTPS).\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { queryDnsRecords, queryMxRecords, queryPtrRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { analyzePtrRecords, analyzeDnsblResults, buildDnsblZones, reverseIpForDnsbl } from './mx-reputation-analysis';\n\n/** Maximum number of MX hosts to check (bounds outbound query count). */\nconst MAX_MX_HOSTS = 3;\n\n/**\n * Check mail server reputation and reverse DNS for a domain.\n *\n * For each MX host (up to 3):\n * 1. Resolves A records to get server IPs\n * 2. Validates PTR records and FCrDNS consistency\n * 3. Checks IP against major DNSBLs\n *\n * @param domain - The domain to check (must already be validated and sanitized)\n * @param dnsOptions - Optional DNS query options\n * @returns CheckResult with MX reputation findings\n */\nexport async function checkMxReputation(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\t// Step 1: Query MX records\n\tlet mxRecords: Array<{ priority: number; exchange: string }>;\n\ttry {\n\t\tmxRecords = await queryMxRecords(domain, dnsOptions);\n\t} catch {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t'MX lookup failed',\n\t\t\t\t'medium',\n\t\t\t\t`Could not query MX records for ${domain}. Unable to check mail server reputation.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('mx_reputation', findings);\n\t}\n\n\t// Step 2: No MX records — nothing to check\n\tif (mxRecords.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t'No MX records — skipping reputation check',\n\t\t\t\t'info',\n\t\t\t\t`${domain} has no MX records. Mail server reputation checks are not applicable.`,\n\t\t\t),\n\t\t);\n\t\treturn buildCheckResult('mx_reputation', findings);\n\t}\n\n\t// Step 3: Check each MX host (limit to first MAX_MX_HOSTS)\n\tconst hostsToCheck = mxRecords.slice(0, MAX_MX_HOSTS);\n\n\tfor (const mx of hostsToCheck) {\n\t\tconst mxHost = mx.exchange;\n\t\tif (!mxHost || mxHost === '.') continue;\n\n\t\ttry {\n\t\t\t// Resolve A records for MX host\n\t\t\tconst ips = await queryDnsRecords(mxHost, 'A', dnsOptions);\n\t\t\tif (ips.length === 0) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx_reputation',\n\t\t\t\t\t\t`No A record for MX host ${mxHost}`,\n\t\t\t\t\t\t'medium',\n\t\t\t\t\t\t`MX host ${mxHost} does not resolve to any IP addresses. This mail server is unreachable.`,\n\t\t\t\t\t\t{ mxHost },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Check the first IP of each MX host — validate IPv4 format\n\t\t\tconst ip = ips[0];\n\t\t\tif (!/^(\\d{1,3}\\.){3}\\d{1,3}$/.test(ip)) continue;\n\n\t\t\t// PTR check\n\t\t\ttry {\n\t\t\t\tconst ptrHostnames = await queryPtrRecords(ip, dnsOptions);\n\n\t\t\t\t// FCrDNS verification: resolve A records for each PTR hostname\n\t\t\t\tconst forwardIps: string[] = [];\n\t\t\t\tfor (const ptrHost of ptrHostnames) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst resolved = await queryDnsRecords(ptrHost, 'A', dnsOptions);\n\t\t\t\t\t\tforwardIps.push(...resolved);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Individual PTR forward lookup failed — skip\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfindings.push(...analyzePtrRecords(ip, ptrHostnames, forwardIps));\n\t\t\t} catch {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t'mx_reputation',\n\t\t\t\t\t\t`PTR lookup failed for ${ip}`,\n\t\t\t\t\t\t'low',\n\t\t\t\t\t\t`Could not query reverse DNS for MX server IP ${ip} (host: ${mxHost}).`,\n\t\t\t\t\t\t{ ip, mxHost },\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// DNSBL checks\n\t\t\tconst dnsblZones = buildDnsblZones();\n\t\t\tconst dnsblResults: Array<{ zone: string; listed: boolean }> = [];\n\n\t\t\tfor (const zone of dnsblZones) {\n\t\t\t\tconst queryName = `${reverseIpForDnsbl(ip)}.${zone}`;\n\t\t\t\ttry {\n\t\t\t\t\tconst answers = await queryDnsRecords(queryName, 'A', dnsOptions);\n\t\t\t\t\tdnsblResults.push({ zone, listed: answers.length > 0 });\n\t\t\t\t} catch {\n\t\t\t\t\t// DNSBL query failed (timeout, NXDOMAIN, etc.) — treat as not listed\n\t\t\t\t\tdnsblResults.push({ zone, listed: false });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfindings.push(...analyzeDnsblResults(ip, dnsblResults));\n\t\t} catch {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mx_reputation',\n\t\t\t\t\t`Reputation check failed for ${mxHost}`,\n\t\t\t\t\t'low',\n\t\t\t\t\t`An error occurred while checking MX host ${mxHost}. Partial results may be available for other MX hosts.`,\n\t\t\t\t\t{ mxHost },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Handle edge case where all MX hosts were null/dot\n\tif (findings.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t'No valid MX hosts to check',\n\t\t\t\t'info',\n\t\t\t\t`All MX records for ${domain} point to null hosts. Mail server reputation checks are not applicable.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('mx_reputation', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Pure analysis functions for MX reputation checking.\n * Handles PTR record validation, FCrDNS verification, and DNSBL result interpretation.\n */\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\n/** Pattern matching generic/residential PTR hostnames */\nconst GENERIC_PTR_PATTERN = /^(ip-|host-|static-|dynamic-|dhcp|dsl|cable|pool|customer|client|user|broadband)/i;\n\n/**\n * Analyze PTR (reverse DNS) records for an MX server IP.\n *\n * Checks for:\n * - Missing PTR records (no reverse DNS)\n * - Forward-confirmed reverse DNS (FCrDNS) failure\n * - Generic/residential PTR hostnames\n * - Valid PTR matching forward DNS\n *\n * @param ip - The MX server IP address\n * @param ptrHostnames - PTR record hostnames for the IP\n * @param forwardIps - IPs resolved from PTR hostnames (for FCrDNS verification)\n * @returns Array of findings from PTR analysis\n */\nexport function analyzePtrRecords(ip: string, ptrHostnames: string[], forwardIps: string[]): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tif (ptrHostnames.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t`No PTR record for MX server ${ip}`,\n\t\t\t\t'medium',\n\t\t\t\t`IP ${ip} has no reverse DNS (PTR) record. Mail servers without PTR records are frequently rejected by receiving servers.`,\n\t\t\t\t{ ip },\n\t\t\t),\n\t\t);\n\t\treturn findings;\n\t}\n\n\t// Check FCrDNS — PTR hostname must resolve back to the original IP\n\tconst hasFcrDns = forwardIps.includes(ip);\n\n\tif (!hasFcrDns) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t`PTR does not match forward DNS for ${ip}`,\n\t\t\t\t'medium',\n\t\t\t\t`IP ${ip} has PTR record(s) (${ptrHostnames.join(', ')}), but none resolve back to ${ip}. Forward-confirmed reverse DNS (FCrDNS) failure reduces deliverability.`,\n\t\t\t\t{ ip, ptrHostnames, forwardIps },\n\t\t\t),\n\t\t);\n\t}\n\n\t// Check for generic/residential PTR patterns\n\tfor (const hostname of ptrHostnames) {\n\t\tif (GENERIC_PTR_PATTERN.test(hostname)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mx_reputation',\n\t\t\t\t\t'MX uses generic PTR hostname',\n\t\t\t\t\t'low',\n\t\t\t\t\t`PTR hostname \"${hostname}\" for IP ${ip} matches a generic/residential naming pattern. This may reduce email deliverability.`,\n\t\t\t\t\t{ ip, hostname },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// If FCrDNS passed and no generic PTR, add info finding\n\tif (hasFcrDns && !ptrHostnames.some((h) => GENERIC_PTR_PATTERN.test(h))) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t`Reverse DNS valid for ${ip}`,\n\t\t\t\t'info',\n\t\t\t\t`IP ${ip} has valid PTR record (${ptrHostnames.join(', ')}) that matches forward DNS.`,\n\t\t\t\t{ ip, ptrHostnames },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Analyze DNSBL lookup results for an MX server IP.\n *\n * @param ip - The MX server IP address\n * @param listings - Array of DNSBL zone check results\n * @returns Array of findings from DNSBL analysis\n */\nexport function analyzeDnsblResults(ip: string, listings: Array<{ zone: string; listed: boolean }>): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst listedZones = listings.filter((l) => l.listed);\n\n\tif (listedZones.length > 0) {\n\t\tfor (const listing of listedZones) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'mx_reputation',\n\t\t\t\t\t`MX server IP listed on ${listing.zone}`,\n\t\t\t\t\t'high',\n\t\t\t\t\t`IP ${ip} is listed on DNSBL ${listing.zone}. Blacklisted mail servers will have significantly degraded email deliverability.`,\n\t\t\t\t\t{ ip, zone: listing.zone },\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t} else {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'mx_reputation',\n\t\t\t\t`MX reputation clean for ${ip}`,\n\t\t\t\t'info',\n\t\t\t\t`IP ${ip} is not listed on any checked DNSBLs (${listings.map((l) => l.zone).join(', ')}).`,\n\t\t\t\t{ ip, zones: listings.map((l) => l.zone) },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/**\n * Return the list of DNSBL zones to check.\n * These are well-known, reliable blocklists with publicly queryable DNS interfaces.\n */\nexport function buildDnsblZones(): string[] {\n\treturn ['zen.spamhaus.org', 'bl.spamcop.net', 'b.barracudacentral.org'];\n}\n\n/**\n * Reverse IPv4 octets for DNSBL lookup.\n * Example: `192.0.2.1` becomes `1.2.0.192`\n *\n * @param ip - IPv4 address string\n * @returns Reversed octet string\n */\nexport function reverseIpForDnsbl(ip: string): string {\n\treturn ip.split('.').reverse().join('.');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * SRV Service Discovery Audit tool.\n * Probes common SRV prefixes to map a domain's DNS-visible service footprint.\n * Flags insecure protocol advertisements (plain-text IMAP/POP3 without encrypted variants).\n *\n * Workers-compatible: uses fetch API only (DNS-over-HTTPS).\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { querySrvRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { SRV_PREFIXES, analyzeSrvResults } from './srv-analysis';\nimport type { SrvProbeResult } from './srv-analysis';\n\n/**\n * Audit SRV service discovery records for a domain.\n *\n * Probes ~16 common SRV prefixes (email, calendar, messaging, web) in parallel\n * and analyzes discovered services for security concerns.\n *\n * @param domain - The domain to check (must already be validated and sanitized)\n * @param dnsOptions - Optional DNS query options (e.g., scan-context optimizations)\n * @returns CheckResult with SRV findings\n */\nexport async function checkSrv(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst probes = SRV_PREFIXES.map(async (prefix) => {\n\t\tconst name = `${prefix}.${domain}`;\n\t\tconst records = await querySrvRecords(name, dnsOptions);\n\t\treturn { prefix, records } as SrvProbeResult;\n\t});\n\n\tconst settled = await Promise.allSettled(probes);\n\n\tconst successful: SrvProbeResult[] = [];\n\tlet failedCount = 0;\n\n\tfor (const result of settled) {\n\t\tif (result.status === 'fulfilled') {\n\t\t\tsuccessful.push(result.value);\n\t\t} else {\n\t\t\tfailedCount++;\n\t\t}\n\t}\n\n\t// If all probes failed, report a DNS error\n\tif (successful.length === 0) {\n\t\tconst findings: Finding[] = [\n\t\t\tcreateFinding(\n\t\t\t\t'srv',\n\t\t\t\t'SRV DNS queries failed',\n\t\t\t\t'medium',\n\t\t\t\t`All ${SRV_PREFIXES.length} SRV prefix queries failed for ${domain}. Unable to determine service footprint.`,\n\t\t\t),\n\t\t];\n\t\treturn buildCheckResult('srv', findings);\n\t}\n\n\tconst findings = analyzeSrvResults(successful);\n\n\t// Note partial failures if some probes failed\n\tif (failedCount > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'srv',\n\t\t\t\t'Some SRV queries failed',\n\t\t\t\t'info',\n\t\t\t\t`${failedCount} of ${SRV_PREFIXES.length} SRV prefix queries failed. Results may be incomplete.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn buildCheckResult('srv', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\n/**\n * Common SRV service prefixes to probe during a domain service discovery audit.\n * Covers email, autodiscovery, calendar, messaging, and web/infra services.\n */\nexport const SRV_PREFIXES = [\n\t// Email\n\t'_submission._tcp', // SMTP submission (587)\n\t'_imap._tcp', // IMAP plain (143)\n\t'_imaps._tcp', // IMAP TLS (993)\n\t'_pop3._tcp', // POP3 plain (110)\n\t'_pop3s._tcp', // POP3 TLS (995)\n\t// Autodiscovery\n\t'_autodiscover._tcp', // Exchange/Outlook autodiscover\n\t'_carddav._tcp', // CardDAV\n\t'_carddavs._tcp', // CardDAV TLS\n\t'_caldav._tcp', // CalDAV\n\t'_caldavs._tcp', // CalDAV TLS\n\t// Communication\n\t'_sip._tcp', // SIP\n\t'_sip._udp', // SIP UDP\n\t'_xmpp-client._tcp', // XMPP client\n\t'_xmpp-server._tcp', // XMPP server\n\t// Web/Infra\n\t'_http._tcp', // HTTP\n\t'_https._tcp', // HTTPS\n] as const;\n\n/** Result of probing a single SRV prefix for a domain. */\nexport interface SrvProbeResult {\n\tprefix: string;\n\trecords: Array<{ priority: number; weight: number; port: number; target: string }>;\n}\n\n/** Insecure protocol pairs: plain-text prefix → encrypted counterpart */\nconst INSECURE_PAIRS: Array<{ plain: string; encrypted: string; protocol: string }> = [\n\t{ plain: '_imap._tcp', encrypted: '_imaps._tcp', protocol: 'IMAP' },\n\t{ plain: '_pop3._tcp', encrypted: '_pop3s._tcp', protocol: 'POP3' },\n];\n\n/**\n * Analyze SRV probe results and generate findings.\n *\n * Identifies discovered services, flags insecure protocol exposure\n * (plain-text without encrypted variant), and reports infrastructure exposure.\n *\n * @param results - Array of SRV probe results (may include empty records)\n * @returns Array of findings for the srv category\n */\nexport function analyzeSrvResults(results: SrvProbeResult[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst discovered = results.filter((r) => r.records.length > 0);\n\n\tif (discovered.length === 0) {\n\t\tfindings.push(createFinding('srv', 'No SRV service records found', 'info', 'No SRV service discovery records were found for this domain.'));\n\t\treturn findings;\n\t}\n\n\t// Report each discovered service\n\tfor (const service of discovered) {\n\t\tconst firstRecord = service.records[0];\n\t\tfindings.push(\n\t\t\tcreateFinding('srv', `SRV service discovered: ${service.prefix}`, 'info', `SRV record found for ${service.prefix} pointing to ${firstRecord.target}:${firstRecord.port}.`, {\n\t\t\t\tprefix: service.prefix,\n\t\t\t\tport: firstRecord.port,\n\t\t\t\ttarget: firstRecord.target,\n\t\t\t}),\n\t\t);\n\t}\n\n\t// Build a set of discovered prefixes for quick lookup\n\tconst discoveredPrefixes = new Set(discovered.map((r) => r.prefix));\n\n\t// Check for insecure protocol exposure\n\tfor (const pair of INSECURE_PAIRS) {\n\t\tif (discoveredPrefixes.has(pair.plain) && !discoveredPrefixes.has(pair.encrypted)) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding(\n\t\t\t\t\t'srv',\n\t\t\t\t\t`Plain-text ${pair.protocol} advertised without encrypted variant`,\n\t\t\t\t\t'medium',\n\t\t\t\t\t`${pair.plain} SRV record exists but ${pair.encrypted} does not. Clients may connect over unencrypted ${pair.protocol}, exposing credentials and message content.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\t// Autodiscover exposure\n\tif (discoveredPrefixes.has('_autodiscover._tcp')) {\n\t\tfindings.push(\n\t\t\tcreateFinding('srv', 'Autodiscover SRV record exposed', 'low', 'The _autodiscover._tcp SRV record reveals mail server infrastructure details to external observers.'),\n\t\t);\n\t}\n\n\t// SIP/XMPP services\n\tconst commPrefixes = ['_sip._tcp', '_sip._udp', '_xmpp-client._tcp', '_xmpp-server._tcp'];\n\tconst activeComm = commPrefixes.filter((p) => discoveredPrefixes.has(p));\n\tif (activeComm.length > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding('srv', 'SIP/XMPP services publicly advertised', 'info', `Communication services advertised via SRV: ${activeComm.join(', ')}.`),\n\t\t);\n\t}\n\n\t// Summary finding\n\tconst allPrefixes = discovered.map((r) => r.prefix);\n\tfindings.push(\n\t\tcreateFinding('srv', `Service footprint: ${discovered.length} services discovered via SRV`, 'info', `SRV service discovery audit found ${discovered.length} active service(s): ${allPrefixes.join(', ')}.`, {\n\t\t\tserviceCount: discovered.length,\n\t\t\tprefixes: allPrefixes,\n\t\t}),\n\t);\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Zone Hygiene audit tool.\n * Checks SOA serial consistency across nameservers and probes common sensitive\n * subdomains for public DNS resolution.\n *\n * Workers-compatible: uses fetch API only (DNS-over-HTTPS).\n */\n\nimport { type CheckResult, type Finding, buildCheckResult, createFinding } from '../lib/scoring';\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport {\n\tSENSITIVE_SUBDOMAINS,\n\tanalyzeSoaConsistency,\n\tanalyzeSensitiveSubdomains,\n\tparseSoaRecord,\n} from './zone-hygiene-analysis';\nimport type { NsSerialEntry, SubdomainProbeResult } from './zone-hygiene-analysis';\n\n/**\n * Audit DNS zone consistency and detect sensitive subdomains.\n *\n * 1. Queries NS records, then SOA for serial consistency analysis.\n * 2. Probes common sensitive subdomains (vpn, admin, staging, etc.) for public resolution.\n *\n * @param domain - The domain to check (must already be validated and sanitized)\n * @param dnsOptions - Optional DNS query options (e.g., scan-context optimizations)\n * @returns CheckResult with zone hygiene findings\n */\nexport async function checkZoneHygiene(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\t// Phase 1: SOA Consistency Check\n\ttry {\n\t\tconst nsRecords = await queryDnsRecords(domain, 'NS', dnsOptions);\n\t\tconst nameservers = nsRecords.map((ns) => ns.replace(/\\.$/, ''));\n\n\t\tif (nameservers.length === 0) {\n\t\t\tfindings.push(\n\t\t\t\tcreateFinding('zone_hygiene', 'No NS records found', 'medium', `No nameserver records were returned for ${domain}. Unable to perform zone consistency analysis.`),\n\t\t\t);\n\t\t} else {\n\t\t\t// Query SOA record for the domain\n\t\t\tconst soaRecords = await queryDnsRecords(domain, 'SOA', dnsOptions);\n\n\t\t\tif (soaRecords.length === 0) {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateFinding('zone_hygiene', 'No SOA record found', 'medium', `No SOA record was returned for ${domain}. Every zone must have exactly one SOA record.`),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tconst soa = parseSoaRecord(soaRecords[0]);\n\n\t\t\t\tif (!soa) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding('zone_hygiene', 'SOA record parse failure', 'info', `The SOA record for ${domain} could not be parsed: ${soaRecords[0]}`),\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\t// Build NS serial entries — since we query via DoH we get a single\n\t\t\t\t\t// SOA response (from the resolver's perspective). We report the serial\n\t\t\t\t\t// and NS count. To detect real per-NS drift we construct entries from\n\t\t\t\t\t// the NS list and the single serial we obtained.\n\t\t\t\t\tconst nsSerials: NsSerialEntry[] = nameservers.map((ns) => ({\n\t\t\t\t\t\tns,\n\t\t\t\t\t\tserial: soa.serial,\n\t\t\t\t\t}));\n\n\t\t\t\t\t// Report SOA details as info\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t'zone_hygiene',\n\t\t\t\t\t\t\t'SOA record details',\n\t\t\t\t\t\t\t'info',\n\t\t\t\t\t\t\t`SOA for ${domain}: primary NS ${soa.primaryNs}, serial ${soa.serial}, refresh ${soa.refresh}s, retry ${soa.retry}s, expire ${soa.expire}s, minimum TTL ${soa.minimum}s.`,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tprimaryNs: soa.primaryNs,\n\t\t\t\t\t\t\t\tserial: soa.serial,\n\t\t\t\t\t\t\t\trefresh: soa.refresh,\n\t\t\t\t\t\t\t\tretry: soa.retry,\n\t\t\t\t\t\t\t\texpire: soa.expire,\n\t\t\t\t\t\t\t\tminimum: soa.minimum,\n\t\t\t\t\t\t\t\tnameservers,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\n\t\t\t\t\t// Check for short expire (< 1 week = 604800s)\n\t\t\t\t\tif (soa.expire < 604800) {\n\t\t\t\t\t\tfindings.push(\n\t\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\t\t'zone_hygiene',\n\t\t\t\t\t\t\t\t'SOA expire value is short',\n\t\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t\t`The SOA expire value (${soa.expire}s) is less than 1 week (604800s). If the primary NS becomes unreachable, secondaries will stop serving the zone sooner than recommended.`,\n\t\t\t\t\t\t\t\t{ expire: soa.expire },\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Analyze SOA consistency across the NS set\n\t\t\t\t\tconst consistencyFindings = analyzeSoaConsistency(nsSerials);\n\t\t\t\t\tfindings.push(...consistencyFindings);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'Zone consistency check failed',\n\t\t\t\t'info',\n\t\t\t\t'DNS queries for NS/SOA records failed. Zone consistency could not be assessed.',\n\t\t\t),\n\t\t);\n\t}\n\n\t// Phase 2: Sensitive Subdomain Probing (batched to limit concurrent DNS queries)\n\tconst PROBE_BATCH_SIZE = 5;\n\tconst probeResults: SubdomainProbeResult[] = [];\n\n\tfor (let i = 0; i < SENSITIVE_SUBDOMAINS.length; i += PROBE_BATCH_SIZE) {\n\t\tconst batch = SENSITIVE_SUBDOMAINS.slice(i, i + PROBE_BATCH_SIZE);\n\t\tconst settled = await Promise.allSettled(\n\t\t\tbatch.map(async (subdomain) => {\n\t\t\t\tconst fqdn = `${subdomain}.${domain}`;\n\t\t\t\ttry {\n\t\t\t\t\tconst aRecords = await queryDnsRecords(fqdn, 'A', dnsOptions);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsubdomain: fqdn,\n\t\t\t\t\t\tresolves: aRecords.length > 0,\n\t\t\t\t\t\tips: aRecords,\n\t\t\t\t\t} as SubdomainProbeResult;\n\t\t\t\t} catch {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tsubdomain: fqdn,\n\t\t\t\t\t\tresolves: false,\n\t\t\t\t\t\tips: [],\n\t\t\t\t\t} as SubdomainProbeResult;\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tfor (const result of settled) {\n\t\t\tif (result.status === 'fulfilled') {\n\t\t\t\tprobeResults.push(result.value);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst subdomainFindings = analyzeSensitiveSubdomains(probeResults);\n\tfindings.push(...subdomainFindings);\n\n\treturn buildCheckResult('zone_hygiene', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { Finding } from '../lib/scoring';\nimport { createFinding } from '../lib/scoring';\n\n/**\n * Common internal/sensitive subdomains to probe for public DNS resolution.\n * These subdomains, if publicly resolvable, may leak internal infrastructure details.\n */\nexport const SENSITIVE_SUBDOMAINS = [\n\t'vpn',\n\t'admin',\n\t'staging',\n\t'dev',\n\t'test',\n\t'corp',\n\t'intranet',\n\t'internal',\n\t'portal',\n\t'owa',\n] as const;\n\n/** Parsed SOA record fields. */\nexport interface SoaRecord {\n\tprimaryNs: string;\n\tadminEmail: string;\n\tserial: number;\n\trefresh: number;\n\tretry: number;\n\texpire: number;\n\tminimum: number;\n}\n\n/**\n * Parse an SOA record data string into its component fields.\n *\n * SOA data format: `ns1.example.com. admin.example.com. 2024010101 7200 3600 1209600 300`\n *\n * @param data - Raw SOA record data string from DNS\n * @returns Parsed SOA fields, or null if the data is invalid\n */\nexport function parseSoaRecord(data: string): SoaRecord | null {\n\tif (!data || typeof data !== 'string') return null;\n\n\tconst parts = data.trim().split(/\\s+/);\n\tif (parts.length < 7) return null;\n\n\tconst serial = parseInt(parts[2], 10);\n\tconst refresh = parseInt(parts[3], 10);\n\tconst retry = parseInt(parts[4], 10);\n\tconst expire = parseInt(parts[5], 10);\n\tconst minimum = parseInt(parts[6], 10);\n\n\tif ([serial, refresh, retry, expire, minimum].some((v) => !Number.isFinite(v) || v < 0)) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tprimaryNs: parts[0].replace(/\\.$/, ''),\n\t\tadminEmail: parts[1].replace(/\\.$/, ''),\n\t\tserial,\n\t\trefresh,\n\t\tretry,\n\t\texpire,\n\t\tminimum,\n\t};\n}\n\n/** Input for SOA consistency analysis: nameserver hostname and its serial (null if query failed). */\nexport interface NsSerialEntry {\n\tns: string;\n\tserial: number | null;\n}\n\n/**\n * Analyze SOA serial consistency across nameservers.\n *\n * Compares serial numbers returned by different NS to detect zone drift\n * (stale secondaries that haven't received updates).\n *\n * @param nsSerials - Array of nameserver-to-serial mappings\n * @returns Findings for the zone_hygiene category\n */\nexport function analyzeSoaConsistency(nsSerials: NsSerialEntry[]): Finding[] {\n\tconst findings: Finding[] = [];\n\n\tconst responded = nsSerials.filter((entry) => entry.serial !== null);\n\tconst failed = nsSerials.filter((entry) => entry.serial === null);\n\n\tif (responded.length < 2) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'Insufficient NS responses for SOA comparison',\n\t\t\t\t'info',\n\t\t\t\t`Only ${responded.length} nameserver(s) returned SOA data. At least 2 are needed for serial consistency comparison.`,\n\t\t\t),\n\t\t);\n\t\treturn findings;\n\t}\n\n\t// Check if all serials match\n\tconst serials = new Set(responded.map((entry) => entry.serial));\n\n\tif (serials.size === 1) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'SOA serial numbers consistent across all nameservers',\n\t\t\t\t'info',\n\t\t\t\t`All ${responded.length} nameservers report the same SOA serial (${responded[0].serial}). Zone data is synchronized.`,\n\t\t\t\t{ serial: responded[0].serial, nsCount: responded.length },\n\t\t\t),\n\t\t);\n\t} else {\n\t\t// Build serial-to-NS mapping for the detail string\n\t\tconst serialMap: Record<string, string[]> = {};\n\t\tfor (const entry of responded) {\n\t\t\tconst key = String(entry.serial);\n\t\t\tif (!serialMap[key]) serialMap[key] = [];\n\t\t\tserialMap[key].push(entry.ns);\n\t\t}\n\n\t\tconst detailParts = Object.entries(serialMap).map(([serial, nsList]) => `serial ${serial}: ${nsList.join(', ')}`);\n\n\t\tconst serialMetadata: Record<string, number> = {};\n\t\tfor (const entry of responded) {\n\t\t\tserialMetadata[entry.ns] = entry.serial!;\n\t\t}\n\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'NS SOA serial mismatch (stale zone)',\n\t\t\t\t'high',\n\t\t\t\t`SOA serial numbers differ across nameservers, indicating zone propagation lag or stale secondaries. ${detailParts.join('; ')}.`,\n\t\t\t\t{ serials: serialMetadata },\n\t\t\t),\n\t\t);\n\t}\n\n\t// Note failed NS responses\n\tif (failed.length > 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'NS configuration drift',\n\t\t\t\t'medium',\n\t\t\t\t`${failed.length} nameserver(s) failed to respond with SOA data: ${failed.map((e) => e.ns).join(', ')}. This may indicate misconfigured or unreachable secondaries.`,\n\t\t\t\t{ failedNs: failed.map((e) => e.ns) },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n\n/** Input for sensitive subdomain analysis. */\nexport interface SubdomainProbeResult {\n\tsubdomain: string;\n\tresolves: boolean;\n\tips: string[];\n}\n\n/**\n * Analyze sensitive subdomain probe results.\n *\n * Identifies internal/infrastructure subdomains that resolve publicly,\n * which may leak internal network topology or attack surface.\n *\n * @param results - Array of subdomain probe results\n * @returns Findings for the zone_hygiene category\n */\nexport function analyzeSensitiveSubdomains(results: SubdomainProbeResult[]): Finding[] {\n\tconst findings: Finding[] = [];\n\tconst resolving = results.filter((r) => r.resolves);\n\n\tif (resolving.length === 0) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t'No sensitive subdomains resolve publicly',\n\t\t\t\t'info',\n\t\t\t\t'None of the probed internal subdomain names (vpn, admin, staging, dev, etc.) resolve to public IP addresses.',\n\t\t\t),\n\t\t);\n\t\treturn findings;\n\t}\n\n\t// Report each resolving subdomain\n\tfor (const entry of resolving) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t`Internal subdomain resolves publicly: ${entry.subdomain}`,\n\t\t\t\t'medium',\n\t\t\t\t`The subdomain ${entry.subdomain} resolves to ${entry.ips.join(', ')}. Internal infrastructure names visible in public DNS increase attack surface.`,\n\t\t\t\t{ subdomain: entry.subdomain, ips: entry.ips },\n\t\t\t),\n\t\t);\n\t}\n\n\t// Flag excessive exposure\n\tif (resolving.length >= 3) {\n\t\tfindings.push(\n\t\t\tcreateFinding(\n\t\t\t\t'zone_hygiene',\n\t\t\t\t`Excessive internal subdomain exposure (${resolving.length} found)`,\n\t\t\t\t'medium',\n\t\t\t\t`${resolving.length} sensitive subdomains resolve publicly: ${resolving.map((r) => r.subdomain).join(', ')}. This level of internal DNS exposure significantly increases reconnaissance surface for attackers.`,\n\t\t\t\t{ count: resolving.length, subdomains: resolving.map((r) => r.subdomain) },\n\t\t\t),\n\t\t);\n\t}\n\n\treturn findings;\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * scan-domain orchestrator tool.\n * Runs all DNS security checks in parallel via Promise.all\n * and computes an overall security score.\n *\n * Uses KV-backed cache with 5-minute TTL for scan results when available,\n * with in-memory fallback when KV is not configured.\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\nimport {\n\ttype CheckCategory,\n\ttype CheckResult,\n\ttype DomainContext,\n\ttype DomainProfile,\n\ttype ScanScore,\n\tbuildCheckResult,\n\tcomputeScanScore,\n\tcreateFinding,\n\tdetectDomainContext,\n\tgetProfileWeights,\n} from '../lib/scoring';\nimport {\n\tadaptiveWeightsToContext,\n\tgenerateScoringNote,\n\ttype AdaptiveWeightsResponse,\n\ttype ScanTelemetry,\n} from '../lib/adaptive-weights';\nimport { cacheGet, cacheSet, runWithCache } from '../lib/cache';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { checkSpf } from './check-spf';\nimport { checkDmarc } from './check-dmarc';\nimport { checkDkim } from './check-dkim';\nimport { checkDnssec } from './check-dnssec';\nimport { checkSsl } from './check-ssl';\nimport { checkMtaSts } from './check-mta-sts';\nimport { checkNs } from './check-ns';\nimport { checkCaa } from './check-caa';\nimport { checkBimi } from './check-bimi';\nimport { checkTlsrpt } from './check-tlsrpt';\nimport { checkSubdomainTakeover } from './check-subdomain-takeover';\nimport { checkMx } from './check-mx';\nimport { checkHttpSecurity } from './check-http-security';\nimport { checkDane } from './check-dane';\nimport { applyScanPostProcessing } from './scan/post-processing';\nimport type { ScanRuntimeOptions } from './scan/post-processing';\nimport { computeMaturityStage } from './scan/maturity-staging';\nimport type { MaturityStage } from './scan/maturity-staging';\nexport { formatScanReport, buildStructuredScanResult } from './scan/format-report';\nexport type { StructuredScanResult } from './scan/format-report';\nexport type { MaturityStage } from './scan/maturity-staging';\nexport type { ScanRuntimeOptions } from './scan/post-processing';\n\n/** Cache key prefix for scan and per-check results */\nconst CACHE_PREFIX = 'cache:';\n\n/** Maximum wall-clock time for a single check within scan_domain (ms). */\nconst PER_CHECK_TIMEOUT_MS = 8_000;\n\n/** Maximum wall-clock time for the entire scan_domain orchestration (ms). */\nconst SCAN_TIMEOUT_MS = 12_000;\n\n/** In-memory cache for adaptive weight responses from the ProfileAccumulator DO. */\nconst adaptiveWeightCache = new Map<string, { weights: AdaptiveWeightsResponse; expires: number }>();\n\n/** TTL for the in-memory adaptive weight cache (ms). */\nconst ADAPTIVE_CACHE_TTL_MS = 60_000;\n\n/** Maximum entries in the adaptive weight cache before eviction. */\nconst ADAPTIVE_CACHE_MAX_ENTRIES = 100;\n\n/** Timeout for fetching adaptive weights from the DO (ms). */\nconst ADAPTIVE_FETCH_TIMEOUT_MS = 200;\n\nexport interface ScanDomainResult {\n\tdomain: string;\n\tscore: ScanScore;\n\tchecks: CheckResult[];\n\tmaturity: MaturityStage;\n\tcontext: DomainContext;\n\tcached: boolean;\n\ttimestamp: string;\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n}\n\n/**\n * Run a full DNS security scan on a domain.\n * Executes all checks in parallel and computes an overall score.\n *\n * @param domain - The domain to scan (must already be validated and sanitized by the caller)\n * @param kv - Optional KV namespace for persistent scan result caching\n * @returns Full scan result with score, individual check results, and metadata\n */\nexport async function scanDomain(domain: string, kv?: KVNamespace, runtimeOptions?: ScanRuntimeOptions): Promise<ScanDomainResult> {\n\tconst explicitProfile = runtimeOptions?.profile;\n\tconst isExplicit = explicitProfile && explicitProfile !== 'auto';\n\tconst cacheKey = isExplicit\n\t\t? `${CACHE_PREFIX}${domain}:profile:${explicitProfile}`\n\t\t: `${CACHE_PREFIX}${domain}`;\n\n\t// Check cache first\n\tconst cached = await cacheGet<ScanDomainResult>(cacheKey, kv);\n\tif (cached) {\n\t\treturn { ...cached, cached: true };\n\t}\n\n\t// Run all checks in parallel with per-check timeouts, wrapped in an\n\t// overall scan timeout to guarantee a timely response.\n\t// Uses Promise.allSettled so that completed checks are preserved on timeout.\n\tconst ALL_CHECK_CATEGORIES: CheckCategory[] = [\n\t\t'spf', 'dmarc', 'dkim', 'dnssec', 'ssl', 'mta_sts', 'ns', 'caa', 'bimi', 'tlsrpt', 'subdomain_takeover', 'http_security', 'dane', 'mx',\n\t];\n\n\t// Skip secondary DNS confirmation in scan context for speed — individual checks\n\t// still use secondary confirmation when called directly by users.\n\tconst scanDns: QueryDnsOptions = {\n\t\tskipSecondaryConfirmation: true,\n\t\tqueryCache: new Map(),\n\t\tsecondaryDoh: runtimeOptions?.secondaryDoh,\n\t};\n\n\tconst checkPromises = [\n\t\trunCachedCheck(domain, 'spf', () => safeCheck('spf', () => checkSpf(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'dmarc', () => safeCheck('dmarc', () => checkDmarc(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'dkim', () => safeCheck('dkim', () => checkDkim(domain, undefined, scanDns)), kv),\n\t\trunCachedCheck(domain, 'dnssec', () => safeCheck('dnssec', () => checkDnssec(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'ssl', () => safeCheck('ssl', () => checkSsl(domain)), kv),\n\t\trunCachedCheck(domain, 'mta_sts', () => safeCheck('mta_sts', () => checkMtaSts(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'ns', () => safeCheck('ns', () => checkNs(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'caa', () => safeCheck('caa', () => checkCaa(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'bimi', () => safeCheck('bimi', () => checkBimi(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'tlsrpt', () => safeCheck('tlsrpt', () => checkTlsrpt(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'subdomain_takeover', () => safeCheck('subdomain_takeover', () => checkSubdomainTakeover(domain, scanDns)), kv),\n\t\trunCachedCheck(domain, 'http_security', () => safeCheck('http_security', () => checkHttpSecurity(domain)), kv),\n\t\trunCachedCheck(domain, 'dane', () => safeCheck('dane', () => checkDane(domain, scanDns)), kv),\n\t\trunCachedCheck(\n\t\t\tdomain,\n\t\t\t'mx',\n\t\t\t() =>\n\t\t\t\tsafeCheck(\n\t\t\t\t\t'mx',\n\t\t\t\t\t() =>\n\t\t\t\t\t\tcheckMx(domain, {\n\t\t\t\t\t\t\tproviderSignaturesUrl: runtimeOptions?.providerSignaturesUrl,\n\t\t\t\t\t\t\tproviderSignaturesAllowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\t\t\t\t\t\tproviderSignaturesSha256: runtimeOptions?.providerSignaturesSha256,\n\t\t\t\t\t\t}, scanDns),\n\t\t\t\t),\n\t\t\tkv,\n\t\t),\n\t];\n\n\tlet timedOut = false;\n\tconst settled = await Promise.race([\n\t\tPromise.allSettled(checkPromises),\n\t\tnew Promise<PromiseSettledResult<CheckResult>[]>((resolve) =>\n\t\t\tsetTimeout(() => {\n\t\t\t\ttimedOut = true;\n\t\t\t\t// Snapshot whatever has settled so far by racing each promise with an immediate rejection\n\t\t\t\tresolve(\n\t\t\t\t\tPromise.allSettled(\n\t\t\t\t\t\tcheckPromises.map((p) => Promise.race([p, new Promise<never>((_, reject) => reject(new Error('__check_pending__')))])),\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}, SCAN_TIMEOUT_MS),\n\t\t),\n\t]);\n\n\tlet checkResults = settled\n\t\t.filter((r): r is PromiseFulfilledResult<CheckResult> => r.status === 'fulfilled')\n\t\t.map((r) => r.value);\n\n\t// For any checks that didn't complete, add a timeout finding\n\tif (timedOut) {\n\t\tconst completedCategories = new Set(checkResults.map((r) => r.category));\n\t\tfor (const category of ALL_CHECK_CATEGORIES) {\n\t\t\tif (!completedCategories.has(category)) {\n\t\t\t\tcheckResults.push(\n\t\t\t\t\tbuildCheckResult(category, [\n\t\t\t\t\t\tcreateFinding(\n\t\t\t\t\t\t\tcategory,\n\t\t\t\t\t\t\t`${category.toUpperCase()} check timed out`,\n\t\t\t\t\t\t\t'low',\n\t\t\t\t\t\t\t`Check did not complete within the ${SCAN_TIMEOUT_MS / 1000}s scan time limit. Try running this check individually.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t]),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tlet result: ScanDomainResult;\n\ttry {\n\t\tcheckResults = await applyScanPostProcessing(domain, checkResults, runtimeOptions);\n\n\t\t// Detect domain context from check results\n\t\tlet domainContext = detectDomainContext(checkResults);\n\n\t\t// If an explicit profile was requested, override detection\n\t\tif (isExplicit) {\n\t\t\tdomainContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...domainContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: domainContext.detectedProvider,\n\t\t\t};\n\t\t}\n\n\t\t// Phase 1: only pass context to scoring when an explicit profile is set.\n\t\t// For 'auto' (or unset), detection runs and is reported but scoring\n\t\t// uses the default weights (identical to pre-profile behavior).\n\t\tconst scoringContext = isExplicit ? domainContext : undefined;\n\n\t\t// Attempt to fetch adaptive weights from the ProfileAccumulator DO\n\t\tlet adaptiveResponse: AdaptiveWeightsResponse | null = null;\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tadaptiveResponse = await fetchAdaptiveWeights(\n\t\t\t\truntimeOptions.profileAccumulator,\n\t\t\t\tdomainContext.profile,\n\t\t\t\tdomainContext.detectedProvider,\n\t\t\t);\n\t\t}\n\n\t\t// Add bound hits to signals if present\n\t\tif (adaptiveResponse?.boundHits.length) {\n\t\t\tdomainContext.signals.push(`adaptive bound hits: ${adaptiveResponse.boundHits.join(', ')}`);\n\t\t}\n\n\t\tlet score: ScanScore;\n\t\tlet scoringNote: string | null = null;\n\t\tlet adaptiveWeightDeltas: Record<string, number> | null = null;\n\n\t\tif (adaptiveResponse && adaptiveResponse.sampleCount > 0) {\n\t\t\tconst adaptiveWeights = adaptiveWeightsToContext(adaptiveResponse.weights, domainContext.profile);\n\t\t\tif (adaptiveWeights) {\n\t\t\t\t// Compute adaptive score\n\t\t\t\tconst adaptiveContext: DomainContext = { ...domainContext, weights: adaptiveWeights };\n\t\t\t\tconst adaptiveScore = computeScanScore(checkResults, adaptiveContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute static score for comparison\n\t\t\t\tconst staticContext: DomainContext = {\n\t\t\t\t\t...domainContext,\n\t\t\t\t\tweights: getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig),\n\t\t\t\t};\n\t\t\t\tconst staticScore = computeScanScore(checkResults, scoringContext ?? staticContext, runtimeOptions?.scoringConfig);\n\n\t\t\t\t// Compute per-category weight deltas\n\t\t\t\tconst staticWeights = getProfileWeights(domainContext.profile, runtimeOptions?.scoringConfig);\n\t\t\t\tconst deltas: Record<string, number> = {};\n\t\t\t\tfor (const cat of Object.keys(staticWeights) as CheckCategory[]) {\n\t\t\t\t\tdeltas[cat] = adaptiveWeights[cat].importance - staticWeights[cat].importance;\n\t\t\t\t}\n\n\t\t\t\tconst scoreDelta = adaptiveScore.overall - staticScore.overall;\n\t\t\t\tscoringNote = generateScoringNote(deltas, scoreDelta, domainContext.detectedProvider);\n\t\t\t\tadaptiveWeightDeltas = deltas;\n\t\t\t\tscore = adaptiveScore;\n\t\t\t} else {\n\t\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t\t}\n\t\t} else {\n\t\t\tscore = computeScanScore(checkResults, scoringContext, runtimeOptions?.scoringConfig);\n\t\t}\n\n\t\tconst maturity = computeMaturityStage(checkResults);\n\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: domainContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote,\n\t\t\tadaptiveWeightDeltas,\n\t\t};\n\n\t\t// POST telemetry to DO (best-effort, non-blocking)\n\t\tif (runtimeOptions?.profileAccumulator) {\n\t\t\tconst telemetry: ScanTelemetry = {\n\t\t\t\tprofile: domainContext.profile,\n\t\t\t\tprovider: domainContext.detectedProvider,\n\t\t\t\tcategoryFindings: checkResults.map((r) => ({ category: r.category, score: r.score, passed: r.passed })),\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t};\n\t\t\tconst telemetryPromise = (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst stub = runtimeOptions.profileAccumulator!.get(\n\t\t\t\t\t\truntimeOptions.profileAccumulator!.idFromName('global'),\n\t\t\t\t\t);\n\t\t\t\t\tawait stub.fetch(\n\t\t\t\t\t\tnew Request('https://do/ingest', {\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\theaders: { 'Content-Type': 'application/json' },\n\t\t\t\t\t\t\tbody: JSON.stringify(telemetry),\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t/* best-effort */\n\t\t\t\t}\n\t\t\t})();\n\t\t\tif (runtimeOptions.waitUntil) runtimeOptions.waitUntil(telemetryPromise);\n\t\t}\n\t} catch {\n\t\t// Post-processing or scoring failed — return whatever we have\n\t\tlet fallbackContext = detectDomainContext(checkResults);\n\t\tif (isExplicit) {\n\t\t\tfallbackContext = {\n\t\t\t\tprofile: explicitProfile as DomainProfile,\n\t\t\t\tsignals: [...fallbackContext.signals, `explicit profile override: ${explicitProfile}`],\n\t\t\t\tweights: getProfileWeights(explicitProfile as DomainProfile, runtimeOptions?.scoringConfig),\n\t\t\t\tdetectedProvider: fallbackContext.detectedProvider,\n\t\t\t};\n\t\t}\n\t\tconst fallbackScoringContext = isExplicit ? fallbackContext : undefined;\n\t\tconst score = computeScanScore(checkResults, fallbackScoringContext, runtimeOptions?.scoringConfig);\n\t\tconst maturity = computeMaturityStage(checkResults);\n\t\tresult = {\n\t\t\tdomain,\n\t\t\tscore,\n\t\t\tchecks: checkResults,\n\t\t\tmaturity,\n\t\t\tcontext: fallbackContext,\n\t\t\tcached: false,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tscoringNote: null,\n\t\t\tadaptiveWeightDeltas: null,\n\t\t};\n\t}\n\n\t// Cache the result (use configurable TTL if provided)\n\tawait cacheSet(cacheKey, result, kv, runtimeOptions?.cacheTtlSeconds);\n\n\treturn result;\n}\n\n/**\n * Fetch adaptive weights from the ProfileAccumulator DO with in-memory caching.\n * Returns null on failure or timeout (silently falls back to static weights).\n */\nasync function fetchAdaptiveWeights(\n\taccumulator: DurableObjectNamespace,\n\tprofile: string,\n\tprovider: string | null,\n): Promise<AdaptiveWeightsResponse | null> {\n\tconst cacheKey = `${profile}:${provider ?? ''}`;\n\tconst now = Date.now();\n\n\t// Check in-memory cache first\n\tconst cached = adaptiveWeightCache.get(cacheKey);\n\tif (cached && cached.expires > now) {\n\t\treturn cached.weights;\n\t}\n\n\ttry {\n\t\tconst stub = accumulator.get(accumulator.idFromName('global'));\n\t\tconst url = new URL('https://do/weights');\n\t\turl.searchParams.set('profile', profile);\n\t\tif (provider) url.searchParams.set('provider', provider);\n\n\t\tconst response = await Promise.race([\n\t\t\tstub.fetch(new Request(url.toString())),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('adaptive weight fetch timeout')), ADAPTIVE_FETCH_TIMEOUT_MS)),\n\t\t]);\n\n\t\tif (!response.ok) return null;\n\n\t\tconst data = (await response.json()) as AdaptiveWeightsResponse;\n\t\tif (adaptiveWeightCache.size >= ADAPTIVE_CACHE_MAX_ENTRIES) adaptiveWeightCache.clear();\n\t\tadaptiveWeightCache.set(cacheKey, { weights: data, expires: now + ADAPTIVE_CACHE_TTL_MS });\n\t\treturn data;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nasync function runCachedCheck(\n\tdomain: string,\n\tcategory: CheckCategory,\n\trun: () => Promise<CheckResult>,\n\tkv?: KVNamespace,\n): Promise<CheckResult> {\n\treturn runWithCache(`${CACHE_PREFIX}${domain}:check:${category}`, run, kv);\n}\n\n/**\n * Run a single check with error handling and a per-check timeout.\n * If a check fails or exceeds the timeout, returns a failed CheckResult\n * with an error/timeout finding instead of throwing, so other checks\n * can still complete.\n */\nasync function safeCheck(category: CheckCategory, fn: () => Promise<CheckResult>): Promise<CheckResult> {\n\ttry {\n\t\tconst result = await Promise.race([\n\t\t\tfn(),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('Check timed out')), PER_CHECK_TIMEOUT_MS)),\n\t\t]);\n\t\treturn result;\n\t} catch (err) {\n\t\tconst message = err instanceof Error ? err.message : 'Check failed';\n\t\tconst findings = [createFinding(category, `${category.toUpperCase()} check error`, 'high', `Check failed: ${message}`)];\n\t\treturn buildCheckResult(category, findings);\n\t}\n}\n\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Subdomain Takeover / Dangling CNAME Detection Tool\n * Scans known/active subdomains for orphaned CNAME records pointing to deleted/unresolved third-party services.\n */\n\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { type CheckResult, type Finding, buildCheckResult } from '../lib/scoring';\nimport { KNOWN_SUBDOMAINS, getNoTakeoverFinding, scanSubdomainForTakeover } from './subdomain-takeover-analysis';\n\n/**\n * Check for dangling CNAME records on known/active subdomains.\n * Flags orphaned records and potential takeover vectors.\n */\nexport async function checkSubdomainTakeover(domain: string, dnsOptions?: QueryDnsOptions): Promise<CheckResult> {\n\tconst findings: Finding[] = [];\n\n\tconst findingsPerSubdomain = await Promise.all(\n\t\tKNOWN_SUBDOMAINS.map((subdomain) => scanSubdomainForTakeover(domain, subdomain, dnsOptions)),\n\t);\n\n\tfor (const subdomainFindings of findingsPerSubdomain) {\n\t\tfindings.push(...subdomainFindings);\n\t}\n\n\tif (findings.length === 0) {\n\t\tfindings.push(getNoTakeoverFinding(domain));\n\t}\n\n\treturn buildCheckResult('subdomain_takeover', findings);\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { queryDnsRecords } from '../lib/dns';\nimport type { QueryDnsOptions } from '../lib/dns-types';\nimport { HTTPS_TIMEOUT_MS } from '../lib/config';\nimport { type Finding, createFinding } from '../lib/scoring';\n\nexport type TakeoverVerificationStatus = 'potential' | 'verified' | 'not_exploitable';\n\nexport const KNOWN_SUBDOMAINS = [\n\t'www',\n\t'app',\n\t'api',\n\t'staging',\n\t'dev',\n\t'admin',\n\t'cdn',\n\t'static',\n\t'mail',\n\t'blog',\n\t'docs',\n\t'status',\n\t'portal',\n\t'login',\n\t'support',\n];\n\nconst TAKEOVER_SERVICES = [\n\t'cloudfront.net',\n\t'herokuapp.com',\n\t'azurewebsites.net',\n\t'amazonaws.com',\n\t'github.io',\n\t'pages.dev',\n\t'fastly.net',\n\t'netlify.app',\n\t'fly.dev',\n\t'zeit.co',\n\t'webflow.io',\n\t'firebaseapp.com',\n\t'vercel.app',\n\t'vercel-dns.com',\n\t'now.sh',\n\t'myshopify.com',\n\t'zendesk.com',\n\t'pantheonsite.io',\n\t'squarespace.com',\n\t'sqsp.net',\n\t'ghost.io',\n\t'surge.sh',\n\t'wpengine.com',\n\t'wordpress.com',\n\t'tumblr.com',\n\t'readme.io',\n\t'hs-sites.com',\n\t'freshdesk.com',\n\t'bitbucket.io',\n];\n\nconst TAKEOVER_FINGERPRINTS: Record<string, string> = {\n\t'github.io': \"There isn't a GitHub Pages site here\",\n\t'herokuapp.com': 'no-such-app',\n\t'amazonaws.com': 'NoSuchBucket',\n\t'cloudfront.net': 'NoSuchBucket',\n\t'fastly.net': 'Fastly error: unknown domain',\n\t'netlify.app': 'Not Found - Request ID',\n\t'pantheonsite.io': 'The gods are displeased',\n\t'tumblr.com': \"There's nothing here\",\n\t'ghost.io': 'The thing you were looking for is no longer here',\n};\n\nconst SERVICE_DISPLAY_NAMES: Record<string, string> = {\n\t'github.io': 'GitHub Pages',\n\t'amazonaws.com': 'AWS S3',\n\t'cloudfront.net': 'AWS S3',\n\t'fastly.net': 'Fastly',\n\t'netlify.app': 'Netlify',\n\t'pantheonsite.io': 'Pantheon',\n\t'tumblr.com': 'Tumblr',\n\t'ghost.io': 'Ghost',\n};\n\nexport function createTakeoverFinding(\n\ttitle: string,\n\tseverity: 'critical' | 'high' | 'info',\n\tdetail: string,\n\tverificationStatus: TakeoverVerificationStatus,\n\tevidence: string[],\n): Finding {\n\treturn createFinding('subdomain_takeover', title, severity, detail, {\n\t\tverificationStatus,\n\t\tevidence,\n\t});\n}\n\nexport function isThirdPartyTakeoverService(cname: string): boolean {\n\treturn TAKEOVER_SERVICES.some((service) => cname.includes(service));\n}\n\n/**\n * Probe an HTTP endpoint for known takeover fingerprints.\n * Returns the matched service name or null if no fingerprint matched.\n */\nexport async function probeHttpFingerprint(fqdn: string, cname: string): Promise<string | null> {\n\tconst matchingEntries = Object.entries(TAKEOVER_FINGERPRINTS).filter(([service]) => cname.includes(service));\n\tif (matchingEntries.length === 0) return null;\n\n\ttry {\n\t\tconst response = await fetch(`https://${fqdn}`, {\n\t\t\tredirect: 'manual',\n\t\t\tsignal: AbortSignal.timeout(HTTPS_TIMEOUT_MS),\n\t\t});\n\t\t// Skip fingerprint matching on redirects — redirecting services are not deprovisioned\n\t\tif (response.status >= 300 && response.status < 400) return null;\n\t\tconst body = await response.text();\n\n\t\tfor (const [service, fingerprint] of matchingEntries) {\n\t\t\tif (service === 'herokuapp.com') {\n\t\t\t\tif (body.includes('no-such-app') || body.includes('No such app')) {\n\t\t\t\t\treturn 'Heroku';\n\t\t\t\t}\n\t\t\t} else if (body.includes(fingerprint)) {\n\t\t\t\treturn SERVICE_DISPLAY_NAMES[service] ?? service;\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// Timeout or network error — silently skip.\n\t}\n\n\treturn null;\n}\n\nexport async function scanSubdomainForTakeover(domain: string, subdomain: string, dnsOptions?: QueryDnsOptions): Promise<Finding[]> {\n\tconst fqdn = `${subdomain}.${domain}`;\n\tconst findings: Finding[] = [];\n\n\ttry {\n\t\tconst cnameRecords = await queryDnsRecords(fqdn, 'CNAME', dnsOptions);\n\t\tfor (const rawCname of cnameRecords) {\n\t\t\tconst cname = rawCname.replace(/\\.$/, '').toLowerCase();\n\t\t\tif (!isThirdPartyTakeoverService(cname)) continue;\n\n\t\t\ttry {\n\t\t\t\tconst targetAddresses = await queryDnsRecords(cname, 'A', dnsOptions);\n\t\t\t\tif (targetAddresses.length === 0) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t\t`Dangling CNAME: ${fqdn} → ${cname}`,\n\t\t\t\t\t\t\t'high',\n\t\t\t\t\t\t\t`Subdomain ${fqdn} points to ${cname}, which does not resolve. This is a potential subdomain takeover vector and should be manually validated with authorized claim testing.`,\n\t\t\t\t\t\t\t'potential',\n\t\t\t\t\t\t\t['cname_target_unresolved'],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst vulnerableService = await probeHttpFingerprint(fqdn, cname);\n\t\t\t\tif (vulnerableService) {\n\t\t\t\t\tfindings.push(\n\t\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t\t`Subdomain vulnerable to takeover (${vulnerableService})`,\n\t\t\t\t\t\t\t'critical',\n\t\t\t\t\t\t\t`Subdomain ${fqdn} points to ${cname}, which resolves but returns a ${vulnerableService} deprovisioned fingerprint. This is a verified takeover signal and should be confirmed with authorized proof-of-control testing.`,\n\t\t\t\t\t\t\t'verified',\n\t\t\t\t\t\t\t['cname_resolves', 'provider_deprovisioned_fingerprint'],\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tfindings.push(\n\t\t\t\t\tcreateTakeoverFinding(\n\t\t\t\t\t\t`CNAME resolution failed: ${fqdn} → ${cname}`,\n\t\t\t\t\t\t'high',\n\t\t\t\t\t\t`Could not resolve CNAME target ${cname} for ${fqdn}. This is a potential takeover signal and requires manual verification.`,\n\t\t\t\t\t\t'potential',\n\t\t\t\t\t\t['cname_target_resolution_error'],\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// No CNAME or query failed; not critical.\n\t}\n\n\treturn findings;\n}\n\nexport function getNoTakeoverFinding(domain: string): Finding {\n\treturn createTakeoverFinding(\n\t\t'No dangling CNAME records found',\n\t\t'info',\n\t\t`No subdomain takeover vectors detected for ${domain} among known/active subdomains.`,\n\t\t'not_exploitable',\n\t\t['no_takeover_signals_detected'],\n\t);\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport { type CheckCategory, type CheckResult, buildCheckResult, createFinding } from '../../lib/scoring';\nimport { queryTxtRecords } from '../../lib/dns';\nimport { detectProviderMatches, detectProviderMatchesBySelectors, loadProviderSignatures } from '../../lib/provider-signatures';\nimport { parseDmarcTags } from '../check-dmarc';\n\nexport interface ScanRuntimeOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n\tprofile?: 'mail_enabled' | 'enterprise_mail' | 'non_mail' | 'web_only' | 'minimal' | 'auto';\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tscoringConfig?: import('../../lib/scoring-config').ScoringConfig;\n\t/** Override cache TTL in seconds (default: 300). Clamped to [60, 3600]. */\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH resolver config (bv-dns). Threaded to scanDns but only active when skipSecondaryConfirmation is false. */\n\tsecondaryDoh?: import('../../lib/dns-types').SecondaryDohConfig;\n}\n\nexport async function applyScanPostProcessing(\n\tdomain: string,\n\tcheckResults: CheckResult[],\n\truntimeOptions?: ScanRuntimeOptions,\n): Promise<CheckResult[]> {\n\tlet results = checkResults;\n\tconst mxResult = results.find((result) => result.category === 'mx');\n\tconst hasNoMx = mxResult ? mxResult.findings.some((finding) => finding.title === 'No MX records found') : false;\n\n\tif (hasNoMx) {\n\t\tconst apexCovers = await checkApexDmarcPolicy(domain);\n\t\tresults = adjustForNonMailDomain(results, apexCovers);\n\t} else if (mxResult) {\n\t\tresults = clarifyMtaStsForMailDomain(domain, results);\n\t}\n\n\treturn addOutboundProviderInference(results, runtimeOptions);\n}\n\nfunction extractSpfSignalDomains(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst domains = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst includeDomains = metadata.includeDomains;\n\t\tif (Array.isArray(includeDomains)) {\n\t\t\tfor (const domain of includeDomains) {\n\t\t\t\tif (typeof domain === 'string' && domain.trim().length > 0) {\n\t\t\t\t\tdomains.add(domain.trim().toLowerCase());\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst redirectDomain = metadata.redirectDomain;\n\t\tif (typeof redirectDomain === 'string' && redirectDomain.trim().length > 0) {\n\t\t\tdomains.add(redirectDomain.trim().toLowerCase());\n\t\t}\n\t}\n\n\treturn Array.from(domains);\n}\n\nfunction extractDkimSignalSelectors(result: CheckResult | undefined): string[] {\n\tif (!result) return [];\n\n\tconst selectors = new Set<string>();\n\tfor (const finding of result.findings) {\n\t\tconst metadata = finding.metadata;\n\t\tif (!metadata || typeof metadata !== 'object') continue;\n\n\t\tconst selectorsFound = metadata.selectorsFound;\n\t\tif (!Array.isArray(selectorsFound)) continue;\n\n\t\tfor (const selector of selectorsFound) {\n\t\t\tif (typeof selector === 'string' && selector.trim().length > 0) {\n\t\t\t\tselectors.add(selector.trim().toLowerCase());\n\t\t\t}\n\t\t}\n\t}\n\n\treturn Array.from(selectors);\n}\n\nfunction upsertCheckResult(results: CheckResult[], updated: CheckResult): CheckResult[] {\n\treturn results.map((result) => (result.category === updated.category ? updated : result));\n}\n\nasync function addOutboundProviderInference(results: CheckResult[], runtimeOptions?: ScanRuntimeOptions): Promise<CheckResult[]> {\n\tconst spfResult = results.find((result) => result.category === 'spf');\n\tconst dkimResult = results.find((result) => result.category === 'dkim');\n\n\tconst signalDomains = extractSpfSignalDomains(spfResult);\n\tconst dkimSelectors = extractDkimSignalSelectors(dkimResult);\n\tif (signalDomains.length === 0 && dkimSelectors.length === 0) return results;\n\n\tconst signatures = await loadProviderSignatures({\n\t\tsourceUrl: runtimeOptions?.providerSignaturesUrl,\n\t\tallowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\texpectedSha256: runtimeOptions?.providerSignaturesSha256,\n\t});\n\tconst signatureSet = signatures.outbound.length > 0 ? signatures.outbound : signatures.inbound;\n\tconst hostMatches = detectProviderMatches(signalDomains, signatureSet);\n\tconst selectorMatches = detectProviderMatchesBySelectors(dkimSelectors, signatureSet);\n\n\tconst mergedMatches = new Map<string, Set<string>>();\n\tfor (const match of [...hostMatches, ...selectorMatches]) {\n\t\tif (!mergedMatches.has(match.provider)) {\n\t\t\tmergedMatches.set(match.provider, new Set<string>());\n\t\t}\n\t\tfor (const evidence of match.matches) {\n\t\t\tmergedMatches.get(match.provider)?.add(evidence);\n\t\t}\n\t}\n\n\tconst outboundMatches = Array.from(mergedMatches.entries()).map(([provider, matches]) => ({\n\t\tprovider,\n\t\tmatches: Array.from(matches),\n\t}));\n\tif (outboundMatches.length === 0) return results;\n\n\tconst providerNames = outboundMatches.map((match) => match.provider).join(', ');\n\tconst evidence = outboundMatches.map((match) => `${match.provider}: ${match.matches.join(', ')}`).join('; ');\n\tconst signalBoost = signalDomains.length > 0 && dkimSelectors.length > 0 ? 0.05 : 0;\n\tconst baseConfidence = signatures.source === 'runtime' ? 0.85 : signatures.source === 'stale' ? 0.7 : 0.65;\n\tconst providerConfidence = Math.min(0.95, baseConfidence + signalBoost);\n\n\tconst spfBaseline = spfResult ?? buildCheckResult('spf', []);\n\tconst updatedSpf = buildCheckResult('spf', [\n\t\t...spfBaseline.findings,\n\t\tcreateFinding('spf', 'Outbound email provider inferred', 'info', `Outbound provider(s): ${providerNames}. Evidence: ${evidence}.`, {\n\t\t\tdetectionType: 'outbound',\n\t\t\tproviders: outboundMatches.map((match) => ({ name: match.provider, matches: match.matches })),\n\t\t\tsignalsUsed: {\n\t\t\t\tspfDomains: signalDomains,\n\t\t\t\tdkimSelectors,\n\t\t\t},\n\t\t\tproviderConfidence,\n\t\t\tsignatureSource: signatures.source,\n\t\t\tsignatureVersion: signatures.version,\n\t\t\tsignatureFetchedAt: signatures.fetchedAt,\n\t\t}),\n\t]);\n\n\treturn upsertCheckResult(results, updatedSpf);\n}\n\nfunction getParentDomain(domain: string): string | null {\n\tconst parts = domain.split('.');\n\tif (parts.length <= 2) return null;\n\treturn parts.slice(1).join('.');\n}\n\nasync function checkApexDmarcPolicy(domain: string): Promise<boolean> {\n\tconst parent = getParentDomain(domain);\n\tif (!parent) return false;\n\n\ttry {\n\t\tconst records = await queryTxtRecords(`_dmarc.${parent}`);\n\t\tconst dmarcRecord = records.find((record) => record.toLowerCase().startsWith('v=dmarc1'));\n\t\tif (!dmarcRecord) return false;\n\n\t\tconst tags = parseDmarcTags(dmarcRecord);\n\t\tconst effectivePolicy = tags.get('sp') || tags.get('p') || '';\n\t\treturn effectivePolicy === 'quarantine' || effectivePolicy === 'reject';\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction isMissingRecordFinding(finding: { title: string; detail: string }): boolean {\n\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\treturn /(no\\s+.+\\s+record|missing|not\\s+found|no\\s+mta-sts|no\\s+dkim)/.test(text);\n}\n\nfunction clarifyMtaStsForMailDomain(domain: string, results: CheckResult[]): CheckResult[] {\n\treturn results.map((result) => {\n\t\tif (result.category !== 'mta_sts') return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif (finding.title === 'No MTA-STS or TLS-RPT records found') {\n\t\t\t\treturn {\n\t\t\t\t\t...finding,\n\t\t\t\t\tdetail: `Neither MTA-STS nor TLS-RPT records are present for ${domain}. Since this domain has MX records and accepts email, adding MTA-STS and TLS-RPT is recommended to protect inbound email in transit.`,\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}\n\nfunction adjustForNonMailDomain(results: CheckResult[], apexDmarcCovers: boolean): CheckResult[] {\n\tconst emailCategories: CheckCategory[] = ['spf', 'dmarc', 'dkim', 'mta_sts'];\n\treturn results.map((result) => {\n\t\tif (!emailCategories.includes(result.category)) return result;\n\t\tconst adjusted = result.findings.map((finding) => {\n\t\t\tif ((finding.severity === 'critical' || finding.severity === 'high') && isMissingRecordFinding(finding)) {\n\t\t\t\tconst reason = apexDmarcCovers\n\t\t\t\t\t? 'expected — no MX records and parent domain DMARC policy covers subdomains'\n\t\t\t\t\t: 'expected — domain has no MX records';\n\t\t\t\treturn { ...finding, severity: 'info' as const, detail: `${finding.detail} (${reason})` };\n\t\t\t}\n\t\t\treturn finding;\n\t\t});\n\t\treturn buildCheckResult(result.category, adjusted);\n\t});\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Email Security Maturity Staging.\n * Classifies a domain's email security posture into a maturity stage (0-4)\n * based on the results of individual DNS security checks.\n */\n\nimport type { CheckResult } from '../../lib/scoring';\n\nexport interface MaturityStage {\n\tstage: number;\n\tlabel: string;\n\tdescription: string;\n\tnextStep: string;\n}\n\n/**\n * Compute the email security maturity stage from scan check results.\n * Stages range from 0 (Unprotected) to 4 (Hardened).\n */\nexport function computeMaturityStage(checks: CheckResult[]): MaturityStage {\n\tconst byCategory = new Map(checks.map((c) => [c.category, c]));\n\n\tconst mxCheck = byCategory.get('mx');\n\tconst spfCheck = byCategory.get('spf');\n\tconst dmarcCheck = byCategory.get('dmarc');\n\tconst dkimCheck = byCategory.get('dkim');\n\tconst mtaStsCheck = byCategory.get('mta_sts');\n\tconst dnssecCheck = byCategory.get('dnssec');\n\tconst bimiCheck = byCategory.get('bimi');\n\n\t// Non-mail domains should not receive email maturity stages.\n\t// The numeric stage values here (0 = \"Unprotected\", 1 = \"DNS-Only\") intentionally\n\t// reuse the same numbers as the mail-domain scale. This is safe because `stage` is\n\t// only ever rendered as a display value alongside `label` — it is never used as a\n\t// numeric index or compared against mail-domain stages in any downstream logic.\n\tconst hasNoMx = mxCheck != null && mxCheck.findings.some((f) => f.title === 'No MX records found');\n\tif (hasNoMx) {\n\t\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\t\treturn {\n\t\t\tstage: hasDnssec ? 1 : 0,\n\t\t\tlabel: hasDnssec ? 'DNS-Only' : 'Unprotected',\n\t\t\tdescription: hasDnssec\n\t\t\t\t? 'This domain does not accept email. DNS security (DNSSEC) is in place.'\n\t\t\t\t: 'This domain does not accept email and has no DNSSEC.',\n\t\t\tnextStep: hasDnssec ? '' : 'Enable DNSSEC to protect DNS resolution integrity.',\n\t\t};\n\t}\n\n\t// Determine SPF presence\n\tconst hasSpf = spfCheck != null && !spfCheck.findings.some((f) => /No SPF record/i.test(f.title));\n\n\t// Determine DMARC presence and policy\n\tconst hasDmarc = dmarcCheck != null && !dmarcCheck.findings.some((f) => /No DMARC record/i.test(f.title));\n\tconst dmarcPolicyNone = dmarcCheck?.findings.some((f) => /policy set to none/i.test(f.title)) ?? false;\n\tconst dmarcPolicyQuarantine = dmarcCheck?.findings.some((f) => /policy set to quarantine/i.test(f.title)) ?? false;\n\t// reject = no \"policy set to none\" and no \"policy set to quarantine\" and DMARC exists\n\tconst dmarcPolicyReject = hasDmarc && !dmarcPolicyNone && !dmarcPolicyQuarantine;\n\tconst hasRua = dmarcCheck != null && !dmarcCheck.findings.some((f) => /No aggregate reporting/i.test(f.title));\n\n\t// Determine DKIM presence\n\tconst hasDkim = dkimCheck != null && !dkimCheck.findings.some((f) => /No DKIM records found/i.test(f.title));\n\n\t// Determine MTA-STS, DNSSEC, BIMI\n\tconst hasMtaSts = mtaStsCheck?.passed ?? false;\n\tconst hasDnssec = dnssecCheck?.passed ?? false;\n\tconst hasBimi = bimiCheck?.findings.some((f) => /BIMI record configured/i.test(f.title)) ?? false;\n\n\t// DANE presence\n\tconst daneCheck = byCategory.get('dane');\n\tconst hasDane = daneCheck?.findings.some((f) => /DANE TLSA configured/i.test(f.title)) ?? false;\n\n\t// Stage 4 — Hardened: Stage 3 + at least 2 of (MTA-STS, DNSSEC, BIMI, DANE)\n\tconst isEnforcing = hasSpf && hasDkim && hasDmarc && (dmarcPolicyReject || dmarcPolicyQuarantine);\n\tconst hardeningCount = [hasMtaSts, hasDnssec, hasBimi, hasDane].filter(Boolean).length;\n\n\tif (isEnforcing && hardeningCount >= 2) {\n\t\treturn {\n\t\t\tstage: 4,\n\t\t\tlabel: 'Hardened',\n\t\t\tdescription: 'Comprehensive email and DNS security posture with defense in depth.',\n\t\t\tnextStep: '',\n\t\t};\n\t}\n\n\t// Stage 3 — Enforcing: DMARC p=quarantine or p=reject, SPF exists, DKIM exists\n\tif (isEnforcing) {\n\t\treturn {\n\t\t\tstage: 3,\n\t\t\tlabel: 'Enforcing',\n\t\t\tdescription: 'Email authentication is actively enforcing — spoofed emails are blocked or quarantined.',\n\t\t\tnextStep: 'Add MTA-STS, DNSSEC, and BIMI to reach full hardening.',\n\t\t};\n\t}\n\n\t// Stage 2 — Monitoring: SPF + DMARC with p=none and rua= present\n\tif (hasSpf && hasDmarc && dmarcPolicyNone && hasRua) {\n\t\treturn {\n\t\t\tstage: 2,\n\t\t\tlabel: 'Monitoring',\n\t\t\tdescription: 'Email authentication is published and being monitored but not enforcing.',\n\t\t\tnextStep: 'After reviewing DMARC reports, move to p=quarantine and ensure DKIM is active.',\n\t\t};\n\t}\n\n\t// Stage 1 — Basic: SPF exists but DMARC is p=none or DMARC has no rua=\n\tif (hasSpf && hasDmarc) {\n\t\treturn {\n\t\t\tstage: 1,\n\t\t\tlabel: 'Basic',\n\t\t\tdescription: 'Basic email records exist but are not enforcing or monitoring.',\n\t\t\tnextStep: 'Add DMARC aggregate reporting (rua=) and monitor for 2-4 weeks before enforcing.',\n\t\t};\n\t}\n\n\t// Stage 0 — Unprotected\n\treturn {\n\t\tstage: 0,\n\t\tlabel: 'Unprotected',\n\t\tdescription: 'No email authentication — any server can send email as this domain.',\n\t\tnextStep: 'Publish SPF and DMARC records to begin protecting your domain.',\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { sanitizeInput } from './sanitize';\n\nconst MARKDOWN_SYNTAX = /[`*_#[\\]()>|]/g;\n\nexport function sanitizeOutputText(input: string, maxLength = 240): string {\n\tconst trimmed = sanitizeInput(input, maxLength * 2)\n\t\t.replace(/\\x1b\\[[0-9;]*[a-zA-Z]/g, '')\n\t\t.replace(MARKDOWN_SYNTAX, ' ')\n\t\t.replace(/\\s+/g, ' ')\n\t\t.trim();\n\n\tif (trimmed.length <= maxLength) {\n\t\treturn trimmed;\n\t}\n\n\treturn `${trimmed.slice(0, maxLength - 3).trimEnd()}...`;\n}","export interface ExplanationTemplate {\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\nexport interface ImpactNarrative {\n\timpact?: string;\n\tadverseConsequences?: string;\n}\n\nexport interface SpecificImpactRule extends ImpactNarrative {\n\tcheckType?: string;\n\ttitleIncludes?: string[];\n\tdetailIncludes?: string[];\n}\n\nexport const EXPLANATIONS: Record<string, ExplanationTemplate> = {\n\tSUBDOMAIN_TAKEOVER_CRITICAL: {\n\t\ttitle: 'Dangling CNAME — Subdomain Takeover Risk',\n\t\tseverity: 'critical',\n\t\texplanation:\n\t\t\t'A subdomain points to a third-party service (e.g., CloudFront, Heroku) that does not resolve. This is a potential subdomain takeover vector, allowing attackers to claim the orphaned resource and control the subdomain.',\n\t\timpact: 'Attackers may host malicious content or capture traffic on a trusted subdomain, enabling phishing and session abuse.',\n\t\tadverseConsequences:\n\t\t\t'Brand trust can be damaged, users can be redirected to attacker infrastructure, and incident response costs can increase.',\n\t\trecommendation: 'Remove or update the CNAME record to point to a valid, owned resource. Regularly audit DNS for orphaned records.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t\t'https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CNAMEs.html',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_HIGH: {\n\t\ttitle: 'CNAME Resolution Failed — Manual Review Needed',\n\t\tseverity: 'high',\n\t\texplanation:\n\t\t\t'A subdomain CNAME points to a third-party service but the target could not be resolved. This may indicate a takeover risk or DNS misconfiguration.',\n\t\timpact: 'If the target is orphaned, an attacker may be able to claim it and gain control of the affected subdomain.',\n\t\tadverseConsequences: 'Users may be exposed to fraudulent pages and the organization may face reputation damage until DNS is remediated.',\n\t\trecommendation: 'Manually review the CNAME target and remove or update if orphaned. Use DNS monitoring tools for ongoing checks.',\n\t\treferences: [\n\t\t\t'https://github.com/EdOverflow/can-i-take-over-xyz',\n\t\t\t'https://www.hackerone.com/blog/Guide-Subdomain-Takeover',\n\t\t],\n\t},\n\tSUBDOMAIN_TAKEOVER_INFO: {\n\t\ttitle: 'No Dangling CNAME Records Found',\n\t\tseverity: 'info',\n\t\texplanation: 'No subdomain takeover vectors detected among known/active subdomains. DNS configuration is secure for this check.',\n\t\trecommendation: 'Continue regular DNS audits and monitoring for new subdomains or changes.',\n\t\treferences: ['https://github.com/EdOverflow/can-i-take-over-xyz'],\n\t},\n\tSPF_PASS: {\n\t\ttitle: 'SPF Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is properly configured. The domain specifies which mail servers are authorized to send email on its behalf.',\n\t\trecommendation: 'Maintain your current SPF configuration. Ensure you update it when adding new email sending sources.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208'],\n\t},\n\tSPF_FAIL: {\n\t\ttitle: 'SPF Validation Failed',\n\t\tseverity: 'fail',\n\t\texplanation: 'SPF validation failed - emails from this domain are being rejected because the sending server is not authorized.',\n\t\timpact: 'Email authentication becomes unreliable, and spoofed or misrouted messages may evade expected controls.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email delivery can degrade, while impersonation attempts can increase helpdesk and abuse handling load.',\n\t\trecommendation:\n\t\t\t'Review your SPF record and ensure all legitimate email sources are included. Common issue: using -all but missing include statements.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tSPF_WARNING: {\n\t\ttitle: 'SPF Soft Fail',\n\t\tseverity: 'warning',\n\t\texplanation: 'SPF uses a soft fail (~all) policy. Emails that fail SPF will be accepted but may be flagged as suspicious.',\n\t\timpact: 'Failing SPF messages are often still accepted, so spoofed mail may continue reaching recipients.',\n\t\tadverseConsequences: 'Phishing risk remains elevated and security teams may need to manually triage suspicious mail.',\n\t\trecommendation: 'Upgrade to hard fail (-all) after verifying all legitimate sources are in your SPF record.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208#section-8.1'],\n\t},\n\tSPF_MISSING: {\n\t\ttitle: 'No SPF Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'SPF (Sender Policy Framework) is a DNS TXT record that specifies which mail servers are authorized to send email on behalf of your domain. Without SPF, any server can send email pretending to be from your domain.',\n\t\timpact: 'Any internet host can attempt to send email as your domain, making sender impersonation significantly easier.',\n\t\tadverseConsequences: 'Spoofing and phishing campaigns can harm brand trust, increase abuse complaints, and impair deliverability.',\n\t\trecommendation: \"Add a TXT record to your domain's DNS with a valid SPF policy. Start with: v=spf1 include:<your-email-provider> -all\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7208', 'https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/'],\n\t},\n\tDMARC_PASS: {\n\t\ttitle: 'DMARC Policy Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DMARC (Domain-based Message Authentication, Reporting & Conformance) is properly configured with a policy that provides protection against email spoofing.',\n\t\trecommendation:\n\t\t\t'Monitor your DMARC reports to ensure legitimate email is not being blocked. Consider enabling reject policy for stronger protection.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489'],\n\t},\n\tDMARC_FAIL: {\n\t\ttitle: 'No DMARC Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'DMARC builds on SPF and DKIM to provide email authentication policy. Without DMARC, receivers have no policy guidance for handling authentication failures.',\n\t\timpact: 'Receiving systems cannot consistently quarantine or reject forged messages that fail authentication.',\n\t\tadverseConsequences: 'Domain spoofing can reach inboxes more often, increasing phishing exposure and reputational damage.',\n\t\trecommendation: 'Add a TXT record at _dmarc.<domain> with at minimum: v=DMARC1; p=quarantine; rua=mailto:dmarc@<domain>',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/'],\n\t},\n\tDMARC_WARNING: {\n\t\ttitle: 'DMARC Policy Not Enforcing',\n\t\tseverity: 'warning',\n\t\texplanation: \"DMARC policy is set to 'none' (monitoring only) or 'quarantine'. This provides limited protection against spoofing.\",\n\t\timpact: 'Authentication failures may not be fully blocked, allowing some malicious mail to be delivered.',\n\t\tadverseConsequences: 'Attackers can still impersonate the domain in recipient inboxes, leading to fraud and support overhead.',\n\t\trecommendation: \"After reviewing DMARC reports, upgrade the policy to 'reject' to actively protect against email spoofing.\",\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc7489#section-6.3'],\n\t},\n\tDKIM_PASS: {\n\t\ttitle: 'DKIM Validated',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DKIM (DomainKeys Identified Mail) is properly configured. Outgoing emails are digitally signed and can be verified by receivers.',\n\t\trecommendation: 'Maintain your DKIM configuration. Rotate keys periodically as per your security policy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376'],\n\t},\n\tDKIM_FAIL: {\n\t\ttitle: 'No DKIM Records Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DKIM adds a digital signature to outgoing emails, allowing receivers to verify the email was sent by an authorized server and wasn't modified in transit.\",\n\t\timpact: 'Receivers lose a key authenticity signal, which weakens anti-spoofing and anti-tampering protections.',\n\t\tadverseConsequences:\n\t\t\t'Legitimate email may be distrusted while fraudulent messages are harder to distinguish, hurting deliverability and trust.',\n\t\trecommendation: 'Configure DKIM signing with your email provider. They will provide the DKIM DNS records to publish.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc6376', 'https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/'],\n\t},\n\tDNSSEC_PASS: {\n\t\ttitle: 'DNSSEC Enabled',\n\t\tseverity: 'pass',\n\t\texplanation:\n\t\t\t'DNSSEC is properly configured with valid cryptographic signatures. This protects against DNS spoofing and cache poisoning attacks.',\n\t\trecommendation: 'Maintain your DNSSEC configuration. Monitor for any validation failures in your logs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033'],\n\t},\n\tDNSSEC_FAIL: {\n\t\ttitle: 'DNSSEC Not Validated',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t\"DNSSEC adds cryptographic signatures to DNS records, preventing DNS spoofing and cache poisoning attacks. Without DNSSEC, attackers can redirect your domain's traffic.\",\n\t\timpact: 'DNS responses can be forged in transit, enabling redirection to attacker-controlled infrastructure.',\n\t\tadverseConsequences: 'Users may be sent to malicious destinations, causing credential theft, service disruption, and incident response costs.',\n\t\trecommendation: 'Enable DNSSEC through your domain registrar and DNS provider. Most providers offer one-click DNSSEC activation.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc4033', 'https://www.cloudflare.com/dns/dnssec/how-dnssec-works/'],\n\t},\n\tSSL_PASS: {\n\t\ttitle: 'SSL/TLS Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain properly serves content over HTTPS with a valid certificate.',\n\t\trecommendation: 'Maintain your SSL certificate. Consider implementing HSTS for additional security.',\n\t\treferences: ['https://https.cio.gov/hsts/'],\n\t},\n\tSSL_FAIL: {\n\t\ttitle: 'HTTPS Not Available',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'The domain does not have a valid SSL/TLS certificate or the HTTPS server is not responding. This means traffic to the domain is not encrypted.',\n\t\timpact: 'Network attackers can intercept or tamper with data exchanged between users and the site.',\n\t\tadverseConsequences: 'Credentials and sensitive data may be exposed, and browser trust warnings can reduce conversion and user confidence.',\n\t\trecommendation: \"Install a valid SSL/TLS certificate. Free certificates are available from Let's Encrypt or Cloudflare.\",\n\t\treferences: ['https://letsencrypt.org/', 'https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_WARNING: {\n\t\ttitle: 'Mixed Content or Redirect Issues',\n\t\tseverity: 'warning',\n\t\texplanation: 'HTTPS is available but there may be issues with redirects or mixed content.',\n\t\timpact: 'Some resources may still load insecurely, creating opportunities for content manipulation or privacy leakage.',\n\t\tadverseConsequences: 'User sessions and page integrity can be weakened, and security posture may fail audit expectations.',\n\t\trecommendation: 'Ensure all resources load over HTTPS and implement proper redirects from HTTP to HTTPS.',\n\t\treferences: ['https://www.cloudflare.com/ssl/'],\n\t},\n\tSSL_MEDIUM: {\n\t\ttitle: 'HSTS or Redirect Issues',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'HTTPS is available but the domain is missing HSTS (Strict-Transport-Security) headers or does not redirect HTTP to HTTPS. Without HSTS, browsers may still attempt insecure connections.',\n\t\timpact: 'Clients may be downgraded to insecure HTTP connections, especially on first visit or hostile networks.',\n\t\tadverseConsequences: 'Session data can be exposed in transit and users remain vulnerable to downgrade or interception attacks.',\n\t\trecommendation:\n\t\t\t'Add a Strict-Transport-Security header with max-age of at least 1 year (31536000). Configure your web server to redirect all HTTP requests to HTTPS.',\n\t\treferences: ['https://https.cio.gov/hsts/', 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security'],\n\t},\n\tSSL_LOW: {\n\t\ttitle: 'HSTS Configuration Suboptimal',\n\t\tseverity: 'low',\n\t\texplanation:\n\t\t\t'HSTS is configured but could be improved. Common issues include a short max-age value or missing includeSubDomains directive.',\n\t\timpact: 'Partial HSTS coverage leaves windows where transport security guarantees are weaker than expected.',\n\t\tadverseConsequences: 'Subdomains or returning sessions may still face avoidable downgrade exposure and policy non-compliance findings.',\n\t\trecommendation:\n\t\t\t'Set max-age to at least 31536000 (1 year) and include the includeSubDomains directive. Consider adding your domain to the HSTS preload list.',\n\t\treferences: [\n\t\t\t'https://hstspreload.org/',\n\t\t\t'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security',\n\t\t],\n\t},\n\tMTA_STS_PASS: {\n\t\ttitle: 'MTA-STS Enabled',\n\t\tseverity: 'pass',\n\t\texplanation: 'MTA-STS (Mail Transfer Agent Strict Transport Security) is properly configured and enforces TLS for incoming email.',\n\t\trecommendation: 'Monitor your MTA-STS reports to ensure legitimate mail servers can deliver successfully.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_FAIL: {\n\t\ttitle: 'No MTA-STS Record Found',\n\t\tseverity: 'fail',\n\t\texplanation:\n\t\t\t'MTA-STS enforces TLS encryption for incoming email, preventing downgrade attacks where an attacker forces email to be sent unencrypted.',\n\t\timpact: 'Inbound SMTP sessions are more susceptible to TLS downgrade and interception attempts.',\n\t\tadverseConsequences: 'Sensitive email content can be exposed in transit, raising confidentiality and compliance risks.',\n\t\trecommendation:\n\t\t\t'Publish an MTA-STS TXT record at _mta-sts.<domain> and host a policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tMTA_STS_WARNING: {\n\t\ttitle: 'MTA-STS in Testing Mode',\n\t\tseverity: 'warning',\n\t\texplanation: 'MTA-STS is configured but in testing mode (mode=testing) rather than enforcement mode.',\n\t\timpact: 'Delivery behavior is monitored but not enforced, so some insecure transport paths may still be accepted.',\n\t\tadverseConsequences: 'Security gaps can persist longer and confidentiality controls for inbound mail remain partially effective.',\n\t\trecommendation: 'After verifying all mail servers can successfully deliver over TLS, upgrade to mode=enforce.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8461'],\n\t},\n\tNS_PASS: {\n\t\ttitle: 'Nameservers Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'The domain has properly configured nameservers that are responding to queries.',\n\t\trecommendation: 'Maintain your current nameserver configuration. Use at least two geographically distributed nameservers for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tNS_FAIL: {\n\t\ttitle: 'Nameserver Issues Detected',\n\t\tseverity: 'fail',\n\t\texplanation: 'One or more nameservers for this domain are not responding or are misconfigured, which can cause DNS resolution failures.',\n\t\timpact: 'Resolvers may fail to resolve the domain, degrading access to web, API, and mail services.',\n\t\tadverseConsequences: 'Users can experience outages, failed transactions, and business continuity disruptions.',\n\t\trecommendation: 'Verify all listed nameservers are operational and properly configured. Ensure NS records match those at the registrar.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035', 'https://www.cloudflare.com/learning/dns/dns-records/dns-ns-record/'],\n\t},\n\tNS_WARNING: {\n\t\ttitle: 'Nameserver Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'Nameservers are functional but the configuration could be improved for better reliability or security.',\n\t\timpact: 'Single points of failure or weak diversity can reduce DNS resilience during provider or network incidents.',\n\t\tadverseConsequences: 'Availability and latency can degrade under stress, increasing user-facing instability.',\n\t\trecommendation: 'Consider adding additional nameservers for redundancy and ensuring they are geographically distributed.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc1035'],\n\t},\n\tCAA_PASS: {\n\t\ttitle: 'CAA Records Configured',\n\t\tseverity: 'pass',\n\t\texplanation: 'CAA (Certificate Authority Authorization) records are properly configured, restricting which CAs can issue certificates for this domain.',\n\t\trecommendation: 'Maintain your CAA records. Review periodically to ensure they reflect your current certificate issuance needs.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tCAA_FAIL: {\n\t\ttitle: 'No CAA Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No CAA records are present for this domain. Without CAA, any certificate authority can issue certificates for your domain.',\n\t\timpact: 'Certificate issuance controls are broad, increasing the chance of unauthorized or misissued certificates.',\n\t\tadverseConsequences: 'Attackers may abuse misissuance for impersonation and interception, with trust and compliance implications.',\n\t\trecommendation: 'Add CAA DNS records to restrict certificate issuance to your authorized CAs (e.g., \"0 issue letsencrypt.org\").',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659', 'https://www.cloudflare.com/learning/dns/dns-records/dns-caa-record/'],\n\t},\n\tCAA_WARNING: {\n\t\ttitle: 'CAA Configuration Incomplete',\n\t\tseverity: 'warning',\n\t\texplanation: 'CAA records exist but may not fully restrict certificate issuance. Consider adding iodef or wildcard policies.',\n\t\timpact: 'Incomplete CAA policy can leave gaps in issuance constraints for wildcard or incident-reporting scenarios.',\n\t\tadverseConsequences: 'Certificate governance may be weaker than intended, increasing operational and audit risk.',\n\t\trecommendation: 'Review your CAA records and add an iodef tag for incident reporting. Consider restricting wildcard certificate issuance separately.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc8659'],\n\t},\n\tMX_PASS: {\n\t\ttitle: 'MX Records Validated',\n\t\tseverity: 'pass',\n\t\texplanation: 'MX (Mail Exchange) records are properly configured, directing email to the correct mail servers.',\n\t\trecommendation: 'Maintain your MX records. Ensure backup MX entries exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_FAIL: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'fail',\n\t\texplanation: 'No MX records are present for this domain. Without MX records, email delivery to this domain will fail or fall back to A record delivery.',\n\t\timpact: 'Mail routing is unreliable or unavailable for intended recipients on this domain.',\n\t\tadverseConsequences: 'Inbound communications may be lost, causing business disruption and missed security notifications.',\n\t\trecommendation: 'Add MX records pointing to your mail server. If this domain does not handle email, consider adding a null MX record (0 .).',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n\tMX_WARNING: {\n\t\ttitle: 'MX Configuration Suboptimal',\n\t\tseverity: 'warning',\n\t\texplanation: 'MX records exist but the configuration could be improved, such as missing backup MX or unusual priority values.',\n\t\timpact: 'Mail delivery reliability is reduced during server failures or routing anomalies.',\n\t\tadverseConsequences: 'Message delays and intermittent delivery failures can affect operations and customer support.',\n\t\trecommendation: 'Review MX priorities and add at least one backup MX record for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_INFO: {\n\t\ttitle: 'MX Records Present',\n\t\tseverity: 'info',\n\t\texplanation: 'Mail exchange records are properly configured for this domain.',\n\t\trecommendation: 'No action required. Ensure backup MX records exist for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_LOW: {\n\t\ttitle: 'MX Configuration Could Be Improved',\n\t\tseverity: 'low',\n\t\texplanation: 'MX records are present but the configuration has minor issues such as missing backup MX records.',\n\t\timpact: 'Resilience to mail infrastructure outages is lower than recommended.',\n\t\tadverseConsequences: 'Short outages can become user-visible delivery delays and increase operational toil.',\n\t\trecommendation: 'Add at least one backup MX record with a different priority for redundancy.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_HIGH: {\n\t\ttitle: 'MX Configuration Error',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'MX records have a configuration error such as pointing to an IP address instead of a hostname (violating RFC 5321) or referencing a hostname that does not resolve to any address record.',\n\t\timpact: 'Standards-incompatible or unresolvable MX targets can cause mail rejection or routing failures across sending systems.',\n\t\tadverseConsequences: 'Business-critical messages may bounce, delaying incident response and external communication.',\n\t\trecommendation:\n\t\t\t'Update MX records to point to valid hostnames, not IP addresses. Ensure all MX targets resolve to valid A/AAAA records.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321'],\n\t},\n\tMX_MEDIUM: {\n\t\ttitle: 'No MX Records Found',\n\t\tseverity: 'medium',\n\t\texplanation:\n\t\t\t'No MX records are present for this domain. Email delivery will fall back to A record delivery or fail entirely.',\n\t\timpact: 'Email reception may fail or behave inconsistently depending on sender fallback behavior.',\n\t\tadverseConsequences: 'Organizations may miss customer, partner, or security messages, creating operational and reputational risk.',\n\t\trecommendation:\n\t\t\t'If this domain should receive email, add MX records. If not, publish a null MX record per RFC 7505 to explicitly declare that.',\n\t\treferences: ['https://datatracker.ietf.org/doc/html/rfc5321', 'https://datatracker.ietf.org/doc/html/rfc7505'],\n\t},\n};\n\nexport const DEFAULT_EXPLANATION: ExplanationTemplate = {\n\ttitle: 'Security Check Complete',\n\tseverity: 'info',\n\texplanation: \"This check has been completed. Review the findings above for details on your domain's security posture.\",\n\trecommendation: 'Refer to the specific check documentation for detailed remediation steps.',\n\treferences: ['https://www.cloudflare.com/learning/dns/what-is-dns/'],\n};\n\nexport const CATEGORY_TO_CHECKTYPE: Record<string, string> = {\n\tspf: 'SPF',\n\tdmarc: 'DMARC',\n\tdkim: 'DKIM',\n\tdnssec: 'DNSSEC',\n\tssl: 'SSL',\n\tmta_sts: 'MTA_STS',\n\tns: 'NS',\n\tcaa: 'CAA',\n\tmx: 'MX',\n\tsubdomain_takeover: 'SUBDOMAIN_TAKEOVER',\n};\n\nexport const CATEGORY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tSPF: {\n\t\timpact: 'SPF coverage is weak, so unauthorized senders can spoof domain identity more easily.',\n\t\tadverseConsequences: 'Phishing attempts and deliverability disputes increase security and support workload.',\n\t},\n\tDMARC: {\n\t\timpact: 'DMARC enforcement is reduced or absent at receiving systems.',\n\t\tadverseConsequences: 'Forged messages are more likely to reach users and erode brand trust.',\n\t},\n\tDKIM: {\n\t\timpact: 'DKIM assurance is weak, reducing message integrity and sender-authenticity confidence.',\n\t\tadverseConsequences: 'Legitimate messages may be distrusted while impersonation attempts become harder to detect.',\n\t},\n\tDNSSEC: {\n\t\timpact: 'DNS answers are more exposed to spoofing and tampering in transit.',\n\t\tadverseConsequences: 'Users can be redirected to attacker infrastructure, causing security and availability incidents.',\n\t},\n\tSSL: {\n\t\timpact: 'Transport security guarantees are reduced, increasing interception and tampering risk.',\n\t\tadverseConsequences: 'Sensitive user data may be exposed and browser trust can decline.',\n\t},\n\tMTA_STS: {\n\t\timpact: 'Inbound SMTP delivery is not consistently protected from downgrade attacks.',\n\t\tadverseConsequences: 'Confidential email content may be exposed in transit, increasing compliance risk.',\n\t},\n\tNS: {\n\t\timpact: 'DNS resolution reliability is reduced, which weakens service reachability.',\n\t\tadverseConsequences: 'Users may experience outages and business transactions may fail.',\n\t},\n\tCAA: {\n\t\timpact: 'Certificate issuance controls are weak, raising unauthorized issuance risk.',\n\t\tadverseConsequences: 'Domain impersonation and TLS trust incidents become more likely.',\n\t},\n\tMX: {\n\t\timpact: 'Mail routing reliability is reduced by MX configuration gaps or errors.',\n\t\tadverseConsequences: 'Important communications can be delayed, bounced, or lost.',\n\t},\n\tSUBDOMAIN_TAKEOVER: {\n\t\timpact: 'An orphaned delegated subdomain may be claimable by an attacker.',\n\t\tadverseConsequences: 'Users can be redirected to malicious content hosted under a trusted hostname.',\n\t},\n};\n\nexport const SEVERITY_FALLBACK_IMPACT: Record<string, ImpactNarrative> = {\n\tcritical: {\n\t\timpact: 'This is a high-likelihood weakness with immediate exploitation potential.',\n\t\tadverseConsequences: 'Compromise, disruption, or abuse can occur without prompt remediation.',\n\t},\n\thigh: {\n\t\timpact: 'This weakness materially increases attack surface and failure risk.',\n\t\tadverseConsequences: 'Business operations, user trust, and response workload can be negatively affected.',\n\t},\n\tmedium: {\n\t\timpact: 'This issue weakens defenses and compounds risk when paired with other gaps.',\n\t\tadverseConsequences: 'Over time it can degrade reliability, security assurance, and compliance posture.',\n\t},\n\twarning: {\n\t\timpact: 'This configuration is partially protective but leaves avoidable exposure.',\n\t\tadverseConsequences: 'If unresolved, incidents become harder to prevent or contain.',\n\t},\n\tfail: {\n\t\timpact: 'A required control is missing or not functioning as intended.',\n\t\tadverseConsequences: 'Security and availability incidents become more likely until it is corrected.',\n\t},\n\tlow: {\n\t\timpact: 'This is a minor weakness that still reduces resilience.',\n\t\tadverseConsequences: 'Operational friction and audit findings can increase over time.',\n\t},\n};\n\nexport const SPECIFIC_IMPACT_RULES: SpecificImpactRule[] = [\n\t{\n\t\tcheckType: 'DKIM',\n\t\ttitleIncludes: ['weak rsa key'],\n\t\timpact: 'Weak DKIM keys are easier to forge, reducing message authenticity assurance.',\n\t\tadverseConsequences: 'Attackers can impersonate trusted senders more easily, increasing fraud and phishing risk.',\n\t},\n\t{\n\t\tcheckType: 'SSL',\n\t\ttitleIncludes: ['no hsts header', 'no http to https redirect', 'mixed content'],\n\t\timpact: 'Users are exposed to insecure transport paths that permit interception or downgrade attacks.',\n\t\tadverseConsequences: 'Sensitive sessions and data can leak on hostile networks, weakening trust and compliance posture.',\n\t},\n\t{\n\t\tcheckType: 'DMARC',\n\t\ttitleIncludes: ['no aggregate reporting'],\n\t\timpact: 'Authentication failures and spoofing activity become harder to observe at scale.',\n\t\tadverseConsequences: 'Threats can persist longer without detection, increasing response time and abuse volume.',\n\t},\n\t{\n\t\tcheckType: 'MX',\n\t\ttitleIncludes: ['no mx records found', 'mx configuration error'],\n\t\timpact: 'Inbound email delivery becomes unreliable or fails for recipients on this domain.',\n\t\tadverseConsequences: 'Critical business and security communications may be delayed, bounced, or silently lost.',\n\t},\n\t{\n\t\tcheckType: 'NS',\n\t\ttitleIncludes: ['no soa record', 'nameserver', 'low nameserver diversity'],\n\t\timpact: 'DNS resilience and consistency are reduced, increasing partial or full resolution outage risk.',\n\t\tadverseConsequences: 'Availability incidents can affect websites, APIs, and transactional workflows.',\n\t},\n\t{\n\t\tcheckType: 'CAA',\n\t\ttitleIncludes: ['no caa records', 'issuewild', 'iodef'],\n\t\timpact: 'Certificate governance controls are weakened, especially for unauthorized or wildcard issuance.',\n\t\tadverseConsequences: 'TLS trust incidents and audit findings become more likely if certificate misuse occurs.',\n\t},\n\t{\n\t\tcheckType: 'SPF',\n\t\ttitleIncludes: ['permissive spf: +all', 'multiple spf records'],\n\t\tdetailIncludes: ['+all', 'multiple records'],\n\t\timpact: 'SPF policy becomes ineffective or ambiguous, allowing unauthorized senders to appear legitimate.',\n\t\tadverseConsequences: 'Spoofing, phishing, and deliverability failures can increase simultaneously.',\n\t},\n\t{\n\t\tcheckType: 'MTA_STS',\n\t\ttitleIncludes: ['no mta-sts', 'testing mode', 'tls-rpt'],\n\t\timpact: 'SMTP transport protections are not consistently enforced for inbound mail delivery.',\n\t\tadverseConsequences: 'Confidential email may traverse weaker paths, increasing confidentiality and regulatory risk.',\n\t},\n];","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Explain Finding tool.\n * Provides static explanations for DNS security findings.\n * No AI binding required - uses a built-in knowledge base.\n */\n\nimport {\n\tCATEGORY_FALLBACK_IMPACT,\n\tCATEGORY_TO_CHECKTYPE,\n\tDEFAULT_EXPLANATION,\n\tEXPLANATIONS,\n\ttype ExplanationTemplate,\n\ttype ImpactNarrative,\n\tSEVERITY_FALLBACK_IMPACT,\n\tSPECIFIC_IMPACT_RULES,\n} from './explain-finding-data';\n\nexport interface ExplanationResult {\n\tcheckType: string;\n\tstatus: string;\n\tdetails?: string;\n\ttitle: string;\n\tseverity: string;\n\texplanation: string;\n\timpact?: string;\n\tadverseConsequences?: string;\n\trecommendation: string;\n\treferences: string[];\n}\n\ntype ExplanationEntry = ExplanationTemplate;\n\nfunction matchesRule(ruleValues: string[] | undefined, source: string): boolean {\n\tif (!ruleValues || ruleValues.length === 0) return true;\n\treturn ruleValues.some((value) => source.includes(value));\n}\n\nfunction resolveSpecificNarrative(params: {\n\tcheckType?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative | undefined {\n\tconst checkType = params.checkType?.toUpperCase();\n\tconst title = params.title?.toLowerCase() ?? '';\n\tconst detail = params.detail?.toLowerCase() ?? '';\n\n\tfor (const rule of SPECIFIC_IMPACT_RULES) {\n\t\tif (rule.checkType && checkType && rule.checkType !== checkType) continue;\n\t\tif (!matchesRule(rule.titleIncludes, title)) continue;\n\t\tif (!matchesRule(rule.detailIncludes, detail)) continue;\n\t\treturn {\n\t\t\timpact: rule.impact,\n\t\t\tadverseConsequences: rule.adverseConsequences,\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\nfunction getNarrativeFromEntry(entry: ExplanationEntry | undefined): ImpactNarrative | undefined {\n\tif (!entry) return undefined;\n\tif (!entry.impact && !entry.adverseConsequences) return undefined;\n\treturn {\n\t\timpact: entry.impact,\n\t\tadverseConsequences: entry.adverseConsequences,\n\t};\n}\n\n/**\n * Resolve impact/adverse-consequence narrative for a finding context.\n * Uses explicit explanation entries first, then category, then severity fallback.\n */\nexport function resolveImpactNarrative(params: {\n\tcheckType?: string;\n\tcategory?: string;\n\tstatus?: string;\n\tseverity?: string;\n\ttitle?: string;\n\tdetail?: string;\n}): ImpactNarrative {\n\tconst normalizedCheckType = params.checkType?.toUpperCase();\n\tconst normalizedStatus = params.status?.toUpperCase();\n\tconst normalizedSeverity = params.severity?.toLowerCase();\n\tconst derivedCheckType = params.category ? CATEGORY_TO_CHECKTYPE[params.category.toLowerCase()] : undefined;\n\n\tif (normalizedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (normalizedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${normalizedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedStatus) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedStatus}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tif (derivedCheckType && normalizedSeverity) {\n\t\tconst narrative = getNarrativeFromEntry(EXPLANATIONS[`${derivedCheckType}_${normalizedSeverity.toUpperCase()}`]);\n\t\tif (narrative) return narrative;\n\t}\n\n\tconst specificNarrative = resolveSpecificNarrative({\n\t\tcheckType: normalizedCheckType ?? derivedCheckType,\n\t\ttitle: params.title,\n\t\tdetail: params.detail,\n\t});\n\tif (specificNarrative) return specificNarrative;\n\n\tif (normalizedCheckType && CATEGORY_FALLBACK_IMPACT[normalizedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[normalizedCheckType];\n\t}\n\n\tif (derivedCheckType && CATEGORY_FALLBACK_IMPACT[derivedCheckType]) {\n\t\treturn CATEGORY_FALLBACK_IMPACT[derivedCheckType];\n\t}\n\n\tif (normalizedSeverity && SEVERITY_FALLBACK_IMPACT[normalizedSeverity]) {\n\t\treturn SEVERITY_FALLBACK_IMPACT[normalizedSeverity];\n\t}\n\n\treturn {};\n}\n\nexport function explainFinding(checkType: string, status: string, details?: string): ExplanationResult {\n\tconst normalizedType = checkType.toUpperCase();\n\tconst key = `${normalizedType}_${status.toUpperCase()}`;\n\n\t// 1. Try checkType_STATUS key\n\tlet entry: ExplanationTemplate | undefined = EXPLANATIONS[key];\n\n\t// 2. Fall back to default\n\tif (!entry) {\n\t\tentry = DEFAULT_EXPLANATION;\n\t}\n\n\tconst narrative = resolveImpactNarrative({ checkType: normalizedType, status, detail: details });\n\n\treturn {\n\t\tcheckType: normalizedType,\n\t\tstatus,\n\t\tdetails,\n\t\t...entry,\n\t\timpact: entry.impact ?? narrative.impact,\n\t\tadverseConsequences: entry.adverseConsequences ?? narrative.adverseConsequences,\n\t};\n}\n\nexport function formatExplanation(result: ExplanationResult): string {\n\tconst lines = [`## ${result.title}`, `**Check Type:** ${result.checkType} | **Status:** ${result.status}`, ''];\n\n\tlines.push(`### What this means`, result.explanation, '');\n\n\tif (result.impact) {\n\t\tlines.push(`### Potential Impact`, result.impact, '');\n\t}\n\n\tif (result.adverseConsequences) {\n\t\tlines.push(`### Adverse Consequences`, result.adverseConsequences, '');\n\t}\n\n\tlines.push(`### Recommendation`, result.recommendation, '', `### References`, ...result.references.map((reference) => `- ${reference}`));\n\treturn lines.join('\\n');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { ScanDomainResult } from '../scan-domain';\nimport { sanitizeOutputText } from '../../lib/output-sanitize';\nimport { resolveImpactNarrative } from '../explain-finding';\n\n/** Structured scan result for machine-readable consumption (e.g., CI/CD actions). */\nexport interface StructuredScanResult {\n\tdomain: string;\n\tscore: number;\n\tgrade: string;\n\tpassed: boolean;\n\tmaturityStage: number | null;\n\tmaturityLabel: string | null;\n\tcategoryScores: Record<string, number>;\n\tfindingCounts: { critical: number; high: number; medium: number; low: number };\n\tscoringProfile: string;\n\tscoringSignals: string[];\n\tscoringNote: string | null;\n\tadaptiveWeightDeltas: Record<string, number> | null;\n\ttimestamp: string;\n\tcached: boolean;\n}\n\n/** Build a machine-readable structured result from a scan. */\nexport function buildStructuredScanResult(result: ScanDomainResult): StructuredScanResult {\n\treturn {\n\t\tdomain: result.domain,\n\t\tscore: result.score.overall,\n\t\tgrade: result.score.grade,\n\t\tpassed: result.score.overall >= 50,\n\t\tmaturityStage: result.maturity?.stage ?? null,\n\t\tmaturityLabel: result.maturity?.label ?? null,\n\t\tcategoryScores: result.score.categoryScores,\n\t\tfindingCounts: {\n\t\t\tcritical: result.score.findings.filter((f) => f.severity === 'critical').length,\n\t\t\thigh: result.score.findings.filter((f) => f.severity === 'high').length,\n\t\t\tmedium: result.score.findings.filter((f) => f.severity === 'medium').length,\n\t\t\tlow: result.score.findings.filter((f) => f.severity === 'low').length,\n\t\t},\n\t\tscoringProfile: result.context?.profile ?? 'mail_enabled',\n\t\tscoringSignals: (result.context?.signals ?? []).map((s) => s.replace(/[<>&\"']/g, '')),\n\t\tscoringNote: result.scoringNote ?? null,\n\t\tadaptiveWeightDeltas: result.adaptiveWeightDeltas ?? null,\n\t\ttimestamp: result.timestamp,\n\t\tcached: result.cached,\n\t};\n}\n\nexport function formatScanReport(result: ScanDomainResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push(`DNS Security Scan: ${result.domain}`);\n\tlines.push(`${'='.repeat(40)}`);\n\tlines.push(`Overall Score: ${result.score.overall}/100 (${result.score.grade})`);\n\tlines.push(`${result.score.summary}`);\n\tlines.push('');\n\n\tif (result.maturity) {\n\t\tlines.push(`Email Security Maturity: Stage ${result.maturity.stage} — ${result.maturity.label}`);\n\t\tlines.push(result.maturity.description);\n\t\tif (result.maturity.nextStep) {\n\t\t\tlines.push(`Next step: ${result.maturity.nextStep}`);\n\t\t}\n\t\tlines.push('');\n\t}\n\n\tif (result.context) {\n\t\tconst signalSummary = result.context.signals.length > 0 ? result.context.signals.join(', ') : 'default';\n\t\tlines.push(`Scoring Profile: ${result.context.profile} (${signalSummary})`);\n\t\tlines.push('');\n\t}\n\n\tif (result.scoringNote) {\n\t\tlines.push(result.scoringNote);\n\t\tlines.push('');\n\t}\n\n\tlines.push('Category Scores:');\n\tlines.push('-'.repeat(30));\n\tfor (const [category, score] of Object.entries(result.score.categoryScores)) {\n\t\tconst status = score >= 80 ? '✓' : score >= 50 ? '⚠' : '✗';\n\t\tlines.push(` ${status} ${category.toUpperCase().padEnd(10)} ${score}/100`);\n\t}\n\tlines.push('');\n\n\tconst nonInfoFindings = result.score.findings.filter((finding) => finding.severity !== 'info');\n\tif (nonInfoFindings.length > 0) {\n\t\tlines.push('Findings:');\n\t\tlines.push('-'.repeat(30));\n\t\tfor (const finding of nonInfoFindings) {\n\t\t\tlines.push(` [${finding.severity.toUpperCase()}] ${sanitizeOutputText(finding.title, 120)}`);\n\t\t\tlines.push(` ${sanitizeOutputText(finding.detail)}`);\n\t\t\tconst verificationStatus =\n\t\t\t\tfinding.category === 'subdomain_takeover' && finding.metadata?.verificationStatus\n\t\t\t\t\t? String(finding.metadata.verificationStatus)\n\t\t\t\t\t: undefined;\n\t\t\tif (verificationStatus) {\n\t\t\t\tlines.push(` Takeover Verification: ${sanitizeOutputText(verificationStatus, 80)}`);\n\t\t\t}\n\t\t\tconst confidence = finding.metadata?.confidence ? String(finding.metadata.confidence) : undefined;\n\t\t\tif (confidence) {\n\t\t\t\tlines.push(` Confidence: ${sanitizeOutputText(confidence, 80)}`);\n\t\t\t}\n\t\t\tconst narrative = resolveImpactNarrative({\n\t\t\t\tcategory: finding.category,\n\t\t\t\tseverity: finding.severity,\n\t\t\t\ttitle: finding.title,\n\t\t\t\tdetail: finding.detail,\n\t\t\t});\n\t\t\tif (narrative.impact) {\n\t\t\t\tlines.push(` Potential Impact: ${narrative.impact}`);\n\t\t\t}\n\t\t\tif (narrative.adverseConsequences) {\n\t\t\t\tlines.push(` Adverse Consequences: ${narrative.adverseConsequences}`);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tlines.push('No security issues found.');\n\t}\n\n\tif (result.cached) {\n\t\tlines.push('');\n\t\tlines.push('(Results served from cache)');\n\t}\n\n\tlines.push('');\n\tlines.push(`Scan completed: ${result.timestamp}`);\n\treturn lines.join('\\n');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Baseline comparison tool.\n * Compares a scan result against a policy floor for org-level enforcement.\n */\n\nimport type { CheckCategory } from '../lib/scoring';\nimport type { ScanDomainResult } from './scan-domain';\n\nconst GRADE_ORDER = ['A+', 'A', 'B+', 'B', 'C+', 'C', 'D+', 'D', 'E', 'F'] as const;\n\nconst CATEGORY_REQUIREMENTS: Array<{ key: keyof PolicyBaseline; category: CheckCategory; label: string }> = [\n\t{ key: 'require_spf', category: 'spf', label: 'SPF' },\n\t{ key: 'require_dkim', category: 'dkim', label: 'DKIM' },\n\t{ key: 'require_dnssec', category: 'dnssec', label: 'DNSSEC' },\n\t{ key: 'require_mta_sts', category: 'mta_sts', label: 'MTA-STS' },\n\t{ key: 'require_caa', category: 'caa', label: 'CAA' },\n];\n\n/** A single baseline rule violation. */\nexport interface BaselineViolation {\n\trule: string;\n\tmessage: string;\n\texpected: string | number | boolean;\n\tactual: string | number | boolean;\n}\n\n/** Result of comparing one scan against one baseline. */\nexport interface BaselineResult {\n\tdomain: string;\n\tpassed: boolean;\n\tviolations: BaselineViolation[];\n\tcheckedRules: number;\n\tscoringProfile?: string;\n\ttimestamp: string;\n}\n\n/** User-defined policy baseline. */\nexport interface PolicyBaseline {\n\tgrade?: string;\n\tscore?: number;\n\trequire_dmarc_enforce?: boolean;\n\trequire_spf?: boolean;\n\trequire_dkim?: boolean;\n\trequire_dnssec?: boolean;\n\trequire_mta_sts?: boolean;\n\trequire_caa?: boolean;\n\tmax_critical_findings?: number;\n\tmax_high_findings?: number;\n}\n\nfunction gradeWorseThan(actual: string, minimum: string): boolean {\n\tconst actualIndex = GRADE_ORDER.indexOf(actual as (typeof GRADE_ORDER)[number]);\n\tconst minimumIndex = GRADE_ORDER.indexOf(minimum as (typeof GRADE_ORDER)[number]);\n\tif (actualIndex === -1 || minimumIndex === -1) return false;\n\treturn actualIndex > minimumIndex;\n}\n\nfunction categoryPassed(scan: ScanDomainResult, category: CheckCategory): boolean {\n\tconst check = scan.checks.find((value) => value.category === category);\n\treturn check?.passed ?? false;\n}\n\nfunction dmarcEnforced(scan: ScanDomainResult): boolean {\n\tconst dmarcCheck = scan.checks.find((value) => value.category === 'dmarc');\n\tif (!dmarcCheck) return false;\n\n\tconst hasNonePolicyFinding = dmarcCheck.findings.some((finding) => {\n\t\tconst text = `${finding.title} ${finding.detail}`.toLowerCase();\n\t\treturn finding.severity !== 'info' && (text.includes('p=none') || text.includes('policy is none'));\n\t});\n\n\treturn dmarcCheck.passed && !hasNonePolicyFinding;\n}\n\n/** Compare a scan result against a policy baseline. */\nexport function compareBaseline(scan: ScanDomainResult, baseline: PolicyBaseline): BaselineResult {\n\tconst violations: BaselineViolation[] = [];\n\tlet checkedRules = 0;\n\n\tif (baseline.grade !== undefined) {\n\t\tcheckedRules++;\n\t\tif (gradeWorseThan(scan.score.grade, baseline.grade)) {\n\t\t\tviolations.push({\n\t\t\t\trule: 'grade',\n\t\t\t\tmessage: `Grade ${scan.score.grade} is below minimum ${baseline.grade}`,\n\t\t\t\texpected: baseline.grade,\n\t\t\t\tactual: scan.score.grade,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (baseline.score !== undefined) {\n\t\tcheckedRules++;\n\t\tif (scan.score.overall < baseline.score) {\n\t\t\tviolations.push({\n\t\t\t\trule: 'score',\n\t\t\t\tmessage: `Score ${scan.score.overall} is below minimum ${baseline.score}`,\n\t\t\t\texpected: baseline.score,\n\t\t\t\tactual: scan.score.overall,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (baseline.require_dmarc_enforce) {\n\t\tcheckedRules++;\n\t\tif (!dmarcEnforced(scan)) {\n\t\t\tviolations.push({\n\t\t\t\trule: 'require_dmarc_enforce',\n\t\t\t\tmessage: 'DMARC enforcement (p=quarantine or p=reject) is required but not met',\n\t\t\t\texpected: true,\n\t\t\t\tactual: false,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const requirement of CATEGORY_REQUIREMENTS) {\n\t\tif (baseline[requirement.key]) {\n\t\t\tcheckedRules++;\n\t\t\tif (!categoryPassed(scan, requirement.category)) {\n\t\t\t\tviolations.push({\n\t\t\t\t\trule: requirement.key,\n\t\t\t\t\tmessage: `${requirement.label} is required but check did not pass`,\n\t\t\t\t\texpected: true,\n\t\t\t\t\tactual: false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tif (baseline.max_critical_findings !== undefined) {\n\t\tcheckedRules++;\n\t\tconst criticalCount = scan.score.findings.filter((finding) => finding.severity === 'critical').length;\n\t\tif (criticalCount > baseline.max_critical_findings) {\n\t\t\tviolations.push({\n\t\t\t\trule: 'max_critical_findings',\n\t\t\t\tmessage: `${criticalCount} critical findings exceed maximum of ${baseline.max_critical_findings}`,\n\t\t\t\texpected: baseline.max_critical_findings,\n\t\t\t\tactual: criticalCount,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (baseline.max_high_findings !== undefined) {\n\t\tcheckedRules++;\n\t\tconst highCount = scan.score.findings.filter((finding) => finding.severity === 'high').length;\n\t\tif (highCount > baseline.max_high_findings) {\n\t\t\tviolations.push({\n\t\t\t\trule: 'max_high_findings',\n\t\t\t\tmessage: `${highCount} high findings exceed maximum of ${baseline.max_high_findings}`,\n\t\t\t\texpected: baseline.max_high_findings,\n\t\t\t\tactual: highCount,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn {\n\t\tdomain: scan.domain,\n\t\tpassed: violations.length === 0,\n\t\tviolations,\n\t\tcheckedRules,\n\t\tscoringProfile: scan.context?.profile,\n\t\ttimestamp: new Date().toISOString(),\n\t};\n}\n\n/** Format baseline result as readable markdown text for MCP clients. */\nexport function formatBaselineResult(result: BaselineResult): string {\n\tconst lines: string[] = [];\n\n\tlines.push(`## Baseline Comparison: ${result.domain}`);\n\tlines.push(`**Result:** ${result.passed ? 'PASS' : 'FAIL'}`);\n\tlines.push(`**Rules checked:** ${result.checkedRules}`);\n\tlines.push(`**Violations:** ${result.violations.length}`);\n\tlines.push('');\n\n\tif (result.violations.length === 0) {\n\t\tlines.push('All baseline rules met.');\n\t\treturn lines.join('\\n');\n\t}\n\n\tlines.push('### Violations');\n\tfor (const violation of result.violations) {\n\t\tlines.push(`- **${violation.rule}** - ${violation.message}`);\n\t\tlines.push(` Expected: ${violation.expected} | Actual: ${violation.actual}`);\n\t}\n\n\treturn lines.join('\\n');\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { logEvent, logError } from '../lib/log';\nimport type { AnalyticsClient } from '../lib/analytics';\nimport type { McpClientType } from '../lib/client-detection';\n\ntype ToolSuccessStatus = 'pass' | 'fail';\ntype ToolFailureSeverity = 'warn' | 'error';\n\ninterface ToolExecutionBase {\n\ttoolName: string;\n\tdurationMs: number;\n\tdomain?: string;\n\tanalytics?: AnalyticsClient;\n\tcountry?: string;\n\tclientType?: McpClientType;\n\tauthTier?: string;\n}\n\nexport function logToolSuccess(options: ToolExecutionBase & {\n\tstatus: ToolSuccessStatus;\n\tlogResult: string;\n\tlogDetails: unknown;\n\tseverity?: 'info' | 'warn';\n}): void {\n\toptions.analytics?.emitToolEvent({\n\t\ttoolName: options.toolName,\n\t\tstatus: options.status,\n\t\tdurationMs: options.durationMs,\n\t\tdomain: options.domain,\n\t\tisError: false,\n\t\tcountry: options.country,\n\t\tclientType: options.clientType,\n\t\tauthTier: options.authTier,\n\t});\n\n\tlogEvent({\n\t\ttimestamp: new Date().toISOString(),\n\t\ttool: options.toolName,\n\t\tdomain: options.domain,\n\t\tresult: options.logResult,\n\t\tdetails: options.logDetails,\n\t\tdurationMs: options.durationMs,\n\t\tseverity: options.severity ?? (options.status === 'pass' ? 'info' : 'warn'),\n\t});\n}\n\nexport function logToolFailure(options: ToolExecutionBase & {\n\terror: unknown;\n\targs: Record<string, unknown>;\n\tseverity?: ToolFailureSeverity;\n}): void {\n\toptions.analytics?.emitToolEvent({\n\t\ttoolName: options.toolName,\n\t\tstatus: 'error',\n\t\tdurationMs: options.durationMs,\n\t\tdomain: options.domain,\n\t\tisError: true,\n\t\tcountry: options.country,\n\t\tclientType: options.clientType,\n\t\tauthTier: options.authTier,\n\t});\n\n\tlogError(options.error instanceof Error ? options.error : String(options.error), {\n\t\ttool: options.toolName,\n\t\tdomain: options.domain,\n\t\tdetails: options.args,\n\t\tseverity: options.severity ?? 'error',\n\t});\n}","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { CheckResult } from '../lib/scoring';\nimport { sanitizeOutputText } from '../lib/output-sanitize';\nimport { resolveImpactNarrative } from '../tools/explain-finding';\n\nexport interface McpContent {\n\ttype: 'text';\n\ttext: string;\n}\n\nexport function mcpError(message: string): McpContent {\n\treturn { type: 'text', text: `Error: ${message}` };\n}\n\nexport function mcpText(text: string): McpContent {\n\treturn { type: 'text', text };\n}\n\nexport function formatCheckResult(result: CheckResult): string {\n\tconst lines: string[] = [];\n\tlines.push(`## ${result.category.toUpperCase()} Check`);\n\tlines.push(`**Status:** ${result.passed ? '✅ Passed' : '❌ Failed'}`);\n\tlines.push(`**Score:** ${result.score}/100`);\n\tlines.push('');\n\n\tif (result.findings.length > 0) {\n\t\tlines.push('### Findings');\n\t\tfor (const finding of result.findings) {\n\t\t\tconst icon =\n\t\t\t\tfinding.severity === 'info'\n\t\t\t\t\t? 'ℹ️'\n\t\t\t\t\t: finding.severity === 'low'\n\t\t\t\t\t\t? '⚠️'\n\t\t\t\t\t\t: finding.severity === 'medium'\n\t\t\t\t\t\t\t? '🔶'\n\t\t\t\t\t\t\t: finding.severity === 'high'\n\t\t\t\t\t\t\t\t? '🔴'\n\t\t\t\t\t\t\t\t: '🚨';\n\t\t\t\t\tlines.push(`- ${icon} **[${finding.severity.toUpperCase()}]** ${sanitizeOutputText(finding.title, 120)}`);\n\t\t\t\t\tlines.push(` ${sanitizeOutputText(finding.detail)}`);\n\n\t\t\tconst verificationStatus =\n\t\t\t\tfinding.category === 'subdomain_takeover' && finding.metadata?.verificationStatus\n\t\t\t\t\t? String(finding.metadata.verificationStatus)\n\t\t\t\t\t: undefined;\n\t\t\tif (verificationStatus) {\n\t\t\t\tlines.push(` Takeover Verification: ${sanitizeOutputText(verificationStatus, 80)}`);\n\t\t\t}\n\n\t\t\tconst confidence = finding.metadata?.confidence ? String(finding.metadata.confidence) : undefined;\n\t\t\tif (confidence) {\n\t\t\t\tlines.push(` Confidence: ${sanitizeOutputText(confidence, 80)}`);\n\t\t\t}\n\n\t\t\tif (finding.severity !== 'info') {\n\t\t\t\tconst narrative = resolveImpactNarrative({\n\t\t\t\t\tcategory: finding.category,\n\t\t\t\t\tseverity: finding.severity,\n\t\t\t\t\ttitle: finding.title,\n\t\t\t\t\tdetail: finding.detail,\n\t\t\t\t});\n\t\t\t\tif (narrative.impact) {\n\t\t\t\t\tlines.push(` Potential Impact: ${narrative.impact}`);\n\t\t\t\t}\n\t\t\t\tif (narrative.adverseConsequences) {\n\t\t\t\t\tlines.push(` Adverse Consequences: ${narrative.adverseConsequences}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn lines.join('\\n');\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MCP Tool schema definitions for Blackveil DNS.\n * Contains all tool metadata (names, descriptions, input schemas)\n * used by the tools/list MCP method.\n *\n * Separated from dispatch logic in tools.ts for clarity.\n */\n\n/** MCP Tool definition */\nexport interface McpTool {\n\tname: string;\n\tdescription: string;\n\tinputSchema: {\n\t\ttype: 'object';\n\t\tproperties: Record<string, unknown>;\n\t\trequired: string[];\n\t};\n}\n\n/** Domain-only input schema shared by most tools */\nexport const DOMAIN_INPUT_SCHEMA = {\n\ttype: 'object' as const,\n\tproperties: {\n\t\tdomain: {\n\t\t\ttype: 'string',\n\t\t\tdescription: 'The domain name to check (e.g., example.com)',\n\t\t},\n\t},\n\trequired: ['domain'],\n};\n\n/** All MCP tool definitions */\nexport const TOOLS: McpTool[] = [\n\t{\n\t\tname: 'check_mx',\n\t\tdescription:\n\t\t\t'Validate mail exchange infrastructure and email routing configuration. Checks MX record presence, priority ordering, and provider detection to assess whether a domain can send and receive email reliably.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_spf',\n\t\tdescription:\n\t\t\t'Detect email spoofing risk from missing or misconfigured SPF records. Validates SPF TXT records for syntax, mechanism quality, lookup limits, policy strictness (-all vs ~all), and trust surface exposure from shared SaaS platforms.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_dmarc',\n\t\tdescription:\n\t\t\t'Assess domain protection against email impersonation and phishing. Validates DMARC policy enforcement level (none/quarantine/reject), reporting configuration, alignment modes, subdomain policy, and percentage coverage.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_dkim',\n\t\tdescription:\n\t\t\t'Verify email message integrity and sender authenticity via DKIM. Probes common selectors across major providers, validates key strength, and checks tag configuration.',\n\t\tinputSchema: {\n\t\t\ttype: 'object' as const,\n\t\t\tproperties: {\n\t\t\t\tdomain: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'The domain name to check (e.g., example.com)',\n\t\t\t\t},\n\t\t\t\tselector: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: \"Optional: specific DKIM selector to check (e.g., 'google', 'selector1'). If omitted, common selectors are probed.\",\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['domain'],\n\t\t},\n\t},\n\t{\n\t\tname: 'check_dnssec',\n\t\tdescription:\n\t\t\t'Check whether DNS responses are cryptographically signed and tamper-proof. Verifies DNSSEC validation, DNSKEY/DS record presence — protects against DNS cache poisoning and man-in-the-middle attacks.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_ssl',\n\t\tdescription:\n\t\t\t'Verify SSL/TLS certificate health and HTTPS configuration. Validates certificate availability, expiry, and configuration — essential for transport security and browser trust.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_mta_sts',\n\t\tdescription:\n\t\t\t'Check if email transport is protected against TLS downgrade attacks. Validates MTA-STS (RFC 8461) policy ensuring SMTP connections between mail servers are encrypted and cannot be intercepted.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_ns',\n\t\tdescription:\n\t\t\t'Evaluate DNS infrastructure resilience and redundancy. Analyzes nameserver delegation, provider diversity, and proper delegation to identify single points of failure.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_caa',\n\t\tdescription:\n\t\t\t'Check which Certificate Authorities are authorized to issue SSL certificates for a domain. Missing CAA records mean any CA can issue certificates, increasing unauthorized issuance risk.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_bimi',\n\t\tdescription:\n\t\t\t'Check if a domain has Brand Indicators for Message Identification (BIMI) configured for email client logo display. Validates BIMI TXT record, logo URL format, and VMC authority evidence.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_tlsrpt',\n\t\tdescription:\n\t\t\t'Check if SMTP TLS failure reporting is configured. Validates TLS-RPT (RFC 8460) records that enable receiving reports when email transport encryption fails — critical for monitoring MTA-STS enforcement.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_http_security',\n\t\tdescription:\n\t\t\t'Audit HTTP security headers protecting against XSS, clickjacking, and data leakage. Checks Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Permissions-Policy, Referrer-Policy, CORP, and COOP.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_dane',\n\t\tdescription:\n\t\t\t'Verify DNS-based certificate pinning (DANE/TLSA) for mail servers and HTTPS endpoints. Prevents certificate substitution attacks even if a CA is compromised.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_lookalikes',\n\t\tdescription:\n\t\t\t'Detect registered lookalike and typosquat domains that could be used for phishing or brand impersonation. Generates permutations (character swaps, homoglyphs, TLD variants) and checks for active infrastructure. Standalone — not in scan_domain due to query volume.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'scan_domain',\n\t\tdescription:\n\t\t\t'Run a comprehensive DNS and email security audit on any domain. Executes 14 checks in parallel (SPF, DMARC, DKIM, DNSSEC, SSL, MTA-STS, NS, CAA, MX, BIMI, TLS-RPT, Subdomain Takeover, HTTP Security, DANE) and returns an overall security score (0-100), letter grade (A+ to F), maturity stage, and prioritized findings with remediation guidance. Start here for any domain security question.',\n\t\tinputSchema: {\n\t\t\ttype: 'object' as const,\n\t\t\tproperties: {\n\t\t\t\tdomain: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'The domain name to check (e.g., example.com)',\n\t\t\t\t},\n\t\t\t\tprofile: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['auto', 'mail_enabled', 'enterprise_mail', 'non_mail', 'web_only', 'minimal'],\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t'Scoring profile to apply. \"auto\" (default) detects the profile from scan results. Explicit values override detection and change scoring weights.',\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['domain'],\n\t\t},\n\t},\n\t{\n\t\tname: 'compare_baseline',\n\t\tdescription:\n\t\t\t'Enforce security policy compliance by comparing a domain against minimum acceptable standards. Returns specific violations below baseline requirements. Designed for MSPs, security teams, and CI/CD pipelines enforcing organization-level DNS security standards.',\n\t\tinputSchema: {\n\t\t\ttype: 'object' as const,\n\t\t\tproperties: {\n\t\t\t\tdomain: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'The domain to scan and compare.',\n\t\t\t\t},\n\t\t\t\tbaseline: {\n\t\t\t\t\ttype: 'object',\n\t\t\t\t\tdescription: 'Policy baseline. Keys are category names or \"grade\"/\"score\". Values are minimums.',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tgrade: {\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdescription: 'Minimum acceptable grade (e.g., \"B+\"). Violation if scan grade is worse.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tscore: {\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\tdescription: 'Minimum acceptable overall score (0-100).',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_dmarc_enforce: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require DMARC p=quarantine or p=reject (not p=none).',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_spf: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require a valid SPF record.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_dkim: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require at least one DKIM key.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_dnssec: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require DNSSEC validation.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_mta_sts: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require MTA-STS policy.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trequire_caa: {\n\t\t\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\t\t\tdescription: 'Require CAA records.',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmax_critical_findings: {\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\tdescription: 'Maximum allowed critical-severity findings (default: 0).',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmax_high_findings: {\n\t\t\t\t\t\t\ttype: 'number',\n\t\t\t\t\t\t\tdescription: 'Maximum allowed high-severity findings.',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['domain', 'baseline'],\n\t\t},\n\t},\n\t{\n\t\tname: 'check_shadow_domains',\n\t\tdescription:\n\t\t\t'Discover alternate-TLD variants of a domain (e.g., .org, .net, .co) with active DNS/mail infrastructure and assess email spoofing risk. Identifies shadow domains lacking email authentication that attackers could use for impersonation. Standalone — not in scan_domain due to query volume.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_txt_hygiene',\n\t\tdescription:\n\t\t\t'Audit TXT records for stale service verifications, unexpected platform registrations, excessive accumulation, and cross-domain trust delegations. Maps the organization\\'s verified SaaS platform exposure from public DNS — useful for shadow IT discovery.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_mx_reputation',\n\t\tdescription:\n\t\t\t'Check mail server reputation and deliverability risk. Resolves MX IPs, checks against major blocklists (Spamhaus, SpamCop, Barracuda), and validates reverse DNS (PTR/FCrDNS) consistency.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_srv',\n\t\tdescription:\n\t\t\t'Map the DNS-visible service footprint by probing SRV records. Discovers email, calendar, messaging, and other service advertisements, and flags insecure protocol advertisements.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'check_zone_hygiene',\n\t\tdescription:\n\t\t\t'Audit DNS zone consistency and detect exposed internal infrastructure. Checks SOA serial propagation and probes sensitive subdomains (vpn, admin, staging, corp) for unintended public DNS resolution.',\n\t\tinputSchema: DOMAIN_INPUT_SCHEMA,\n\t},\n\t{\n\t\tname: 'explain_finding',\n\t\tdescription:\n\t\t\t'Get a plain-language explanation of any DNS security finding, including real-world impact, adverse consequences if unresolved, and step-by-step remediation guidance with RFC references.',\n\t\tinputSchema: {\n\t\t\ttype: 'object' as const,\n\t\t\tproperties: {\n\t\t\t\tcheckType: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: \"The check type (e.g. 'SPF', 'DMARC', 'DKIM', 'DNSSEC', 'SSL', 'MTA_STS')\",\n\t\t\t\t},\n\t\t\t\tstatus: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tenum: ['pass', 'fail', 'warning', 'critical', 'high', 'medium', 'low', 'info'],\n\t\t\t\t\tdescription: 'The check status or finding severity (e.g., pass, fail, warning, critical, high, medium, low, info)',\n\t\t\t\t},\n\t\t\t\tdetails: {\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'Optional details from the check result',\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['checkType', 'status'],\n\t\t},\n\t},\n];\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport type { CheckResult } from '../lib/scoring';\nimport type { QueryDnsOptions, SecondaryDohConfig } from '../lib/dns-types';\nimport { runWithCache } from '../lib/cache';\nimport { sanitizeErrorMessage } from '../lib/json-rpc';\nimport { checkSpf } from '../tools/check-spf';\nimport { checkDmarc } from '../tools/check-dmarc';\nimport { checkDkim } from '../tools/check-dkim';\nimport { checkDnssec } from '../tools/check-dnssec';\nimport { checkSsl } from '../tools/check-ssl';\nimport { checkMtaSts } from '../tools/check-mta-sts';\nimport { checkNs } from '../tools/check-ns';\nimport { checkCaa } from '../tools/check-caa';\nimport { checkBimi } from '../tools/check-bimi';\nimport { checkTlsrpt } from '../tools/check-tlsrpt';\nimport { checkLookalikes } from '../tools/check-lookalikes';\nimport { checkShadowDomains } from '../tools/check-shadow-domains';\nimport { checkTxtHygiene } from '../tools/check-txt-hygiene';\nimport { checkHttpSecurity } from '../tools/check-http-security';\nimport { checkDane } from '../tools/check-dane';\nimport { checkMxReputation } from '../tools/check-mx-reputation';\nimport { checkSrv } from '../tools/check-srv';\nimport { checkZoneHygiene } from '../tools/check-zone-hygiene';\nimport { scanDomain, formatScanReport, buildStructuredScanResult } from '../tools/scan-domain';\nimport { explainFinding, formatExplanation } from '../tools/explain-finding';\nimport { compareBaseline, formatBaselineResult } from '../tools/compare-baseline';\nimport type { PolicyBaseline } from '../tools/compare-baseline';\nimport type { AnalyticsClient } from '../lib/analytics';\nimport { extractAndValidateDomain, extractBaseline, extractDkimSelector, extractExplainFindingArgs, extractScanProfile, normalizeToolName } from './tool-args';\nimport { logToolFailure, logToolSuccess } from './tool-execution';\nimport { formatCheckResult, mcpError, mcpText } from './tool-formatters';\nimport type { McpContent } from './tool-formatters';\nimport { TOOLS } from './tool-schemas';\nimport type { McpTool } from './tool-schemas';\n\n/** MCP tools/call result */\ninterface McpToolResult {\n\tcontent: McpContent[];\n\tisError?: boolean;\n}\n\n/**\n * Handle the MCP tools/list method.\n * Returns all available tool definitions.\n */\nexport function handleToolsList(): { tools: McpTool[] } {\n\treturn { tools: TOOLS };\n}\n\n/** Wrapper for dynamic check_mx import (required for test mock isolation) */\ninterface ToolRuntimeOptions {\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string[];\n\tproviderSignaturesSha256?: string;\n\tanalytics?: AnalyticsClient;\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tscoringConfig?: import('../lib/scoring-config').ScoringConfig;\n\t/** When provided, receives the raw CheckResult before MCP text formatting. Used by internal structured response mode. */\n\tresultCapture?: (result: CheckResult) => void;\n\t/** Override cache TTL in seconds for scan results. Threaded to scanDomain. */\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH resolver config (bv-dns). Threaded to dnsOptions for individual checks. */\n\tsecondaryDoh?: SecondaryDohConfig;\n\tcountry?: string;\n\tclientType?: string;\n\tauthTier?: string;\n}\n\n/** Build QueryDnsOptions for individual check calls from runtime options. */\nfunction buildDnsOptions(runtimeOptions?: ToolRuntimeOptions): QueryDnsOptions | undefined {\n\tif (!runtimeOptions?.secondaryDoh) return undefined;\n\treturn { secondaryDoh: runtimeOptions.secondaryDoh };\n}\n\nasync function dynamicCheckMx(domain: string, runtimeOptions?: ToolRuntimeOptions): Promise<CheckResult> {\n\tconst { checkMx } = await import('../tools/check-mx');\n\treturn checkMx(domain, {\n\t\tproviderSignaturesUrl: runtimeOptions?.providerSignaturesUrl,\n\t\tproviderSignaturesAllowedHosts: runtimeOptions?.providerSignaturesAllowedHosts,\n\t\tproviderSignaturesSha256: runtimeOptions?.providerSignaturesSha256,\n\t}, buildDnsOptions(runtimeOptions));\n}\n\n/**\n * Registry mapping tool names to their cache key and execution function.\n * Replaces repetitive switch cases for individual DNS check tools.\n */\nconst TOOL_REGISTRY: Record<\n\tstring,\n\t{\n\t\tcacheKey: (args: Record<string, unknown>) => string;\n\t\texecute: (domain: string, args: Record<string, unknown>, runtimeOptions?: ToolRuntimeOptions) => Promise<CheckResult>;\n\t\tcacheTtlSeconds?: number;\n\t}\n> = {\n\tcheck_mx: { cacheKey: () => 'mx', execute: (d, _args, ro) => dynamicCheckMx(d, ro) },\n\tcheck_spf: { cacheKey: () => 'spf', execute: (d, _args, ro) => checkSpf(d, buildDnsOptions(ro)) },\n\tcheck_dmarc: { cacheKey: () => 'dmarc', execute: (d, _args, ro) => checkDmarc(d, buildDnsOptions(ro)) },\n\tcheck_dkim: {\n\t\tcacheKey: (args) => {\n\t\t\tconst sel = extractDkimSelector(args);\n\t\t\treturn sel ? `dkim:${sel}` : 'dkim';\n\t\t},\n\t\texecute: (d, args, ro) => checkDkim(d, extractDkimSelector(args), buildDnsOptions(ro)),\n\t},\n\tcheck_dnssec: { cacheKey: () => 'dnssec', execute: (d, _args, ro) => checkDnssec(d, buildDnsOptions(ro)) },\n\tcheck_ssl: { cacheKey: () => 'ssl', execute: (d) => checkSsl(d) },\n\tcheck_mta_sts: { cacheKey: () => 'mta_sts', execute: (d, _args, ro) => checkMtaSts(d, buildDnsOptions(ro)) },\n\tcheck_ns: { cacheKey: () => 'ns', execute: (d, _args, ro) => checkNs(d, buildDnsOptions(ro)) },\n\tcheck_caa: { cacheKey: () => 'caa', execute: (d, _args, ro) => checkCaa(d, buildDnsOptions(ro)) },\n\tcheck_bimi: { cacheKey: () => 'bimi', execute: (d, _args, ro) => checkBimi(d, buildDnsOptions(ro)) },\n\tcheck_tlsrpt: { cacheKey: () => 'tlsrpt', execute: (d, _args, ro) => checkTlsrpt(d, buildDnsOptions(ro)) },\n\tcheck_lookalikes: { cacheKey: () => 'lookalikes', execute: (d) => checkLookalikes(d), cacheTtlSeconds: 3600 },\n\tcheck_shadow_domains: { cacheKey: () => 'shadow_domains', execute: (d, _args, ro) => checkShadowDomains(d, buildDnsOptions(ro)), cacheTtlSeconds: 3600 },\n\tcheck_txt_hygiene: { cacheKey: () => 'txt_hygiene', execute: (d, _args, ro) => checkTxtHygiene(d, buildDnsOptions(ro)) },\n\tcheck_http_security: { cacheKey: () => 'http_security', execute: (d) => checkHttpSecurity(d) },\n\tcheck_dane: { cacheKey: () => 'dane', execute: (d, _args, ro) => checkDane(d, buildDnsOptions(ro)) },\n\tcheck_mx_reputation: { cacheKey: () => 'mx_reputation', execute: (d, _args, ro) => checkMxReputation(d, buildDnsOptions(ro)), cacheTtlSeconds: 3600 },\n\tcheck_srv: { cacheKey: () => 'srv', execute: (d, _args, ro) => checkSrv(d, buildDnsOptions(ro)) },\n\tcheck_zone_hygiene: { cacheKey: () => 'zone_hygiene', execute: (d, _args, ro) => checkZoneHygiene(d, buildDnsOptions(ro)) },\n};\n\nfunction buildToolErrorResult(message: string): McpToolResult {\n\treturn { content: [mcpError(message)], isError: true };\n}\n\nfunction handleExplainFindingValidationError(\n\targs: Record<string, unknown>,\n\tdurationMs: number,\n\truntimeOptions?: ToolRuntimeOptions,\n): McpToolResult {\n\tconst error = new Error('Missing required parameters: checkType and status');\n\tlogToolFailure({\n\t\ttoolName: 'explain_finding',\n\t\tdurationMs,\n\t\tanalytics: runtimeOptions?.analytics,\n\t\terror,\n\t\targs,\n\t\tseverity: 'warn',\n\t\tcountry: runtimeOptions?.country,\n\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\tauthTier: runtimeOptions?.authTier,\n\t});\n\treturn buildToolErrorResult(error.message);\n}\n\n/**\n * Handle the MCP tools/call method.\n * Dispatches to the appropriate tool function based on the tool name.\n *\n * @param params - Tool call parameters (name and arguments)\n * @param scanCacheKV - Optional KV namespace for scan result caching\n */\n/** Maximum wall-clock time for any single tool call (ms). */\nconst TOOL_CALL_TIMEOUT_MS = 28_000;\n\nexport async function handleToolsCall(\n\tparams: {\n\t\tname: string;\n\t\targuments?: Record<string, unknown>;\n\t},\n\tscanCacheKV?: KVNamespace,\n\truntimeOptions?: ToolRuntimeOptions,\n): Promise<McpToolResult> {\n\tconst name = normalizeToolName(params.name);\n\tconst args = params.arguments ?? {};\n\tconst startTime = Date.now();\n\tlet domain: string | undefined;\n\tlet logResult: string | undefined;\n\tlet logDetails: unknown;\n\ttry {\n\t\t// Extract and validate domain for tools that need it (all except explain_finding)\n\t\tif (name !== 'explain_finding') {\n\t\t\tdomain = extractAndValidateDomain(args);\n\t\t}\n\t\t// `validDomain` is guaranteed to be a string for all branches that use it\n\t\tconst validDomain: string = domain ?? '';\n\n\t\tconst executeDispatch = async (): Promise<McpToolResult> => {\n\t\t\t// Dispatch to the appropriate tool — check registry first, then special cases\n\t\t\tconst registeredTool = TOOL_REGISTRY[name];\n\t\t\tif (registeredTool) {\n\t\t\t\tconst checkName = registeredTool.cacheKey(args);\n\t\t\t\tconst cacheKey = `cache:${validDomain}:check:${checkName}`;\n\t\t\t\tconst result = await runWithCache(cacheKey, () => registeredTool.execute(validDomain, args, runtimeOptions), scanCacheKV, registeredTool.cacheTtlSeconds);\n\t\t\t\truntimeOptions?.resultCapture?.(result);\n\t\t\t\tlogResult = result.passed ? 'pass' : 'fail';\n\t\t\t\tlogDetails = result;\n\t\t\t\tlogToolSuccess({\n\t\t\t\t\ttoolName: name,\n\t\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\t\tdomain,\n\t\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\t\tstatus: result.passed ? 'pass' : 'fail',\n\t\t\t\t\tlogResult,\n\t\t\t\t\tlogDetails,\n\t\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t\t});\n\t\t\t\treturn { content: [mcpText(formatCheckResult(result))] };\n\t\t\t}\n\n\t\t\tswitch (name) {\n\t\t\t\tcase 'scan_domain': {\n\t\t\t\t\tconst profile = extractScanProfile(args);\n\t\t\t\t\tconst scanOptions = profile ? { ...runtimeOptions, profile } : runtimeOptions;\n\t\t\t\t\tconst result = await scanDomain(validDomain, scanCacheKV, scanOptions);\n\t\t\t\t\tlogResult = result.score.grade;\n\t\t\t\t\tlogDetails = result;\n\t\t\t\t\tlogToolSuccess({\n\t\t\t\t\t\ttoolName: name,\n\t\t\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\t\t\tdomain,\n\t\t\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\t\t\tstatus: result.score.overall >= 50 ? 'pass' : 'fail',\n\t\t\t\t\t\tlogResult,\n\t\t\t\t\t\tlogDetails,\n\t\t\t\t\t\tseverity: 'info',\n\t\t\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t\t\t});\n\t\t\t\t\tconst structured = buildStructuredScanResult(result);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\tmcpText(formatScanReport(result)),\n\t\t\t\t\t\t\tmcpText(`<!-- STRUCTURED_RESULT\\n${JSON.stringify(structured)}\\nSTRUCTURED_RESULT -->`),\n\t\t\t\t\t\t],\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tcase 'compare_baseline': {\n\t\t\t\t\tconst baseline = extractBaseline(args) as PolicyBaseline;\n\t\t\t\t\tconst scan = await scanDomain(validDomain, scanCacheKV, runtimeOptions);\n\t\t\t\t\tconst result = compareBaseline(scan, baseline);\n\t\t\t\t\tlogResult = result.passed ? 'pass' : 'fail';\n\t\t\t\t\tlogDetails = result;\n\t\t\t\t\tlogToolSuccess({\n\t\t\t\t\t\ttoolName: name,\n\t\t\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\t\t\tdomain,\n\t\t\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\t\t\tstatus: result.passed ? 'pass' : 'fail',\n\t\t\t\t\t\tlogResult,\n\t\t\t\t\t\tlogDetails,\n\t\t\t\t\t\tseverity: 'info',\n\t\t\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t\t\t});\n\t\t\t\t\treturn { content: [mcpText(formatBaselineResult(result))] };\n\t\t\t\t}\n\t\t\t\tcase 'explain_finding': {\n\t\t\t\t\tlet explainArgs: ReturnType<typeof extractExplainFindingArgs>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\texplainArgs = extractExplainFindingArgs(args);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn handleExplainFindingValidationError(args, Date.now() - startTime, runtimeOptions);\n\t\t\t\t\t}\n\t\t\t\t\tconst { checkType, status, details } = explainArgs;\n\t\t\t\t\tconst result = explainFinding(checkType, status, details);\n\t\t\t\t\tlogToolSuccess({\n\t\t\t\t\t\ttoolName: name,\n\t\t\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\t\t\tstatus: 'pass',\n\t\t\t\t\t\tlogResult: status,\n\t\t\t\t\t\tlogDetails: { checkType, details },\n\t\t\t\t\t\tseverity: 'info',\n\t\t\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t\t\t});\n\t\t\t\t\treturn { content: [mcpText(formatExplanation(result))] };\n\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\tlogToolFailure({\n\t\t\t\t\t\ttoolName: name,\n\t\t\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\t\t\tdomain,\n\t\t\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\t\t\terror: `Unknown tool: ${name}`,\n\t\t\t\t\t\targs,\n\t\t\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t\t\t});\n\t\t\t\t\treturn buildToolErrorResult(`Unknown tool: ${name}`);\n\t\t\t}\n\t\t};\n\n\t\treturn await Promise.race([\n\t\t\texecuteDispatch(),\n\t\t\tnew Promise<never>((_, reject) => setTimeout(() => reject(new Error('__tool_timeout__')), TOOL_CALL_TIMEOUT_MS)),\n\t\t]);\n\t} catch (err) {\n\t\tif (err instanceof Error && err.message === '__tool_timeout__') {\n\t\t\tlogToolFailure({\n\t\t\t\ttoolName: name,\n\t\t\t\tdurationMs: Date.now() - startTime,\n\t\t\t\tdomain,\n\t\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\t\terror: 'Tool call timed out',\n\t\t\t\targs,\n\t\t\t\tcountry: runtimeOptions?.country,\n\t\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t\t});\n\t\t\treturn {\n\t\t\t\tcontent: [mcpError(`${name} timed out after ${TOOL_CALL_TIMEOUT_MS / 1000}s. Try a simpler check or retry — cached partial results make retries faster.`)],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t\tconst message = sanitizeErrorMessage(err, 'An unexpected error occurred');\n\t\tlogToolFailure({\n\t\t\ttoolName: name,\n\t\t\tdurationMs: Date.now() - startTime,\n\t\t\tdomain,\n\t\t\tanalytics: runtimeOptions?.analytics,\n\t\t\terror: err,\n\t\t\targs,\n\t\t\tcountry: runtimeOptions?.country,\n\t\t\tclientType: runtimeOptions?.clientType as import('../lib/client-detection').McpClientType,\n\t\t\tauthTier: runtimeOptions?.authTier,\n\t\t});\n\t\treturn buildToolErrorResult(message);\n\t}\n}\n","/**\n * MCP Resources handler for Blackveil DNS.\n * Exposes static documentation resources about DNS/email security checks,\n * scoring methodology, and supported DNS record types.\n *\n * Handles JSON-RPC methods: resources/list, resources/read\n * Compatible with Cloudflare Workers runtime (no Node.js APIs).\n */\n\n/** MCP Resource descriptor */\ninterface McpResource {\n\turi: string;\n\tname: string;\n\tdescription: string;\n\tmimeType: string;\n}\n\n/** MCP Resource content */\ninterface McpResourceContent {\n\turi: string;\n\tmimeType: string;\n\ttext: string;\n}\n\n/** Static resource definitions */\nconst RESOURCES: McpResource[] = [\n {\n uri: 'dns-security://guides/security-checks',\n name: 'DNS Security Checks Guide',\n description:\n\t\t 'Overview of all DNS/email security checks performed by Blackveil DNS, including SPF, DMARC, DKIM, DNSSEC, SSL/TLS, MTA-STS, NS, CAA, MX, and Subdomain Takeover.',\n mimeType: 'text/markdown',\n },\n {\n uri: 'dns-security://guides/scoring',\n name: 'Scoring Methodology',\n description: 'How DNS/email security scores and grades are calculated, including category weights and severity penalties.',\n mimeType: 'text/markdown',\n },\n\t{\n\t\turi: 'dns-security://guides/record-types',\n\t\tname: 'Supported DNS Record Types',\n\t\tdescription: 'List of DNS record types queried by this server and their purpose in security analysis.',\n\t\tmimeType: 'text/markdown',\n\t},\n\t{\n\t\turi: 'dns-security://guides/agent-workflows',\n\t\tname: 'Agent Workflow Guide',\n\t\tdescription: 'Recommended tool usage patterns and decision trees for common DNS security tasks.',\n\t\tmimeType: 'text/markdown',\n\t},\n];\n\n/** Resource content keyed by URI */\nconst RESOURCE_CONTENT: Record<string, string> = {\n\t'dns-security://guides/security-checks': `# DNS Security Checks\n\nThe Blackveil DNS scanner evaluates **57+ checks** grouped into 20 categories.\n\nThis MCP server exposes 22 tools that cover the core checks in each category and returns findings compatible with Blackveil DNS scoring.\n\n## Coverage by Tier\n\n| Category | Total Scanner Checks | Free Tier (MCP/Core) | Premium Platform |\n|---|---:|---|---|\n| SPF | 8 | Core SPF policy and syntax checks | Advanced include-chain and sender-path analytics |\n| DMARC | 10 | Core policy, pct, reporting checks, URI validation, alignment modes | Alignment depth, subdomain inheritance, reporting quality analytics |\n| DKIM | 9 | Selector discovery, RSA key strength validation, v= tag checks | Selector entropy, rotation heuristics, key-age and drift analytics |\n| DNSSEC | 6 | AD validation and signed-zone baseline | Chain-of-trust and rollover posture analytics |\n| SSL/TLS | 8 | Certificate availability and baseline validity checks | Protocol/cipher depth, PKI posture, renewal-risk analytics |\n| MTA-STS | 5 | TXT policy presence and basic policy retrieval checks | Policy hardening and reporting-depth analytics |\n| NS | 4 | Delegation, diversity, and resiliency baseline checks | Infrastructure concentration and availability analytics |\n| CAA | 4 | CAA presence and issuer-allowlist baseline checks | Issuance surface modeling and mis-issuance risk analytics |\n| MX | 4 | MX presence, routing quality, and outbound provider inference | Mail routing posture and provider analytics |\n| Subdomain Takeover | 2 | Dangling CNAME detection across known subdomains | Expanded asset discovery and takeover surface analytics |\n| HTTP Security | 7 | CSP, X-Frame-Options, COOP, CORP, Permissions-Policy checks | Header depth analytics |\n| DANE | 3 | TLSA record validation for MX and HTTPS | Certificate pinning posture |\n| Shadow Domains | 1 | Alternate-TLD email spoofing risk detection | Extended TLD coverage |\n| TXT Hygiene | 1 | Stale verifications, SaaS exposure mapping | Shadow IT discovery |\n| MX Reputation | 1 | DNSBL and PTR/FCrDNS validation | Deliverability analytics |\n| SRV | 1 | Service footprint discovery via SRV records | Protocol exposure analytics |\n| Zone Hygiene | 1 | SOA consistency and sensitive subdomain detection | Infrastructure exposure |\n| BIMI | 1 | Record presence, logo URL, VMC | Brand indicator compliance |\n| TLS-RPT | 1 | Record presence, reporting URI | Reporting depth |\n| Lookalikes | 1 | Typosquat detection, DNS + MX probing | Expanded permutation strategies |\n\n> Total checks: **57+** across 20 categories.\n\n## Categories and Tool Mapping\n\n## SPF (Sender Policy Framework)\nTool: \\`check_spf\\` \nValidates SPF TXT records to reduce spoofing risk. Includes presence, mechanism quality, lookup pressure, and policy strictness checks.\n\n## DMARC (Domain-based Message Authentication)\nTool: \\`check_dmarc\\` \nChecks \\`_dmarc\\` policy posture including enforcement mode, reporting URIs (rua=/ruf=), alignment modes (adkim=/aspf=), subdomain policy, and third-party aggregator detection. Validates URI format and identifies known aggregator services.\n\n## DKIM (DomainKeys Identified Mail)\nTool: \\`check_dkim\\` \nProbes common selectors under \\`_domainkey\\` and validates key records. Includes RSA key strength validation (512/1024/2048/4096-bit detection via base64 length heuristic), v=DKIM1 tag validation, and comprehensive selector discovery across major providers.\n\n## DNSSEC (DNS Security Extensions)\nTool: \\`check_dnssec\\` \nVerifies DNSSEC validation state and signed-response posture for the queried domain.\n\n## SSL/TLS Certificate\nTool: \\`check_ssl\\` \nChecks HTTPS certificate presence and baseline certificate health.\n\n## MTA-STS (Mail Transfer Agent Strict Transport Security)\nTool: \\`check_mta_sts\\` \nValidates \\`_mta-sts\\` policy publication and retrieval for secure SMTP transport.\n\n## NS (Name Server) Configuration\nTool: \\`check_ns\\` \nAnalyzes delegation resilience and provider diversity indicators.\n\n## CAA (Certificate Authority Authorization)\nTool: \\`check_caa\\`\nChecks CA authorization posture and issuance restriction baseline.\n\n## MX (Mail Exchange)\nTool: \\`check_mx\\`\nValidates presence and quality of MX records for a domain, including outbound email provider detection.\n\n## Subdomain Takeover Detection\nTool: internal to \\`scan_domain\\` (not directly callable)\nScans known subdomains for dangling CNAME records pointing to unresolved third-party services.\n\n## HTTP Security Headers\nTool: \\`check_http_security\\`\nAudits HTTP response headers for XSS, clickjacking, and data leakage protections.\n\n## DANE (DNS-Based Authentication of Named Entities)\nTool: \\`check_dane\\`\nVerifies TLSA records for certificate pinning on MX and HTTPS endpoints.\n\n## Shadow Domains\nTool: \\`check_shadow_domains\\`\nDiscovers alternate-TLD variants with active infrastructure and assesses email spoofing risk.\n\n## TXT Record Hygiene\nTool: \\`check_txt_hygiene\\`\nAudits TXT records for stale service verifications, SaaS exposure, and cross-domain trust delegations.\n\n## MX Reputation\nTool: \\`check_mx_reputation\\`\nChecks mail server reputation via DNSBL lookups and validates reverse DNS consistency.\n\n## SRV Service Discovery\nTool: \\`check_srv\\`\nProbes SRV records to map the DNS-visible service footprint.\n\n## Zone Hygiene\nTool: \\`check_zone_hygiene\\`\nAudits SOA serial propagation and detects sensitive subdomains exposed in public DNS.\n\n## Composite Tools\n\n- \\`scan_domain\\`: Runs 14 checks in parallel and produces an overall score + grade.\n- \\`explain_finding\\`: Provides plain-language context and remediation guidance for individual findings.\n- \\`compare_baseline\\`: Compares a domain against minimum acceptable security standards.\n`,\n\n\t'dns-security://guides/scoring': `# Scoring Methodology\n\nThis server uses scanner-aligned scoring for the overlapping controls currently implemented by MCP tools.\n\n## Importance Weights (Scanner-Aligned)\nOverall score is based on importance points per category, not a flat average:\n\n| Category | Importance Points |\n|---|---:|\n| SPF | 19 |\n| DMARC | 22 |\n| DKIM | 10 |\n| DNSSEC | 3 |\n| SSL/TLS | 8 |\n| MTA-STS | 3 |\n| NS | 3 |\n| CAA | 2 |\n| Subdomain Takeover | 2 |\n| MX | 0 (informational) |\n\nAdditional bonus: up to **+5** points for strong combined email-auth posture.\n\n## Per-Category Penalties\nEach category starts at 100 and penalties are applied per finding severity:\n\n| Severity | Penalty |\n|----------|---------|\n| Critical | -40 pts |\n| High | -25 pts |\n| Medium | -15 pts |\n| Low | -5 pts |\n| Info | 0 pts |\n\n## Missing-Control Handling\nFor categories where a required control is missing (for example, \"No DMARC record found\"), effective contribution can be treated as zeroed in overall scoring.\n\n## Critical-Finding Adjustment\nIf any **verified**-confidence **critical** finding exists in the scan, an additional **-15 overall points** adjustment is applied.\nThis ensures verified critical risks materially impact final grades even when they occur in low-importance categories.\n\n## Grading Scale\nThe overall weighted score maps to a letter grade:\n- **A+**: 90+\n- **A**: 85-89\n- **B+**: 80-84\n- **B**: 75-79\n- **C+**: 70-74\n- **C**: 65-69\n- **D+**: 60-64\n- **D**: 55-59\n- **E**: 50-54\n- **F**: <50\n`,\n\n\t'dns-security://guides/agent-workflows': `# Agent Workflow Guide\n\nRecommended tool usage patterns for common DNS security tasks.\n\n## Decision Tree: What Tool Should I Use?\n\n| User Intent | Recommended Tools | Notes |\n|---|---|---|\n| \"Is my domain secure?\" / \"Audit my domain\" | \\`scan_domain\\` | Start here — runs 14 checks in parallel, returns score + grade + prioritized findings |\n| \"Can someone spoof my email?\" / \"Email spoofing risk\" | \\`check_spf\\` → \\`check_dmarc\\` → \\`check_dkim\\` | The email authentication triad — check all three for a complete picture |\n| \"Are there phishing lookalikes?\" / \"Brand impersonation risk\" | \\`check_lookalikes\\` + \\`check_shadow_domains\\` | Standalone checks — not in scan_domain due to query volume |\n| \"Is my DNS infrastructure solid?\" | \\`check_ns\\` + \\`check_zone_hygiene\\` + \\`check_dnssec\\` | Infrastructure resilience + zone consistency + tamper protection |\n| \"Are my web security headers OK?\" | \\`check_http_security\\` + \\`check_ssl\\` + \\`check_caa\\` | Web security posture: headers + certificate + CA authorization |\n| \"Is our email transport encrypted?\" | \\`check_mta_sts\\` + \\`check_tlsrpt\\` + \\`check_dane\\` | TLS enforcement + failure reporting + certificate pinning |\n| \"Do we meet compliance requirements?\" | \\`compare_baseline\\` | Pass policy minimums as baseline — returns specific violations |\n| \"What does this finding mean?\" | \\`explain_finding\\` | Plain-language explanation with remediation steps |\n| \"What services are published in DNS?\" | \\`check_srv\\` + \\`check_txt_hygiene\\` | SRV records + TXT verification records map service footprint |\n| \"Are our mail servers blacklisted?\" | \\`check_mx_reputation\\` | DNSBL checks + reverse DNS validation |\n\n## Common Workflows\n\n### Full Security Audit\n1. \\`scan_domain\\` — get overall score and all findings\n2. \\`explain_finding\\` — for each critical/high finding, get remediation guidance\n3. Summarize with prioritized action plan\n\n### Email Authentication Hardening\n1. \\`check_spf\\` — validate SPF record and trust surface\n2. \\`check_dmarc\\` — check enforcement level (none → quarantine → reject)\n3. \\`check_dkim\\` — verify key presence and strength\n4. \\`check_mta_sts\\` — ensure transport encryption\n5. \\`explain_finding\\` — remediation for any failures\n\n### Brand Protection Assessment\n1. \\`check_lookalikes\\` — find registered typosquat domains\n2. \\`check_shadow_domains\\` — find alternate-TLD variants lacking email auth\n3. \\`scan_domain\\` — baseline security of the primary domain\n\n### CI/CD Policy Enforcement\nUse \\`compare_baseline\\` with policy requirements:\n\\`\\`\\`json\n{\n \"grade\": \"B\",\n \"require_spf\": true,\n \"require_dmarc_enforce\": true,\n \"require_dkim\": true,\n \"max_critical_findings\": 0\n}\n\\`\\`\\`\nReturns pass/fail with specific violations — ideal for automated gates.\n\n## Tips\n- \\`scan_domain\\` caches results for 5 minutes — subsequent individual checks on the same domain return cached data\n- \\`check_lookalikes\\` and \\`check_shadow_domains\\` are rate-limited (20/day unauthenticated) — use judiciously\n- All checks are passive and read-only — safe to run against any domain\n- Use the \\`profile\\` parameter on \\`scan_domain\\` for non-mail domains (web_only, non_mail) to get more relevant scoring\n`,\n\n\t'dns-security://guides/record-types': `# Supported DNS Record Types\n\nThis server queries the following DNS record types via Cloudflare DNS-over-HTTPS:\n\n| Type | Code | Purpose |\n|--------|------|---------|\n| A | 1 | IPv4 address records |\n| AAAA | 28 | IPv6 address records |\n| CNAME | 5 | Canonical name aliases |\n| MX | 15 | Mail exchange servers |\n| TXT | 16 | Text records (SPF, DMARC, DKIM, MTA-STS) |\n| NS | 2 | Name server delegation |\n| SOA | 6 | Start of authority |\n| CAA | 257 | Certificate authority authorization |\n| TLSA | 52 | TLS authentication (DANE) |\n| DNSKEY | 48 | DNSSEC public keys |\n| DS | 43 | DNSSEC delegation signer |\n| RRSIG | 46 | DNSSEC resource record signatures |\n\nAll queries use the JSON wire format (\\`application/dns-json\\`) via \\`https://cloudflare-dns.com/dns-query\\`.\n`,\n};\n\n/**\n * Handle the MCP resources/list method.\n * Returns all available resource descriptors.\n */\nexport function handleResourcesList(): { resources: McpResource[] } {\n\treturn { resources: RESOURCES };\n}\n\n/**\n * Handle the MCP resources/read method.\n * Returns the content of a specific resource by URI.\n */\nexport function handleResourcesRead(params: Record<string, unknown>): {\n\tcontents: McpResourceContent[];\n} {\n\tconst uri = params.uri;\n\tif (typeof uri !== 'string') {\n\t\tthrow new Error('Missing required parameter: uri');\n\t}\n\tconst content = RESOURCE_CONTENT[uri];\n\tif (!content) {\n\t\tthrow new Error(`Resource not found: ${uri}`);\n\t}\n\tconst resource = RESOURCES.find((r) => r.uri === uri);\n\treturn {\n\t\tcontents: [\n\t\t\t{\n\t\t\t\turi,\n\t\t\t\tmimeType: resource?.mimeType ?? 'text/plain',\n\t\t\t\ttext: content,\n\t\t\t},\n\t\t],\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * MCP Prompts handler for Blackveil DNS.\n * Provides pre-built workflows agents can discover and offer to users\n * via prompts/list + prompts/get.\n */\n\n/** MCP Prompt argument definition */\ninterface McpPromptArgument {\n\tname: string;\n\tdescription: string;\n\trequired: boolean;\n}\n\n/** MCP Prompt definition */\ninterface McpPrompt {\n\tname: string;\n\tdescription: string;\n\targuments: McpPromptArgument[];\n}\n\n/** MCP Prompt message */\ninterface McpPromptMessage {\n\trole: 'user' | 'assistant';\n\tcontent: {\n\t\ttype: 'text';\n\t\ttext: string;\n\t};\n}\n\n/** All MCP prompt definitions */\nconst PROMPTS: McpPrompt[] = [\n\t{\n\t\tname: 'full-security-audit',\n\t\tdescription: 'Run a comprehensive DNS and email security audit with remediation guidance',\n\t\targuments: [\n\t\t\t{\n\t\t\t\tname: 'domain',\n\t\t\t\tdescription: 'The domain to audit (e.g., example.com)',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: 'email-auth-check',\n\t\tdescription: 'Check email authentication posture — SPF, DMARC, DKIM, and MTA-STS',\n\t\targuments: [\n\t\t\t{\n\t\t\t\tname: 'domain',\n\t\t\t\tdescription: 'The domain to check (e.g., example.com)',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t],\n\t},\n\t{\n\t\tname: 'policy-compliance-check',\n\t\tdescription: 'Compare a domain against security policy baselines for compliance enforcement',\n\t\targuments: [\n\t\t\t{\n\t\t\t\tname: 'domain',\n\t\t\t\tdescription: 'The domain to check (e.g., example.com)',\n\t\t\t\trequired: true,\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: 'minimum_grade',\n\t\t\t\tdescription: 'Minimum acceptable letter grade (default: \"B\")',\n\t\t\t\trequired: false,\n\t\t\t},\n\t\t],\n\t},\n];\n\n/** Prompt message templates keyed by prompt name */\nfunction getPromptMessages(name: string, args: Record<string, string>): McpPromptMessage[] {\n\tconst domain = args.domain;\n\n\tswitch (name) {\n\t\tcase 'full-security-audit':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Run a comprehensive DNS and email security audit on ${domain}.\n\n1. Start by running scan_domain on ${domain} to get the overall security score, grade, and all findings.\n2. For any critical or high severity findings, run explain_finding to get plain-language remediation guidance.\n3. Summarize the results with:\n - Overall score and grade\n - Maturity stage\n - Critical and high findings with remediation steps\n - Prioritized action plan for improving the security posture`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\n\t\tcase 'email-auth-check':\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Check the email authentication posture for ${domain}.\n\n1. Run check_spf to validate SPF records and identify trust surface exposure.\n2. Run check_dmarc to assess DMARC policy enforcement and reporting configuration.\n3. Run check_dkim to verify DKIM key presence and strength.\n4. Run check_mta_sts to check SMTP transport encryption enforcement.\n5. For any failures, run explain_finding to get remediation guidance.\n6. Summarize whether ${domain} is protected against email spoofing and phishing, with specific steps to fix any gaps.`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\n\t\tcase 'policy-compliance-check': {\n\t\t\tconst grade = args.minimum_grade || 'B';\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\trole: 'user',\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\ttext: `Check if ${domain} meets security policy compliance requirements.\n\nRun compare_baseline on ${domain} with the following baseline:\n{\n \"grade\": \"${grade}\",\n \"require_spf\": true,\n \"require_dmarc_enforce\": true,\n \"require_dkim\": true,\n \"max_critical_findings\": 0\n}\n\nReport whether the domain passes or fails compliance, listing each specific violation and the remediation needed to achieve compliance.`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t];\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(`Invalid prompt name: ${name}`);\n\t}\n}\n\n/**\n * Handle the MCP prompts/list method.\n * Returns all available prompt definitions.\n */\nexport function handlePromptsList(): { prompts: McpPrompt[] } {\n\treturn { prompts: PROMPTS };\n}\n\n/**\n * Handle the MCP prompts/get method.\n * Returns the messages for a specific prompt.\n */\nexport function handlePromptsGet(params: Record<string, unknown>): {\n\tdescription: string;\n\tmessages: McpPromptMessage[];\n} {\n\tconst name = params.name;\n\tif (typeof name !== 'string') {\n\t\tthrow new Error('Missing required parameter: name');\n\t}\n\n\tconst prompt = PROMPTS.find((p) => p.name === name);\n\tif (!prompt) {\n\t\tthrow new Error(`Invalid prompt name: ${name}`);\n\t}\n\n\tconst args = (params.arguments as Record<string, string>) ?? {};\n\tconst messages = getPromptMessages(name, args);\n\n\treturn {\n\t\tdescription: prompt.description,\n\t\tmessages,\n\t};\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\n/**\n * Audit logging for security-related events.\n * Tracks authentication, rate limiting, and suspicious patterns.\n */\n\nimport { logEvent } from './log';\n\nexport type AuditEventType = 'session-created';\n\nexport interface AuditLogEvent {\n\teventType: AuditEventType;\n\tip: string;\n\ttimestamp: string;\n\tsessionId?: string;\n\ttool?: string;\n\tdomain?: string;\n\tseverity: 'info' | 'warn' | 'error';\n\tmessage: string;\n\tdetails?: Record<string, unknown>;\n}\n\n/**\n * Log a security-relevant audit event\n */\nexport function auditLog(event: AuditLogEvent): void {\n\tlogEvent({\n\t\ttimestamp: event.timestamp || new Date().toISOString(),\n\t\tseverity: event.severity,\n\t\tcategory: 'audit',\n\t\tdetails: {\n\t\t\teventType: event.eventType,\n\t\t\tip: event.ip,\n\t\t\thasSessionId: Boolean(event.sessionId),\n\t\t\ttool: event.tool,\n\t\t\tdomain: event.domain,\n\t\t\tmessage: event.message,\n\t\t\t...event.details,\n\t\t},\n\t});\n}\n\n/**\n * Log session creation\n */\nexport function auditSessionCreated(ip: string, sessionId: string): void {\n\tauditLog({\n\t\teventType: 'session-created',\n\t\tip,\n\t\tsessionId,\n\t\ttimestamp: new Date().toISOString(),\n\t\tseverity: 'info',\n\t\tmessage: 'New session created',\n\t});\n}\n","// SPDX-License-Identifier: BUSL-1.1\n\nimport { handleToolsList, handleToolsCall } from '../handlers/tools';\nimport { handleResourcesList, handleResourcesRead } from '../handlers/resources';\nimport { handlePromptsList, handlePromptsGet } from '../handlers/prompts';\nimport { parseAllowedHosts } from './request';\nimport { createSession, checkSessionCreateRateLimit } from '../lib/session';\nimport { auditSessionCreated } from '../lib/audit';\nimport { jsonRpcError, jsonRpcSuccess, JSON_RPC_ERRORS } from '../lib/json-rpc';\nimport type { AnalyticsClient } from '../lib/analytics';\n\ntype JsonRpcPayload = ReturnType<typeof jsonRpcSuccess> | ReturnType<typeof jsonRpcError>;\n\nexport interface DispatchMcpMethodOptions {\n\tid: string | number | null | undefined;\n\tmethod: string;\n\tparams: Record<string, unknown> | undefined;\n\tip: string;\n\tisAuthenticated: boolean;\n\trateHeaders: Record<string, string>;\n\tserverVersion: string;\n\trateLimitKv?: KVNamespace;\n\tquotaCoordinator?: DurableObjectNamespace;\n\tsessionStore?: KVNamespace;\n\tscanCache?: KVNamespace;\n\tproviderSignaturesUrl?: string;\n\tproviderSignaturesAllowedHosts?: string;\n\tproviderSignaturesSha256?: string;\n\tanalytics?: AnalyticsClient;\n\tprofileAccumulator?: DurableObjectNamespace;\n\twaitUntil?: (promise: Promise<unknown>) => void;\n\tcreateSessionOnInitialize?: boolean;\n\texistingSessionId?: string;\n\tscoringConfig?: import('../lib/scoring-config').ScoringConfig;\n\tcacheTtlSeconds?: number;\n\t/** Custom secondary DoH endpoint URL (bv-dns). */\n\tsecondaryDohEndpoint?: string;\n\t/** Auth token for custom secondary DoH. */\n\tsecondaryDohToken?: string;\n\tcountry?: string;\n\tclientType?: string;\n\tauthTier?: string;\n}\n\nexport type DispatchMcpMethodResult =\n\t| {\n\t\t\tkind: 'success';\n\t\t\tpayload: JsonRpcPayload;\n\t\t\tnewSessionId?: string;\n\t\t\tlogCategory: string;\n\t\t\tlogTool?: string;\n\t\t\tlogResult?: string;\n\t\t\tlogDetails?: unknown;\n\t }\n\t| {\n\t\t\tkind: 'early-error';\n\t\t\tpayload: ReturnType<typeof jsonRpcError>;\n\t\t\tstatus: 429;\n\t\t\theaders: Record<string, string>;\n\t };\n\nexport async function dispatchMcpMethod(options: DispatchMcpMethodOptions): Promise<DispatchMcpMethodResult> {\n\tswitch (options.method) {\n\t\tcase 'initialize': {\n\t\t\t\tconst createSessionOnInitialize = options.createSessionOnInitialize !== false;\n\t\t\t\tif (createSessionOnInitialize && !options.isAuthenticated) {\n\t\t\t\tconst sessionCreateGate = await checkSessionCreateRateLimit(options.ip, options.rateLimitKv, options.quotaCoordinator);\n\t\t\t\tif (!sessionCreateGate.allowed) {\n\t\t\t\t\tconst retryAfterSeconds = Math.ceil((sessionCreateGate.retryAfterMs ?? 0) / 1000);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tkind: 'early-error',\n\t\t\t\t\t\tpayload: jsonRpcError(options.id, JSON_RPC_ERRORS.RATE_LIMITED, `Rate limit exceeded. Retry after ${retryAfterSeconds}s`),\n\t\t\t\t\t\tstatus: 429,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t...options.rateHeaders,\n\t\t\t\t\t\t\t'retry-after': String(retryAfterSeconds),\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\tconst sessionId = createSessionOnInitialize ? await createSession(options.sessionStore) : options.existingSessionId;\n\t\t\t\tif (createSessionOnInitialize && sessionId) {\n\t\t\t\t\tauditSessionCreated(options.ip, sessionId);\n\t\t\t\t\toptions.analytics?.emitSessionEvent({\n\t\t\t\t\t\taction: 'created',\n\t\t\t\t\t\tcountry: options.country,\n\t\t\t\t\t\tclientType: options.clientType as import('../lib/client-detection').McpClientType,\n\t\t\t\t\t\tauthTier: options.authTier,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, {\n\t\t\t\t\tprotocolVersion: '2025-03-26',\n\t\t\t\t\tcapabilities: {\n\t\t\t\t\t\ttools: { listChanged: false },\n\t\t\t\t\t\tresources: { subscribe: false, listChanged: false },\n\t\t\t\t\t\tprompts: { listChanged: false },\n\t\t\t\t\t},\n\t\t\t\t\tserverInfo: {\n\t\t\t\t\t\tname: 'Blackveil DNS',\n\t\t\t\t\t\tversion: options.serverVersion,\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t'Open-source DNS & email security scanner — 80+ checks across 20 categories with scoring, grading, and remediation guidance',\n\t\t\t\t\t},\n\t\t\t\t\tinstructions: `Blackveil DNS is a DNS and email security scanner. Use this server when users ask about:\n\n- Email security, email spoofing, phishing protection, or email deliverability\n- DNS security posture, DNS hardening, or domain security audits\n- SPF, DMARC, DKIM, DNSSEC, MTA-STS, BIMI, DANE, or TLS-RPT configuration\n- SSL/TLS certificate status or HTTP security headers\n- Domain reputation, mail server blacklisting, or MX reputation\n- Subdomain takeover risks or dangling DNS records\n- Lookalike/typosquat domain detection\n- Shadow domain discovery (alternate TLD variants with spoofing risk)\n- Pre-deployment or pre-migration DNS validation\n- Compliance checks or security baseline enforcement\n\nStart with scan_domain for a comprehensive assessment (14 checks in parallel, scored 0-100 with letter grade). Use individual check_* tools for targeted investigation. Use explain_finding for plain-language remediation guidance. Use compare_baseline to enforce policy minimums.\n\nAll checks are passive, read-only, and use public DNS — no authorization from the target domain is needed. Free to use, no API key required.`,\n\t\t\t\t}),\n\t\t\t\tnewSessionId: createSessionOnInitialize ? sessionId : undefined,\n\t\t\t\tlogCategory: 'session',\n\t\t\t\tlogResult: 'initialized',\n\t\t\t};\n\t\t}\n\n\t\tcase 'tools/list':\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, handleToolsList()),\n\t\t\t\tlogCategory: 'tools',\n\t\t\t\tlogResult: 'list',\n\t\t\t};\n\n\t\tcase 'tools/call': {\n\t\t\t// params are validated by validateJsonRpcRequest upstream — name is required by MCP spec\n\t\t\tconst toolParams = options.params as { name: string; arguments?: Record<string, unknown> };\n\t\t\tconst result = await handleToolsCall(toolParams, options.scanCache, {\n\t\t\t\tproviderSignaturesUrl: options.providerSignaturesUrl,\n\t\t\t\tproviderSignaturesAllowedHosts: parseAllowedHosts(options.providerSignaturesAllowedHosts),\n\t\t\t\tproviderSignaturesSha256: options.providerSignaturesSha256,\n\t\t\t\tanalytics: options.analytics,\n\t\t\t\tprofileAccumulator: options.profileAccumulator,\n\t\t\t\twaitUntil: options.waitUntil,\n\t\t\t\tscoringConfig: options.scoringConfig,\n\t\t\t\tcacheTtlSeconds: options.cacheTtlSeconds,\n\t\t\t\tsecondaryDoh: options.secondaryDohEndpoint\n\t\t\t\t\t? { endpoint: options.secondaryDohEndpoint, token: options.secondaryDohToken }\n\t\t\t\t\t: undefined,\n\t\t\t\tcountry: options.country,\n\t\t\t\tclientType: options.clientType,\n\t\t\t\tauthTier: options.authTier,\n\t\t\t});\n\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, result),\n\t\t\t\tlogCategory: 'tools',\n\t\t\t\tlogTool: toolParams.name,\n\t\t\t\t// result shape varies by tool — narrowing via 'in' guard before access\n\t\t\tlogResult: typeof result === 'object' && result && 'status' in result ? String((result as { status: unknown }).status) : undefined,\n\t\t\t\tlogDetails: result,\n\t\t\t};\n\t\t}\n\n\t\tcase 'resources/list':\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, handleResourcesList()),\n\t\t\t\tlogCategory: 'resources',\n\t\t\t\tlogResult: 'list',\n\t\t\t};\n\n\t\tcase 'resources/read': {\n\t\t\t// params are validated by validateJsonRpcRequest upstream — uri is required by MCP spec\n\t\t\tconst resourceParams = options.params as { uri: string };\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, handleResourcesRead(resourceParams)),\n\t\t\t\tlogCategory: 'resources',\n\t\t\t\tlogResult: 'read',\n\t\t\t\tlogDetails: resourceParams,\n\t\t\t};\n\t\t}\n\n\t\tcase 'prompts/list':\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, handlePromptsList()),\n\t\t\t\tlogCategory: 'prompts',\n\t\t\t\tlogResult: 'list',\n\t\t\t};\n\n\t\tcase 'prompts/get': {\n\t\t\tconst promptParams = options.params as { name: string; arguments?: Record<string, string> };\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, handlePromptsGet(promptParams)),\n\t\t\t\tlogCategory: 'prompts',\n\t\t\t\tlogResult: 'get',\n\t\t\t\tlogDetails: promptParams,\n\t\t\t};\n\t\t}\n\n\t\tcase 'ping':\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcSuccess(options.id, {}),\n\t\t\t\tlogCategory: 'session',\n\t\t\t\tlogResult: 'ping',\n\t\t\t};\n\n\t\tdefault:\n\t\t\treturn {\n\t\t\t\tkind: 'success',\n\t\t\t\tpayload: jsonRpcError(options.id, JSON_RPC_ERRORS.METHOD_NOT_FOUND, `Method not found: ${options.method}`),\n\t\t\t\tlogCategory: 'error',\n\t\t\t\tlogResult: 'method_not_found',\n\t\t\t};\n\t}\n}","// SPDX-License-Identifier: BUSL-1.1\n\n/** Server version — keep in sync with package.json */\nexport const SERVER_VERSION = '1.4.0';","#!/usr/bin/env node\n// SPDX-License-Identifier: BUSL-1.1\n\nimport { parseJsonRpcRequest } from './mcp/request';\nimport { executeMcpRequest } from './mcp/execute';\nimport { JSON_RPC_ERRORS, jsonRpcError } from './lib/json-rpc';\nimport { SERVER_VERSION } from './lib/server-version';\nimport type { JsonRpcRequest } from './lib/json-rpc';\n\ndeclare const process: {\n\targv: string[];\n\tstdin: {\n\t\tsetEncoding(encoding: string): void;\n\t\tresume(): void;\n\t\ton(event: 'data', listener: (chunk: string) => void): void;\n\t\ton(event: 'end', listener: () => void): void;\n\t};\n\tstdout: {\n\t\twrite(chunk: string): boolean;\n\t};\n\tstderr: {\n\t\twrite(chunk: string): boolean;\n\t};\n\texitCode?: number;\n};\n\ntype JsonRpcResponsePayload = ReturnType<typeof jsonRpcError> | ReturnType<typeof import('./lib/json-rpc').jsonRpcSuccess>;\n\nexport interface StdioServerState {\n\tinitialized: boolean;\n}\n\nexport interface StdioServer {\n\treadonly state: StdioServerState;\n\thandleMessage(rawMessage: string): Promise<string[]>;\n}\n\nfunction buildNotInitializedError(id: string | number | null | undefined): ReturnType<typeof jsonRpcError> {\n\treturn jsonRpcError(id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Server not initialized');\n}\n\nfunction buildInvalidBatchInitializeError(id: string | number | null | undefined): ReturnType<typeof jsonRpcError> {\n\treturn jsonRpcError(id, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC batch request: initialize cannot be batched with other messages');\n}\n\nasync function processRequest(\n\trequest: JsonRpcRequest,\n\tstate: StdioServerState,\n\tbatchSize: number,\n): Promise<JsonRpcResponsePayload | undefined> {\n\tconst { id, method } = request;\n\tif (batchSize > 1 && method === 'initialize') {\n\t\treturn buildInvalidBatchInitializeError(id);\n\t}\n\n\tconst isNotification = id === undefined || id === null;\n\tif (method !== 'initialize' && !state.initialized) {\n\t\treturn isNotification ? undefined : buildNotInitializedError(id);\n\t}\n\n\tif (isNotification) {\n\t\tif (method === 'notifications/initialized') {\n\t\t\tstate.initialized = true;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tconst result = await executeMcpRequest({\n\t\tbody: request,\n\t\tallowStreaming: false,\n\t\tbatchMode: batchSize > 1,\n\t\tbatchSize,\n\t\tresponseTransport: 'json',\n\t\tstartTime: Date.now(),\n\t\tip: 'stdio',\n\t\tisAuthenticated: true,\n\t\tvalidateSession: false,\n\t\tcreateSessionOnInitialize: false,\n\t\tserverVersion: SERVER_VERSION,\n\t});\n\tif (result.kind === 'notification') {\n\t\treturn undefined;\n\t}\n\n\tif (method === 'initialize') {\n\t\tstate.initialized = true;\n\t}\n\n\treturn result.payload as JsonRpcResponsePayload;\n}\n\nasync function processUnknownRequest(\n\tentry: unknown,\n\tstate: StdioServerState,\n\tbatchSize: number,\n): Promise<JsonRpcResponsePayload | undefined> {\n\tif (!entry || typeof entry !== 'object' || Array.isArray(entry)) {\n\t\treturn jsonRpcError(null, JSON_RPC_ERRORS.INVALID_REQUEST, 'Invalid JSON-RPC 2.0 request');\n\t}\n\n\treturn processRequest(entry as JsonRpcRequest, state, batchSize);\n}\n\nexport function createStdioServer(): StdioServer {\n\tconst state: StdioServerState = { initialized: false };\n\n\treturn {\n\t\tstate,\n\t\tasync handleMessage(rawMessage: string): Promise<string[]> {\n\t\t\tconst trimmed = rawMessage.trim();\n\t\t\tif (!trimmed) return [];\n\n\t\t\tconst parsed = parseJsonRpcRequest(trimmed);\n\t\t\tif (!parsed.ok) {\n\t\t\t\treturn [JSON.stringify(parsed.payload)];\n\t\t\t}\n\n\t\t\tif (parsed.isBatch) {\n\t\t\t\tconst entries = parsed.body as unknown[];\n\t\t\t\tconst payloads = await Promise.all(\n\t\t\t\t\tentries.map((entry) => processUnknownRequest(entry, state, entries.length)),\n\t\t\t\t);\n\t\t\t\tconst responses = payloads.filter((payload): payload is JsonRpcResponsePayload => payload !== undefined);\n\t\t\t\treturn responses.length > 0 ? [JSON.stringify(responses)] : [];\n\t\t\t}\n\n\t\t\tconst payload = await processUnknownRequest(parsed.body, state, 1);\n\t\t\treturn payload ? [JSON.stringify(payload)] : [];\n\t\t},\n\t};\n}\n\nexport async function runStdioServer(): Promise<void> {\n\tconst server = createStdioServer();\n\tlet buffer = '';\n\tlet pending = Promise.resolve();\n\n\tconst flushLine = (line: string): void => {\n\t\tpending = pending\n\t\t\t.then(async () => {\n\t\t\t\tconst outputs = await server.handleMessage(line);\n\t\t\t\tfor (const output of outputs) {\n\t\t\t\t\tprocess.stdout.write(`${output}\\n`);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tconst message = error instanceof Error ? error.message : 'Unknown stdio server error';\n\t\t\t\tprocess.stderr.write(`[blackveil-dns-mcp] ${message}\\n`);\n\t\t\t\tprocess.exitCode = 1;\n\t\t\t});\n\t};\n\n\tprocess.stdin.setEncoding('utf8');\n\tprocess.stdin.on('data', (chunk: string) => {\n\t\tbuffer += chunk;\n\t\tconst lines = buffer.split(/\\r?\\n/);\n\t\tbuffer = lines.pop() ?? '';\n\t\tfor (const line of lines) {\n\t\t\tflushLine(line);\n\t\t}\n\t});\n\n\tprocess.stdin.on('end', () => {\n\t\tif (buffer.trim().length > 0) {\n\t\t\tflushLine(buffer);\n\t\t\tbuffer = '';\n\t\t}\n\t});\n\n\tprocess.stdin.resume();\n\tawait pending;\n}\n\nconst directRunCandidate = process.argv[1] ?? '';\nconst isDirectRun = typeof directRunCandidate === 'string' && import.meta.url === new URL(directRunCandidate, 'file:').href;\n\nif (isDirectRun) {\n\tvoid runStdioServer();\n}"]}
|