@attest-it/cli 0.0.2 → 0.2.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/dist/bin/attest-it.js +998 -208
- package/dist/bin/attest-it.js.map +1 -1
- package/dist/index.cjs +996 -210
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +997 -207
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/output.ts","../../src/utils/prompts.ts","../../src/utils/exit-codes.ts","../../src/commands/init.ts","../../src/commands/status.ts","../../src/commands/run.ts","../../src/commands/keygen.ts","../../src/commands/prune.ts","../../src/commands/verify.ts","../../src/index.ts","../../bin/attest-it.ts"],"names":["Command","loadConfig","computeFingerprint","readAttestations","fs2","parseShellCommand","resolve","getDefaultPrivateKeyPath","fs3","fs4","writeSignedAttestations","result"],"mappings":";;;;;;;;;;;;AASA,IAAI,gBAA+B,EAAC;AAE7B,SAAS,iBAAiB,OAAA,EAA8B;AAC7D,EAAA,aAAA,GAAgB,OAAA;AAClB;AAOO,SAAS,IAAI,OAAA,EAAuB;AACzC,EAAA,IAAI,CAAC,cAAc,KAAA,EAAO;AACxB,IAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EACrB;AACF;AAEO,SAAS,QAAQ,OAAA,EAAuB;AAC7C,EAAA,IAAI,aAAA,CAAc,OAAA,IAAW,CAAC,aAAA,CAAc,KAAA,EAAO;AACjD,IAAA,OAAA,CAAQ,GAAA,CAAI,EAAA,CAAG,GAAA,CAAI,OAAO,CAAC,CAAA;AAAA,EAC7B;AACF;AAEO,SAAS,QAAQ,OAAA,EAAuB;AAC7C,EAAA,GAAA,CAAI,EAAA,CAAG,KAAA,CAAM,SAAA,GAAO,OAAO,CAAC,CAAA;AAC9B;AAEO,SAAS,MAAM,OAAA,EAAuB;AAC3C,EAAA,OAAA,CAAQ,KAAA,CAAM,EAAA,CAAG,GAAA,CAAI,SAAA,GAAO,OAAO,CAAC,CAAA;AACtC;AAEO,SAAS,KAAK,OAAA,EAAuB;AAC1C,EAAA,IAAI,CAAC,cAAc,KAAA,EAAO;AACxB,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAA,CAAG,MAAA,CAAO,SAAA,GAAO,OAAO,CAAC,CAAA;AAAA,EACxC;AACF;AAEO,SAAS,KAAK,OAAA,EAAuB;AAC1C,EAAA,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,SAAA,GAAO,OAAO,CAAC,CAAA;AAC7B;AAUO,SAAS,YAAY,IAAA,EAA0B;AAEpD,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,EAAS,QAAA,EAAU,eAAe,KAAK,CAAA;AAGxD,EAAA,MAAM,YAAA,GAAe,CAAC,GAAA,KAA4B;AAAA,IAChD,GAAA,CAAI,KAAA;AAAA,IACJ,GAAA,CAAI,MAAA;AAAA,IACJ,GAAA,CAAI,WAAA;AAAA,IACJ,GAAA,CAAI;AAAA,GACN;AAEA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACnC,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM;AACnC,MAAA,MAAM,MAAA,GAAS,aAAa,CAAC,CAAA;AAE7B,MAAA,OAAO,MAAA,CAAO,CAAC,CAAA,IAAK,EAAA;AAAA,IACtB,CAAC,CAAA;AACD,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,EAAG,CAAC,CAAA;AACvE,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,MAAA,EAAQ,cAAc,CAAA;AAAA,EAC1C,CAAC,CAAA;AAGD,EAAA,MAAM,SAAA,GAAY,QAAA;AAClB,EAAA,MAAM,QAAkB,EAAC;AAIzB,EAAA,KAAA,CAAM,KAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,UAAK,CAAC,CAAA;AACtE,EAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,SAAA,CAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,oBAAK,CAAC,CAAA;AAG7D,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,MAAA,GAAS,aAAa,GAAG,CAAA;AAE/B,IAAA,KAAA,CAAM,KAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,UAAK,CAAC,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAGO,SAAS,eAAe,MAAA,EAAwB;AACrD,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,OAAA;AACH,MAAA,OAAO,EAAA,CAAG,MAAM,MAAM,CAAA;AAAA,IACxB,KAAK,mBAAA;AAAA,IACL,KAAK,qBAAA;AACH,MAAA,OAAO,EAAA,CAAG,OAAO,MAAM,CAAA;AAAA,IACzB,KAAK,SAAA;AAAA,IACL,KAAK,uBAAA;AACH,MAAA,OAAO,EAAA,CAAG,IAAI,MAAM,CAAA;AAAA,IACtB,KAAK,mBAAA;AACH,MAAA,OAAO,EAAA,CAAG,GAAA,CAAI,EAAA,CAAG,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,IAC/B;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;AAGO,SAAS,WAAW,IAAA,EAAqB;AAC9C,EAAA,OAAA,CAAQ,IAAI,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAC,CAAA;AAC3C;ACjHA,eAAsB,cAAc,OAAA,EAA2C;AAC7E,EAAA,OAAO,OAAA,CAAQ;AAAA,IACb,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA,GAC7B,CAAA;AACH;AAOA,eAAsB,aAA+B,OAAA,EAAuC;AAC1F,EAAA,OAAO,MAAA,CAAO;AAAA,IACZ,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,SAAS,OAAA,CAAQ;AAAA,GAClB,CAAA;AACH;AAQA,eAAsB,SAAS,OAAA,EAAwC;AACrE,EAAA,MAAM,WAAA,GAIF;AAAA,IACF,SAAS,OAAA,CAAQ;AAAA,GACnB;AAEA,EAAA,IAAI,OAAA,CAAQ,YAAY,MAAA,EAAW;AACjC,IAAA,WAAA,CAAY,UAAU,OAAA,CAAQ,OAAA;AAAA,EAChC;AAEA,EAAA,IAAI,OAAA,CAAQ,aAAa,MAAA,EAAW;AAClC,IAAA,WAAA,CAAY,WAAW,OAAA,CAAQ,QAAA;AAAA,EACjC;AAEA,EAAA,OAAO,MAAM,WAAW,CAAA;AAC1B;;;ACrCO,IAAM,QAAA,GAAW;AAAA;AAAA,EAEtB,OAAA,EAAS,CAAA;AAAA;AAAA,EAET,OAAA,EAAS,CAAA;AAAA;AAAA,EAET,YAAA,EAAc,CAAA;AAAA;AAAA,EAEd,SAAA,EAAW,CAAA;AAAA;AAAA,EAEX,WAAA,EAAa;AACf,CAAA;;;AChBO,IAAM,WAAA,GAAc,IAAI,OAAA,CAAQ,MAAM,EAC1C,WAAA,CAAY,oCAAoC,CAAA,CAChD,MAAA,CAAO,mBAAA,EAAqB,kBAAA,EAAoB,wBAAwB,CAAA,CACxE,MAAA,CAAO,aAAA,EAAe,2BAA2B,CAAA,CACjD,MAAA,CAAO,UAAU,6BAA6B,CAAA,CAC9C,MAAA,CAAO,OAAO,OAAA,KAAyB;AACtC,EAAA,MAAM,QAAQ,OAAO,CAAA;AACvB,CAAC,CAAA;AA4CH,eAAe,QAAQ,OAAA,EAAqC;AAC1D,EAAA,IAAI;AAEF,IAAA,MAAM,UAAA,GAAkB,IAAA,CAAA,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAiB,aAAQ,UAAU,CAAA;AAEzC,IAAA,IAAO,EAAA,CAAA,UAAA,CAAW,UAAU,CAAA,IAAK,CAAC,QAAQ,KAAA,EAAO;AAC/C,MAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc;AAAA,QACpC,OAAA,EAAS,4BAA4B,UAAU,CAAA,YAAA,CAAA;AAAA,QAC/C,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,KAAA,CAAM,gBAAgB,CAAA;AACtB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,MACjC;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,IAAA,CAAK,uBAAuB,CAAA;AAC5B,IAAA,GAAA,CAAI,0EAA0E,CAAA;AAC9E,IAAA,GAAA,CAAI,EAAE,CAAA;AAGN,IAAA,MAAM,UAAA,GAAa,MAAM,QAAA,CAAS;AAAA,MAChC,OAAA,EAAS,iCAAA;AAAA,MACT,OAAA,EAAS,IAAA;AAAA,MACT,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,QAAA,MAAM,CAAA,GAAI,QAAA,CAAS,CAAA,EAAG,EAAE,CAAA;AACxB,QAAA,OAAO,CAAC,KAAA,CAAM,CAAC,CAAA,IAAK,CAAA,GAAI,IAAI,IAAA,GAAO,2BAAA;AAAA,MACrC;AAAA,KACD,CAAA;AAED,IAAA,MAAM,SAAA,GAAY,MAAM,YAAA,CAAa;AAAA,MACnC,OAAA,EAAS,oBAAA;AAAA,MACT,OAAA,EAAS;AAAA,QACP;AAAA,UACE,KAAA,EAAO,SAAA;AAAA,UACP,IAAA,EAAM,uBAAA;AAAA,UACN,WAAA,EAAa;AAAA,SACf;AAAA,QACA,EAAE,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,aAAa,uBAAA;AAAwB;AACpE,KACD,CAAA;AAGD,IAAA,MAAM,SAAuB,EAAC;AAC9B,IAAA,IAAI,OAAA,GAAU,IAAA;AAEd,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,IAAA,CAAK,iCAAiC,CAAA;AACtC,IAAA,GAAA,CAAI,6DAA6D,CAAA;AACjE,IAAA,GAAA,CAAI,EAAE,CAAA;AAEN,IAAA,OAAO,OAAA,EAAS;AACd,MAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS;AAAA,QAC/B,OAAA,EAAS,aAAA;AAAA,QACT,UAAU,CAAC,CAAA,KAAO,CAAA,CAAE,MAAA,GAAS,IAAI,IAAA,GAAO;AAAA,OACzC,CAAA;AAED,MAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS;AAAA,QACjC,OAAA,EAAS;AAAA,OACV,CAAA;AAED,MAAA,MAAM,aAAA,GAAgB,MAAM,QAAA,CAAS;AAAA,QACnC,OAAA,EAAS,kCAAA;AAAA,QACT,OAAA,EAAS,YAAY,SAAS,CAAA,CAAA;AAAA,QAC9B,UAAU,CAAC,CAAA,KAAO,CAAA,CAAE,MAAA,GAAS,IAAI,IAAA,GAAO;AAAA,OACzC,CAAA;AAED,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS;AAAA,QAC7B,OAAA,EAAS,eAAA;AAAA,QACT,OAAA,EAAS,CAAA,YAAA,EAAe,aAAA,CAAc,KAAA,CAAM,GAAG,EAAE,CAAC,CAAA,EAAG,IAAA,EAAK,IAAK,EAAE,CAAA;AAAA,OAClE,CAAA;AAED,MAAA,MAAA,CAAO,IAAA,CAAK;AAAA,QACV,IAAA,EAAM,SAAA;AAAA,QACN,WAAA;AAAA,QACA,QAAA,EAAU,aAAA,CACP,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAM,CAAA,CACnB,OAAO,OAAO,CAAA;AAAA,QACjB;AAAA,OACD,CAAA;AAED,MAAA,OAAA,GAAU,MAAM,aAAA,CAAc;AAAA,QAC5B,OAAA,EAAS,oBAAA;AAAA,QACT,OAAA,EAAS;AAAA,OACV,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,MAAA,KAAA,CAAM,gCAAgC,CAAA;AACtC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,MAAA,GAAiB;AAAA,MACrB,OAAA,EAAS,CAAA;AAAA,MACT,QAAA,EAAU;AAAA,QACR,UAAA,EAAY,QAAA,CAAS,UAAA,EAAY,EAAE,CAAA;AAAA,QACnC,aAAA,EAAe,uBAAA;AAAA,QACf,gBAAA,EAAkB,8BAAA;AAAA,QAClB;AAAA,OACF;AAAA,MACA,QAAQ,MAAA,CAAO,WAAA;AAAA,QACb,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM;AAChB,UAAA,MAAM,KAAA,GAAqB;AAAA,YACzB,UAAU,CAAA,CAAE,QAAA;AAAA,YACZ,SAAS,CAAA,CAAE;AAAA,WACb;AAEA,UAAA,IAAI,EAAE,WAAA,EAAa;AACjB,YAAA,KAAA,CAAM,cAAc,CAAA,CAAE,WAAA;AAAA,UACxB;AACA,UAAA,OAAO,CAAC,CAAA,CAAE,IAAA,EAAM,KAAK,CAAA;AAAA,QACvB,CAAC;AAAA;AACH,KACF;AAGA,IAAA,MAAS,YAAS,KAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAGtD,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,IAAA,GACpB,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAA,GAC9B,KAAK,SAAA,CAAU,MAAA,EAAQ,EAAE,MAAA,EAAQ,GAAG,CAAA;AAExC,IAAA,MAAS,EAAA,CAAA,QAAA,CAAS,SAAA,CAAU,UAAA,EAAY,OAAA,EAAS,OAAO,CAAA;AAGxD,IAAA,MAAM,SAAA,GAAiB,IAAA,CAAA,OAAA;AAAA,MAChB,aAAa,IAAA,CAAA,OAAA,CAAQ,UAAU,CAAA,EAAG,MAAA,CAAO,SAAS,gBAAgB;AAAA,KACzE;AACA,IAAA,MAAS,YAAS,KAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAEtD,IAAA,OAAA,CAAQ,CAAA,yBAAA,EAA4B,UAAU,CAAA,CAAE,CAAA;AAChD,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,aAAa,CAAA;AACjB,IAAA,GAAA,CAAI,kDAAkD,CAAA;AACtD,IAAA,GAAA,CAAI,4BAA4B,CAAA;AAChC,IAAA,GAAA,CAAI,8CAA8C,CAAA;AAClD,IAAA,GAAA,CAAI,kCAAkC,CAAA;AAAA,EACxC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AC5LO,IAAM,gBAAgB,IAAIA,OAAAA,CAAQ,QAAQ,CAAA,CAC9C,WAAA,CAAY,wCAAwC,CAAA,CACpD,MAAA,CAAO,oBAAA,EAAsB,qCAAqC,EAClE,MAAA,CAAO,QAAA,EAAU,iCAAiC,CAAA,CAClD,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AA2BH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAGhC,IAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,IAAA,IAAI,gBAAA,GAA4C,IAAA;AAChD,IAAA,IAAI;AACF,MAAA,gBAAA,GAAmB,MAAM,iBAAiB,gBAAgB,CAAA;AAAA,IAC5D,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAI,eAAe,KAAA,IAAS,CAAC,IAAI,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC3D,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AACA,IAAA,MAAM,YAAA,GAAe,gBAAA,EAAkB,YAAA,IAAgB,EAAC;AAGxD,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,GAAQ,CAAC,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAG9E,IAAA,IAAI,QAAQ,KAAA,IAAS,CAAC,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClD,MAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,UAAyB,EAAC;AAChC,IAAA,IAAI,UAAA,GAAa,KAAA;AAEjB,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAElC,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,MAAA,IAAI,CAAC,WAAA,EAAa;AAGlB,MAAA,MAAM,iBAAA,GAAoB,MAAM,kBAAA,CAAmB;AAAA,QACjD,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,OACxD,CAAA;AAGD,MAAA,MAAM,WAAA,GAAc,eAAA;AAAA,QAClB;AAAA,UACE,aAAA,EAAe,GAAA;AAAA,UACf,YAAA;AAAA,UACA,SAAA,EAAW;AAAA,SACb;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,MAAA,GAAS,eAAA;AAAA,QACb,WAAA,IAAe,IAAA;AAAA,QACf,iBAAA,CAAkB,WAAA;AAAA,QAClB,OAAO,QAAA,CAAS;AAAA,OAClB;AAGA,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,QAAA,GAAA,GAAM,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAAA,MAC9E;AAEA,MAAA,IAAI,WAAW,OAAA,EAAS;AACtB,QAAA,UAAA,GAAa,IAAA;AAAA,MACf;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,SAAA;AAAA,QACN,MAAA;AAAA,QACA,oBAAoB,iBAAA,CAAkB,WAAA;AAAA,QACtC,qBAAqB,WAAA,EAAa,WAAA;AAAA,QAClC,YAAY,WAAA,EAAa,UAAA;AAAA,QACzB;AAAA,OACD,CAAA;AAAA,IACH;AAGA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,UAAA,CAAW,OAAO,CAAA;AAAA,IACpB,CAAA,MAAO;AACL,MAAA,kBAAA,CAAmB,SAAS,UAAU,CAAA;AAAA,IACxC;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,GAAa,QAAA,CAAS,OAAA,GAAU,SAAS,OAAO,CAAA;AAAA,EAC/D,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AAEA,SAAS,eAAA,CACP,WAAA,EACA,kBAAA,EACA,UAAA,EACoB;AACpB,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,mBAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,CAAY,gBAAgB,kBAAA,EAAoB;AAClD,IAAA,OAAO,qBAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAExF,EAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,CAAmB,SAAwB,UAAA,EAA2B;AAC7E,EAAA,MAAM,SAAA,GAAwB,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAChD,OAAO,CAAA,CAAE,IAAA;AAAA,IACT,MAAA,EAAQ,cAAA,CAAe,CAAA,CAAE,MAAM,CAAA;AAAA,IAC/B,aAAa,CAAA,CAAE,kBAAA,CAAmB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAAA,IACjD,GAAA,EAAK,UAAU,CAAC;AAAA,GAClB,CAAE,CAAA;AAEF,EAAA,GAAA,CAAI,EAAE,CAAA;AACN,EAAA,GAAA,CAAI,WAAA,CAAY,SAAS,CAAC,CAAA;AAC1B,EAAA,GAAA,CAAI,EAAE,CAAA;AAEN,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,GAAA,CAAI,2DAA2D,CAAA;AAAA,EACjE,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,wBAAwB,CAAA;AAAA,EAClC;AACF;AAEA,SAAS,UAAU,MAAA,EAA6B;AAC9C,EAAA,IAAI,MAAA,CAAO,WAAW,OAAA,EAAS;AAC7B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,CAAA,KAAA,CAAA;AAAA,EACnC;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,qBAAA,EAAuB;AAC3C,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,mBAAA,EAAqB;AACzC,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAC/B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,CAAA,eAAA,CAAA;AAAA,EACnC;AAEA,EAAA,OAAO,GAAA;AACT;AC7LO,IAAM,UAAA,GAAa,IAAIA,OAAAA,CAAQ,KAAK,CAAA,CACxC,WAAA,CAAY,sCAAsC,CAAA,CAClD,MAAA,CAAO,oBAAA,EAAsB,4CAA4C,CAAA,CACzE,MAAA,CAAO,aAAa,oCAAoC,CAAA,CACxD,MAAA,CAAO,aAAA,EAAe,wCAAwC,CAAA,CAC9D,MAAA,CAAO,WAAA,EAAa,0BAA0B,CAAA,CAC9C,MAAA,CAAO,OAAO,OAAA,KAAwB;AACrC,EAAA,MAAM,SAAS,OAAO,CAAA;AACxB,CAAC,CAAA;AAsBH,eAAe,SAAS,OAAA,EAAoC;AAC1D,EAAA,IAAI;AAEF,IAAA,IAAI,CAAC,OAAA,CAAQ,KAAA,IAAS,CAAC,QAAQ,GAAA,EAAK;AAClC,MAAA,KAAA,CAAM,qCAAqC,CAAA;AAC3C,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,MAAA,GAAS,MAAMC,UAAAA,EAAW;AAGhC,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,GAAA,GACxB,MAAA,CAAO,KAAK,MAAA,CAAO,MAAM,CAAA,GACzB,OAAA,CAAQ,KAAA,GACN,CAAC,OAAA,CAAQ,KAAK,IACd,EAAC;AAGP,IAAA,IAAI,QAAQ,KAAA,IAAS,CAAC,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClD,MAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,OAAA,GAAU,MAAM,qBAAA,EAAsB;AAC5C,IAAA,IAAI,OAAA,EAAS;AACX,MAAA,KAAA,CAAM,gFAAgF,CAAA;AACtF,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,KAAA,MAAW,aAAa,WAAA,EAAa;AAEnC,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,MAAA,IAAI,CAAC,WAAA,EAAa;AAElB,MAAA,GAAA,CAAI;AAAA,mBAAA,EAAwB,SAAS,CAAA;AAAA,CAAQ,CAAA;AAG7C,MAAA,MAAM,kBAAA,GAAqB;AAAA,QACzB,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,OACzD;AACA,MAAA,MAAM,iBAAA,GAAoB,MAAMC,kBAAAA,CAAmB,kBAAkB,CAAA;AACrE,MAAA,OAAA,CAAQ,CAAA,aAAA,EAAgB,iBAAA,CAAkB,WAAW,CAAA,CAAE,CAAA;AACvD,MAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,iBAAA,CAAkB,SAAS,CAAC,CAAA,CAAE,CAAA;AAGvD,MAAA,MAAM,UAAU,YAAA,CAAa,MAAA,EAAQ,WAAA,CAAY,OAAA,EAAS,YAAY,KAAK,CAAA;AAC3E,MAAA,GAAA,CAAI,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACzB,MAAA,GAAA,CAAI,EAAE,CAAA;AAGN,MAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,OAAO,CAAA;AAE7C,MAAA,IAAI,aAAa,CAAA,EAAG;AAClB,QAAA,KAAA,CAAM,CAAA,4BAAA,EAA+B,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAE,CAAA;AACvD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,MAC/B;AAEA,MAAA,OAAA,CAAQ,eAAe,CAAA;AAGvB,MAAA,IAAI,OAAA,CAAQ,WAAW,KAAA,EAAO;AAC5B,QAAA,GAAA,CAAI,oCAAoC,CAAA;AACxC,QAAA;AAAA,MACF;AAGA,MAAA,MAAM,YAAA,GACJ,OAAA,CAAQ,GAAA,IACP,MAAM,aAAA,CAAc;AAAA,QACnB,OAAA,EAAS,qBAAA;AAAA,QACT,OAAA,EAAS;AAAA,OACV,CAAA;AAEH,MAAA,IAAI,CAAC,YAAA,EAAc;AACjB,QAAA,IAAA,CAAK,uBAAuB,CAAA;AAC5B,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,MACjC;AAGA,MAAA,MAAM,cAAc,iBAAA,CAAkB;AAAA,QACpC,KAAA,EAAO,SAAA;AAAA,QACP,aAAa,iBAAA,CAAkB,WAAA;AAAA,QAC/B,OAAA;AAAA,QACA,UAAA,EAAe,aAAS,CAAE;AAAA,OAC3B,CAAA;AAGD,MAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,MAAA,MAAM,YAAA,GAAe,MAAMC,gBAAAA,CAAiB,gBAAgB,CAAA;AAC5D,MAAA,MAAM,oBAAA,GAAuB,YAAA,EAAc,YAAA,IAAgB,EAAC;AAG5D,MAAA,MAAM,eAAA,GAAkB,iBAAA,CAAkB,oBAAA,EAAsB,WAAW,CAAA;AAG3E,MAAA,MAAM,iBAAiB,wBAAA,EAAyB;AAGhD,MAAA,IAAI,CAAIC,EAAA,CAAA,UAAA,CAAW,cAAc,CAAA,EAAG;AAClC,QAAA,KAAA,CAAM,CAAA,uBAAA,EAA0B,cAAc,CAAA,CAAE,CAAA;AAChD,QAAA,KAAA,CAAM,qDAAqD,CAAA;AAC3D,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,WAAW,CAAA;AAAA,MACnC;AAGA,MAAA,MAAM,uBAAA,CAAwB;AAAA,QAC5B,QAAA,EAAU,gBAAA;AAAA,QACV,YAAA,EAAc,eAAA;AAAA,QACd;AAAA,OACD,CAAA;AAED,MAAA,OAAA,CAAQ,CAAA,wBAAA,EAA2B,SAAS,CAAA,CAAE,CAAA;AAC9C,MAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,iBAAA,CAAkB,WAAW,CAAA,CAAE,CAAA;AACrD,MAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,WAAA,CAAY,UAAU,CAAA,CAAE,CAAA;AAC9C,MAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,WAAA,CAAY,UAAU,CAAA,CAAE,CAAA;AAAA,IAChD;AAEA,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,OAAA,CAAQ,uBAAuB,CAAA;AAC/B,IAAA,GAAA;AAAA,MACE;AAAA,mBAAA,EAAwB,MAAA,CAAO,SAAS,gBAAgB,CAAA,uCAAA;AAAA,KAC1D;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AAeA,SAAS,YAAA,CAAa,MAAA,EAAgB,YAAA,EAAuB,UAAA,EAA+B;AAE1F,EAAA,IAAI,OAAA,GAAU,YAAA,IAAgB,MAAA,CAAO,QAAA,CAAS,cAAA;AAE9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,KAAA,CAAM,kEAAkE,CAAA;AACxE,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,IAAK,UAAA,EAAY;AAC9C,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACjC,IAAA,OAAA,GAAU,OAAA,CAAQ,UAAA,CAAW,UAAA,EAAY,KAAK,CAAA;AAAA,EAChD;AAEA,EAAA,OAAO,OAAA;AACT;AAoBA,SAAS,aAAa,OAAA,EAAgC;AACpD,EAAA,MAAM,MAAA,GAASC,MAAkB,OAAO,CAAA;AAIxC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAA2B;AAC3D,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA;AAAA,EAC1B,CAAC,CAAA;AAED,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,EAC9E;AAEA,EAAA,MAAM,CAAC,UAAA,EAAY,GAAG,IAAI,CAAA,GAAI,UAAA;AAG9B,EAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,EAC9E;AAEA,EAAA,OAAO,EAAE,YAAY,IAAA,EAAK;AAC5B;AAWA,eAAe,eAAe,OAAA,EAAkC;AAC9D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACC,QAAAA,KAAY;AAC9B,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,aAAa,OAAO,CAAA;AAAA,IAC/B,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,eAAe,KAAA,EAAO;AACxB,QAAA,KAAA,CAAM,CAAA,yBAAA,EAA4B,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,MACjD,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,wCAAwC,CAAA;AAAA,MAChD;AACA,MAAAA,SAAQ,CAAC,CAAA;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,MAAA,CAAO,UAAA,EAAY,OAAO,IAAA,EAAM;AAAA,MAClD,KAAA,EAAO;AAAA;AAAA,KACR,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAAA,QAAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,IACnB,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,KAAA,CAAM,CAAA,2BAAA,EAA8B,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AACjD,MAAAA,SAAQ,CAAC,CAAA;AAAA,IACX,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAQA,eAAe,qBAAA,GAA0C;AACvD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACA,QAAAA,KAAY;AAC9B,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA,EAAO,CAAC,QAAA,EAAU,aAAa,CAAA,EAAG;AAAA,MACpD,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAEtB,MAAAA,QAAAA,CAAQ,MAAA,CAAO,IAAA,EAAK,CAAE,SAAS,CAAC,CAAA;AAAA,IAClC,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAEtB,MAAAA,SAAQ,KAAK,CAAA;AAAA,IACf,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AC1TO,IAAM,aAAA,GAAgB,IAAIN,OAAAA,CAAQ,QAAQ,EAC9C,WAAA,CAAY,qDAAqD,CAAA,CACjE,MAAA,CAAO,qBAAA,EAAuB,yBAAyB,EACvD,MAAA,CAAO,qBAAA,EAAuB,wBAAwB,CAAA,CACtD,MAAA,CAAO,eAAe,yBAAyB,CAAA,CAC/C,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AAoBH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,GAAA,CAAI,qBAAqB,CAAA;AACzB,IAAA,MAAM,OAAA,GAAU,MAAM,YAAA,EAAa;AACnC,IAAA,IAAA,CAAK,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAG1B,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,IAAUO,wBAAAA,EAAyB;AAC/D,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,IAAU,uBAAA,EAAwB;AAE7D,IAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,WAAW,CAAA,CAAE,CAAA;AACjC,IAAA,GAAA,CAAI,CAAA,YAAA,EAAe,UAAU,CAAA,CAAE,CAAA;AAG/B,IAAA,MAAM,aAAA,GAAmBC,cAAW,WAAW,CAAA;AAC/C,IAAA,MAAM,YAAA,GAAkBA,cAAW,UAAU,CAAA;AAE7C,IAAA,IAAA,CAAK,aAAA,IAAiB,YAAA,KAAiB,CAAC,OAAA,CAAQ,KAAA,EAAO;AACrD,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAA,CAAK,CAAA,4BAAA,EAA+B,WAAW,CAAA,CAAE,CAAA;AAAA,MACnD;AACA,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAA,CAAK,CAAA,2BAAA,EAA8B,UAAU,CAAA,CAAE,CAAA;AAAA,MACjD;AAEA,MAAA,MAAM,eAAA,GAAkB,MAAM,aAAA,CAAc;AAAA,QAC1C,OAAA,EAAS,0BAAA;AAAA,QACT,OAAA,EAAS;AAAA,OACV,CAAA;AAED,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,KAAA,CAAM,kBAAkB,CAAA;AACxB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,MACjC;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,kCAAkC,CAAA;AAEtC,IAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB;AAAA,MACnC,WAAA;AAAA,MACA,UAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,CAAA;AAGD,IAAA,MAAM,iBAAA,CAAkB,OAAO,WAAW,CAAA;AAE1C,IAAA,OAAA,CAAQ,iCAAiC,CAAA;AACzC,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,4BAA4B,CAAA;AAChC,IAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,WAAW,CAAA,CAAE,CAAA;AAC7B,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,8BAA8B,CAAA;AAClC,IAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AAC5B,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,IAAA,CAAK,+CAA+C,CAAA;AACpD,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,aAAa,CAAA;AACjB,IAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AACvC,IAAA,GAAA,CAAI,4DAA4D,CAAA;AAChE,IAAA,GAAA,CAAI,yCAAyC,CAAA;AAAA,EAC/C,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AC9FO,IAAM,eAAe,IAAIR,OAAAA,CAAQ,OAAO,CAAA,CAC5C,WAAA,CAAY,2BAA2B,CAAA,CACvC,MAAA,CAAO,iBAAiB,6CAA6C,CAAA,CACrE,OAAO,qBAAA,EAAuB,qCAAA,EAAuC,IAAI,CAAA,CACzE,MAAA,CAAO,OAAO,OAAA,KAA0B;AACvC,EAAA,MAAM,SAAS,OAAO,CAAA;AACxB,CAAC,CAAA;AAmBH,eAAe,SAAS,OAAA,EAAsC;AAC5D,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAC9C,IAAA,IAAI,KAAA,CAAM,QAAQ,CAAA,IAAK,QAAA,GAAW,CAAA,EAAG;AACnC,MAAA,KAAA,CAAM,wCAAwC,CAAA;AAC9C,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAClC,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAMC,UAAAA,EAAW;AAGhC,IAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,IAAA,MAAM,IAAA,GAAO,MAAME,gBAAAA,CAAiB,gBAAgB,CAAA;AAEpD,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,YAAA,CAAa,WAAW,CAAA,EAAG;AAC3C,MAAA,IAAA,CAAK,0BAA0B,CAAA;AAC/B,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAGzC,IAAA,MAAM,QAAuB,EAAC;AAC9B,IAAA,MAAM,OAAsB,EAAC;AAE7B,IAAA,KAAA,MAAW,WAAA,IAAe,KAAK,YAAA,EAAc;AAC3C,MAAA,MAAM,aAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,EAAE,OAAA,EAAQ;AAC5D,MAAA,MAAM,QAAQ,GAAA,GAAM,UAAA;AACpB,MAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,SAAS,GAAA,GAAO,EAAA,GAAK,KAAK,EAAA,CAAG,CAAA;AAGxD,MAAA,MAAM,WAAA,GAAc,WAAA,CAAY,KAAA,IAAS,MAAA,CAAO,MAAA;AAGhD,MAAA,IAAI,kBAAA,GAAqB,KAAA;AACzB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,KAAK,CAAA;AACnD,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAM,kBAAA,GAAqB;AAAA,YACzB,UAAU,WAAA,CAAY,QAAA;AAAA,YACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,WACzD;AACA,UAAA,MAAM,MAAA,GAAS,MAAMD,kBAAAA,CAAmB,kBAAkB,CAAA;AAC1D,UAAA,kBAAA,GAAqB,MAAA,CAAO,gBAAgB,WAAA,CAAY,WAAA;AAAA,QAC1D;AAAA,MACF;AAKA,MAAA,MAAM,OAAA,GAAU,CAAC,kBAAA,IAAsB,KAAA,GAAQ,MAAA;AAC/C,MAAA,MAAM,WAAW,CAAC,WAAA;AAElB,MAAA,IAAI,WAAW,QAAA,EAAU;AACvB,QAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,QAAA,MAAM,MAAA,GAAS,QAAA,GACX,eAAA,GACA,CAAC,qBACC,qBAAA,GACA,SAAA;AACN,QAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,YAAY,KAAK,CAAA,EAAA,EAAK,MAAM,CAAA,EAAA,EAAK,MAAA,CAAO,OAAO,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,MAChF,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,KAAK,WAAW,CAAA;AAAA,MACvB;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,6BAA6B,CAAA;AACrC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,CAAA,MAAA,EAAS,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA,sBAAA,CAAwB,CAAA;AACzD,IAAA,KAAA,MAAW,eAAe,KAAA,EAAO;AAC/B,MAAA,MAAM,UAAU,IAAA,CAAK,KAAA;AAAA,QAAA,CAClB,GAAA,GAAM,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,EAAE,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA;AAAA,OACzE;AACA,MAAA,GAAA,CAAI,OAAO,WAAA,CAAY,KAAK,KAAK,MAAA,CAAO,OAAO,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,MAAA,IAAA,CAAK,2BAA2B,CAAA;AAChC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,iBAAiBK,wBAAAA,EAAyB;AAChD,IAAA,IAAI,CAAIE,EAAA,CAAA,UAAA,CAAW,cAAc,CAAA,EAAG;AAClC,MAAA,KAAA,CAAM,CAAA,uBAAA,EAA0B,cAAc,CAAA,CAAE,CAAA;AAChD,MAAA,KAAA,CAAM,mCAAmC,CAAA;AACzC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,WAAW,CAAA;AACjC,MAAA;AAAA,IACF;AAGA,IAAA,MAAMC,uBAAAA,CAAwB;AAAA,MAC5B,QAAA,EAAU,gBAAA;AAAA,MACV,YAAA,EAAc,IAAA;AAAA,MACd;AAAA,KACD,CAAA;AAED,IAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA,qBAAA,CAAuB,CAAA;AAC7D,IAAA,GAAA,CAAI,CAAA,WAAA,EAAc,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA,eAAA,CAAiB,CAAA;AACtD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACd,IAAA;AAAA,EACF;AACF;AC5IO,IAAM,aAAA,GAAgB,IAAIV,OAAAA,CAAQ,QAAQ,EAC9C,WAAA,CAAY,kCAAkC,CAAA,CAC9C,MAAA,CAAO,oBAAA,EAAsB,4BAA4B,EACzD,MAAA,CAAO,QAAA,EAAU,iCAAiC,CAAA,CAClD,MAAA,CAAO,YAAY,uCAAuC,CAAA,CAC1D,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AAoBH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GAAS,MAAMC,UAAAA,EAAW;AAGhC,IAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,MAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACjC,QAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,MACpC;AAEA,MAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AACtD,MAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,QAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,MACpC;AACA,MAAA,MAAM,cAAA,GAAyB;AAAA,QAC7B,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,QAAQ,EAAE,CAAC,OAAA,CAAQ,KAAK,GAAG,kBAAA;AAAmB,OAChD;AAGA,MAAA,MAAMU,OAAAA,GAAS,MAAM,kBAAA,CAAmB,EAAE,QAAQ,gBAAA,CAAiB,cAAc,GAAG,CAAA;AAGpF,MAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,QAAA,UAAA,CAAWA,OAAM,CAAA;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,cAAA,CAAeA,OAAAA,EAAQ,cAAA,CAAe,QAAA,CAAS,UAAA,EAAY,QAAQ,MAAM,CAAA;AAAA,MAC3E;AAGA,MAAA,IAAI,CAACA,QAAO,OAAA,EAAS;AACnB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,QAAQ,MAAA,IAAU,WAAA,CAAYA,SAAQ,cAAA,CAAe,QAAA,CAAS,UAAU,CAAA,EAAG;AAC7E,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,kBAAA,CAAmB,EAAE,QAAQ,gBAAA,CAAiB,MAAM,GAAG,CAAA;AAG5E,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,UAAA,CAAW,MAAM,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,MAAA,EAAQ,MAAA,CAAO,QAAA,CAAS,UAAA,EAAY,QAAQ,MAAM,CAAA;AAAA,IACnE;AAGA,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B;AAEA,IAAA,IAAI,QAAQ,MAAA,IAAU,WAAA,CAAY,QAAQ,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,EAAG;AACrE,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF;AAYA,SAAS,cAAA,CAAe,MAAA,EAAsB,UAAA,EAAoB,MAAA,EAAwB;AACxF,EAAA,GAAA,CAAI,EAAE,CAAA;AAGN,EAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC1B,IAAA,KAAA,CAAM,+BAA+B,CAAA;AACrC,IAAA,GAAA,CAAI,oDAAoD,CAAA;AACxD,IAAA,GAAA,CAAI,EAAE,CAAA;AAAA,EACR;AAGA,EAAA,KAAA,MAAW,QAAA,IAAY,OAAO,MAAA,EAAQ;AACpC,IAAA,KAAA,CAAM,QAAQ,CAAA;AAAA,EAChB;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AAC5B,IAAA,GAAA,CAAI,EAAE,CAAA;AAAA,EACR;AAGA,EAAA,MAAM,SAAA,GAAwB,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACtD,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,MAAA,EAAQ,cAAA,CAAe,CAAA,CAAE,MAAM,CAAA;AAAA,IAC/B,aAAa,CAAA,CAAE,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAAA,IAC1C,GAAA,EAAK,gBAAgB,CAAC;AAAA,GACxB,CAAE,CAAA;AAEF,EAAA,GAAA,CAAI,WAAA,CAAY,SAAS,CAAC,CAAA;AAC1B,EAAA,GAAA,CAAI,EAAE,CAAA;AAGN,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAA,CAAQ,wBAAwB,CAAA;AAAA,EAClC,CAAA,MAAO;AAEL,IAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAEzE,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,MAAA,GAAA,CAAI,cAAc,CAAA;AAClB,MAAA,KAAA,MAAW,SAAS,gBAAA,EAAkB;AACpC,QAAA,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAA,CAAM,KAAK,CAAA,CAAE,CAAA;AAC5C,QAAA,IAAI,MAAM,OAAA,EAAS;AACjB,UAAA,GAAA,CAAI,CAAA,IAAA,EAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,MAAM,UAAA,GAAa,OAAO,MAAA,CAAO,MAAA;AAAA,IAC/B,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,GAAA,IAAO,KAAK,UAAA,GAAa;AAAA,GAC7D;AAEA,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,KAAA,MAAW,SAAS,UAAA,EAAY;AAC9B,MAAA,IAAA,CAAK,CAAA,EAAG,MAAM,KAAK,CAAA,iCAAA,EAAoC,OAAO,KAAA,CAAM,GAAG,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,IACtF;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,iDAAiD,CAAA;AAAA,IACvD;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,CAAA,EAAoC;AAC3D,EAAA,IAAI,CAAA,CAAE,WAAW,OAAA,EAAS;AACxB,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,GAAA,IAAO,CAAC,CAAC,CAAA,KAAA,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,mBAAA,EAAqB;AACpC,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,SAAA,EAAW;AAC1B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,GAAA,IAAO,CAAC,CAAC,CAAA,eAAA,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,qBAAA,EAAuB;AACtC,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,uBAAA,EAAyB;AACxC,IAAA,OAAO,eAAA;AAAA,EACT;AAEA,EAAA,OAAO,GAAA;AACT;AAaA,SAAS,WAAA,CAAY,QAAsB,UAAA,EAA6B;AACtE,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,OAAO,OAAO,MAAA,CAAO,IAAA;AAAA,IACnB,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,GAAA,IAAO,KAAK,UAAA,GAAa;AAAA,GAC7D;AACF;;;ACvOA,IAAM,OAAA,GAAU,IAAIX,OAAAA,EAAQ;AAE5B,OAAA,CACG,KAAK,WAAW,CAAA,CAChB,YAAY,qCAAqC,CAAA,CACjD,QAAQ,OAAO,CAAA,CACf,OAAO,qBAAA,EAAuB,qBAAqB,EACnD,MAAA,CAAO,eAAA,EAAiB,gBAAgB,CAAA,CACxC,MAAA,CAAO,eAAe,gBAAgB,CAAA;AAGzC,OAAA,CAAQ,WAAW,WAAW,CAAA;AAC9B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAChC,OAAA,CAAQ,WAAW,UAAU,CAAA;AAC7B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAChC,OAAA,CAAQ,WAAW,YAAY,CAAA;AAC/B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAEzB,SAAS,GAAA,GAAY;AAE1B,EAAA,OAAA,CAAQ,KAAA,EAAM;AACd,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,EAA6C;AAErE,EAAA,MAAM,gBAAwD,EAAC;AAC/D,EAAA,IAAI,OAAA,CAAQ,YAAY,MAAA,EAAW;AACjC,IAAA,aAAA,CAAc,UAAU,OAAA,CAAQ,OAAA;AAAA,EAClC;AACA,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW;AAC/B,IAAA,aAAA,CAAc,QAAQ,OAAA,CAAQ,KAAA;AAAA,EAChC;AAEA,EAAA,gBAAA,CAAiB,aAAa,CAAA;AAChC;;;ACvCA,GAAA,EAAI","file":"attest-it.js","sourcesContent":["import pc from 'picocolors'\n\nexport interface OutputOptions {\n verbose?: boolean\n quiet?: boolean\n json?: boolean\n}\n\n// Singleton for global output options\nlet globalOptions: OutputOptions = {}\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOptions = options\n}\n\nexport function getOutputOptions(): OutputOptions {\n return globalOptions\n}\n\n// Logging functions\nexport function log(message: string): void {\n if (!globalOptions.quiet) {\n console.log(message)\n }\n}\n\nexport function verbose(message: string): void {\n if (globalOptions.verbose && !globalOptions.quiet) {\n console.log(pc.dim(message))\n }\n}\n\nexport function success(message: string): void {\n log(pc.green('✓ ' + message))\n}\n\nexport function error(message: string): void {\n console.error(pc.red('✗ ' + message))\n}\n\nexport function warn(message: string): void {\n if (!globalOptions.quiet) {\n console.warn(pc.yellow('⚠ ' + message))\n }\n}\n\nexport function info(message: string): void {\n log(pc.blue('ℹ ' + message))\n}\n\n// Table formatting for status display\nexport interface TableRow {\n suite: string\n status: string\n fingerprint: string\n age: string\n}\n\nexport function formatTable(rows: TableRow[]): string {\n // Calculate column widths\n const headers = ['Suite', 'Status', 'Fingerprint', 'Age']\n\n // Helper to get row values in consistent order\n const getRowValues = (row: TableRow): string[] => [\n row.suite,\n row.status,\n row.fingerprint,\n row.age,\n ]\n\n const widths = headers.map((h, i) => {\n const columnValues = rows.map((r) => {\n const values = getRowValues(r)\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n return values[i] ?? ''\n })\n const maxValueLength = Math.max(...columnValues.map((v) => v.length), 0)\n return Math.max(h.length, maxValueLength)\n })\n\n // Build table\n const separator = '─'\n const lines: string[] = []\n\n // Header\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n lines.push(headers.map((h, i) => h.padEnd(widths[i] ?? 0)).join(' │ '))\n lines.push(widths.map((w) => separator.repeat(w)).join('─┼─'))\n\n // Rows\n for (const row of rows) {\n const values = getRowValues(row)\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n lines.push(values.map((v, i) => v.padEnd(widths[i] ?? 0)).join(' │ '))\n }\n\n return lines.join('\\n')\n}\n\n// Status colorization\nexport function colorizeStatus(status: string): string {\n switch (status) {\n case 'VALID':\n return pc.green(status)\n case 'NEEDS_ATTESTATION':\n case 'FINGERPRINT_CHANGED':\n return pc.yellow(status)\n case 'EXPIRED':\n case 'INVALIDATED_BY_PARENT':\n return pc.red(status)\n case 'SIGNATURE_INVALID':\n return pc.red(pc.bold(status))\n default:\n return status\n }\n}\n\n// JSON output\nexport function outputJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2))\n}\n","import { confirm, input, select } from '@inquirer/prompts'\n\nexport interface ConfirmOptions {\n message: string\n default?: boolean\n}\n\nexport async function confirmAction(options: ConfirmOptions): Promise<boolean> {\n return confirm({\n message: options.message,\n default: options.default ?? false,\n })\n}\n\nexport interface SelectOptions<T extends string> {\n message: string\n choices: { value: T; name: string; description?: string }[]\n}\n\nexport async function selectOption<T extends string>(options: SelectOptions<T>): Promise<T> {\n return select({\n message: options.message,\n choices: options.choices,\n })\n}\n\nexport interface InputOptions {\n message: string\n default?: string\n validate?: (value: string) => boolean | string\n}\n\nexport async function getInput(options: InputOptions): Promise<string> {\n const inputConfig: {\n message: string\n default?: string\n validate?: (value: string) => boolean | string\n } = {\n message: options.message,\n }\n\n if (options.default !== undefined) {\n inputConfig.default = options.default\n }\n\n if (options.validate !== undefined) {\n inputConfig.validate = options.validate\n }\n\n return input(inputConfig)\n}\n","/**\n * Standard exit codes for the attest-it CLI.\n *\n * These codes follow Unix conventions and provide consistent error reporting\n * across all CLI commands.\n *\n * @packageDocumentation\n */\n\n/**\n * Standard exit codes for the attest-it CLI.\n * @public\n */\nexport const ExitCode = {\n /** Operation completed successfully */\n SUCCESS: 0,\n /** Tests failed or attestation invalid */\n FAILURE: 1,\n /** Configuration or validation error */\n CONFIG_ERROR: 2,\n /** User cancelled the operation */\n CANCELLED: 3,\n /** Missing required key file */\n MISSING_KEY: 4,\n} as const\n\n/**\n * Type representing all possible exit codes.\n * @public\n */\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode]\n","import { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport YAML from 'yaml'\nimport { log, success, error, info } from '../utils/output.js'\nimport { confirmAction, getInput, selectOption } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const initCommand = new Command('init')\n .description('Initialize attest-it configuration')\n .option('-p, --path <path>', 'Config file path', '.attest-it/config.yaml')\n .option('-f, --force', 'Overwrite existing config')\n .option('--json', 'Output JSON instead of YAML')\n .action(async (options: InitOptions) => {\n await runInit(options)\n })\n\ninterface InitOptions {\n path: string\n force?: boolean\n json?: boolean\n}\n\ninterface SuiteInput {\n name: string\n description: string\n packages: string[]\n command: string\n}\n\ninterface ConfigSuite {\n description?: string\n packages: string[]\n command: string\n}\n\ninterface Config {\n version: number\n settings: {\n maxAgeDays: number\n publicKeyPath: string\n attestationsPath: string\n algorithm: string\n }\n suites: Record<string, ConfigSuite>\n}\n\n/**\n * Run the init command to create a new attest-it configuration.\n *\n * Interactively prompts the user for settings and suite configurations,\n * then creates a configuration file in the specified location.\n *\n * @param options - Command options\n * @param options.path - Config file path (default: .attest-it/config.yaml)\n * @param options.force - Overwrite existing config without prompting\n * @param options.json - Output JSON instead of YAML\n * @public\n */\nasync function runInit(options: InitOptions): Promise<void> {\n try {\n // Check if config already exists\n const configPath = path.resolve(options.path)\n const configDir = path.dirname(configPath)\n\n if (fs.existsSync(configPath) && !options.force) {\n const overwrite = await confirmAction({\n message: `Config already exists at ${configPath}. Overwrite?`,\n default: false,\n })\n if (!overwrite) {\n error('Init cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n }\n\n log('')\n info('Welcome to attest-it!')\n log('This will create a configuration file for human-gated test attestations.')\n log('')\n\n // Gather settings\n const maxAgeDays = await getInput({\n message: 'Maximum attestation age (days):',\n default: '30',\n validate: (v) => {\n const n = parseInt(v, 10)\n return !isNaN(n) && n > 0 ? true : 'Must be a positive number'\n },\n })\n\n const algorithm = await selectOption({\n message: 'Signing algorithm:',\n choices: [\n {\n value: 'ed25519',\n name: 'Ed25519 (Recommended)',\n description: 'Fast, modern, secure',\n },\n { value: 'rsa', name: 'RSA', description: 'Broader compatibility' },\n ],\n })\n\n // Gather suites\n const suites: SuiteInput[] = []\n let addMore = true\n\n log('')\n info('Now configure your test suites.')\n log('Suites are groups of tests that require human verification.')\n log('')\n\n while (addMore) {\n const suiteName = await getInput({\n message: 'Suite name:',\n validate: (v) => (v.length > 0 ? true : 'Required'),\n })\n\n const description = await getInput({\n message: 'Description (optional):',\n })\n\n const packagesInput = await getInput({\n message: 'Package paths (comma-separated):',\n default: `packages/${suiteName}`,\n validate: (v) => (v.length > 0 ? true : 'At least one package required'),\n })\n\n const command = await getInput({\n message: 'Test command:',\n default: `pnpm vitest ${packagesInput.split(',')[0]?.trim() ?? ''}`,\n })\n\n suites.push({\n name: suiteName,\n description,\n packages: packagesInput\n .split(',')\n .map((p) => p.trim())\n .filter(Boolean),\n command,\n })\n\n addMore = await confirmAction({\n message: 'Add another suite?',\n default: false,\n })\n }\n\n if (suites.length === 0) {\n error('At least one suite is required')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Build config object\n const config: Config = {\n version: 1,\n settings: {\n maxAgeDays: parseInt(maxAgeDays, 10),\n publicKeyPath: '.attest-it/pubkey.pem',\n attestationsPath: '.attest-it/attestations.json',\n algorithm,\n },\n suites: Object.fromEntries(\n suites.map((s) => {\n const suite: ConfigSuite = {\n packages: s.packages,\n command: s.command,\n }\n // Only add description if it's not empty\n if (s.description) {\n suite.description = s.description\n }\n return [s.name, suite]\n }),\n ),\n }\n\n // Create directory\n await fs.promises.mkdir(configDir, { recursive: true })\n\n // Write config\n const content = options.json\n ? JSON.stringify(config, null, 2)\n : YAML.stringify(config, { indent: 2 })\n\n await fs.promises.writeFile(configPath, content, 'utf-8')\n\n // Create .gitkeep for attestations directory\n const attestDir = path.dirname(\n path.resolve(path.dirname(configPath), config.settings.attestationsPath),\n )\n await fs.promises.mkdir(attestDir, { recursive: true })\n\n success(`Configuration created at ${configPath}`)\n log('')\n log('Next steps:')\n log(' 1. Review and edit the configuration as needed')\n log(' 2. Run: attest-it keygen')\n log(' 3. Run: attest-it run --suite <suite-name>')\n log(' 4. Commit the attestation file')\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nexport { runInit }\n","import { Command } from 'commander'\nimport {\n loadConfig,\n computeFingerprint,\n readAttestations,\n findAttestation,\n type VerificationStatus,\n type AttestationsFile,\n type Attestation,\n} from '@attest-it/core'\nimport {\n log,\n success,\n error,\n formatTable,\n colorizeStatus,\n outputJson,\n type TableRow,\n} from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const statusCommand = new Command('status')\n .description('Show attestation status for all suites')\n .option('-s, --suite <name>', 'Show status for specific suite only')\n .option('--json', 'Output JSON for machine parsing')\n .action(async (options: StatusOptions) => {\n await runStatus(options)\n })\n\ninterface StatusOptions {\n suite?: string\n json?: boolean\n}\n\ninterface SuiteStatus {\n name: string\n status: VerificationStatus\n currentFingerprint: string\n attestedFingerprint?: string | undefined\n attestedAt?: string | undefined\n age?: number | undefined\n}\n\n/**\n * Run the status command to show attestation status.\n *\n * Displays the current status of attestations for all suites or a specific suite,\n * including validation status, fingerprints, and age information.\n *\n * @param options - Command options\n * @param options.suite - Show status for specific suite only\n * @param options.json - Output JSON for machine parsing\n * @public\n */\nasync function runStatus(options: StatusOptions): Promise<void> {\n try {\n // Load config\n const config = await loadConfig()\n\n // Load attestations (may not exist)\n const attestationsPath = config.settings.attestationsPath\n let attestationsFile: AttestationsFile | null = null\n try {\n attestationsFile = await readAttestations(attestationsPath)\n } catch (err) {\n // Attestations file may not exist yet - that's okay\n if (err instanceof Error && !err.message.includes('ENOENT')) {\n throw err\n }\n }\n const attestations = attestationsFile?.attestations ?? []\n\n // Get suites to check\n const suiteNames = options.suite ? [options.suite] : Object.keys(config.suites)\n\n // Validate suite exists\n if (options.suite && !config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Check each suite\n const results: SuiteStatus[] = []\n let hasInvalid = false\n\n for (const suiteName of suiteNames) {\n // eslint-disable-next-line security/detect-object-injection\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) continue\n\n // Compute current fingerprint\n const fingerprintResult = await computeFingerprint({\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n })\n\n // Find existing attestation\n const attestation = findAttestation(\n {\n schemaVersion: '1',\n attestations,\n signature: '',\n },\n suiteName,\n )\n\n // Determine status\n const status = determineStatus(\n attestation ?? null,\n fingerprintResult.fingerprint,\n config.settings.maxAgeDays,\n )\n\n // Calculate age if attestation exists\n let age: number | undefined\n if (attestation) {\n const attestedAt = new Date(attestation.attestedAt)\n age = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n }\n\n if (status !== 'VALID') {\n hasInvalid = true\n }\n\n results.push({\n name: suiteName,\n status,\n currentFingerprint: fingerprintResult.fingerprint,\n attestedFingerprint: attestation?.fingerprint,\n attestedAt: attestation?.attestedAt,\n age,\n })\n }\n\n // Output results\n if (options.json) {\n outputJson(results)\n } else {\n displayStatusTable(results, hasInvalid)\n }\n\n process.exit(hasInvalid ? ExitCode.FAILURE : ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nfunction determineStatus(\n attestation: Attestation | null,\n currentFingerprint: string,\n maxAgeDays: number,\n): VerificationStatus {\n if (!attestation) {\n return 'NEEDS_ATTESTATION'\n }\n\n if (attestation.fingerprint !== currentFingerprint) {\n return 'FINGERPRINT_CHANGED'\n }\n\n const attestedAt = new Date(attestation.attestedAt)\n const ageInDays = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n\n if (ageInDays > maxAgeDays) {\n return 'EXPIRED'\n }\n\n return 'VALID'\n}\n\nfunction displayStatusTable(results: SuiteStatus[], hasInvalid: boolean): void {\n const tableRows: TableRow[] = results.map((r) => ({\n suite: r.name,\n status: colorizeStatus(r.status),\n fingerprint: r.currentFingerprint.slice(0, 16) + '...',\n age: formatAge(r),\n }))\n\n log('')\n log(formatTable(tableRows))\n log('')\n\n if (hasInvalid) {\n log('Run `attest-it run --suite <name>` to update attestations')\n } else {\n success('All attestations valid')\n }\n}\n\nfunction formatAge(result: SuiteStatus): string {\n if (result.status === 'VALID') {\n return `${String(result.age ?? 0)} days`\n }\n\n if (result.status === 'FINGERPRINT_CHANGED') {\n return '(changed)'\n }\n\n if (result.status === 'NEEDS_ATTESTATION') {\n return '(none)'\n }\n\n if (result.status === 'EXPIRED') {\n return `${String(result.age ?? 0)} days (expired)`\n }\n\n return '-'\n}\n\nexport { runStatus }\n","/**\n * Run command implementation for attest-it CLI.\n */\n\nimport { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport { parse as parseShellCommand } from 'shell-quote'\nimport {\n loadConfig,\n computeFingerprint,\n readAttestations,\n writeSignedAttestations,\n upsertAttestation,\n createAttestation,\n getDefaultPrivateKeyPath,\n type Config,\n} from '@attest-it/core'\nimport { log, success, error, warn, verbose } from '../utils/output.js'\nimport { confirmAction } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const runCommand = new Command('run')\n .description('Execute tests and create attestation')\n .option('-s, --suite <name>', 'Run specific suite (required unless --all)')\n .option('-a, --all', 'Run all suites needing attestation')\n .option('--no-attest', 'Run tests without creating attestation')\n .option('-y, --yes', 'Skip confirmation prompt')\n .action(async (options: RunOptions) => {\n await runTests(options)\n })\n\ninterface RunOptions {\n suite?: string\n all?: boolean\n attest?: boolean // Note: --no-attest sets this to false\n yes?: boolean\n}\n\n/**\n * Run tests and create attestations.\n *\n * Executes test commands for specified suite(s), computes fingerprints,\n * and creates signed attestations upon successful test completion.\n *\n * @param options - Command options\n * @param options.suite - Run specific suite (required unless --all)\n * @param options.all - Run all suites needing attestation\n * @param options.attest - Create attestation after tests (default: true)\n * @param options.yes - Skip confirmation prompt\n * @public\n */\nasync function runTests(options: RunOptions): Promise<void> {\n try {\n // Validate options\n if (!options.suite && !options.all) {\n error('Either --suite or --all is required')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Load config\n const config = await loadConfig()\n\n // Determine which suites to run\n const suitesToRun = options.all\n ? Object.keys(config.suites)\n : options.suite\n ? [options.suite]\n : []\n\n // Validate suite exists\n if (options.suite && !config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Check for dirty working tree\n const isDirty = await checkDirtyWorkingTree()\n if (isDirty) {\n error('Working tree has uncommitted changes. Please commit or stash before attesting.')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Process each suite\n for (const suiteName of suitesToRun) {\n // eslint-disable-next-line security/detect-object-injection -- suiteName is from validated config keys\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) continue\n\n log(`\\n=== Running suite: ${suiteName} ===\\n`)\n\n // Compute fingerprint before running\n const fingerprintOptions = {\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const fingerprintResult = await computeFingerprint(fingerprintOptions)\n verbose(`Fingerprint: ${fingerprintResult.fingerprint}`)\n verbose(`Files: ${String(fingerprintResult.fileCount)}`)\n\n // Build the test command\n const command = buildCommand(config, suiteConfig.command, suiteConfig.files)\n log(`Running: ${command}`)\n log('')\n\n // Execute tests\n const exitCode = await executeCommand(command)\n\n if (exitCode !== 0) {\n error(`Tests failed with exit code ${String(exitCode)}`)\n process.exit(ExitCode.FAILURE)\n }\n\n success('Tests passed!')\n\n // Skip attestation if --no-attest\n if (options.attest === false) {\n log('Skipping attestation (--no-attest)')\n continue\n }\n\n // Confirm attestation\n const shouldAttest =\n options.yes ??\n (await confirmAction({\n message: 'Create attestation?',\n default: true,\n }))\n\n if (!shouldAttest) {\n warn('Attestation cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n\n // Create attestation\n const attestation = createAttestation({\n suite: suiteName,\n fingerprint: fingerprintResult.fingerprint,\n command,\n attestedBy: os.userInfo().username,\n })\n\n // Load existing attestations\n const attestationsPath = config.settings.attestationsPath\n const existingFile = await readAttestations(attestationsPath)\n const existingAttestations = existingFile?.attestations ?? []\n\n // Upsert the new attestation\n const newAttestations = upsertAttestation(existingAttestations, attestation)\n\n // Get private key path (from config or default)\n const privateKeyPath = getDefaultPrivateKeyPath()\n\n // Check if private key exists\n if (!fs.existsSync(privateKeyPath)) {\n error(`Private key not found: ${privateKeyPath}`)\n error('Run \"attest-it keygen\" first to generate a keypair.')\n process.exit(ExitCode.MISSING_KEY)\n }\n\n // Write signed attestations\n await writeSignedAttestations({\n filePath: attestationsPath,\n attestations: newAttestations,\n privateKeyPath,\n })\n\n success(`Attestation created for ${suiteName}`)\n log(` Fingerprint: ${fingerprintResult.fingerprint}`)\n log(` Attested by: ${attestation.attestedBy}`)\n log(` Attested at: ${attestation.attestedAt}`)\n }\n\n log('')\n success('All suites completed!')\n log(\n `\\nTo commit: git add ${config.settings.attestationsPath} && git commit -m \"Update attestations\"`,\n )\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\n/**\n * Build the test command to execute.\n *\n * Uses suite-specific command if provided, otherwise falls back to\n * default command from settings. Substitutes ${files} placeholder\n * with suite file patterns.\n *\n * @param config - Configuration object\n * @param suiteCommand - Suite-specific command (optional)\n * @param suiteFiles - File patterns for suite (optional)\n * @returns Constructed command string\n * @public\n */\nfunction buildCommand(config: Config, suiteCommand?: string, suiteFiles?: string[]): string {\n // Use suite command if specified, otherwise default\n let command = suiteCommand ?? config.settings.defaultCommand\n\n if (!command) {\n error('No command specified for suite and no defaultCommand in settings')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Substitute ${files} if present (replace all occurrences)\n if (command.includes('${files}') && suiteFiles) {\n const files = suiteFiles.join(' ')\n command = command.replaceAll('${files}', files)\n }\n\n return command\n}\n\n/**\n * Parsed command result.\n */\ninterface ParsedCommand {\n executable: string\n args: string[]\n}\n\n/**\n * Parse a command string into executable and arguments.\n *\n * Uses shell-quote to safely parse shell syntax without using shell: true.\n *\n * @param command - Command string to parse\n * @returns Parsed command with executable and arguments\n * @throws Error if command is empty or contains only control operators\n * @public\n */\nfunction parseCommand(command: string): ParsedCommand {\n const parsed = parseShellCommand(command)\n\n // shell-quote returns an array of strings and special control operators\n // We only want the string arguments\n const stringArgs = parsed.filter((token): token is string => {\n return typeof token === 'string'\n })\n\n if (stringArgs.length === 0) {\n throw new Error('Command string is empty or contains only control operators')\n }\n\n const [executable, ...args] = stringArgs\n // TypeScript doesn't know that stringArgs.length > 0 guarantees executable is defined\n // The check above ensures stringArgs[0] exists, but we assert it for type safety\n if (executable === undefined) {\n throw new Error('Command string is empty or contains only control operators')\n }\n\n return { executable, args }\n}\n\n/**\n * Execute a command and return its exit code.\n *\n * Spawns a child process and streams output to the terminal.\n *\n * @param command - Command string to execute\n * @returns Exit code from the command (0 for success)\n * @public\n */\nasync function executeCommand(command: string): Promise<number> {\n return new Promise((resolve) => {\n let parsed: ParsedCommand\n try {\n parsed = parseCommand(command)\n } catch (err) {\n if (err instanceof Error) {\n error(`Failed to parse command: ${err.message}`)\n } else {\n error('Failed to parse command: Unknown error')\n }\n resolve(1)\n return\n }\n\n const child = spawn(parsed.executable, parsed.args, {\n stdio: 'inherit', // Stream output to terminal\n })\n\n child.on('close', (code) => {\n resolve(code ?? 1)\n })\n\n child.on('error', (err) => {\n error(`Failed to execute command: ${err.message}`)\n resolve(1)\n })\n })\n}\n\n/**\n * Check if the git working tree has uncommitted changes.\n *\n * @returns True if there are uncommitted changes, false otherwise\n * @public\n */\nasync function checkDirtyWorkingTree(): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn('git', ['status', '--porcelain'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let output = ''\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString()\n })\n\n child.on('close', () => {\n // If output is non-empty, there are uncommitted changes\n resolve(output.trim().length > 0)\n })\n\n child.on('error', () => {\n // If git not available, assume not dirty\n resolve(false)\n })\n })\n}\n\n// Export for testing\nexport { buildCommand, parseCommand, executeCommand, checkDirtyWorkingTree }\n","import { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport {\n checkOpenSSL,\n generateKeyPair,\n getDefaultPrivateKeyPath,\n getDefaultPublicKeyPath,\n setKeyPermissions,\n} from '@attest-it/core'\nimport { log, success, error, warn, info } from '../utils/output.js'\nimport { confirmAction } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const keygenCommand = new Command('keygen')\n .description('Generate a new RSA keypair for signing attestations')\n .option('-o, --output <path>', 'Private key output path')\n .option('-p, --public <path>', 'Public key output path')\n .option('-f, --force', 'Overwrite existing keys')\n .action(async (options: KeygenOptions) => {\n await runKeygen(options)\n })\n\ninterface KeygenOptions {\n output?: string\n public?: string\n force?: boolean\n}\n\n/**\n * Run the keygen command to generate a new cryptographic keypair.\n *\n * Generates an RSA-2048 keypair with SHA-256 signatures, which is universally\n * supported across all OpenSSL and LibreSSL versions.\n *\n * @param options - Command options\n * @param options.output - Private key output path\n * @param options.public - Public key output path\n * @param options.force - Overwrite existing keys without prompting\n * @public\n */\nasync function runKeygen(options: KeygenOptions): Promise<void> {\n try {\n // Check OpenSSL\n log('Checking OpenSSL...')\n const version = await checkOpenSSL()\n info(`OpenSSL: ${version}`)\n\n // Determine paths\n const privatePath = options.output ?? getDefaultPrivateKeyPath()\n const publicPath = options.public ?? getDefaultPublicKeyPath()\n\n log(`Private key: ${privatePath}`)\n log(`Public key: ${publicPath}`)\n\n // Check if keys already exist\n const privateExists = fs.existsSync(privatePath)\n const publicExists = fs.existsSync(publicPath)\n\n if ((privateExists || publicExists) && !options.force) {\n if (privateExists) {\n warn(`Private key already exists: ${privatePath}`)\n }\n if (publicExists) {\n warn(`Public key already exists: ${publicPath}`)\n }\n\n const shouldOverwrite = await confirmAction({\n message: 'Overwrite existing keys?',\n default: false,\n })\n\n if (!shouldOverwrite) {\n error('Keygen cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n }\n\n // Generate keypair\n log('\\nGenerating RSA-2048 keypair...')\n\n const result = await generateKeyPair({\n privatePath,\n publicPath,\n force: true,\n })\n\n // Set permissions on private key\n await setKeyPermissions(result.privatePath)\n\n success('Keypair generated successfully!')\n log('')\n log('Private key (KEEP SECRET):')\n log(` ${result.privatePath}`)\n log('')\n log('Public key (commit to repo):')\n log(` ${result.publicPath}`)\n log('')\n info('Important: Back up your private key securely!')\n log('')\n log('Next steps:')\n log(` 1. git add ${result.publicPath}`)\n log(' 2. Update .attest-it/config.yaml publicKeyPath if needed')\n log(' 3. attest-it run --suite <suite-name>')\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nexport { runKeygen }\n","/**\n * Prune command implementation for attest-it CLI.\n */\n\nimport { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport {\n loadConfig,\n readAttestations,\n writeSignedAttestations,\n computeFingerprint,\n getDefaultPrivateKeyPath,\n type Attestation,\n} from '@attest-it/core'\nimport { log, success, error, info, verbose } from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const pruneCommand = new Command('prune')\n .description('Remove stale attestations')\n .option('-n, --dry-run', 'Show what would be removed without removing')\n .option('-k, --keep-days <n>', 'Keep attestations newer than n days', '30')\n .action(async (options: PruneOptions) => {\n await runPrune(options)\n })\n\ninterface PruneOptions {\n dryRun?: boolean\n keepDays: string\n}\n\n/**\n * Run the prune command to remove stale attestations.\n *\n * Removes attestations that are outdated (older than keepDays and\n * fingerprint doesn't match current code) or orphaned (suite no\n * longer exists in config). Re-signs the attestations file.\n *\n * @param options - Command options\n * @param options.dryRun - Show what would be removed without removing\n * @param options.keepDays - Keep attestations newer than n days\n * @public\n */\nasync function runPrune(options: PruneOptions): Promise<void> {\n try {\n const keepDays = parseInt(options.keepDays, 10)\n if (isNaN(keepDays) || keepDays < 1) {\n error('--keep-days must be a positive integer')\n process.exit(ExitCode.CONFIG_ERROR)\n return\n }\n\n // Load config\n const config = await loadConfig()\n\n // Load attestations\n const attestationsPath = config.settings.attestationsPath\n const file = await readAttestations(attestationsPath)\n\n if (!file || file.attestations.length === 0) {\n info('No attestations to prune')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n const now = Date.now()\n const keepMs = keepDays * 24 * 60 * 60 * 1000\n\n // Identify stale attestations\n const stale: Attestation[] = []\n const keep: Attestation[] = []\n\n for (const attestation of file.attestations) {\n const attestedAt = new Date(attestation.attestedAt).getTime()\n const ageMs = now - attestedAt\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))\n\n // Check if suite still exists in config\n const suiteExists = attestation.suite in config.suites\n\n // Check if fingerprint still matches current code\n let fingerprintMatches = false\n if (suiteExists) {\n const suiteConfig = config.suites[attestation.suite]\n if (suiteConfig) {\n const fingerprintOptions = {\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const result = await computeFingerprint(fingerprintOptions)\n fingerprintMatches = result.fingerprint === attestation.fingerprint\n }\n }\n\n // Keep if:\n // 1. Age is within keepDays AND fingerprint matches, OR\n // 2. Fingerprint matches current code (regardless of age)\n const isStale = !fingerprintMatches && ageMs > keepMs\n const orphaned = !suiteExists\n\n if (isStale || orphaned) {\n stale.push(attestation)\n const reason = orphaned\n ? 'suite removed'\n : !fingerprintMatches\n ? 'fingerprint changed'\n : 'expired'\n verbose(`Stale: ${attestation.suite} (${reason}, ${String(ageDays)} days old)`)\n } else {\n keep.push(attestation)\n }\n }\n\n // Report what will be pruned\n if (stale.length === 0) {\n success('No stale attestations found')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n log(`Found ${String(stale.length)} stale attestation(s):`)\n for (const attestation of stale) {\n const ageDays = Math.floor(\n (now - new Date(attestation.attestedAt).getTime()) / (1000 * 60 * 60 * 24),\n )\n log(` - ${attestation.suite} (${String(ageDays)} days old)`)\n }\n\n if (options.dryRun) {\n info('Dry run - no changes made')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n // Check for private key\n const privateKeyPath = getDefaultPrivateKeyPath()\n if (!fs.existsSync(privateKeyPath)) {\n error(`Private key not found: ${privateKeyPath}`)\n error('Cannot re-sign attestations file.')\n process.exit(ExitCode.MISSING_KEY)\n return\n }\n\n // Write updated attestations\n await writeSignedAttestations({\n filePath: attestationsPath,\n attestations: keep,\n privateKeyPath,\n })\n\n success(`Pruned ${String(stale.length)} stale attestation(s)`)\n log(`Remaining: ${String(keep.length)} attestation(s)`)\n process.exit(ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(2)\n return\n }\n}\n\nexport { runPrune }\n","import { Command } from 'commander'\nimport {\n loadConfig,\n toAttestItConfig,\n verifyAttestations,\n type Config,\n type VerifyResult,\n type SuiteVerificationResult,\n} from '@attest-it/core'\nimport {\n log,\n success,\n error,\n warn,\n formatTable,\n colorizeStatus,\n outputJson,\n type TableRow,\n} from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const verifyCommand = new Command('verify')\n .description('Verify all attestations (for CI)')\n .option('-s, --suite <name>', 'Verify specific suite only')\n .option('--json', 'Output JSON for machine parsing')\n .option('--strict', 'Fail on warnings (approaching expiry)')\n .action(async (options: VerifyOptions) => {\n await runVerify(options)\n })\n\ninterface VerifyOptions {\n suite?: string\n json?: boolean\n strict?: boolean\n}\n\n/**\n * Run the verify command to validate attestations.\n *\n * Verifies signature validity and checks attestation status for all suites\n * or a specific suite. Intended for CI/CD pipelines.\n *\n * @param options - Command options\n * @param options.suite - Verify specific suite only\n * @param options.json - Output JSON for machine parsing\n * @param options.strict - Fail on warnings (approaching expiry)\n * @public\n */\nasync function runVerify(options: VerifyOptions): Promise<void> {\n try {\n // Load config\n const config = await loadConfig()\n\n // Filter to specific suite if requested\n if (options.suite) {\n if (!config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n // Create filtered config\n const filteredSuiteEntry = config.suites[options.suite]\n if (!filteredSuiteEntry) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n const filteredConfig: Config = {\n version: config.version,\n settings: config.settings,\n suites: { [options.suite]: filteredSuiteEntry },\n }\n\n // Run verification with filtered config, converting from Zod Config to AttestItConfig\n const result = await verifyAttestations({ config: toAttestItConfig(filteredConfig) })\n\n // Output results\n if (options.json) {\n outputJson(result)\n } else {\n displayResults(result, filteredConfig.settings.maxAgeDays, options.strict)\n }\n\n // Determine exit code\n if (!result.success) {\n process.exit(ExitCode.FAILURE)\n return\n }\n\n if (options.strict && hasWarnings(result, filteredConfig.settings.maxAgeDays)) {\n process.exit(ExitCode.FAILURE)\n return\n }\n\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n // Run verification with full config, converting from Zod Config to AttestItConfig\n const result = await verifyAttestations({ config: toAttestItConfig(config) })\n\n // Output results\n if (options.json) {\n outputJson(result)\n } else {\n displayResults(result, config.settings.maxAgeDays, options.strict)\n }\n\n // Determine exit code\n if (!result.success) {\n process.exit(ExitCode.FAILURE)\n }\n\n if (options.strict && hasWarnings(result, config.settings.maxAgeDays)) {\n process.exit(ExitCode.FAILURE)\n }\n\n process.exit(ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(2)\n }\n}\n\n/**\n * Display verification results in a formatted table.\n *\n * Shows signature status, errors, suite results, and remediation steps.\n *\n * @param result - Verification result from verifyAttestations\n * @param maxAgeDays - Maximum age in days before expiry\n * @param strict - Whether to show warnings as errors\n * @public\n */\nfunction displayResults(result: VerifyResult, maxAgeDays: number, strict?: boolean): void {\n log('')\n\n // Signature status\n if (!result.signatureValid) {\n error('Signature verification FAILED')\n log('The attestations file may have been tampered with.')\n log('')\n }\n\n // Errors\n for (const errorMsg of result.errors) {\n error(errorMsg)\n }\n if (result.errors.length > 0) {\n log('')\n }\n\n // Suite results as table\n const tableRows: TableRow[] = result.suites.map((s) => ({\n suite: s.suite,\n status: colorizeStatus(s.status),\n fingerprint: s.fingerprint.slice(0, 16) + '...',\n age: formatAgeColumn(s),\n }))\n\n log(formatTable(tableRows))\n log('')\n\n // Summary\n if (result.success) {\n success('All attestations valid')\n } else {\n // Show remediation steps\n const needsAttestation = result.suites.filter((s) => s.status !== 'VALID')\n\n if (needsAttestation.length > 0) {\n log('Remediation:')\n for (const suite of needsAttestation) {\n log(` attest-it run --suite ${suite.suite}`)\n if (suite.message) {\n log(` ${suite.message}`)\n }\n }\n }\n }\n\n // Warnings (approaching expiry)\n const warningThreshold = 7 // days before expiry to warn\n const nearExpiry = result.suites.filter(\n (s) => s.status === 'VALID' && (s.age ?? 0) > maxAgeDays - warningThreshold,\n )\n\n if (nearExpiry.length > 0) {\n log('')\n for (const suite of nearExpiry) {\n warn(`${suite.suite} attestation approaching expiry (${String(suite.age)} days old)`)\n }\n if (strict) {\n log('(--strict mode: warnings are treated as errors)')\n }\n }\n}\n\nfunction formatAgeColumn(s: SuiteVerificationResult): string {\n if (s.status === 'VALID') {\n return `${String(s.age ?? 0)} days`\n }\n\n if (s.status === 'NEEDS_ATTESTATION') {\n return '(none)'\n }\n\n if (s.status === 'EXPIRED') {\n return `${String(s.age ?? 0)} days (expired)`\n }\n\n if (s.status === 'FINGERPRINT_CHANGED') {\n return '(changed)'\n }\n\n if (s.status === 'INVALIDATED_BY_PARENT') {\n return '(invalidated)'\n }\n\n return '-'\n}\n\n/**\n * Check if verification result has warnings.\n *\n * Returns true if any valid attestations are approaching expiry\n * (within 7 days of maxAgeDays).\n *\n * @param result - Verification result to check\n * @param maxAgeDays - Maximum age in days before expiry\n * @returns True if warnings exist, false otherwise\n * @public\n */\nfunction hasWarnings(result: VerifyResult, maxAgeDays: number): boolean {\n const warningThreshold = 7 // days before expiry to warn\n return result.suites.some(\n (s) => s.status === 'VALID' && (s.age ?? 0) > maxAgeDays - warningThreshold,\n )\n}\n\nexport { runVerify, displayResults, hasWarnings }\n","import { Command } from 'commander'\nimport { initCommand } from './commands/init.js'\nimport { statusCommand } from './commands/status.js'\nimport { runCommand } from './commands/run.js'\nimport { keygenCommand } from './commands/keygen.js'\nimport { pruneCommand } from './commands/prune.js'\nimport { verifyCommand } from './commands/verify.js'\nimport { setOutputOptions } from './utils/output.js'\n\nconst program = new Command()\n\nprogram\n .name('attest-it')\n .description('Human-gated test attestation system')\n .version('0.0.1')\n .option('-c, --config <path>', 'Path to config file')\n .option('-v, --verbose', 'Verbose output')\n .option('-q, --quiet', 'Minimal output')\n\n// Register commands\nprogram.addCommand(initCommand)\nprogram.addCommand(statusCommand)\nprogram.addCommand(runCommand)\nprogram.addCommand(keygenCommand)\nprogram.addCommand(pruneCommand)\nprogram.addCommand(verifyCommand)\n\nexport function run(): void {\n // Parse options and set global output options\n program.parse()\n const options = program.opts<{ verbose?: boolean; quiet?: boolean }>()\n\n const outputOptions: { verbose?: boolean; quiet?: boolean } = {}\n if (options.verbose !== undefined) {\n outputOptions.verbose = options.verbose\n }\n if (options.quiet !== undefined) {\n outputOptions.quiet = options.quiet\n }\n\n setOutputOptions(outputOptions)\n}\n\nexport { program }\n","import { run } from '../src/index.js'\n\nrun()\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/output.ts","../../src/utils/prompts.ts","../../src/utils/exit-codes.ts","../../src/commands/init.ts","../../src/commands/status.ts","../../src/components/Header.tsx","../../src/components/StatusBadge.tsx","../../src/components/SuiteTable.tsx","../../src/components/SelectionPrompt.tsx","../../src/components/SuiteSelector.tsx","../../src/components/ProgressSummary.tsx","../../src/components/TestRunner.tsx","../../src/components/InteractiveRun.tsx","../../src/commands/run-utils.ts","../../src/session/session.ts","../../src/commands/run-interactive.tsx","../../src/commands/run.ts","../../src/commands/keygen.ts","../../src/commands/prune.ts","../../src/commands/verify.ts","../../src/index.ts","../../bin/attest-it.ts"],"names":["Command","jsx","Text","Box","jsxs","React5","useInput","createAttestation","currentSuite","saveSession","React8","determineStatus","readAttestations","computeFingerprint","findAttestation","dirname","loadConfig","fs2","resolve","parseShellCommand","executeCommand","spawn","checkDirtyWorkingTree","os2","upsertAttestation","getDefaultPrivateKeyPath","fs3","writeSignedAttestations","fs4","fs5","result"],"mappings":";;;;;;;;;;;;;;;;AASA,IAAI,gBAA+B,EAAC;AAGpC,IAAI,KAAA;AAMJ,eAAsB,SAAA,GAA2B;AAC/C,EAAA,KAAA,GAAQ,MAAM,WAAA,EAAY;AAC5B;AAMA,SAAS,QAAA,GAAkB;AACzB,EAAA,IAAI,CAAC,KAAA,EAAO;AAGV,IAAA,MAAM,MAAA,GAAS,CAAC,GAAA,KAAgB,GAAA;AAChC,IAAA,MAAM,YAAY,MAAM,MAAA;AAExB,IAAA,KAAA,GAAQ;AAAA,MACN,GAAA,EAAK,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,GAAA,EAAK,SAAA,EAAW,CAAA;AAAA,MAC9D,KAAA,EAAO,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,GAAA,EAAK,SAAA,EAAW,CAAA;AAAA,MAChE,MAAA,EAAQ,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,GAAA,EAAK,SAAA,EAAW,CAAA;AAAA,MACjE,IAAA,EAAM,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,IAAA,EAAM,SAAA,EAAW,GAAA,EAAK,SAAA,EAAW,CAAA;AAAA,MAC/D,OAAA,EAAS,MAAA;AAAA,MACT,KAAA,EAAO,MAAA;AAAA,MACP,OAAA,EAAS,MAAA;AAAA,MACT,IAAA,EAAM,MAAA;AAAA,MACN,KAAA,EAAO;AAAA,KACT;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAEO,SAAS,iBAAiB,OAAA,EAA8B;AAC7D,EAAA,aAAA,GAAgB,OAAA;AAClB;AAOO,SAAS,IAAI,OAAA,EAAuB;AACzC,EAAA,IAAI,CAAC,cAAc,KAAA,EAAO;AACxB,IAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AAAA,EACrB;AACF;AAEO,SAAS,QAAQ,OAAA,EAAuB;AAC7C,EAAA,IAAI,aAAA,CAAc,OAAA,IAAW,CAAC,aAAA,CAAc,KAAA,EAAO;AACjD,IAAA,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAS,CAAE,KAAA,CAAM,OAAO,CAAC,CAAA;AAAA,EACvC;AACF;AAEO,SAAS,QAAQ,OAAA,EAAuB;AAC7C,EAAA,GAAA,CAAI,QAAA,EAAS,CAAE,OAAA,CAAQ,SAAA,GAAO,OAAO,CAAC,CAAA;AACxC;AAEO,SAAS,MAAM,OAAA,EAAuB;AAC3C,EAAA,OAAA,CAAQ,MAAM,QAAA,EAAS,CAAE,KAAA,CAAM,SAAA,GAAO,OAAO,CAAC,CAAA;AAChD;AAEO,SAAS,KAAK,OAAA,EAAuB;AAC1C,EAAA,IAAI,CAAC,cAAc,KAAA,EAAO;AACxB,IAAA,OAAA,CAAQ,KAAK,QAAA,EAAS,CAAE,OAAA,CAAQ,SAAA,GAAO,OAAO,CAAC,CAAA;AAAA,EACjD;AACF;AAEO,SAAS,KAAK,OAAA,EAAuB;AAC1C,EAAA,GAAA,CAAI,QAAA,EAAS,CAAE,IAAA,CAAK,SAAA,GAAO,OAAO,CAAC,CAAA;AACrC;AAUO,SAAS,YAAY,IAAA,EAA0B;AAEpD,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,EAAS,QAAA,EAAU,eAAe,KAAK,CAAA;AAGxD,EAAA,MAAM,YAAA,GAAe,CAAC,GAAA,KAA4B;AAAA,IAChD,GAAA,CAAI,KAAA;AAAA,IACJ,GAAA,CAAI,MAAA;AAAA,IACJ,GAAA,CAAI,WAAA;AAAA,IACJ,GAAA,CAAI;AAAA,GACN;AAEA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAG,CAAA,KAAM;AACnC,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM;AACnC,MAAA,MAAM,MAAA,GAAS,aAAa,CAAC,CAAA;AAE7B,MAAA,OAAO,MAAA,CAAO,CAAC,CAAA,IAAK,EAAA;AAAA,IACtB,CAAC,CAAA;AACD,IAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,GAAG,YAAA,CAAa,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,EAAG,CAAC,CAAA;AACvE,IAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,MAAA,EAAQ,cAAc,CAAA;AAAA,EAC1C,CAAC,CAAA;AAGD,EAAA,MAAM,SAAA,GAAY,QAAA;AAClB,EAAA,MAAM,QAAkB,EAAC;AAIzB,EAAA,KAAA,CAAM,KAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,UAAK,CAAC,CAAA;AACtE,EAAA,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,SAAA,CAAU,MAAA,CAAO,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,oBAAK,CAAC,CAAA;AAG7D,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,MAAA,GAAS,aAAa,GAAG,CAAA;AAE/B,IAAA,KAAA,CAAM,KAAK,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,CAAO,MAAA,CAAO,CAAC,KAAK,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,UAAK,CAAC,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAGO,SAAS,eAAe,MAAA,EAAwB;AACrD,EAAA,MAAM,IAAI,QAAA,EAAS;AACnB,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,CAAE,MAAM,MAAM,CAAA;AAAA,IACvB,KAAK,mBAAA;AAAA,IACL,KAAK,qBAAA;AACH,MAAA,OAAO,CAAA,CAAE,OAAO,MAAM,CAAA;AAAA,IACxB,KAAK,SAAA;AAAA,IACL,KAAK,uBAAA;AACH,MAAA,OAAO,CAAA,CAAE,IAAI,MAAM,CAAA;AAAA,IACrB,KAAK,mBAAA;AACH,MAAA,OAAO,CAAA,CAAE,GAAA,CAAI,IAAA,EAAK,CAAE,MAAM,CAAA;AAAA,IAC5B;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;AAGO,SAAS,WAAW,IAAA,EAAqB;AAC9C,EAAA,OAAA,CAAQ,IAAI,IAAA,CAAK,SAAA,CAAU,IAAA,EAAM,IAAA,EAAM,CAAC,CAAC,CAAA;AAC3C;ACvJA,eAAsB,cAAc,OAAA,EAA2C;AAC7E,EAAA,OAAO,OAAA,CAAQ;AAAA,IACb,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,OAAA,EAAS,QAAQ,OAAA,IAAW;AAAA,GAC7B,CAAA;AACH;;;ACCO,IAAM,QAAA,GAAW;AAAA;AAAA,EAEtB,OAAA,EAAS,CAAA;AAAA;AAAA,EAET,OAAA,EAAS,CAAA;AAAA;AAAA,EAET,OAAA,EAAS,CAAA;AAAA;AAAA,EAET,YAAA,EAAc,CAAA;AAAA;AAAA,EAEd,SAAA,EAAW,CAAA;AAAA;AAAA,EAEX,WAAA,EAAa;AACf,CAAA;;;ACnBO,IAAM,cAAc,IAAI,OAAA,CAAQ,MAAM,CAAA,CAC1C,WAAA,CAAY,oCAAoC,CAAA,CAChD,MAAA,CAAO,qBAAqB,kBAAA,EAAoB,wBAAwB,EACxE,MAAA,CAAO,aAAA,EAAe,2BAA2B,CAAA,CACjD,MAAA,CAAO,OAAO,OAAA,KAAyB;AACtC,EAAA,MAAM,QAAQ,OAAO,CAAA;AACvB,CAAC,CAAA;AAOH,IAAM,eAAA,GAAkB,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,CAAA;AAgDxB,eAAe,QAAQ,OAAA,EAAqC;AAC1D,EAAA,IAAI;AACF,IAAA,MAAM,UAAA,GAAkB,IAAA,CAAA,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAC5C,IAAA,MAAM,SAAA,GAAiB,aAAQ,UAAU,CAAA;AAEzC,IAAA,IAAO,EAAA,CAAA,UAAA,CAAW,UAAU,CAAA,IAAK,CAAC,QAAQ,KAAA,EAAO;AAC/C,MAAA,MAAM,SAAA,GAAY,MAAM,aAAA,CAAc;AAAA,QACpC,OAAA,EAAS,4BAA4B,UAAU,CAAA,YAAA,CAAA;AAAA,QAC/C,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,KAAA,CAAM,gBAAgB,CAAA;AACtB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,MACjC;AAAA,IACF;AAGA,IAAA,MAAS,YAAS,KAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AACtD,IAAA,MAAS,EAAA,CAAA,QAAA,CAAS,SAAA,CAAU,UAAA,EAAY,eAAA,EAAiB,OAAO,CAAA;AAEhE,IAAA,OAAA,CAAQ,CAAA,yBAAA,EAA4B,UAAU,CAAA,CAAE,CAAA;AAChD,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,aAAa,CAAA;AACjB,IAAA,GAAA,CAAI,CAAA,UAAA,EAAa,OAAA,CAAQ,IAAI,CAAA,2BAAA,CAA6B,CAAA;AAC1D,IAAA,GAAA,CAAI,4BAA4B,CAAA;AAChC,IAAA,GAAA,CAAI,4BAA4B,CAAA;AAAA,EAClC,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;ACjFO,IAAM,gBAAgB,IAAIA,OAAAA,CAAQ,QAAQ,CAAA,CAC9C,WAAA,CAAY,wCAAwC,CAAA,CACpD,MAAA,CAAO,oBAAA,EAAsB,qCAAqC,EAClE,MAAA,CAAO,QAAA,EAAU,iCAAiC,CAAA,CAClD,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AA2BH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GAAS,MAAM,UAAA,EAAW;AAGhC,IAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,IAAA,IAAI,gBAAA,GAA4C,IAAA;AAChD,IAAA,IAAI;AACF,MAAA,gBAAA,GAAmB,MAAM,iBAAiB,gBAAgB,CAAA;AAAA,IAC5D,SAAS,GAAA,EAAK;AAEZ,MAAA,IAAI,eAAe,KAAA,IAAS,CAAC,IAAI,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC3D,QAAA,MAAM,GAAA;AAAA,MACR;AAAA,IACF;AACA,IAAA,MAAM,YAAA,GAAe,gBAAA,EAAkB,YAAA,IAAgB,EAAC;AAGxD,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,GAAQ,CAAC,OAAA,CAAQ,KAAK,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AAG9E,IAAA,IAAI,QAAQ,KAAA,IAAS,CAAC,OAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAClD,MAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,IACpC;AAGA,IAAA,MAAM,UAAyB,EAAC;AAChC,IAAA,IAAI,UAAA,GAAa,KAAA;AAEjB,IAAA,KAAA,MAAW,aAAa,UAAA,EAAY;AAElC,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,MAAA,IAAI,CAAC,WAAA,EAAa;AAGlB,MAAA,MAAM,iBAAA,GAAoB,MAAM,kBAAA,CAAmB;AAAA,QACjD,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,OACxD,CAAA;AAGD,MAAA,MAAM,WAAA,GAAc,eAAA;AAAA,QAClB;AAAA,UACE,aAAA,EAAe,GAAA;AAAA,UACf,YAAA;AAAA,UACA,SAAA,EAAW;AAAA,SACb;AAAA,QACA;AAAA,OACF;AAGA,MAAA,MAAM,MAAA,GAAS,eAAA;AAAA,QACb,WAAA,IAAe,IAAA;AAAA,QACf,iBAAA,CAAkB,WAAA;AAAA,QAClB,OAAO,QAAA,CAAS;AAAA,OAClB;AAGA,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,QAAA,GAAA,GAAM,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAAA,MAC9E;AAEA,MAAA,IAAI,WAAW,OAAA,EAAS;AACtB,QAAA,UAAA,GAAa,IAAA;AAAA,MACf;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,SAAA;AAAA,QACN,MAAA;AAAA,QACA,oBAAoB,iBAAA,CAAkB,WAAA;AAAA,QACtC,qBAAqB,WAAA,EAAa,WAAA;AAAA,QAClC,YAAY,WAAA,EAAa,UAAA;AAAA,QACzB;AAAA,OACD,CAAA;AAAA,IACH;AAGA,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,UAAA,CAAW,OAAO,CAAA;AAAA,IACpB,CAAA,MAAO;AACL,MAAA,kBAAA,CAAmB,SAAS,UAAU,CAAA;AAAA,IACxC;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,UAAA,GAAa,QAAA,CAAS,OAAA,GAAU,SAAS,OAAO,CAAA;AAAA,EAC/D,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AAEA,SAAS,eAAA,CACP,WAAA,EACA,kBAAA,EACA,UAAA,EACoB;AACpB,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,mBAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,CAAY,gBAAgB,kBAAA,EAAoB;AAClD,IAAA,OAAO,qBAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAExF,EAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,kBAAA,CAAmB,SAAwB,UAAA,EAA2B;AAC7E,EAAA,MAAM,SAAA,GAAwB,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAChD,OAAO,CAAA,CAAE,IAAA;AAAA,IACT,MAAA,EAAQ,cAAA,CAAe,CAAA,CAAE,MAAM,CAAA;AAAA,IAC/B,aAAa,CAAA,CAAE,kBAAA,CAAmB,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAAA,IACjD,GAAA,EAAK,UAAU,CAAC;AAAA,GAClB,CAAE,CAAA;AAEF,EAAA,GAAA,CAAI,EAAE,CAAA;AACN,EAAA,GAAA,CAAI,WAAA,CAAY,SAAS,CAAC,CAAA;AAC1B,EAAA,GAAA,CAAI,EAAE,CAAA;AAEN,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,GAAA,CAAI,2DAA2D,CAAA;AAAA,EACjE,CAAA,MAAO;AACL,IAAA,OAAA,CAAQ,wBAAwB,CAAA;AAAA,EAClC;AACF;AAEA,SAAS,UAAU,MAAA,EAA6B;AAC9C,EAAA,IAAI,MAAA,CAAO,WAAW,OAAA,EAAS;AAC7B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,CAAA,KAAA,CAAA;AAAA,EACnC;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,qBAAA,EAAuB;AAC3C,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,mBAAA,EAAqB;AACzC,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAC/B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,CAAA,eAAA,CAAA;AAAA,EACnC;AAEA,EAAA,OAAO,GAAA;AACT;ACpMO,SAAS,MAAA,CAAO,EAAE,YAAA,EAAa,EAAoC;AACxE,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,YAAA,CAAa,QAAA,EAAU,CAAA,MAAA,EAAS,YAAA,KAAiB,CAAA,GAAI,EAAA,GAAK,GAAG,CAAA,KAAA,EAAQ,YAAA,KAAiB,CAAA,GAAI,MAAM,EAAE,CAAA,YAAA,CAAA;AAErH,EAAA,uBACE,GAAA,CAAC,OAAI,WAAA,EAAY,QAAA,EAAS,UAAU,CAAA,EAClC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAM,QAAA,EAAA,OAAA,EAAQ,CAAA,EACjB,CAAA;AAEJ;ACIO,SAAS,WAAA,CAAY,EAAE,MAAA,EAAO,EAAyC;AAE5E,EAAA,MAAM,YAAA,GAAe,gBAAgB,MAAM,CAAA;AAG3C,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,uBACEC,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAO,aAAa,KAAA,EAAO,IAAA,EAAI,IAAA,EAClC,QAAA,EAAA,YAAA,CAAa,IAAA,EAChB,CAAA;AAAA,EAEJ;AAEA,EAAA,uBAAOD,IAACC,IAAAA,EAAA,EAAK,OAAO,YAAA,CAAa,KAAA,EAAQ,uBAAa,IAAA,EAAK,CAAA;AAC7D;AAgBA,SAAS,gBAAgB,MAAA,EAA0C;AACjE,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,OAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,cAAA,EAAW,KAAA,EAAO,OAAA,EAAQ;AAAA,IAC3C,KAAK,mBAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,QAAA,EAAS;AAAA,IAC5C,KAAK,qBAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,QAAA,EAAS;AAAA,IAC5C,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,KAAA,EAAM;AAAA,IACvC,KAAK,mBAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,KAAA,EAAO,MAAM,IAAA,EAAK;AAAA,IACrD,KAAK,uBAAA;AACH,MAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,KAAA,EAAO,KAAA,EAAM;AAAA,IAC7C,SAAS;AAEP,MAAA,MAAM,WAAA,GAAqB,MAAA;AAC3B,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,CAAO,WAAW,CAAA,EAAG,OAAO,QAAA,EAAS;AAAA,IACtD;AAAA;AAEJ;AC9BO,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,UAAA,GAAa,KAAA;AAAA,EACb,QAAA,uBAAe,GAAA;AACjB,CAAA,EAAwC;AAEtC,EAAA,MAAM,YAAA,GAAe,qBAAA,CAAsB,MAAkB,CAAA;AAE7D,EAAA,uBACE,IAAA,CAACC,GAAAA,EAAA,EAAI,aAAA,EAAc,QAAA,EAEjB,QAAA,EAAA;AAAA,oBAAA,IAAA,CAACA,KAAA,EACE,QAAA,EAAA;AAAA,MAAA,UAAA,oBAAcF,GAAAA,CAACC,IAAAA,EAAA,EAAM,QAAA,EAAA,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,EAAE,CAAA;AAAA,sBACpCD,GAAAA,CAACC,IAAAA,EAAA,EAAK,IAAA,EAAI,MAAE,QAAA,EAAA,MAAA,CAAO,QAAA,EAAU,YAAA,CAAa,MAAM,CAAA,EAAE,CAAA;AAAA,sBAClDD,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,sBACPD,GAAAA,CAACC,IAAAA,EAAA,EAAK,IAAA,EAAI,MAAE,QAAA,EAAA,MAAA,CAAO,OAAA,EAAS,YAAA,CAAa,KAAK,CAAA,EAAE,CAAA;AAAA,sBAChDD,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,sBACPD,GAAAA,CAACC,IAAAA,EAAA,EAAK,IAAA,EAAI,MAAC,QAAA,EAAA,QAAA,EAAM;AAAA,KAAA,EACnB,CAAA;AAAA,oBAGAD,GAAAA,CAACE,GAAAA,EAAA,EACC,QAAA,kBAAAF,IAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,MAAA,EACT,QAAA,EAAA,QAAA,CAAI,MAAA;AAAA,MAAA,CACF,aAAa,CAAA,GAAI,CAAA,IAAK,aAAa,MAAA,GAAS,YAAA,CAAa,QAAQ,YAAA,CAAa;AAAA,OAEnF,CAAA,EACF,CAAA;AAAA,IAGC,OAAO,GAAA,CAAI,CAAC,KAAA,qBACX,IAAA,CAACC,KAAA,EACE,QAAA,EAAA;AAAA,MAAA,UAAA,oBAAcF,GAAAA,CAACC,IAAAA,EAAA,EAAM,QAAA,EAAA,QAAA,CAAS,IAAI,KAAA,CAAM,IAAI,CAAA,GAAI,WAAA,GAAS,MAAA,EAAO,CAAA;AAAA,sBACjED,GAAAA,CAACE,GAAAA,EAAA,EAAI,KAAA,EAAO,YAAA,CAAa,MAAA,EACvB,QAAA,kBAAAF,GAAAA,CAAC,WAAA,EAAA,EAAY,MAAA,EAAQ,KAAA,CAAM,QAAQ,CAAA,EACrC,CAAA;AAAA,sBACAA,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,sBACPD,IAACC,IAAAA,EAAA,EAAM,iBAAO,KAAA,CAAM,IAAA,EAAM,YAAA,CAAa,KAAK,CAAA,EAAE,CAAA;AAAA,sBAC9CD,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAA,GAAA,EAAC,CAAA;AAAA,sBACPD,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,MAAA,EAAQ,gBAAM,MAAA,EAAO;AAAA,KAAA,EAAA,EARzB,KAAA,CAAM,IAShB,CACD;AAAA,GAAA,EACH,CAAA;AAEJ;AAgBA,SAAS,qBAAA,CAAsB,QAAqB,WAAA,EAAoC;AACtF,EAAA,MAAM,YAAA,GAAe,QAAA;AACrB,EAAA,MAAM,WAAA,GAAc,OAAA;AACpB,EAAA,MAAM,YAAA,GAAe,QAAA;AAIrB,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,YAAA,CAAa,QAAQ,EAAE,CAAA;AAGpD,EAAA,MAAM,UAAA,GAAa,IAAA,CAAK,GAAA,CAAI,WAAA,CAAY,MAAA,EAAQ,GAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,MAAM,CAAC,CAAA;AAGnF,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,YAAA,CAAa,MAAA,EAAQ,GAAG,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,CAAO,MAAM,CAAC,CAAA;AAEvF,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,WAAA;AAAA,IACR,KAAA,EAAO,UAAA;AAAA,IACP,MAAA,EAAQ;AAAA,GACV;AACF;AAMA,SAAS,MAAA,CAAO,KAAa,KAAA,EAAuB;AAClD,EAAA,OAAO,GAAA,CAAI,MAAA,CAAO,KAAA,EAAO,GAAG,CAAA;AAC9B;ACzGO,SAAS,eAAA,CAAgB;AAAA,EAC9B,OAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA6C;AAC3C,EAAA,QAAA,CAAS,CAAC,KAAA,KAAU;AAElB,IAAA,MAAM,gBAAgB,OAAA,CAAQ,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,CAAI,SAAS,KAAK,CAAA;AAC9D,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,QAAA,CAAS,cAAc,KAAK,CAAA;AAC5B,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,eAAe,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,CAAM,SAAS,KAAK,CAAA;AAChE,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,QAAA,CAAS,aAAa,IAAI,CAAA;AAAA,MAC5B;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,uBACEE,IAAAA,CAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EACjB,QAAA,EAAA;AAAA,oBAAAF,GAAAA,CAACC,IAAAA,EAAA,EAAK,IAAA,EAAI,MAAE,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,oBACpBD,GAAAA,CAACE,GAAAA,EAAA,EAAI,WAAW,CAAA,EAAG,GAAA,EAAK,CAAA,EACrB,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAC,MAAA,qBACZC,IAAAA,CAACF,MAAA,EACE,QAAA,EAAA;AAAA,MAAA,MAAA,CAAO,IAAA,oBACNE,IAAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,wBAAAA,IAAAA,CAACF,IAAAA,EAAA,EAAK,KAAA,EAAM,MAAA,EAAO,QAAA,EAAA;AAAA,UAAA,GAAA;AAAA,UAAE,MAAA,CAAO,IAAA;AAAA,UAAK;AAAA,SAAA,EAAC,CAAA;AAAA,QAAQ;AAAA,OAAA,EAC5C,CAAA;AAAA,MAED,MAAA,CAAO;AAAA,KAAA,EAAA,EANC,MAAA,CAAO,KAOlB,CACD,CAAA,EACH,CAAA;AAAA,IACC,UAAU,MAAA,CAAO,MAAA,GAAS,qBACzBD,GAAAA,CAACE,KAAA,EAAI,SAAA,EAAW,GAAG,GAAA,EAAK,CAAA,EACrB,iBAAO,GAAA,CAAI,CAAC,0BACXC,IAAAA,CAACF,MAAA,EACC,QAAA,EAAA;AAAA,sBAAAE,IAAAA,CAACF,IAAAA,EAAA,EAAK,KAAA,EAAM,MAAA,EAAO,QAAA,EAAA;AAAA,QAAA,GAAA;AAAA,QAAE,KAAA,CAAM,IAAA;AAAA,QAAK;AAAA,OAAA,EAAC,CAAA;AAAA,MAAO,GAAA;AAAA,MAAE,KAAA,CAAM;AAAA,KAAA,EAAA,EADvC,KAAA,CAAM,IAEjB,CACD,CAAA,EACH;AAAA,GAAA,EAEJ,CAAA;AAEJ;AC1CO,SAAS,aAAA,CAAc;AAAA,EAC5B,aAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAA2C;AACzC,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,IAAUG,MAAA,CAAA,QAAA,iBAAsB,IAAI,KAAK,CAAA;AACjF,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAUA,gBAAS,CAAC,CAAA;AAKtD,EAAA,MAAM,WAAA,GAAoBA,MAAA,CAAA,WAAA,CAAY,CAAC,SAAA,KAAsB;AAC3D,IAAA,iBAAA,CAAkB,CAAC,IAAA,KAAS;AAC1B,MAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,IAAI,CAAA;AACzB,MAAA,IAAI,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA,EAAG;AACvB,QAAA,IAAA,CAAK,OAAO,SAAS,CAAA;AAAA,MACvB,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,IAAI,SAAS,CAAA;AAAA,MACpB;AACA,MAAA,OAAO,IAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH,CAAA,EAAG,EAAE,CAAA;AAEL,EAAAC,QAAAA,CAAS,CAAC,KAAA,EAAO,GAAA,KAAQ;AAEvB,IAAA,IAAI,UAAU,GAAA,EAAK;AACjB,MAAA,iBAAA,CAAkB,IAAI,IAAI,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AAC3D,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,UAAU,GAAA,EAAK;AACjB,MAAA,MAAA,EAAO;AACP,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA,EAAG;AACzB,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,KAAA,EAAO,EAAE,CAAA,GAAI,CAAA;AAClC,MAAA,IAAI,GAAA,GAAM,cAAc,MAAA,EAAQ;AAE9B,QAAA,MAAM,KAAA,GAAQ,cAAc,GAAG,CAAA;AAC/B,QAAA,IAAI,KAAA,EAAO;AACT,UAAA,WAAA,CAAY,MAAM,IAAI,CAAA;AAAA,QACxB;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,CAAM,UAAA,CAAW,GAAG,CAAA,IAAK,MAAA,EAAQ;AACnC,MAAA,MAAM,WAAW,QAAA,CAAS,KAAA,CAAM,MAAM,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,CAAA;AAChD,MAAA,MAAM,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AACrC,MAAA,IAAI,QAAA,IAAY,CAAA,IAAK,QAAA,GAAW,UAAA,CAAW,MAAA,EAAQ;AAEjD,QAAA,MAAM,SAAA,GAAY,WAAW,QAAQ,CAAA;AACrC,QAAA,IAAI,SAAA,EAAW;AAEb,UAAA,MAAM,WAAA,GAAwB,MAAA,CAAO,SAAS,CAAA,IAAK,EAAC;AAEpD,UAAA,MAAM,WAAA,GAAc,IAAI,GAAA,CAAI,cAAc,CAAA;AAC1C,UAAA,WAAA,CAAY,QAAQ,CAAC,CAAA,KAAc,WAAA,CAAY,GAAA,CAAI,CAAC,CAAC,CAAA;AACrD,UAAA,iBAAA,CAAkB,WAAW,CAAA;AAAA,QAC/B;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,IAAI,MAAA,EAAQ;AACd,MAAA,QAAA,CAAS,KAAA,CAAM,IAAA,CAAK,cAAc,CAAC,CAAA;AACnC,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,UAAU,GAAA,EAAK;AAEjB,MAAA,MAAM,YAAA,GAAe,cAAc,WAAW,CAAA;AAC9C,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,WAAA,CAAY,aAAa,IAAI,CAAA;AAAA,MAC/B;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,IAAI,OAAA,EAAS;AACf,MAAA,cAAA,CAAe,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAA,GAAc,CAAC,CAAC,CAAA;AAC3C,MAAA;AAAA,IACF;AACA,IAAA,IAAI,IAAI,SAAA,EAAW;AACjB,MAAA,cAAA,CAAe,KAAK,GAAA,CAAI,aAAA,CAAc,SAAS,CAAA,EAAG,WAAA,GAAc,CAAC,CAAC,CAAA;AAClE,MAAA;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,uBACEF,IAAAA,CAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EAEjB,QAAA,EAAA;AAAA,oBAAAF,GAAAA,CAAC,MAAA,EAAA,EAAO,YAAA,EAAc,aAAA,CAAc,MAAA,EAAQ,CAAA;AAAA,oBAE5CA,GAAAA,CAACE,GAAAA,EAAA,EAAI,SAAS,CAAA,EAEZ,QAAA,kBAAAF,GAAAA,CAAC,UAAA,EAAA,EAAW,QAAQ,aAAA,EAAe,UAAA,EAAY,IAAA,EAAM,QAAA,EAAU,gBAAgB,CAAA,EACjF,CAAA;AAAA,IAGC,WAAA,CAAY,MAAA,GAAS,CAAA,oBACpBG,IAAAA,CAACD,KAAA,EAAI,OAAA,EAAS,CAAA,EAAG,aAAA,EAAc,QAAA,EAC7B,QAAA,EAAA;AAAA,sBAAAF,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAQ,MAAC,QAAA,EAAA,gBAAA,EAAc,CAAA;AAAA,MAC5B,WAAA,CAAY,IAAI,CAAC,CAAA,qBAChBE,IAAAA,CAACF,IAAAA,EAAA,EAAkB,QAAA,EAAQ,IAAA,EACxB,QAAA,EAAA;AAAA,QAAA,IAAA;AAAA,QAAK,SAAA;AAAA,QAAG,CAAA,CAAE,IAAA;AAAA,QAAK,aAAA;AAAA,QAAY,MAAA,CAAO,CAAA,CAAE,GAAA,IAAO,CAAC,CAAA;AAAA,QAAE;AAAA,OAAA,EAAA,EADtC,CAAA,CAAE,IAEb,CACD;AAAA,KAAA,EACH,CAAA;AAAA,oBAIFD,GAAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,uBAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,EAAE,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,KAAA,EAAO,MAAM,GAAA,EAAI;AAAA,UAChD,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,QAAA,EAAU,MAAM,KAAA,EAAM;AAAA,UACnD,EAAE,KAAA,EAAO,WAAA,EAAa,KAAA,EAAO,MAAA,EAAQ,MAAM,GAAA;AAAI,SACjD;AAAA,QACA,MAAA,EACE,SACI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,MAAO;AAAA,UACpC,IAAA,EAAM,CAAA,CAAA,EAAI,MAAA,CAAO,CAAA,GAAI,CAAC,CAAC,CAAA,CAAA;AAAA,UACvB,KAAA,EAAO;AAAA,UACP,CAAA,GACF,MAAA;AAAA,QAEN,UAAU,MAAM;AAAA,QAEhB;AAAA;AAAA,KACF;AAAA,oBAGAG,IAAAA,CAACF,IAAAA,EAAA,EAAK,OAAM,MAAA,EAAQ,QAAA,EAAA;AAAA,MAAA,cAAA,CAAe,IAAA;AAAA,MAAK;AAAA,KAAA,EAAkC;AAAA,GAAA,EAC5E,CAAA;AAEJ;AChKO,SAAS,eAAA,CAAgB;AAAA,EAC9B,SAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAA,EAA6C;AAC3C,EAAA,uBACED,GAAAA,CAACE,GAAAA,EAAA,EAAI,WAAA,EAAY,QAAA,EAAS,QAAA,EAAU,CAAA,EAClC,QAAA,kBAAAC,IAAAA,CAACF,IAAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAE,IAAAA,CAACF,IAAAA,EAAA,EAAK,KAAA,EAAM,OAAA,EAAQ,QAAA,EAAA;AAAA,MAAA,aAAA;AAAA,MAAY;AAAA,KAAA,EAAU,CAAA;AAAA,IACzC,MAAA;AAAA,oBACDE,IAAAA,CAACF,IAAAA,EAAA,EAAK,OAAM,QAAA,EAAS,QAAA,EAAA;AAAA,MAAA,aAAA;AAAA,MAAY;AAAA,KAAA,EAAU,CAAA;AAAA,IAC1C,MAAA;AAAA,oBACDE,IAAAA,CAACF,IAAAA,EAAA,EAAK,OAAM,KAAA,EAAM,QAAA,EAAA;AAAA,MAAA,UAAA;AAAA,MAAS;AAAA,KAAA,EAAO,CAAA;AAAA,IACjC,MAAA;AAAA,oBACDE,IAAAA,CAACF,IAAAA,EAAA,EAAK,OAAM,MAAA,EAAO,QAAA,EAAA;AAAA,MAAA,WAAA;AAAA,MAAU;AAAA,KAAA,EAAQ;AAAA,GAAA,EACvC,CAAA,EACF,CAAA;AAEJ;ACNO,SAAS,UAAA,CAAW;AAAA,EACzB,MAAA;AAAA,EACA,WAAA;AAAA,EACA,iBAAA,EAAAK,kBAAAA;AAAA,EACA;AACF,CAAA,EAAwC;AACtC,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAU,gBAAS,CAAC,CAAA;AACxD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,gBAAmB,SAAS,CAAA;AAC5D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAU,MAAA,CAAA,QAAA,CAAqB;AAAA,IACvD,WAAW,EAAC;AAAA,IACZ,QAAQ,EAAC;AAAA,IACT,SAAS;AAAC,GACX,CAAA;AACD,EAAA,MAAM,CAAC,WAAA,EAAa,aAAa,CAAA,GAAU,gBAAS,KAAK,CAAA;AAGzD,EAAA,MAAM,UAAA,GAAmB,cAAO,OAAO,CAAA;AACvC,EAAM,iBAAU,MAAM;AACpB,IAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAAA,EACvB,CAAA,EAAG,CAAC,OAAO,CAAC,CAAA;AAGZ,EAAM,iBAAU,MAAM;AACpB,IAAA,IAAI,UAAU,SAAA,EAAW;AAGzB,IAAA,MAAMC,aAAAA,GAAe,OAAO,YAAY,CAAA;AACxC,IAAA,IAAI,CAACA,aAAAA,EAAc;AAEjB,MAAA,UAAA,CAAW,WAAW,OAAO,CAAA;AAC7B,MAAA,QAAA,CAAS,UAAU,CAAA;AACnB,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,WAAA,CAAYA,aAAY,CAAA,CACrB,IAAA,CAAK,CAAC,MAAA,KAAW;AAChB,MAAA,IAAI,SAAA,EAAW;AAEf,MAAA,aAAA,CAAc,MAAM,CAAA;AACpB,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,QAAA,CAAS,YAAY,CAAA;AAAA,MACvB,CAAA,MAAO;AAEL,QAAA,UAAA,CAAW,CAAC,IAAA,MAAU;AAAA,UACpB,GAAG,IAAA;AAAA,UACH,MAAA,EAAQ,CAAC,GAAG,IAAA,CAAK,QAAQA,aAAY;AAAA,SACvC,CAAE,CAAA;AACF,QAAA,eAAA,CAAgB,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAAA,MACpC;AAAA,IACF,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,MAAA,IAAI,SAAA,EAAW;AAGf,MAAA,UAAA,CAAW,CAAC,IAAA,MAAU;AAAA,QACpB,GAAG,IAAA;AAAA,QACH,MAAA,EAAQ,CAAC,GAAG,IAAA,CAAK,QAAQA,aAAY;AAAA,OACvC,CAAE,CAAA;AACF,MAAA,eAAA,CAAgB,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAAA,IACpC,CAAC,CAAA;AAEH,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,GAAG,CAAC,YAAA,EAAc,OAAO,MAAA,EAAQ,WAAA,EAAa,UAAU,CAAC,CAAA;AAGzD,EAAAF,QAAAA;AAAA,IACE,CAAC,OAAO,GAAA,KAAQ;AACd,MAAA,IAAI,UAAU,YAAA,EAAc;AAG5B,MAAA,MAAME,aAAAA,GAAe,OAAO,YAAY,CAAA;AACxC,MAAA,IAAI,CAACA,aAAAA,EAAc;AAGnB,MAAA,IAAI,KAAA,CAAM,WAAA,EAAY,KAAM,GAAA,IAAO,IAAI,MAAA,EAAQ;AAC7C,QAAAD,kBAAAA,CAAkBC,aAAY,CAAA,CAC3B,IAAA,CAAK,MAAM;AACV,UAAA,UAAA,CAAW,CAAC,IAAA,MAAU;AAAA,YACpB,GAAG,IAAA;AAAA,YACH,SAAA,EAAW,CAAC,GAAG,IAAA,CAAK,WAAWA,aAAY;AAAA,WAC7C,CAAE,CAAA;AACF,UAAA,eAAA,CAAgB,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAClC,UAAA,QAAA,CAAS,SAAS,CAAA;AAAA,QACpB,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AAEX,UAAA,UAAA,CAAW,CAAC,IAAA,MAAU;AAAA,YACpB,GAAG,IAAA;AAAA,YACH,OAAA,EAAS,CAAC,GAAG,IAAA,CAAK,SAASA,aAAY;AAAA,WACzC,CAAE,CAAA;AACF,UAAA,eAAA,CAAgB,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAClC,UAAA,QAAA,CAAS,SAAS,CAAA;AAAA,QACpB,CAAC,CAAA;AAAA,MACL;AAGA,MAAA,IAAI,KAAA,CAAM,WAAA,EAAY,KAAM,GAAA,EAAK;AAC/B,QAAA,UAAA,CAAW,CAAC,IAAA,MAAU;AAAA,UACpB,GAAG,IAAA;AAAA,UACH,OAAA,EAAS,CAAC,GAAG,IAAA,CAAK,SAASA,aAAY;AAAA,SACzC,CAAE,CAAA;AACF,QAAA,eAAA,CAAgB,CAAC,IAAA,KAAS,IAAA,GAAO,CAAC,CAAA;AAClC,QAAA,QAAA,CAAS,SAAS,CAAA;AAAA,MACpB;AAAA,IACF,CAAA;AAAA,IACA,EAAE,QAAA,EAAU,KAAA,KAAU,YAAA;AAAa,GACrC;AAGA,EAAA,MAAM,YAAA,GAAe,OAAO,YAAY,CAAA;AAExC,EAAA,uBACEJ,IAAAA,CAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EAEjB,QAAA,EAAA;AAAA,oBAAAF,GAAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAW,QAAQ,SAAA,CAAU,MAAA;AAAA,QAC7B,MAAA,EAAQ,QAAQ,MAAA,CAAO,MAAA;AAAA,QACvB,SAAA,EAAW,OAAO,MAAA,GAAS,YAAA;AAAA,QAC3B,OAAA,EAAS,QAAQ,OAAA,CAAQ;AAAA;AAAA,KAC3B;AAAA,oBAEAG,IAAAA,CAACD,GAAAA,EAAA,EAAI,SAAS,CAAA,EACX,QAAA,EAAA;AAAA,MAAA,KAAA,KAAU,SAAA,IAAa,YAAA,oBACtBC,IAAAA,CAACD,KAAA,EACC,QAAA,EAAA;AAAA,wBAAAF,IAAC,aAAA,EAAA,EAAc,CAAA;AAAA,wBACfG,IAAAA,CAACF,IAAAA,EAAA,EAAK,QAAA,EAAA;AAAA,UAAA,WAAA;AAAA,UAAU,YAAA;AAAA,UAAa;AAAA,SAAA,EAAG;AAAA,OAAA,EAClC,CAAA;AAAA,MAGD,KAAA,KAAU,gBAAgB,YAAA,oBACzBE,KAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EACjB,QAAA,EAAA;AAAA,wBAAAF,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,SAAQ,QAAA,EAAA,sBAAA,EAAe,CAAA;AAAA,wBACnCE,IAAAA,CAACF,IAAAA,EAAA,EAAK,QAAA,EAAA;AAAA,UAAA,yBAAA;AAAA,UAAwB,YAAA;AAAA,UAAa;AAAA,SAAA,EAAS;AAAA,OAAA,EACtD,CAAA;AAAA,MAGD,UAAU,UAAA,oBACTE,KAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EACjB,QAAA,EAAA;AAAA,wBAAAF,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,SAAQ,QAAA,EAAA,6BAAA,EAAsB,CAAA;AAAA,wBAC1CE,IAAAA,CAACF,IAAAA,EAAA,EAAK,QAAA,EAAA;AAAA,UAAA,aAAA;AAAA,UACQ,QAAQ,SAAA,CAAU,MAAA;AAAA,UAAO,YAAA;AAAA,UAAW,QAAQ,MAAA,CAAO,MAAA;AAAA,UAAO,YAAA;AAAA,UAAW,GAAA;AAAA,UAChF,QAAQ,OAAA,CAAQ;AAAA,SAAA,EACnB;AAAA,OAAA,EACF;AAAA,KAAA,EAEJ;AAAA,GAAA,EACF,CAAA;AAEJ;AAMA,SAAS,aAAA,GAAoC;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,gBAAS,CAAC,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,CAAC,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAA,EAAK,QAAG,CAAA;AAEhE,EAAM,iBAAU,MAAM;AACpB,IAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,MAAA,QAAA,CAAS,CAAC,CAAA,KAAA,CAAO,CAAA,GAAI,CAAA,IAAK,OAAO,MAAM,CAAA;AAAA,IACzC,GAAG,EAAE,CAAA;AACL,IAAA,OAAO,MAAM;AACX,MAAA,aAAA,CAAc,KAAK,CAAA;AAAA,IACrB,CAAA;AAAA,EACF,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,uBAAOD,IAACC,IAAAA,EAAA,EAAK,OAAM,MAAA,EAAQ,QAAA,EAAA,MAAA,CAAO,KAAK,CAAA,EAAE,CAAA;AAC3C;AC7JO,SAAS,cAAA,CAAe;AAAA,EAC7B,SAAA;AAAA,EACA,MAAA;AAAA,EACA,WAAA;AAAA,EACA,iBAAA,EAAAK,kBAAAA;AAAA,EACA,WAAA,EAAAE,YAAAA;AAAA,EACA;AACF,CAAA,EAA4C;AAC1C,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAA,EAAO;AAExB,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAUC,MAAA,CAAA,QAAA,CAAgB,WAAA,GAAc,YAAY,WAAW,CAAA;AACrF,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,IAAUA,MAAA,CAAA,QAAA,CAAmB,WAAA,IAAe,EAAE,CAAA;AACtF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAUA,MAAA,CAAA,QAAA,CAAqB;AAAA,IACvD,WAAW,EAAC;AAAA,IACZ,QAAQ,EAAC;AAAA,IACT,SAAS;AAAC,GACX,CAAA;AAGD,EAAA,MAAM,aAAA,GAAsBA,MAAA,CAAA,OAAA;AAAA,IAC1B,MAAM,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAAA,IAClD,CAAC,SAAS;AAAA,GACZ;AAGA,EAAA,MAAM,WAAA,GAAoBA,MAAA,CAAA,OAAA;AAAA,IACxB,MAAM,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAAA,IAClD,CAAC,SAAS;AAAA,GACZ;AAGA,EAAA,MAAM,YAAA,GAAqBA,MAAA,CAAA,WAAA;AAAA,IACzB,CAAC,QAAA,KAAuB;AACtB,MAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AACzB,QAAA,IAAA,EAAK;AACL,QAAA;AAAA,MACF;AACA,MAAA,iBAAA,CAAkB,QAAQ,CAAA;AAC1B,MAAA,QAAA,CAAS,SAAS,CAAA;AAAA,IACpB,CAAA;AAAA,IACA,CAAC,IAAI;AAAA,GACP;AAGA,EAAA,MAAM,iBAAA,GAA0BA,MAAA,CAAA,WAAA;AAAA,IAC9B,CAAC,UAAA,KAA2B;AAC1B,MAAA,KAAA,CAAM,YAAY;AAChB,QAAA,UAAA,CAAW,UAAU,CAAA;AAGrB,QAAA,IAAI,WAAW,MAAA,CAAO,MAAA,KAAW,KAAK,UAAA,CAAW,OAAA,CAAQ,WAAW,CAAA,EAAG;AAErE,UAAA,MAAMD,aAAY,EAAC,EAAG,EAAC,EAAG,EAAE,CAAA;AAAA,QAC9B,CAAA,MAAO;AAEL,UAAA,MAAMA,aAAY,UAAA,CAAW,SAAA,EAAW,UAAA,CAAW,MAAA,EAAQ,EAAE,CAAA;AAAA,QAC/D;AAEA,QAAA,QAAA,CAAS,UAAU,CAAA;AAAA,MACrB,CAAA,GAAG;AAAA,IACL,CAAA;AAAA,IACA,CAACA,YAAW;AAAA,GACd;AAGA,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,uBACEL,IAAAA,CAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EACjB,QAAA,EAAA;AAAA,sBAAAF,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,SAAQ,QAAA,EAAA,8CAAA,EAAuC,CAAA;AAAA,MAC1D,WAAA,CAAY,SAAS,CAAA,oBACpBE,KAACF,IAAAA,EAAA,EAAK,UAAQ,IAAA,EAAE,QAAA,EAAA;AAAA,QAAA,WAAA,CAAY,MAAA;AAAA,QAAO;AAAA,OAAA,EAA2B;AAAA,KAAA,EAElE,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACEE,IAAAA,CAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EAChB,QAAA,EAAA;AAAA,IAAA,KAAA,KAAU,+BACTF,GAAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,aAAA;AAAA,QACA,WAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA;AAAA,QACf,QAAA,EAAU,YAAA;AAAA,QACV,QAAQ,MAAM;AACZ,UAAA,IAAA,EAAK;AAAA,QACP;AAAA;AAAA,KACF;AAAA,IAGD,KAAA,KAAU,6BACTA,GAAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,cAAA;AAAA,QACR,WAAA;AAAA,QACA,iBAAA,EAAmBM,kBAAAA;AAAA,QACnB,UAAA,EAAY;AAAA;AAAA,KACd;AAAA,IAGD,UAAU,UAAA,oBACTH,KAACD,GAAAA,EAAA,EAAI,eAAc,QAAA,EACjB,QAAA,EAAA;AAAA,sBAAAF,GAAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,QAAQ,SAAA,CAAU,MAAA;AAAA,UAC7B,MAAA,EAAQ,QAAQ,MAAA,CAAO,MAAA;AAAA,UACvB,SAAA,EAAW,CAAA;AAAA,UACX,OAAA,EAAS,QAAQ,OAAA,CAAQ;AAAA;AAAA,OAC3B;AAAA,sBAEAA,GAAAA,CAACE,GAAAA,EAAA,EAAI,OAAA,EAAS,CAAA,EACX,QAAA,EAAA,OAAA,CAAQ,MAAA,CAAO,MAAA,KAAW,CAAA,IAAK,OAAA,CAAQ,OAAA,CAAQ,MAAA,KAAW,CAAA,mBACzDF,GAAAA,CAACC,IAAAA,EAAA,EAAK,KAAA,EAAM,OAAA,EAAQ,QAAA,EAAA,0CAAA,EAAmC,CAAA,mBAEvDE,IAAAA,CAACD,GAAAA,EAAA,EAAI,aAAA,EAAc,QAAA,EAChB,QAAA,EAAA;AAAA,QAAA,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,oBACvBC,KAACF,IAAAA,EAAA,EAAK,OAAM,KAAA,EAAM,QAAA,EAAA;AAAA,UAAA,SAAA;AAAA,UACb,QAAQ,MAAA,CAAO,MAAA;AAAA,UAAO,oBAAA;AAAA,UAAmB,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,IAAI;AAAA,SAAA,EACtE,CAAA;AAAA,wBAEFD,GAAAA,CAACC,IAAAA,EAAA,EAAK,QAAA,EAAA,8DAAA,EAA4D;AAAA,OAAA,EACpE,CAAA,EAEJ;AAAA,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;ACvIA,SAASS,gBAAAA,CACP,WAAA,EACA,kBAAA,EACA,UAAA,EACoB;AACpB,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,OAAO,mBAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,CAAY,gBAAgB,kBAAA,EAAoB;AAClD,IAAA,OAAO,qBAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAExF,EAAA,IAAI,YAAY,UAAA,EAAY;AAC1B,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,OAAO,OAAA;AACT;AASA,eAAsB,oBAAoB,MAAA,EAAwC;AAEhF,EAAA,IAAI,gBAAA,GAA4C,IAAA;AAChD,EAAA,IAAI;AACF,IAAA,gBAAA,GAAmB,MAAMC,gBAAAA,CAAiB,MAAA,CAAO,QAAA,CAAS,gBAAgB,CAAA;AAAA,EAC5E,SAAS,GAAA,EAAK;AAEZ,IAAA,IAAI,eAAe,KAAA,IAAS,CAAC,IAAI,OAAA,CAAQ,QAAA,CAAS,QAAQ,CAAA,EAAG;AAC3D,MAAA,MAAM,GAAA;AAAA,IACR;AAAA,EACF;AACA,EAAA,MAAM,YAAA,GAAe,gBAAA,EAAkB,YAAA,IAAgB,EAAC;AAExD,EAAA,MAAM,UAAyB,EAAC;AAEhC,EAAA,KAAA,MAAW,CAAC,WAAW,WAAW,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AAEpE,IAAA,MAAM,iBAAA,GAAoB,MAAMC,kBAAAA,CAAmB;AAAA,MACjD,UAAU,WAAA,CAAY,QAAA;AAAA,MACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,KACxD,CAAA;AAGD,IAAA,MAAM,WAAA,GAAcC,eAAAA;AAAA,MAClB,EAAE,aAAA,EAAe,GAAA,EAAK,YAAA,EAAc,WAAW,EAAA,EAAG;AAAA,MAClD;AAAA,KACF;AAGA,IAAA,MAAM,MAAA,GAASH,gBAAAA;AAAA,MACb,WAAA;AAAA,MACA,iBAAA,CAAkB,WAAA;AAAA,MAClB,OAAO,QAAA,CAAS;AAAA,KAClB;AAGA,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,MAAM,UAAA,GAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,CAAA;AAClD,MAAA,GAAA,GAAM,IAAA,CAAK,KAAA,CAAA,CAAO,IAAA,CAAK,GAAA,EAAI,GAAI,UAAA,CAAW,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA,CAAG,CAAA;AAAA,IAC9E;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,SAAA;AAAA,MACN,MAAA;AAAA,MACA,QAAQ,kBAAA,CAAmB,MAAA,EAAQ,GAAA,EAAK,MAAA,CAAO,SAAS,UAAU,CAAA;AAAA,MAClE,oBAAoB,iBAAA,CAAkB,WAAA;AAAA,MACtC,qBAAqB,WAAA,EAAa,WAAA;AAAA,MAClC,YAAY,WAAA,EAAa,UAAA;AAAA,MACzB;AAAA,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,OAAA;AACT;AAmDO,SAAS,kBAAA,CACd,MAAA,EACA,GAAA,EACA,UAAA,EACQ;AACR,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,OAAA;AACH,MAAA,OAAO,CAAA,SAAA,EAAY,MAAA,CAAO,GAAA,IAAO,CAAC,CAAC,CAAA,SAAA,CAAA;AAAA,IACrC,KAAK,mBAAA;AACH,MAAA,OAAO,sBAAA;AAAA,IACT,KAAK,qBAAA;AACH,MAAA,OAAO,uBAAA;AAAA,IACT,KAAK,SAAA;AACH,MAAA,OAAO,CAAA,EAAG,OAAO,GAAA,IAAO,CAAC,CAAC,CAAA,gBAAA,EAAmB,MAAA,CAAO,UAAA,IAAc,EAAE,CAAC,CAAA,CAAA,CAAA;AAAA,IACvE,KAAK,mBAAA;AACH,MAAA,OAAO,+BAAA;AAAA,IACT,KAAK,uBAAA;AACH,MAAA,OAAO,6BAAA;AAAA,IACT;AACE,MAAA,OAAO,MAAA;AAAA;AAEb;AC/KO,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAI,EAAG,cAAc,cAAc,CAAA;AACzD;AAMA,eAAsB,WAAA,GAAuC;AAC3D,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,cAAA,IAAkB,OAAO,CAAA;AACxD,IAAA,MAAM,IAAA,GAAgB,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAGxC,IAAA,IAAI,CAAC,cAAA,CAAe,IAAI,CAAA,EAAG;AACzB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAMA,eAAsB,YAAY,OAAA,EAAiC;AACjE,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,GAAA,GAAMI,QAAQ,WAAW,CAAA;AAG/B,EAAA,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,SAAA,EAAW,MAAM,CAAA;AAGpC,EAAA,MAAM,SAAA,CAAU,aAAa,IAAA,CAAK,SAAA,CAAU,SAAS,IAAA,EAAM,CAAC,GAAG,OAAO,CAAA;AACxE;AAMA,eAAsB,YAAA,GAA8B;AAClD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,CAAO,gBAAgB,CAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAmCA,SAAS,eAAe,IAAA,EAAgC;AACtD,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,IAAA,EAAM;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AAIA,EAAA,MAAM,GAAA,GAAM,IAAA;AAEZ,EAAA,OACE,OAAO,GAAA,CAAI,OAAA,KAAY,QAAA,IACvB,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,IAC1B,GAAA,CAAI,QAAA,CAAS,KAAA,CAAM,CAAC,IAAA,KAAS,OAAO,IAAA,KAAS,QAAQ,CAAA,IACrD,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,IAC3B,GAAA,CAAI,SAAA,CAAU,KAAA,CAAM,CAAC,IAAA,KAAS,OAAO,SAAS,QAAQ,CAAA,IACtD,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IACxB,GAAA,CAAI,MAAA,CAAO,KAAA,CAAM,CAAC,IAAA,KAAS,OAAO,IAAA,KAAS,QAAQ,CAAA,IACnD,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA,IAC3B,GAAA,CAAI,SAAA,CAAU,KAAA,CAAM,CAAC,IAAA,KAAS,OAAO,IAAA,KAAS,QAAQ,CAAA;AAE1D;ACzEA,eAAsB,eAAe,OAAA,EAA4C;AAE/E,EAAA,MAAM,MAAA,GAAS,MAAMC,UAAAA,EAAW;AAGhC,EAAA,MAAM,SAAA,GAAY,MAAM,mBAAA,CAAoB,MAAM,CAAA;AAGlD,EAAA,IAAI,WAAA;AACJ,EAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,EAAY;AAClC,IAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,SAAA,CAAU,MAAA,GAAS,CAAA,EAAG;AAC3C,MAAA,WAAA,GAAc,OAAA,CAAQ,SAAA;AACtB,MAAA,GAAA,CAAI,CAAA,sBAAA,EAAyB,MAAA,CAAO,WAAA,CAAY,MAAM,CAAC,CAAA,mBAAA,CAAqB,CAAA;AAAA,IAC9E;AAAA,EACF;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,YAAA,CAAa,SAAA,EAAW,MAAA,EAAQ,OAAA,CAAQ,MAAM,CAAA;AAC9C,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,gBAAgB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAClE,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,GAAA,CAAI,uCAAuC,CAAA;AAC3C,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAGA,EAAA,MAAM,OAAA,GAAU,MAAM,qBAAA,EAAsB;AAC5C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,KAAA,CAAM,gFAAgF,CAAA;AACtF,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,MAAM,WAAA,GAAc,mBAAmB,MAAM,CAAA;AAG7C,EAAA,MAAM,mBAAA,GAAsB,yBAAyB,MAAM,CAAA;AAG3D,EAAA,MAAM,gBAAgB,kBAAA,EAAmB;AAGzC,EAAA,MAAM,mBAAA,GAAsB;AAAA,IAC1B,SAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,iBAAA,EAAmB,mBAAA;AAAA,IACnB,WAAA,EAAa,aAAA;AAAA,IACb,GAAI,WAAA,KAAgB,MAAA,IAAa,EAAE,WAAA;AAAY,GACjD;AAEA,EAAA,MAAM,EAAE,eAAc,GAAI,MAAA,iBAAOf,GAAAA,CAAC,cAAA,EAAA,EAAgB,GAAG,mBAAA,EAAqB,CAAE,CAAA;AAG5E,EAAA,MAAM,aAAA,EAAc;AACtB;AAWA,SAAS,YAAA,CAAa,SAAA,EAA0B,MAAA,EAAgB,aAAA,EAA8B;AAC5F,EAAA,IAAI,gBAAgB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAEhE,EAAA,IAAI,aAAA,EAAe;AACjB,IAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,GAAA,GAAM,aAAA,CAAc,QAAQ,KAAA,EAAO,IAAI,CAAA,GAAI,GAAA,EAAK,GAAG,CAAA;AAC5E,IAAA,aAAA,GAAgB,aAAA,CAAc,OAAO,CAAC,CAAA,KAAM,MAAM,IAAA,CAAK,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,GAAA,CAAI,kDAAkD,CAAA;AACtD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAEA,EAAA,GAAA,CAAI,CAAA,UAAA,EAAa,MAAA,CAAO,aAAA,CAAc,MAAM,CAAC,CAAA,UAAA,CAAY,CAAA;AACzD,EAAA,aAAA,CAAc,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AAC9B,IAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,GAAI,CAAC,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,EACnD,CAAC,CAAA;AACD,EAAA,GAAA,CAAI,EAAE,CAAA;AACN,EAAA,GAAA,CAAI,iCAAiC,CAAA;AACrC,EAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC/B;AASA,SAAS,mBAAmB,MAAA,EAAqD;AAC/E,EAAA,OAAO,OAAO,SAAA,KAAwC;AAEpD,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,qBAAA,CAAuB,CAAA;AAChD,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAI,OAAA,GAAU,WAAA,CAAY,OAAA,IAAW,MAAA,CAAO,QAAA,CAAS,cAAA;AACrD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,KAAA,CAAM,CAAA,gCAAA,EAAmC,SAAS,CAAA,CAAA,CAAG,CAAA;AACrD,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,IAAK,YAAY,KAAA,EAAO;AACrD,MAAA,OAAA,GAAU,QAAQ,UAAA,CAAW,UAAA,EAAY,YAAY,KAAA,CAAM,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACtE;AAEA,IAAA,GAAA,CAAI,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAGzB,IAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,OAAO,CAAA;AAC7C,IAAA,OAAO,QAAA,KAAa,CAAA;AAAA,EACtB,CAAA;AACF;AASA,SAAS,yBAAyB,MAAA,EAAkD;AAClF,EAAA,OAAO,OAAO,SAAA,KAAqC;AAEjD,IAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,WAAA,CAAa,CAAA;AAAA,IAClD;AAGA,IAAA,MAAM,iBAAA,GAAoB,MAAMY,kBAAAA,CAAmB;AAAA,MACjD,UAAU,WAAA,CAAY,QAAA;AAAA,MACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,KACxD,CAAA;AAGD,IAAA,MAAM,cAAc,iBAAA,CAAkB;AAAA,MACpC,KAAA,EAAO,SAAA;AAAA,MACP,aAAa,iBAAA,CAAkB,WAAA;AAAA,MAC/B,OAAA,EAAS,WAAA,CAAY,OAAA,IAAW,MAAA,CAAO,SAAS,cAAA,IAAkB,EAAA;AAAA,MAClE,UAAA,EAAe,aAAS,CAAE;AAAA,KAC3B,CAAA;AAGD,IAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,IAAA,MAAM,eAAe,MAAMD,gBAAAA,CAAiB,gBAAgB,CAAA,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA;AAC9E,IAAA,MAAM,oBAAA,GAAuB,YAAA,EAAc,YAAA,IAAgB,EAAC;AAG5D,IAAA,MAAM,eAAA,GAAkB,iBAAA,CAAkB,oBAAA,EAAsB,WAAW,CAAA;AAG3E,IAAA,MAAM,iBAAiB,wBAAA,EAAyB;AAEhD,IAAA,IAAI,CAAIK,EAAA,CAAA,UAAA,CAAW,cAAc,CAAA,EAAG;AAClC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,cAAc,CAAA,+BAAA,CAAiC,CAAA;AAAA,IAC3F;AAGA,IAAA,MAAM,uBAAA,CAAwB;AAAA,MAC5B,QAAA,EAAU,gBAAA;AAAA,MACV,YAAA,EAAc,eAAA;AAAA,MACd;AAAA,KACD,CAAA;AAED,IAAA,GAAA,CAAI,CAAA,+BAAA,EAA6B,SAAS,CAAA,CAAE,CAAA;AAAA,EAC9C,CAAA;AACF;AAQA,SAAS,kBAAA,GAIU;AACjB,EAAA,OAAO,OAAO,SAAA,EAAqB,MAAA,EAAkB,SAAA,KAAuC;AAC1F,IAAA,IAAI,SAAA,CAAU,WAAW,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,IAAK,SAAA,CAAU,WAAW,CAAA,EAAG;AAE3E,MAAA,MAAM,YAAA,EAAa;AAAA,IACrB,CAAA,MAAO;AAEL,MAAA,MAAM,WAAA,CAAe;AAAA,QACnB,OAAA,EAAA,iBAAS,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY;AAAA,QAChC,UAAU,CAAC,GAAG,WAAW,GAAG,MAAA,EAAQ,GAAG,SAAS,CAAA;AAAA,QAChD,SAAA;AAAA,QACA,MAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AACF;AASA,eAAe,eAAe,OAAA,EAAkC;AAC9D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACC,QAAAA,KAAY;AAC9B,IAAA,MAAM,MAAA,GAASC,MAAkB,OAAO,CAAA;AACxC,IAAA,MAAM,aAAa,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAmB,OAAO,MAAM,QAAQ,CAAA;AAE1E,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,MAAA,KAAA,CAAM,eAAe,CAAA;AACrB,MAAAD,SAAQ,CAAC,CAAA;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,CAAC,UAAA,EAAY,GAAG,IAAI,CAAA,GAAI,UAAA;AAC9B,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAAA,SAAQ,CAAC,CAAA;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,KAAA,CAAM,UAAA,EAAY,MAAM,EAAE,KAAA,EAAO,WAAW,CAAA;AAE1D,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAAA,QAAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,IACnB,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,KAAA,CAAM,CAAA,gBAAA,EAAmB,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AACtC,MAAAA,SAAQ,CAAC,CAAA;AAAA,IACX,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAQA,eAAe,qBAAA,GAA0C;AACvD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACA,QAAAA,KAAY;AAC9B,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA,EAAO,CAAC,QAAA,EAAU,aAAa,CAAA,EAAG;AAAA,MACpD,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AACtB,MAAAA,QAAAA,CAAQ,MAAA,CAAO,IAAA,EAAK,CAAE,SAAS,CAAC,CAAA;AAAA,IAClC,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AACtB,MAAAA,SAAQ,KAAK,CAAA;AAAA,IACf,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;;;AC9SO,IAAM,aAAa,IAAIlB,OAAAA,CAAQ,KAAK,CAAA,CACxC,YAAY,sCAAsC,CAAA,CAClD,MAAA,CAAO,oBAAA,EAAsB,gEAAgE,CAAA,CAC7F,MAAA,CAAO,aAAa,oCAAoC,CAAA,CACxD,OAAO,aAAA,EAAe,wCAAwC,CAAA,CAC9D,MAAA,CAAO,aAAa,0BAA0B,CAAA,CAC9C,MAAA,CAAO,WAAA,EAAa,uCAAuC,CAAA,CAC3D,MAAA,CAAO,gBAAA,EAAkB,4BAA4B,EACrD,MAAA,CAAO,oBAAA,EAAsB,uCAAuC,CAAA,CACpE,MAAA,CAAO,OAAO,OAAA,KAAwB;AACrC,EAAA,MAAM,SAAS,OAAO,CAAA;AACxB,CAAC,CAAA;AA8BH,eAAe,SAAS,OAAA,EAAoC;AAC1D,EAAA,IAAI;AAEF,IAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,MAAA,MAAM,cAAc,OAAO,CAAA;AAC3B,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,QAAQ,GAAA,EAAK;AACf,MAAA,MAAM,cAAc,OAAO,CAAA;AAC3B,MAAA;AAAA,IACF;AAIA,IAAA,MAAM,cAAA,CAAe;AAAA,MACnB,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,QAAQ,OAAA,CAAQ;AAAA,KACjB,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AAeA,SAAS,YAAA,CAAa,MAAA,EAAgB,YAAA,EAAuB,UAAA,EAA+B;AAE1F,EAAA,IAAI,OAAA,GAAU,YAAA,IAAgB,MAAA,CAAO,QAAA,CAAS,cAAA;AAE9C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,KAAA,CAAM,kEAAkE,CAAA;AACxE,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,IAAK,UAAA,EAAY;AAC9C,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,IAAA,CAAK,GAAG,CAAA;AACjC,IAAA,OAAA,GAAU,OAAA,CAAQ,UAAA,CAAW,UAAA,EAAY,KAAK,CAAA;AAAA,EAChD;AAEA,EAAA,OAAO,OAAA;AACT;AAoBA,SAAS,aAAa,OAAA,EAAgC;AACpD,EAAA,MAAM,MAAA,GAASmB,MAAkB,OAAO,CAAA;AAIxC,EAAA,MAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAA2B;AAC3D,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA;AAAA,EAC1B,CAAC,CAAA;AAED,EAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,EAC9E;AAEA,EAAA,MAAM,CAAC,UAAA,EAAY,GAAG,IAAI,CAAA,GAAI,UAAA;AAG9B,EAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,IAAA,MAAM,IAAI,MAAM,4DAA4D,CAAA;AAAA,EAC9E;AAEA,EAAA,OAAO,EAAE,YAAY,IAAA,EAAK;AAC5B;AAWA,eAAeC,gBAAe,OAAA,EAAkC;AAC9D,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACF,QAAAA,KAAY;AAC9B,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,aAAa,OAAO,CAAA;AAAA,IAC/B,SAAS,GAAA,EAAK;AACZ,MAAA,IAAI,eAAe,KAAA,EAAO;AACxB,QAAA,KAAA,CAAM,CAAA,yBAAA,EAA4B,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,MACjD,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,wCAAwC,CAAA;AAAA,MAChD;AACA,MAAAA,SAAQ,CAAC,CAAA;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQG,KAAAA,CAAM,MAAA,CAAO,UAAA,EAAY,OAAO,IAAA,EAAM;AAAA,MAClD,KAAA,EAAO;AAAA;AAAA,KACR,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AAC1B,MAAAH,QAAAA,CAAQ,QAAQ,CAAC,CAAA;AAAA,IACnB,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAQ;AACzB,MAAA,KAAA,CAAM,CAAA,2BAAA,EAA8B,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AACjD,MAAAA,SAAQ,CAAC,CAAA;AAAA,IACX,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAQA,eAAeI,sBAAAA,GAA0C;AACvD,EAAA,OAAO,IAAI,OAAA,CAAQ,CAACJ,QAAAA,KAAY;AAC9B,IAAA,MAAM,QAAQG,KAAAA,CAAM,KAAA,EAAO,CAAC,QAAA,EAAU,aAAa,CAAA,EAAG;AAAA,MACpD,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM;AAAA,KACjC,CAAA;AAED,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAEtB,MAAAH,QAAAA,CAAQ,MAAA,CAAO,IAAA,EAAK,CAAE,SAAS,CAAC,CAAA;AAAA,IAClC,CAAC,CAAA;AAED,IAAA,KAAA,CAAM,EAAA,CAAG,SAAS,MAAM;AAEtB,MAAAA,SAAQ,KAAK,CAAA;AAAA,IACf,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAQA,eAAe,cAAc,OAAA,EAAoC;AAC/D,EAAA,IAAI,CAAC,QAAQ,KAAA,EAAO;AAClB,IAAA,KAAA,CAAM,wCAAwC,CAAA;AAC9C,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,MAAM,MAAA,GAAS,MAAMF,UAAAA,EAAW;AAGhC,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACjC,IAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,MAAM,OAAA,GAAU,MAAMM,sBAAAA,EAAsB;AAC5C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,KAAA,CAAM,gFAAgF,CAAA;AACtF,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,MAAM,cAAA,CAAe,OAAA,CAAQ,KAAA,EAAO,MAAA,EAAQ,OAAO,CAAA;AAEnD,EAAA,GAAA,CAAI,EAAE,CAAA;AACN,EAAA,OAAA,CAAQ,kBAAkB,CAAA;AAC1B,EAAA,GAAA;AAAA,IACE;AAAA,mBAAA,EAAwB,MAAA,CAAO,SAAS,gBAAgB,CAAA,uCAAA;AAAA,GAC1D;AACF;AAQA,eAAe,cAAc,OAAA,EAAoC;AAC/D,EAAA,MAAM,MAAA,GAAS,MAAMN,UAAAA,EAAW;AAChC,EAAA,MAAM,SAAA,GAAY,MAAM,mBAAA,CAAoB,MAAM,CAAA;AAClD,EAAA,MAAM,gBAAgB,SAAA,CAAU,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAElE,EAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAC9B,IAAA,GAAA,CAAI,uCAAuC,CAAA;AAC3C,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAGA,EAAA,IAAI,WAAA,GAAc,aAAA;AAClB,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,GAAA,GAAM,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA,GAAI,GAAA,EAAK,GAAG,CAAA;AAC7E,IAAA,WAAA,GAAc,aAAA,CAAc,OAAO,CAAC,CAAA,KAAM,MAAM,IAAA,CAAK,CAAA,CAAE,IAAI,CAAC,CAAA;AAE5D,IAAA,IAAI,WAAA,CAAY,WAAW,CAAA,EAAG;AAC5B,MAAA,GAAA,CAAI,CAAA,wBAAA,EAA2B,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAC/C,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B;AAAA,EACF;AAGA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,GAAA,CAAI,CAAA,UAAA,EAAa,MAAA,CAAO,WAAA,CAAY,MAAM,CAAC,CAAA,UAAA,CAAY,CAAA;AACvD,IAAA,WAAA,CAAY,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AAC5B,MAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,GAAI,CAAC,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,IAAI,CAAA,EAAA,EAAK,CAAA,CAAE,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,IACnD,CAAC,CAAA;AACD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAGA,EAAA,MAAM,OAAA,GAAU,MAAMM,sBAAAA,EAAsB;AAC5C,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,KAAA,CAAM,gFAAgF,CAAA;AACtF,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAGA,EAAA,KAAA,MAAW,SAAS,WAAA,EAAa;AAC/B,IAAA,MAAM,cAAA,CAAe,KAAA,CAAM,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AAAA,EAClD;AAEA,EAAA,GAAA,CAAI,EAAE,CAAA;AACN,EAAA,OAAA,CAAQ,uBAAuB,CAAA;AAC/B,EAAA,GAAA;AAAA,IACE;AAAA,mBAAA,EAAwB,MAAA,CAAO,SAAS,gBAAgB,CAAA,uCAAA;AAAA,GAC1D;AACF;AAUA,eAAe,cAAA,CACb,SAAA,EACA,MAAA,EACA,OAAA,EACe;AAEf,EAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,SAAS,CAAA;AAC3C,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,KAAA,CAAM,CAAA,OAAA,EAAU,SAAS,CAAA,qBAAA,CAAuB,CAAA;AAChD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AAEA,EAAA,GAAA,CAAI;AAAA,mBAAA,EAAwB,SAAS,CAAA;AAAA,CAAQ,CAAA;AAG7C,EAAA,MAAM,kBAAA,GAAqB;AAAA,IACzB,UAAU,WAAA,CAAY,QAAA;AAAA,IACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,GACzD;AACA,EAAA,MAAM,iBAAA,GAAoB,MAAMT,kBAAAA,CAAmB,kBAAkB,CAAA;AACrE,EAAA,OAAA,CAAQ,CAAA,aAAA,EAAgB,iBAAA,CAAkB,WAAW,CAAA,CAAE,CAAA;AACvD,EAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,iBAAA,CAAkB,SAAS,CAAC,CAAA,CAAE,CAAA;AAGvD,EAAA,MAAM,UAAU,YAAA,CAAa,MAAA,EAAQ,WAAA,CAAY,OAAA,EAAS,YAAY,KAAK,CAAA;AAC3E,EAAA,GAAA,CAAI,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AACzB,EAAA,GAAA,CAAI,EAAE,CAAA;AAGN,EAAA,MAAM,QAAA,GAAW,MAAMO,eAAAA,CAAe,OAAO,CAAA;AAE7C,EAAA,IAAI,aAAa,CAAA,EAAG;AAClB,IAAA,KAAA,CAAM,CAAA,4BAAA,EAA+B,MAAA,CAAO,QAAQ,CAAC,CAAA,CAAE,CAAA;AACvD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B;AAEA,EAAA,OAAA,CAAQ,eAAe,CAAA;AAGvB,EAAA,IAAI,OAAA,CAAQ,WAAW,KAAA,EAAO;AAC5B,IAAA,GAAA,CAAI,oCAAoC,CAAA;AACxC,IAAA;AAAA,EACF;AAGA,EAAA,MAAM,YAAA,GACJ,OAAA,CAAQ,GAAA,IACP,MAAM,aAAA,CAAc;AAAA,IACnB,OAAA,EAAS,qBAAA;AAAA,IACT,OAAA,EAAS;AAAA,GACV,CAAA;AAEH,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,IAAA,CAAK,uBAAuB,CAAA;AAC5B,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,EACjC;AAGA,EAAA,MAAM,cAAcb,iBAAAA,CAAkB;AAAA,IACpC,KAAA,EAAO,SAAA;AAAA,IACP,aAAa,iBAAA,CAAkB,WAAA;AAAA,IAC/B,OAAA;AAAA,IACA,UAAA,EAAegB,aAAS,CAAE;AAAA,GAC3B,CAAA;AAGD,EAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,EAAA,MAAM,YAAA,GAAe,MAAMX,gBAAAA,CAAiB,gBAAgB,CAAA;AAC5D,EAAA,MAAM,oBAAA,GAAuB,YAAA,EAAc,YAAA,IAAgB,EAAC;AAG5D,EAAA,MAAM,eAAA,GAAkBY,iBAAAA,CAAkB,oBAAA,EAAsB,WAAW,CAAA;AAG3E,EAAA,MAAM,iBAAiBC,wBAAAA,EAAyB;AAGhD,EAAA,IAAI,CAAIC,EAAA,CAAA,UAAA,CAAW,cAAc,CAAA,EAAG;AAClC,IAAA,KAAA,CAAM,CAAA,uBAAA,EAA0B,cAAc,CAAA,CAAE,CAAA;AAChD,IAAA,KAAA,CAAM,qDAAqD,CAAA;AAC3D,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,WAAW,CAAA;AAAA,EACnC;AAGA,EAAA,MAAMC,uBAAAA,CAAwB;AAAA,IAC5B,QAAA,EAAU,gBAAA;AAAA,IACV,YAAA,EAAc,eAAA;AAAA,IACd;AAAA,GACD,CAAA;AAED,EAAA,OAAA,CAAQ,CAAA,wBAAA,EAA2B,SAAS,CAAA,CAAE,CAAA;AAC9C,EAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,iBAAA,CAAkB,WAAW,CAAA,CAAE,CAAA;AACrD,EAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,WAAA,CAAY,UAAU,CAAA,CAAE,CAAA;AAC9C,EAAA,GAAA,CAAI,CAAA,eAAA,EAAkB,WAAA,CAAY,UAAU,CAAA,CAAE,CAAA;AAChD;ACpaO,IAAM,aAAA,GAAgB,IAAI3B,OAAAA,CAAQ,QAAQ,EAC9C,WAAA,CAAY,qDAAqD,CAAA,CACjE,MAAA,CAAO,qBAAA,EAAuB,yBAAyB,EACvD,MAAA,CAAO,qBAAA,EAAuB,wBAAwB,CAAA,CACtD,MAAA,CAAO,eAAe,yBAAyB,CAAA,CAC/C,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AAoBH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,GAAA,CAAI,qBAAqB,CAAA;AACzB,IAAA,MAAM,OAAA,GAAU,MAAM,YAAA,EAAa;AACnC,IAAA,IAAA,CAAK,CAAA,SAAA,EAAY,OAAO,CAAA,CAAE,CAAA;AAG1B,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,MAAA,IAAUyB,wBAAAA,EAAyB;AAC/D,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,MAAA,IAAU,uBAAA,EAAwB;AAE7D,IAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,WAAW,CAAA,CAAE,CAAA;AACjC,IAAA,GAAA,CAAI,CAAA,YAAA,EAAe,UAAU,CAAA,CAAE,CAAA;AAG/B,IAAA,MAAM,aAAA,GAAmBG,cAAW,WAAW,CAAA;AAC/C,IAAA,MAAM,YAAA,GAAkBA,cAAW,UAAU,CAAA;AAE7C,IAAA,IAAA,CAAK,aAAA,IAAiB,YAAA,KAAiB,CAAC,OAAA,CAAQ,KAAA,EAAO;AACrD,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,IAAA,CAAK,CAAA,4BAAA,EAA+B,WAAW,CAAA,CAAE,CAAA;AAAA,MACnD;AACA,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,IAAA,CAAK,CAAA,2BAAA,EAA8B,UAAU,CAAA,CAAE,CAAA;AAAA,MACjD;AAEA,MAAA,MAAM,eAAA,GAAkB,MAAM,aAAA,CAAc;AAAA,QAC1C,OAAA,EAAS,0BAAA;AAAA,QACT,OAAA,EAAS;AAAA,OACV,CAAA;AAED,MAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,QAAA,KAAA,CAAM,kBAAkB,CAAA;AACxB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,SAAS,CAAA;AAAA,MACjC;AAAA,IACF;AAGA,IAAA,GAAA,CAAI,kCAAkC,CAAA;AAEtC,IAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB;AAAA,MACnC,WAAA;AAAA,MACA,UAAA;AAAA,MACA,KAAA,EAAO;AAAA,KACR,CAAA;AAGD,IAAA,MAAM,iBAAA,CAAkB,OAAO,WAAW,CAAA;AAE1C,IAAA,OAAA,CAAQ,iCAAiC,CAAA;AACzC,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,4BAA4B,CAAA;AAChC,IAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,WAAW,CAAA,CAAE,CAAA;AAC7B,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,8BAA8B,CAAA;AAClC,IAAA,GAAA,CAAI,CAAA,EAAA,EAAK,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AAC5B,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,IAAA,CAAK,+CAA+C,CAAA;AACpD,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,GAAA,CAAI,aAAa,CAAA;AACjB,IAAA,GAAA,CAAI,CAAA,aAAA,EAAgB,MAAA,CAAO,UAAU,CAAA,CAAE,CAAA;AACvC,IAAA,GAAA,CAAI,4DAA4D,CAAA;AAChE,IAAA,GAAA,CAAI,yCAAyC,CAAA;AAAA,EAC/C,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AC9FO,IAAM,eAAe,IAAI5B,OAAAA,CAAQ,OAAO,CAAA,CAC5C,WAAA,CAAY,2BAA2B,CAAA,CACvC,MAAA,CAAO,iBAAiB,6CAA6C,CAAA,CACrE,OAAO,qBAAA,EAAuB,qCAAA,EAAuC,IAAI,CAAA,CACzE,MAAA,CAAO,OAAO,OAAA,KAA0B;AACvC,EAAA,MAAM,SAAS,OAAO,CAAA;AACxB,CAAC,CAAA;AAmBH,eAAe,SAAS,OAAA,EAAsC;AAC5D,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AAC9C,IAAA,IAAI,KAAA,CAAM,QAAQ,CAAA,IAAK,QAAA,GAAW,CAAA,EAAG;AACnC,MAAA,KAAA,CAAM,wCAAwC,CAAA;AAC9C,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAClC,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAMgB,UAAAA,EAAW;AAGhC,IAAA,MAAM,gBAAA,GAAmB,OAAO,QAAA,CAAS,gBAAA;AACzC,IAAA,MAAM,IAAA,GAAO,MAAMJ,gBAAAA,CAAiB,gBAAgB,CAAA;AAEpD,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,YAAA,CAAa,WAAW,CAAA,EAAG;AAC3C,MAAA,IAAA,CAAK,0BAA0B,CAAA;AAC/B,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AAGzC,IAAA,MAAM,QAAuB,EAAC;AAC9B,IAAA,MAAM,OAAsB,EAAC;AAE7B,IAAA,KAAA,MAAW,WAAA,IAAe,KAAK,YAAA,EAAc;AAC3C,MAAA,MAAM,aAAa,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,EAAE,OAAA,EAAQ;AAC5D,MAAA,MAAM,QAAQ,GAAA,GAAM,UAAA;AACpB,MAAA,MAAM,UAAU,IAAA,CAAK,KAAA,CAAM,SAAS,GAAA,GAAO,EAAA,GAAK,KAAK,EAAA,CAAG,CAAA;AAGxD,MAAA,MAAM,WAAA,GAAc,WAAA,CAAY,KAAA,IAAS,MAAA,CAAO,MAAA;AAGhD,MAAA,IAAI,kBAAA,GAAqB,KAAA;AACzB,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,WAAA,CAAY,KAAK,CAAA;AACnD,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAM,kBAAA,GAAqB;AAAA,YACzB,UAAU,WAAA,CAAY,QAAA;AAAA,YACtB,GAAI,WAAA,CAAY,MAAA,IAAU,EAAE,MAAA,EAAQ,YAAY,MAAA;AAAO,WACzD;AACA,UAAA,MAAM,MAAA,GAAS,MAAMC,kBAAAA,CAAmB,kBAAkB,CAAA;AAC1D,UAAA,kBAAA,GAAqB,MAAA,CAAO,gBAAgB,WAAA,CAAY,WAAA;AAAA,QAC1D;AAAA,MACF;AAKA,MAAA,MAAM,OAAA,GAAU,CAAC,kBAAA,IAAsB,KAAA,GAAQ,MAAA;AAC/C,MAAA,MAAM,WAAW,CAAC,WAAA;AAElB,MAAA,IAAI,WAAW,QAAA,EAAU;AACvB,QAAA,KAAA,CAAM,KAAK,WAAW,CAAA;AACtB,QAAA,MAAM,MAAA,GAAS,QAAA,GACX,eAAA,GACA,CAAC,qBACC,qBAAA,GACA,SAAA;AACN,QAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,YAAY,KAAK,CAAA,EAAA,EAAK,MAAM,CAAA,EAAA,EAAK,MAAA,CAAO,OAAO,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,MAChF,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,KAAK,WAAW,CAAA;AAAA,MACvB;AAAA,IACF;AAGA,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,MAAA,OAAA,CAAQ,6BAA6B,CAAA;AACrC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAEA,IAAA,GAAA,CAAI,CAAA,MAAA,EAAS,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA,sBAAA,CAAwB,CAAA;AACzD,IAAA,KAAA,MAAW,eAAe,KAAA,EAAO;AAC/B,MAAA,MAAM,UAAU,IAAA,CAAK,KAAA;AAAA,QAAA,CAClB,GAAA,GAAM,IAAI,IAAA,CAAK,WAAA,CAAY,UAAU,EAAE,OAAA,EAAQ,KAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,EAAA;AAAA,OACzE;AACA,MAAA,GAAA,CAAI,OAAO,WAAA,CAAY,KAAK,KAAK,MAAA,CAAO,OAAO,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,IAC9D;AAEA,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,MAAA,IAAA,CAAK,2BAA2B,CAAA;AAChC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,iBAAiBY,wBAAAA,EAAyB;AAChD,IAAA,IAAI,CAAII,EAAA,CAAA,UAAA,CAAW,cAAc,CAAA,EAAG;AAClC,MAAA,KAAA,CAAM,CAAA,uBAAA,EAA0B,cAAc,CAAA,CAAE,CAAA;AAChD,MAAA,KAAA,CAAM,mCAAmC,CAAA;AACzC,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,WAAW,CAAA;AACjC,MAAA;AAAA,IACF;AAGA,IAAA,MAAMF,uBAAAA,CAAwB;AAAA,MAC5B,QAAA,EAAU,gBAAA;AAAA,MACV,YAAA,EAAc,IAAA;AAAA,MACd;AAAA,KACD,CAAA;AAED,IAAA,OAAA,CAAQ,CAAA,OAAA,EAAU,MAAA,CAAO,KAAA,CAAM,MAAM,CAAC,CAAA,qBAAA,CAAuB,CAAA;AAC7D,IAAA,GAAA,CAAI,CAAA,WAAA,EAAc,MAAA,CAAO,IAAA,CAAK,MAAM,CAAC,CAAA,eAAA,CAAiB,CAAA;AACtD,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAClC,IAAA;AAAA,EACF;AACF;AC5IO,IAAM,aAAA,GAAgB,IAAI3B,OAAAA,CAAQ,QAAQ,EAC9C,WAAA,CAAY,kCAAkC,CAAA,CAC9C,MAAA,CAAO,oBAAA,EAAsB,4BAA4B,EACzD,MAAA,CAAO,QAAA,EAAU,iCAAiC,CAAA,CAClD,MAAA,CAAO,YAAY,uCAAuC,CAAA,CAC1D,MAAA,CAAO,OAAO,OAAA,KAA2B;AACxC,EAAA,MAAM,UAAU,OAAO,CAAA;AACzB,CAAC,CAAA;AAoBH,eAAe,UAAU,OAAA,EAAuC;AAC9D,EAAA,IAAI;AAEF,IAAA,MAAM,MAAA,GAAS,MAAMgB,UAAAA,EAAW;AAGhC,IAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,MAAA,IAAI,CAAC,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AACjC,QAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,MACpC;AAEA,MAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA;AACtD,MAAA,IAAI,CAAC,kBAAA,EAAoB;AACvB,QAAA,KAAA,CAAM,CAAA,OAAA,EAAU,OAAA,CAAQ,KAAK,CAAA,qBAAA,CAAuB,CAAA;AACpD,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,MACpC;AACA,MAAA,MAAM,cAAA,GAAyB;AAAA,QAC7B,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,QAAQ,EAAE,CAAC,OAAA,CAAQ,KAAK,GAAG,kBAAA;AAAmB,OAChD;AAGA,MAAA,MAAMc,OAAAA,GAAS,MAAM,kBAAA,CAAmB,EAAE,QAAQ,gBAAA,CAAiB,cAAc,GAAG,CAAA;AAGpF,MAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,QAAA,UAAA,CAAWA,OAAM,CAAA;AAAA,MACnB,CAAA,MAAO;AACL,QAAA,cAAA,CAAeA,OAAAA,EAAQ,cAAA,CAAe,QAAA,CAAS,UAAA,EAAY,QAAQ,MAAM,CAAA;AAAA,MAC3E;AAGA,MAAA,IAAI,CAACA,QAAO,OAAA,EAAS;AACnB,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AAEA,MAAA,IAAI,QAAQ,MAAA,IAAU,WAAA,CAAYA,SAAQ,cAAA,CAAe,QAAA,CAAS,UAAU,CAAA,EAAG;AAC7E,QAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAC7B,MAAA;AAAA,IACF;AAGA,IAAA,MAAM,MAAA,GAAS,MAAM,kBAAA,CAAmB,EAAE,QAAQ,gBAAA,CAAiB,MAAM,GAAG,CAAA;AAG5E,IAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,MAAA,UAAA,CAAW,MAAM,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,cAAA,CAAe,MAAA,EAAQ,MAAA,CAAO,QAAA,CAAS,UAAA,EAAY,QAAQ,MAAM,CAAA;AAAA,IACnE;AAGA,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B;AAEA,IAAA,IAAI,QAAQ,MAAA,IAAU,WAAA,CAAY,QAAQ,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,EAAG;AACrE,MAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,IAC/B;AAEA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,OAAO,CAAA;AAAA,EAC/B,SAAS,GAAA,EAAK;AACZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,KAAA,CAAM,IAAI,OAAO,CAAA;AAAA,IACnB,CAAA,MAAO;AACL,MAAA,KAAA,CAAM,wBAAwB,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,SAAS,YAAY,CAAA;AAAA,EACpC;AACF;AAYA,SAAS,cAAA,CAAe,MAAA,EAAsB,UAAA,EAAoB,MAAA,EAAwB;AACxF,EAAA,GAAA,CAAI,EAAE,CAAA;AAGN,EAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC1B,IAAA,KAAA,CAAM,+BAA+B,CAAA;AACrC,IAAA,GAAA,CAAI,oDAAoD,CAAA;AACxD,IAAA,GAAA,CAAI,EAAE,CAAA;AAAA,EACR;AAGA,EAAA,KAAA,MAAW,QAAA,IAAY,OAAO,MAAA,EAAQ;AACpC,IAAA,KAAA,CAAM,QAAQ,CAAA;AAAA,EAChB;AACA,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AAC5B,IAAA,GAAA,CAAI,EAAE,CAAA;AAAA,EACR;AAGA,EAAA,MAAM,SAAA,GAAwB,MAAA,CAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACtD,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,MAAA,EAAQ,cAAA,CAAe,CAAA,CAAE,MAAM,CAAA;AAAA,IAC/B,aAAa,CAAA,CAAE,WAAA,CAAY,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA,GAAI,KAAA;AAAA,IAC1C,GAAA,EAAK,gBAAgB,CAAC;AAAA,GACxB,CAAE,CAAA;AAEF,EAAA,GAAA,CAAI,WAAA,CAAY,SAAS,CAAC,CAAA;AAC1B,EAAA,GAAA,CAAI,EAAE,CAAA;AAGN,EAAA,IAAI,OAAO,OAAA,EAAS;AAClB,IAAA,OAAA,CAAQ,wBAAwB,CAAA;AAAA,EAClC,CAAA,MAAO;AAEL,IAAA,MAAM,gBAAA,GAAmB,OAAO,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,OAAO,CAAA;AAEzE,IAAA,IAAI,gBAAA,CAAiB,SAAS,CAAA,EAAG;AAC/B,MAAA,GAAA,CAAI,cAAc,CAAA;AAClB,MAAA,KAAA,MAAW,SAAS,gBAAA,EAAkB;AACpC,QAAA,GAAA,CAAI,CAAA,wBAAA,EAA2B,KAAA,CAAM,KAAK,CAAA,CAAE,CAAA;AAC5C,QAAA,IAAI,MAAM,OAAA,EAAS;AACjB,UAAA,GAAA,CAAI,CAAA,IAAA,EAAO,KAAA,CAAM,OAAO,CAAA,CAAE,CAAA;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,MAAM,UAAA,GAAa,OAAO,MAAA,CAAO,MAAA;AAAA,IAC/B,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,GAAA,IAAO,KAAK,UAAA,GAAa;AAAA,GAC7D;AAEA,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,IAAA,GAAA,CAAI,EAAE,CAAA;AACN,IAAA,KAAA,MAAW,SAAS,UAAA,EAAY;AAC9B,MAAA,IAAA,CAAK,CAAA,EAAG,MAAM,KAAK,CAAA,iCAAA,EAAoC,OAAO,KAAA,CAAM,GAAG,CAAC,CAAA,UAAA,CAAY,CAAA;AAAA,IACtF;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,GAAA,CAAI,iDAAiD,CAAA;AAAA,IACvD;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,CAAA,EAAoC;AAC3D,EAAA,IAAI,CAAA,CAAE,WAAW,OAAA,EAAS;AACxB,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,GAAA,IAAO,CAAC,CAAC,CAAA,KAAA,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,mBAAA,EAAqB;AACpC,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,SAAA,EAAW;AAC1B,IAAA,OAAO,CAAA,EAAG,MAAA,CAAO,CAAA,CAAE,GAAA,IAAO,CAAC,CAAC,CAAA,eAAA,CAAA;AAAA,EAC9B;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,qBAAA,EAAuB;AACtC,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,IAAI,CAAA,CAAE,WAAW,uBAAA,EAAyB;AACxC,IAAA,OAAO,eAAA;AAAA,EACT;AAEA,EAAA,OAAO,GAAA;AACT;AAaA,SAAS,WAAA,CAAY,QAAsB,UAAA,EAA6B;AACtE,EAAA,MAAM,gBAAA,GAAmB,CAAA;AACzB,EAAA,OAAO,OAAO,MAAA,CAAO,IAAA;AAAA,IACnB,CAAC,MAAM,CAAA,CAAE,MAAA,KAAW,YAAY,CAAA,CAAE,GAAA,IAAO,KAAK,UAAA,GAAa;AAAA,GAC7D;AACF;;;ACvOA,IAAM,OAAA,GAAU,IAAI9B,OAAAA,EAAQ;AAE5B,OAAA,CACG,KAAK,WAAW,CAAA,CAChB,YAAY,qCAAqC,CAAA,CACjD,QAAQ,OAAO,CAAA,CACf,OAAO,qBAAA,EAAuB,qBAAqB,EACnD,MAAA,CAAO,eAAA,EAAiB,gBAAgB,CAAA,CACxC,MAAA,CAAO,eAAe,gBAAgB,CAAA;AAGzC,OAAA,CAAQ,WAAW,WAAW,CAAA;AAC9B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAChC,OAAA,CAAQ,WAAW,UAAU,CAAA;AAC7B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAChC,OAAA,CAAQ,WAAW,YAAY,CAAA;AAC/B,OAAA,CAAQ,WAAW,aAAa,CAAA;AAEhC,eAAsB,GAAA,GAAqB;AAEzC,EAAA,MAAM,SAAA,EAAU;AAGhB,EAAA,OAAA,CAAQ,KAAA,EAAM;AACd,EAAA,MAAM,OAAA,GAAU,QAAQ,IAAA,EAA6C;AAErE,EAAA,MAAM,gBAAwD,EAAC;AAC/D,EAAA,IAAI,OAAA,CAAQ,YAAY,MAAA,EAAW;AACjC,IAAA,aAAA,CAAc,UAAU,OAAA,CAAQ,OAAA;AAAA,EAClC;AACA,EAAA,IAAI,OAAA,CAAQ,UAAU,MAAA,EAAW;AAC/B,IAAA,aAAA,CAAc,QAAQ,OAAA,CAAQ,KAAA;AAAA,EAChC;AAEA,EAAA,gBAAA,CAAiB,aAAa,CAAA;AAChC;;;AC1CA,KAAK,GAAA,EAAI","file":"attest-it.js","sourcesContent":["import { detectTheme, type Theme } from 'chromaterm'\n\nexport interface OutputOptions {\n verbose?: boolean\n quiet?: boolean\n json?: boolean\n}\n\n// Singleton for global output options\nlet globalOptions: OutputOptions = {}\n\n// Theme singleton - will be initialized lazily if not explicitly initialized\nlet theme: Theme | undefined\n\n/**\n * Initialize the color theme by detecting the terminal theme.\n * Must be called before using any color functions.\n */\nexport async function initTheme(): Promise<void> {\n theme = await detectTheme()\n}\n\n/**\n * Get the theme, initializing it synchronously if needed (for tests).\n * Uses a fallback no-op theme if async initialization hasn't been called.\n */\nfunction getTheme(): Theme {\n if (!theme) {\n // Fallback for tests or when initTheme() wasn't called\n // This creates a simple pass-through theme that returns strings unchanged\n const noopFn = (str: string) => str\n const chainable = () => noopFn\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Required mock theme for testing/fallback when async init not called\n theme = {\n red: Object.assign(noopFn, { bold: chainable, dim: chainable }),\n green: Object.assign(noopFn, { bold: chainable, dim: chainable }),\n yellow: Object.assign(noopFn, { bold: chainable, dim: chainable }),\n blue: Object.assign(noopFn, { bold: chainable, dim: chainable }),\n success: noopFn,\n error: noopFn,\n warning: noopFn,\n info: noopFn,\n muted: noopFn,\n } as unknown as Theme\n }\n return theme\n}\n\nexport function setOutputOptions(options: OutputOptions): void {\n globalOptions = options\n}\n\nexport function getOutputOptions(): OutputOptions {\n return globalOptions\n}\n\n// Logging functions\nexport function log(message: string): void {\n if (!globalOptions.quiet) {\n console.log(message)\n }\n}\n\nexport function verbose(message: string): void {\n if (globalOptions.verbose && !globalOptions.quiet) {\n console.log(getTheme().muted(message))\n }\n}\n\nexport function success(message: string): void {\n log(getTheme().success('✓ ' + message))\n}\n\nexport function error(message: string): void {\n console.error(getTheme().error('✗ ' + message))\n}\n\nexport function warn(message: string): void {\n if (!globalOptions.quiet) {\n console.warn(getTheme().warning('⚠ ' + message))\n }\n}\n\nexport function info(message: string): void {\n log(getTheme().info('ℹ ' + message))\n}\n\n// Table formatting for status display\nexport interface TableRow {\n suite: string\n status: string\n fingerprint: string\n age: string\n}\n\nexport function formatTable(rows: TableRow[]): string {\n // Calculate column widths\n const headers = ['Suite', 'Status', 'Fingerprint', 'Age']\n\n // Helper to get row values in consistent order\n const getRowValues = (row: TableRow): string[] => [\n row.suite,\n row.status,\n row.fingerprint,\n row.age,\n ]\n\n const widths = headers.map((h, i) => {\n const columnValues = rows.map((r) => {\n const values = getRowValues(r)\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n return values[i] ?? ''\n })\n const maxValueLength = Math.max(...columnValues.map((v) => v.length), 0)\n return Math.max(h.length, maxValueLength)\n })\n\n // Build table\n const separator = '─'\n const lines: string[] = []\n\n // Header\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n lines.push(headers.map((h, i) => h.padEnd(widths[i] ?? 0)).join(' │ '))\n lines.push(widths.map((w) => separator.repeat(w)).join('─┼─'))\n\n // Rows\n for (const row of rows) {\n const values = getRowValues(row)\n // eslint-disable-next-line security/detect-object-injection -- i is from .map() index\n lines.push(values.map((v, i) => v.padEnd(widths[i] ?? 0)).join(' │ '))\n }\n\n return lines.join('\\n')\n}\n\n// Status colorization\nexport function colorizeStatus(status: string): string {\n const t = getTheme()\n switch (status) {\n case 'VALID':\n return t.green(status)\n case 'NEEDS_ATTESTATION':\n case 'FINGERPRINT_CHANGED':\n return t.yellow(status)\n case 'EXPIRED':\n case 'INVALIDATED_BY_PARENT':\n return t.red(status)\n case 'SIGNATURE_INVALID':\n return t.red.bold()(status)\n default:\n return status\n }\n}\n\n// JSON output\nexport function outputJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2))\n}\n","import { confirm } from '@inquirer/prompts'\n\nexport interface ConfirmOptions {\n message: string\n default?: boolean\n}\n\nexport async function confirmAction(options: ConfirmOptions): Promise<boolean> {\n return confirm({\n message: options.message,\n default: options.default ?? false,\n })\n}\n","/**\n * Standard exit codes for the attest-it CLI.\n *\n * These codes follow Unix conventions and provide consistent error reporting\n * across all CLI commands.\n *\n * @packageDocumentation\n */\n\n/**\n * Standard exit codes for the attest-it CLI.\n * @public\n */\nexport const ExitCode = {\n /** Operation completed successfully */\n SUCCESS: 0,\n /** Tests failed or attestation invalid */\n FAILURE: 1,\n /** Nothing needed attestation */\n NO_WORK: 2,\n /** Configuration or validation error */\n CONFIG_ERROR: 3,\n /** User cancelled the operation */\n CANCELLED: 4,\n /** Missing required key file */\n MISSING_KEY: 5,\n} as const\n\n/**\n * Type representing all possible exit codes.\n * @public\n */\nexport type ExitCode = (typeof ExitCode)[keyof typeof ExitCode]\n","import { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { log, success, error } from '../utils/output.js'\nimport { confirmAction } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const initCommand = new Command('init')\n .description('Initialize attest-it configuration')\n .option('-p, --path <path>', 'Config file path', '.attest-it/config.yaml')\n .option('-f, --force', 'Overwrite existing config')\n .action(async (options: InitOptions) => {\n await runInit(options)\n })\n\ninterface InitOptions {\n path: string\n force?: boolean\n}\n\nconst CONFIG_TEMPLATE = `# attest-it configuration\n# See https://github.com/attest-it/attest-it for documentation\n\nversion: 1\n\nsettings:\n # How long attestations remain valid (in days)\n maxAgeDays: 30\n # Path to the public key used for signature verification\n publicKeyPath: .attest-it/pubkey.pem\n # Path to the attestations file\n attestationsPath: .attest-it/attestations.json\n # Signing algorithm\n algorithm: rsa\n\n# Define your test suites below. Each suite groups tests that require\n# human verification before their attestations are accepted.\n#\n# Example:\n#\n# suites:\n# visual-tests:\n# description: Visual regression tests requiring human review\n# packages:\n# - packages/ui\n# - packages/components\n# command: pnpm vitest packages/ui packages/components\n#\n# integration:\n# description: Integration tests with external services\n# packages:\n# - packages/api\n# command: pnpm vitest packages/api --project=integration\n\nsuites: {}\n`\n\n/**\n * Run the init command to create a new attest-it configuration.\n *\n * Creates a configuration file with sensible defaults and commented\n * examples showing how to define test suites.\n *\n * @param options - Command options\n * @param options.path - Config file path (default: .attest-it/config.yaml)\n * @param options.force - Overwrite existing config without prompting\n * @public\n */\nasync function runInit(options: InitOptions): Promise<void> {\n try {\n const configPath = path.resolve(options.path)\n const configDir = path.dirname(configPath)\n\n if (fs.existsSync(configPath) && !options.force) {\n const overwrite = await confirmAction({\n message: `Config already exists at ${configPath}. Overwrite?`,\n default: false,\n })\n if (!overwrite) {\n error('Init cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n }\n\n // Create directory and write config\n await fs.promises.mkdir(configDir, { recursive: true })\n await fs.promises.writeFile(configPath, CONFIG_TEMPLATE, 'utf-8')\n\n success(`Configuration created at ${configPath}`)\n log('')\n log('Next steps:')\n log(` 1. Edit ${options.path} to define your test suites`)\n log(' 2. Run: attest-it keygen')\n log(' 3. Run: attest-it status')\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nexport { runInit }\n","import { Command } from 'commander'\nimport {\n loadConfig,\n computeFingerprint,\n readAttestations,\n findAttestation,\n type VerificationStatus,\n type AttestationsFile,\n type Attestation,\n} from '@attest-it/core'\nimport {\n log,\n success,\n error,\n formatTable,\n colorizeStatus,\n outputJson,\n type TableRow,\n} from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const statusCommand = new Command('status')\n .description('Show attestation status for all suites')\n .option('-s, --suite <name>', 'Show status for specific suite only')\n .option('--json', 'Output JSON for machine parsing')\n .action(async (options: StatusOptions) => {\n await runStatus(options)\n })\n\ninterface StatusOptions {\n suite?: string\n json?: boolean\n}\n\ninterface SuiteStatus {\n name: string\n status: VerificationStatus\n currentFingerprint: string\n attestedFingerprint?: string | undefined\n attestedAt?: string | undefined\n age?: number | undefined\n}\n\n/**\n * Run the status command to show attestation status.\n *\n * Displays the current status of attestations for all suites or a specific suite,\n * including validation status, fingerprints, and age information.\n *\n * @param options - Command options\n * @param options.suite - Show status for specific suite only\n * @param options.json - Output JSON for machine parsing\n * @public\n */\nasync function runStatus(options: StatusOptions): Promise<void> {\n try {\n // Load config\n const config = await loadConfig()\n\n // Load attestations (may not exist)\n const attestationsPath = config.settings.attestationsPath\n let attestationsFile: AttestationsFile | null = null\n try {\n attestationsFile = await readAttestations(attestationsPath)\n } catch (err) {\n // Attestations file may not exist yet - that's okay\n if (err instanceof Error && !err.message.includes('ENOENT')) {\n throw err\n }\n }\n const attestations = attestationsFile?.attestations ?? []\n\n // Get suites to check\n const suiteNames = options.suite ? [options.suite] : Object.keys(config.suites)\n\n // Validate suite exists\n if (options.suite && !config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Check each suite\n const results: SuiteStatus[] = []\n let hasInvalid = false\n\n for (const suiteName of suiteNames) {\n // eslint-disable-next-line security/detect-object-injection\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) continue\n\n // Compute current fingerprint\n const fingerprintResult = await computeFingerprint({\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n })\n\n // Find existing attestation\n const attestation = findAttestation(\n {\n schemaVersion: '1',\n attestations,\n signature: '',\n },\n suiteName,\n )\n\n // Determine status\n const status = determineStatus(\n attestation ?? null,\n fingerprintResult.fingerprint,\n config.settings.maxAgeDays,\n )\n\n // Calculate age if attestation exists\n let age: number | undefined\n if (attestation) {\n const attestedAt = new Date(attestation.attestedAt)\n age = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n }\n\n if (status !== 'VALID') {\n hasInvalid = true\n }\n\n results.push({\n name: suiteName,\n status,\n currentFingerprint: fingerprintResult.fingerprint,\n attestedFingerprint: attestation?.fingerprint,\n attestedAt: attestation?.attestedAt,\n age,\n })\n }\n\n // Output results\n if (options.json) {\n outputJson(results)\n } else {\n displayStatusTable(results, hasInvalid)\n }\n\n process.exit(hasInvalid ? ExitCode.FAILURE : ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nfunction determineStatus(\n attestation: Attestation | null,\n currentFingerprint: string,\n maxAgeDays: number,\n): VerificationStatus {\n if (!attestation) {\n return 'NEEDS_ATTESTATION'\n }\n\n if (attestation.fingerprint !== currentFingerprint) {\n return 'FINGERPRINT_CHANGED'\n }\n\n const attestedAt = new Date(attestation.attestedAt)\n const ageInDays = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n\n if (ageInDays > maxAgeDays) {\n return 'EXPIRED'\n }\n\n return 'VALID'\n}\n\nfunction displayStatusTable(results: SuiteStatus[], hasInvalid: boolean): void {\n const tableRows: TableRow[] = results.map((r) => ({\n suite: r.name,\n status: colorizeStatus(r.status),\n fingerprint: r.currentFingerprint.slice(0, 16) + '...',\n age: formatAge(r),\n }))\n\n log('')\n log(formatTable(tableRows))\n log('')\n\n if (hasInvalid) {\n log('Run `attest-it run --suite <name>` to update attestations')\n } else {\n success('All attestations valid')\n }\n}\n\nfunction formatAge(result: SuiteStatus): string {\n if (result.status === 'VALID') {\n return `${String(result.age ?? 0)} days`\n }\n\n if (result.status === 'FINGERPRINT_CHANGED') {\n return '(changed)'\n }\n\n if (result.status === 'NEEDS_ATTESTATION') {\n return '(none)'\n }\n\n if (result.status === 'EXPIRED') {\n return `${String(result.age ?? 0)} days (expired)`\n }\n\n return '-'\n}\n\nexport { runStatus }\n","import * as React from 'react'\nimport { Box, Text } from 'ink'\n\nexport interface HeaderProps {\n /** Number of suites needing attestation */\n pendingCount: number\n}\n\n/**\n * Displays a header box with pending suite count.\n *\n * Example output:\n * ┌─────────────────────────────────────────────────────────────┐\n * │ 4 suites need attestation │\n * └─────────────────────────────────────────────────────────────┘\n */\nexport function Header({ pendingCount }: HeaderProps): React.ReactElement {\n const message = `${pendingCount.toString()} suite${pendingCount === 1 ? '' : 's'} need${pendingCount === 1 ? 's' : ''} attestation`\n\n return (\n <Box borderStyle=\"single\" paddingX={1}>\n <Text>{message}</Text>\n </Box>\n )\n}\n","import React from 'react'\nimport { Text } from 'ink'\nimport type { VerificationStatus } from '@attest-it/core'\n\n/**\n * Props for the StatusBadge component.\n * @public\n */\nexport interface StatusBadgeProps {\n /** The verification status to display */\n status: VerificationStatus\n}\n\n/**\n * Displays a colored badge for suite verification status.\n *\n * Status colors:\n * - VALID: green\n * - NEEDS_ATTESTATION: yellow (display as \"MISSING\")\n * - FINGERPRINT_CHANGED: yellow (display as \"CHANGED\")\n * - EXPIRED: red (display as \"STALE\")\n * - SIGNATURE_INVALID: red bold\n * - INVALIDATED_BY_PARENT: red (display as \"INVALIDATED\")\n *\n * @param props - Component props\n * @returns React element\n * @public\n */\nexport function StatusBadge({ status }: StatusBadgeProps): React.ReactElement {\n // Map status to display text and color\n const statusConfig = getStatusConfig(status)\n\n // Only pass bold prop if it's true to avoid exactOptionalPropertyTypes issues\n if (statusConfig.bold) {\n return (\n <Text color={statusConfig.color} bold>\n {statusConfig.text}\n </Text>\n )\n }\n\n return <Text color={statusConfig.color}>{statusConfig.text}</Text>\n}\n\n/**\n * Get display configuration for a verification status.\n * @internal\n */\ninterface StatusConfig {\n text: string\n color: 'green' | 'yellow' | 'red'\n bold?: boolean\n}\n\n/**\n * Get display configuration for a verification status.\n * @internal\n */\nfunction getStatusConfig(status: VerificationStatus): StatusConfig {\n switch (status) {\n case 'VALID':\n return { text: '✓ VALID', color: 'green' }\n case 'NEEDS_ATTESTATION':\n return { text: 'MISSING', color: 'yellow' }\n case 'FINGERPRINT_CHANGED':\n return { text: 'CHANGED', color: 'yellow' }\n case 'EXPIRED':\n return { text: 'STALE', color: 'red' }\n case 'SIGNATURE_INVALID':\n return { text: 'INVALID', color: 'red', bold: true }\n case 'INVALIDATED_BY_PARENT':\n return { text: 'INVALIDATED', color: 'red' }\n default: {\n // Exhaustive check\n const _exhaustive: never = status\n return { text: String(_exhaustive), color: 'yellow' }\n }\n }\n}\n","import React from 'react'\nimport { Box, Text } from 'ink'\nimport { StatusBadge } from './StatusBadge.js'\nimport type { VerificationStatus } from '@attest-it/core'\n\n/**\n * Information about a single suite for display in the table.\n * @public\n */\nexport interface SuiteInfo {\n /** Suite name */\n name: string\n /** Current verification status */\n status: VerificationStatus\n /** Human-readable reason (e.g., \"32 days old (max: 30)\") */\n reason: string\n /** Days since attestation (if exists) */\n age?: number | undefined\n}\n\n/**\n * Props for the SuiteTable component.\n * @public\n */\nexport interface SuiteTableProps {\n /** List of suites to display */\n suites: SuiteInfo[]\n /** Show checkbox column for selection */\n selectable?: boolean | undefined\n /** Currently selected suite names */\n selected?: Set<string> | undefined\n}\n\n/**\n * Displays suites in a table format with status badges.\n *\n * Example output:\n * ```\n * Status Suite Reason\n * ──────────────────────────────────────────────────────────\n * [ ] STALE visual-effects 32 days old (max: 30)\n * [ ] MISSING focus-detection No attestation found\n * ```\n *\n * @param props - Component props\n * @returns React element\n * @public\n */\nexport function SuiteTable({\n suites,\n selectable = false,\n selected = new Set(),\n}: SuiteTableProps): React.ReactElement {\n // Calculate column widths\n const columnWidths = calculateColumnWidths(suites, selectable)\n\n return (\n <Box flexDirection=\"column\">\n {/* Header */}\n <Box>\n {selectable && <Text>{' '.repeat(4)}</Text>}\n <Text bold>{padEnd('Status', columnWidths.status)}</Text>\n <Text> </Text>\n <Text bold>{padEnd('Suite', columnWidths.suite)}</Text>\n <Text> </Text>\n <Text bold>Reason</Text>\n </Box>\n\n {/* Separator */}\n <Box>\n <Text color=\"gray\">\n {'─'.repeat(\n (selectable ? 4 : 0) + columnWidths.status + columnWidths.suite + columnWidths.reason,\n )}\n </Text>\n </Box>\n\n {/* Rows */}\n {suites.map((suite) => (\n <Box key={suite.name}>\n {selectable && <Text>{selected.has(suite.name) ? '[✓] ' : '[ ] '}</Text>}\n <Box width={columnWidths.status}>\n <StatusBadge status={suite.status} />\n </Box>\n <Text> </Text>\n <Text>{padEnd(suite.name, columnWidths.suite)}</Text>\n <Text> </Text>\n <Text color=\"gray\">{suite.reason}</Text>\n </Box>\n ))}\n </Box>\n )\n}\n\n/**\n * Column width information.\n * @internal\n */\ninterface ColumnWidths {\n status: number\n suite: number\n reason: number\n}\n\n/**\n * Calculate column widths based on content.\n * @internal\n */\nfunction calculateColumnWidths(suites: SuiteInfo[], _selectable: boolean): ColumnWidths {\n const statusHeader = 'Status'\n const suiteHeader = 'Suite'\n const reasonHeader = 'Reason'\n\n // Status column - fixed width for badges\n // Maximum status badge length is \"INVALIDATED\" (11 chars) + \"✓ \" (2 chars) = 13\n const statusWidth = Math.max(statusHeader.length, 13)\n\n // Suite column - max of header and all suite names\n const suiteWidth = Math.max(suiteHeader.length, ...suites.map((s) => s.name.length))\n\n // Reason column - max of header and all reasons\n const reasonWidth = Math.max(reasonHeader.length, ...suites.map((s) => s.reason.length))\n\n return {\n status: statusWidth,\n suite: suiteWidth,\n reason: reasonWidth,\n }\n}\n\n/**\n * Pad a string to the right with spaces.\n * @internal\n */\nfunction padEnd(str: string, width: number): string {\n return str.padEnd(width, ' ')\n}\n","import * as React from 'react'\nimport { Box, Text, useInput } from 'ink'\n\ninterface SelectionOption {\n /** Display label */\n label: string\n /** Value returned when selected */\n value: string\n /** Optional keyboard shortcut hint */\n hint?: string\n}\n\nexport interface SelectionPromptProps {\n /** Question to display */\n message: string\n /** Available options */\n options: SelectionOption[]\n /** Callback when option selected */\n onSelect: (value: string) => void\n /** Show group options if available */\n groups?: { name: string; label: string }[] | undefined\n}\n\n/**\n * Displays a selection prompt with keyboard hints.\n *\n * Example output:\n * Select suites to run:\n * [a] All pending [1-4] By number [n] None/exit\n * [g1] ui-tests [g2] behavior-tests\n */\nexport function SelectionPrompt({\n message,\n options,\n onSelect,\n groups,\n}: SelectionPromptProps): React.ReactElement {\n useInput((input) => {\n // Check if input matches any option's hint\n const matchedOption = options.find((opt) => opt.hint === input)\n if (matchedOption) {\n onSelect(matchedOption.value)\n return\n }\n\n // Check if input matches a group name\n if (groups) {\n const matchedGroup = groups.find((group) => group.name === input)\n if (matchedGroup) {\n onSelect(matchedGroup.name)\n }\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>{message}</Text>\n <Box marginTop={1} gap={2}>\n {options.map((option) => (\n <Text key={option.value}>\n {option.hint && (\n <>\n <Text color=\"cyan\">[{option.hint}]</Text>{' '}\n </>\n )}\n {option.label}\n </Text>\n ))}\n </Box>\n {groups && groups.length > 0 && (\n <Box marginTop={1} gap={2}>\n {groups.map((group) => (\n <Text key={group.name}>\n <Text color=\"cyan\">[{group.name}]</Text> {group.label}\n </Text>\n ))}\n </Box>\n )}\n </Box>\n )\n}\n","import * as React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport { Header } from './Header.js'\nimport { SuiteTable } from './SuiteTable.js'\nimport { SelectionPrompt } from './SelectionPrompt.js'\nimport type { SuiteStatus } from '../commands/run-utils.js'\n\ninterface SuiteSelectorProps {\n /** All suites needing attestation */\n pendingSuites: SuiteStatus[]\n /** Valid suites (for \"Already valid\" display) */\n validSuites: SuiteStatus[]\n /** Available groups from config */\n groups?: Record<string, string[]> | undefined\n /** Called when user confirms selection */\n onSelect: (selectedSuites: string[]) => void\n /** Called when user exits */\n onExit: () => void\n}\n\n/**\n * Main suite selection UI component.\n *\n * Displays:\n * 1. Header with pending count\n * 2. Table of pending suites with checkboxes\n * 3. List of already valid suites\n * 4. Selection prompt with keyboard shortcuts\n *\n * Keyboard controls:\n * - a: Select all pending\n * - n: None/exit\n * - 1-9: Toggle individual suite by number\n * - g1, g2, etc: Select group (if groups available)\n * - Enter: Confirm selection\n * - Space: Toggle current suite\n * - Up/Down: Navigate\n */\nexport function SuiteSelector({\n pendingSuites,\n validSuites,\n groups,\n onSelect,\n onExit,\n}: SuiteSelectorProps): React.ReactElement {\n const [selectedSuites, setSelectedSuites] = React.useState<Set<string>>(new Set())\n const [cursorIndex, setCursorIndex] = React.useState(0)\n\n /**\n * Toggle suite selection state\n */\n const toggleSuite = React.useCallback((suiteName: string) => {\n setSelectedSuites((prev) => {\n const next = new Set(prev)\n if (next.has(suiteName)) {\n next.delete(suiteName)\n } else {\n next.add(suiteName)\n }\n return next\n })\n }, [])\n\n useInput((input, key) => {\n // 'a' - select all pending\n if (input === 'a') {\n setSelectedSuites(new Set(pendingSuites.map((s) => s.name)))\n return\n }\n\n // 'n' - none/exit\n if (input === 'n') {\n onExit()\n return\n }\n\n // Numbers 1-9 - toggle by number\n if (/^[1-9]$/.test(input)) {\n const idx = parseInt(input, 10) - 1\n if (idx < pendingSuites.length) {\n // eslint-disable-next-line security/detect-object-injection -- idx is bounds-checked against pendingSuites.length\n const suite = pendingSuites[idx]\n if (suite) {\n toggleSuite(suite.name)\n }\n }\n return\n }\n\n // Handle group shortcuts like 'g1', 'g2'\n if (input.startsWith('g') && groups) {\n const groupIdx = parseInt(input.slice(1), 10) - 1\n const groupNames = Object.keys(groups)\n if (groupIdx >= 0 && groupIdx < groupNames.length) {\n // eslint-disable-next-line security/detect-object-injection -- groupIdx is bounds-checked against groupNames.length\n const groupName = groupNames[groupIdx]\n if (groupName) {\n // eslint-disable-next-line security/detect-object-injection -- groupName is from Object.keys, so it's safe\n const groupSuites: string[] = groups[groupName] ?? []\n // Add all suites in this group to selection\n const newSelected = new Set(selectedSuites)\n groupSuites.forEach((s: string) => newSelected.add(s))\n setSelectedSuites(newSelected)\n }\n }\n return\n }\n\n // Enter - confirm selection\n if (key.return) {\n onSelect(Array.from(selectedSuites))\n return\n }\n\n // Space - toggle current\n if (input === ' ') {\n // eslint-disable-next-line security/detect-object-injection -- cursorIndex is bounds-checked via Math.min/Math.max\n const currentSuite = pendingSuites[cursorIndex]\n if (currentSuite) {\n toggleSuite(currentSuite.name)\n }\n return\n }\n\n // Arrow navigation\n if (key.upArrow) {\n setCursorIndex(Math.max(0, cursorIndex - 1))\n return\n }\n if (key.downArrow) {\n setCursorIndex(Math.min(pendingSuites.length - 1, cursorIndex + 1))\n return\n }\n })\n\n return (\n <Box flexDirection=\"column\">\n {/* Header showing pending count */}\n <Header pendingCount={pendingSuites.length} />\n\n <Box marginY={1}>\n {/* Table of pending suites with numbers and checkboxes */}\n <SuiteTable suites={pendingSuites} selectable={true} selected={selectedSuites} />\n </Box>\n\n {/* Show valid suites if any */}\n {validSuites.length > 0 && (\n <Box marginY={1} flexDirection=\"column\">\n <Text dimColor>Already valid:</Text>\n {validSuites.map((s) => (\n <Text key={s.name} dimColor>\n {' '}✓ {s.name} (attested {String(s.age ?? 0)} days ago)\n </Text>\n ))}\n </Box>\n )}\n\n {/* Selection prompt */}\n <SelectionPrompt\n message=\"Select suites to run:\"\n options={[\n { label: 'All pending', value: 'all', hint: 'a' },\n { label: 'By number', value: 'number', hint: '1-9' },\n { label: 'None/exit', value: 'none', hint: 'n' },\n ]}\n groups={\n groups\n ? Object.keys(groups).map((name, i) => ({\n name: `g${String(i + 1)}`,\n label: name,\n }))\n : undefined\n }\n onSelect={() => {\n /* Handled by useInput */\n }}\n />\n\n {/* Current selection count */}\n <Text color=\"cyan\">{selectedSuites.size} selected. Press Enter to confirm.</Text>\n </Box>\n )\n}\n","import * as React from 'react'\nimport { Box, Text } from 'ink'\n\nexport interface ProgressSummaryProps {\n /** Number of suites completed successfully */\n completed: number\n /** Number of suites remaining to run */\n remaining: number\n /** Number of suites that failed */\n failed: number\n /** Number of suites skipped by user */\n skipped: number\n}\n\n/**\n * Displays a summary box showing test run progress.\n *\n * Example output:\n * ┌─────────────────────────────────────────────────────────────┐\n * │ Completed: 2 Remaining: 2 Failed: 0 Skipped: 0 │\n * └─────────────────────────────────────────────────────────────┘\n */\nexport function ProgressSummary({\n completed,\n remaining,\n failed,\n skipped,\n}: ProgressSummaryProps): React.ReactElement {\n return (\n <Box borderStyle=\"single\" paddingX={1}>\n <Text>\n <Text color=\"green\">Completed: {completed}</Text>\n {' '}\n <Text color=\"yellow\">Remaining: {remaining}</Text>\n {' '}\n <Text color=\"red\">Failed: {failed}</Text>\n {' '}\n <Text color=\"gray\">Skipped: {skipped}</Text>\n </Text>\n </Box>\n )\n}\n","import * as React from 'react'\nimport { Box, Text, useInput } from 'ink'\nimport { ProgressSummary } from './ProgressSummary.js'\n\ntype RunPhase = 'running' | 'confirming' | 'complete'\n\nexport interface TestRunnerProps {\n /** Suites to run in order */\n suites: string[]\n /** Execute a test command and return success/failure */\n executeTest: (suite: string) => Promise<boolean>\n /** Create attestation for a suite */\n createAttestation: (suite: string) => Promise<void>\n /** Called when all suites complete */\n onComplete: (results: RunResults) => void\n}\n\nexport interface RunResults {\n completed: string[]\n failed: string[]\n skipped: string[]\n}\n\n/**\n * Test runner component that executes suites and manages attestations.\n *\n * Flow for each suite:\n * 1. Show \"Running suite-name...\"\n * 2. Execute test command\n * 3. If passed, prompt \"Create attestation? [Y/n]\"\n * 4. If user confirms, create attestation\n * 5. Move to next suite\n *\n * If a test fails, it moves to the next suite without prompting for attestation.\n */\nexport function TestRunner({\n suites,\n executeTest,\n createAttestation,\n onComplete,\n}: TestRunnerProps): React.ReactElement {\n const [currentIndex, setCurrentIndex] = React.useState(0)\n const [phase, setPhase] = React.useState<RunPhase>('running')\n const [results, setResults] = React.useState<RunResults>({\n completed: [],\n failed: [],\n skipped: [],\n })\n const [_testPassed, setTestPassed] = React.useState(false)\n\n // Use a ref to store the latest results for the completion callback\n const resultsRef = React.useRef(results)\n React.useEffect(() => {\n resultsRef.current = results\n }, [results])\n\n // Effect to run tests\n React.useEffect(() => {\n if (phase !== 'running') return\n\n // eslint-disable-next-line security/detect-object-injection -- Safe array access with numeric index\n const currentSuite = suites[currentIndex]\n if (!currentSuite) {\n // All done - use ref to avoid stale closure\n onComplete(resultsRef.current)\n setPhase('complete')\n return\n }\n\n // Execute the test\n let cancelled = false\n executeTest(currentSuite)\n .then((passed) => {\n if (cancelled) return\n\n setTestPassed(passed)\n if (passed) {\n setPhase('confirming')\n } else {\n // Test failed, move to next\n setResults((prev) => ({\n ...prev,\n failed: [...prev.failed, currentSuite],\n }))\n setCurrentIndex((prev) => prev + 1)\n }\n })\n .catch(() => {\n if (cancelled) return\n\n // Execution error, treat as failed\n setResults((prev) => ({\n ...prev,\n failed: [...prev.failed, currentSuite],\n }))\n setCurrentIndex((prev) => prev + 1)\n })\n\n return () => {\n cancelled = true\n }\n }, [currentIndex, phase, suites, executeTest, onComplete])\n\n // Handle attestation confirmation\n useInput(\n (input, key) => {\n if (phase !== 'confirming') return\n\n // eslint-disable-next-line security/detect-object-injection -- Safe array access with numeric index\n const currentSuite = suites[currentIndex]\n if (!currentSuite) return\n\n // Y or Enter = create attestation\n if (input.toLowerCase() === 'y' || key.return) {\n createAttestation(currentSuite)\n .then(() => {\n setResults((prev) => ({\n ...prev,\n completed: [...prev.completed, currentSuite],\n }))\n setCurrentIndex((prev) => prev + 1)\n setPhase('running')\n })\n .catch(() => {\n // If attestation fails, still move on but mark as skipped\n setResults((prev) => ({\n ...prev,\n skipped: [...prev.skipped, currentSuite],\n }))\n setCurrentIndex((prev) => prev + 1)\n setPhase('running')\n })\n }\n\n // N = skip attestation\n if (input.toLowerCase() === 'n') {\n setResults((prev) => ({\n ...prev,\n skipped: [...prev.skipped, currentSuite],\n }))\n setCurrentIndex((prev) => prev + 1)\n setPhase('running')\n }\n },\n { isActive: phase === 'confirming' },\n )\n\n // eslint-disable-next-line security/detect-object-injection -- Safe array access with numeric index\n const currentSuite = suites[currentIndex]\n\n return (\n <Box flexDirection=\"column\">\n {/* Progress summary */}\n <ProgressSummary\n completed={results.completed.length}\n failed={results.failed.length}\n remaining={suites.length - currentIndex}\n skipped={results.skipped.length}\n />\n\n <Box marginY={1}>\n {phase === 'running' && currentSuite && (\n <Box>\n <SimpleSpinner />\n <Text> Running {currentSuite}...</Text>\n </Box>\n )}\n\n {phase === 'confirming' && currentSuite && (\n <Box flexDirection=\"column\">\n <Text color=\"green\">✓ Tests passed!</Text>\n <Text>Create attestation for {currentSuite}? [Y/n]: </Text>\n </Box>\n )}\n\n {phase === 'complete' && (\n <Box flexDirection=\"column\">\n <Text color=\"green\">✓ All suites processed</Text>\n <Text>\n Completed: {results.completed.length}, Failed: {results.failed.length}, Skipped:{' '}\n {results.skipped.length}\n </Text>\n </Box>\n )}\n </Box>\n </Box>\n )\n}\n\n/**\n * Simple spinner component using ASCII animation frames.\n * Fallback for when no dedicated spinner library is available.\n */\nfunction SimpleSpinner(): React.ReactElement {\n const [frame, setFrame] = React.useState(0)\n const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']\n\n React.useEffect(() => {\n const timer = setInterval(() => {\n setFrame((f) => (f + 1) % frames.length)\n }, 80)\n return () => {\n clearInterval(timer)\n }\n }, [])\n\n // eslint-disable-next-line security/detect-object-injection -- Safe array access with numeric index\n return <Text color=\"cyan\">{frames[frame]}</Text>\n}\n","import * as React from 'react'\nimport { Box, Text, useApp } from 'ink'\nimport { SuiteSelector } from './SuiteSelector.js'\nimport { TestRunner } from './TestRunner.js'\nimport { ProgressSummary } from './ProgressSummary.js'\nimport type { SuiteStatus } from '../commands/run-utils.js'\nimport type { Config } from '@attest-it/core'\n\n/**\n * Current phase of the interactive run.\n */\ntype Phase = 'selecting' | 'running' | 'complete'\n\n/**\n * Props for the InteractiveRun component.\n */\nexport interface InteractiveRunProps {\n /** All suite statuses */\n allSuites: SuiteStatus[]\n /** Config for groups and settings */\n config: Config\n /** Execute test for a suite */\n executeTest: (suite: string) => Promise<boolean>\n /** Create attestation for a suite */\n createAttestation: (suite: string) => Promise<void>\n /** Save session state */\n saveSession: (completed: string[], failed: string[], remaining: string[]) => Promise<void>\n /** Optional: pre-selected suites from --continue */\n preSelected?: string[]\n}\n\n/**\n * Results from a test run.\n */\nexport interface RunResults {\n /** Suite names that completed successfully */\n completed: string[]\n /** Suite names that failed */\n failed: string[]\n /** Suite names that were skipped */\n skipped: string[]\n}\n\n/**\n * Main interactive run orchestrator.\n *\n * Phases:\n * 1. selecting - User selects which suites to run\n * 2. running - Tests executing, attestations being created\n * 3. complete - All done, show summary\n */\nexport function InteractiveRun({\n allSuites,\n config,\n executeTest,\n createAttestation,\n saveSession,\n preSelected,\n}: InteractiveRunProps): React.ReactElement {\n const { exit } = useApp()\n\n const [phase, setPhase] = React.useState<Phase>(preSelected ? 'running' : 'selecting')\n const [selectedSuites, setSelectedSuites] = React.useState<string[]>(preSelected ?? [])\n const [results, setResults] = React.useState<RunResults>({\n completed: [],\n failed: [],\n skipped: [],\n })\n\n // Compute pending suites (not VALID)\n const pendingSuites = React.useMemo(\n () => allSuites.filter((s) => s.status !== 'VALID'),\n [allSuites],\n )\n\n // Compute valid suites (already attested)\n const validSuites = React.useMemo(\n () => allSuites.filter((s) => s.status === 'VALID'),\n [allSuites],\n )\n\n // Handle selection completion\n const handleSelect = React.useCallback(\n (selected: string[]) => {\n if (selected.length === 0) {\n exit()\n return\n }\n setSelectedSuites(selected)\n setPhase('running')\n },\n [exit],\n )\n\n // Handle run completion (wrapped to avoid promise return in void context)\n const handleRunComplete = React.useCallback(\n (runResults: RunResults) => {\n void (async () => {\n setResults(runResults)\n\n // Save final session state (clear if all done successfully)\n if (runResults.failed.length === 0 && runResults.skipped.length === 0) {\n // All completed - clear session\n await saveSession([], [], [])\n } else {\n // Some remaining - save for --continue\n await saveSession(runResults.completed, runResults.failed, [])\n }\n\n setPhase('complete')\n })()\n },\n [saveSession],\n )\n\n // Handle case where there are no pending suites\n if (pendingSuites.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text color=\"green\">✓ All suites are valid. Nothing to run.</Text>\n {validSuites.length > 0 && (\n <Text dimColor>{validSuites.length} suite(s) already attested.</Text>\n )}\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\">\n {phase === 'selecting' && (\n <SuiteSelector\n pendingSuites={pendingSuites}\n validSuites={validSuites}\n groups={config.groups}\n onSelect={handleSelect}\n onExit={() => {\n exit()\n }}\n />\n )}\n\n {phase === 'running' && (\n <TestRunner\n suites={selectedSuites}\n executeTest={executeTest}\n createAttestation={createAttestation}\n onComplete={handleRunComplete}\n />\n )}\n\n {phase === 'complete' && (\n <Box flexDirection=\"column\">\n <ProgressSummary\n completed={results.completed.length}\n failed={results.failed.length}\n remaining={0}\n skipped={results.skipped.length}\n />\n\n <Box marginY={1}>\n {results.failed.length === 0 && results.skipped.length === 0 ? (\n <Text color=\"green\">✓ All suites attested successfully!</Text>\n ) : (\n <Box flexDirection=\"column\">\n {results.failed.length > 0 && (\n <Text color=\"red\">\n ✗ {results.failed.length} suite(s) failed: {results.failed.join(', ')}\n </Text>\n )}\n <Text>Run `attest-it run` again to continue with remaining suites.</Text>\n </Box>\n )}\n </Box>\n </Box>\n )}\n </Box>\n )\n}\n","/**\n * Shared utilities for the run command.\n *\n * Provides functions for checking suite status, filtering suites,\n * and formatting status information.\n *\n * @packageDocumentation\n */\n\nimport type { Config, VerificationStatus, Attestation, AttestationsFile } from '@attest-it/core'\nimport { computeFingerprint, readAttestations, findAttestation } from '@attest-it/core'\n\n/**\n * Information about a suite's current status.\n * @public\n */\nexport interface SuiteStatus {\n /** Suite name */\n name: string\n /** Current verification status */\n status: VerificationStatus\n /** Human-readable reason for the status */\n reason: string\n /** Current fingerprint of source files */\n currentFingerprint: string\n /** Fingerprint from existing attestation (if any) */\n attestedFingerprint?: string | undefined\n /** ISO timestamp of attestation (if any) */\n attestedAt?: string | undefined\n /** Days since attestation (if any) */\n age?: number | undefined\n}\n\n/**\n * Determine the verification status for a suite.\n *\n * @param attestation - Existing attestation, if any\n * @param currentFingerprint - Current computed fingerprint\n * @param maxAgeDays - Maximum allowed age in days\n * @returns Verification status\n * @internal\n */\nfunction determineStatus(\n attestation: Attestation | null | undefined,\n currentFingerprint: string,\n maxAgeDays: number,\n): VerificationStatus {\n if (!attestation) {\n return 'NEEDS_ATTESTATION'\n }\n\n if (attestation.fingerprint !== currentFingerprint) {\n return 'FINGERPRINT_CHANGED'\n }\n\n const attestedAt = new Date(attestation.attestedAt)\n const ageInDays = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n\n if (ageInDays > maxAgeDays) {\n return 'EXPIRED'\n }\n\n return 'VALID'\n}\n\n/**\n * Get status information for all suites.\n *\n * @param config - Configuration object\n * @returns Array of suite statuses\n * @public\n */\nexport async function getAllSuiteStatuses(config: Config): Promise<SuiteStatus[]> {\n // Load attestations (may not exist)\n let attestationsFile: AttestationsFile | null = null\n try {\n attestationsFile = await readAttestations(config.settings.attestationsPath)\n } catch (err) {\n // Attestations file may not exist yet - that's okay\n if (err instanceof Error && !err.message.includes('ENOENT')) {\n throw err\n }\n }\n const attestations = attestationsFile?.attestations ?? []\n\n const results: SuiteStatus[] = []\n\n for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {\n // Compute current fingerprint\n const fingerprintResult = await computeFingerprint({\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n })\n\n // Find existing attestation\n const attestation = findAttestation(\n { schemaVersion: '1', attestations, signature: '' },\n suiteName,\n )\n\n // Determine status\n const status = determineStatus(\n attestation,\n fingerprintResult.fingerprint,\n config.settings.maxAgeDays,\n )\n\n // Calculate age\n let age: number | undefined\n if (attestation) {\n const attestedAt = new Date(attestation.attestedAt)\n age = Math.floor((Date.now() - attestedAt.getTime()) / (1000 * 60 * 60 * 24))\n }\n\n results.push({\n name: suiteName,\n status,\n reason: formatStatusReason(status, age, config.settings.maxAgeDays),\n currentFingerprint: fingerprintResult.fingerprint,\n attestedFingerprint: attestation?.fingerprint,\n attestedAt: attestation?.attestedAt,\n age,\n })\n }\n\n return results\n}\n\n/**\n * Get suites that need attestation (not VALID).\n *\n * @param config - Configuration object\n * @returns Array of suite statuses that are not valid\n * @public\n */\nexport async function getSuitesNeedingAttestation(config: Config): Promise<SuiteStatus[]> {\n const allStatuses = await getAllSuiteStatuses(config)\n return allStatuses.filter((s) => s.status !== 'VALID')\n}\n\n/**\n * Filter suites by a glob/regex pattern.\n * Matches against suite name.\n *\n * @param suites - Array of suite statuses to filter\n * @param pattern - Pattern to match (supports * wildcard)\n * @returns Filtered array of suite statuses\n * @public\n */\nexport function filterByPattern(suites: SuiteStatus[], pattern: string): SuiteStatus[] {\n // Support simple glob patterns: * matches anything\n const regex = new RegExp('^' + pattern.replace(/\\*/g, '.*') + '$', 'i')\n return suites.filter((s) => regex.test(s.name))\n}\n\n/**\n * Get suites belonging to a group.\n *\n * @param groupName - Name of the group\n * @param config - Configuration object\n * @returns Array of suite names in the group\n * @public\n */\nexport function getSuitesInGroup(groupName: string, config: Config): string[] {\n // eslint-disable-next-line security/detect-object-injection -- groupName is a user parameter, but we safely return empty array if not found\n return config.groups?.[groupName] ?? []\n}\n\n/**\n * Format a human-readable reason for a suite's status.\n *\n * @param status - Verification status\n * @param age - Age in days (if available)\n * @param maxAgeDays - Maximum allowed age in days (if available)\n * @returns Human-readable status reason\n * @public\n */\nexport function formatStatusReason(\n status: VerificationStatus,\n age?: number,\n maxAgeDays?: number,\n): string {\n switch (status) {\n case 'VALID':\n return `Attested ${String(age ?? 0)} days ago`\n case 'NEEDS_ATTESTATION':\n return 'No attestation found'\n case 'FINGERPRINT_CHANGED':\n return 'Source files modified'\n case 'EXPIRED':\n return `${String(age ?? 0)} days old (max: ${String(maxAgeDays ?? 30)})`\n case 'SIGNATURE_INVALID':\n return 'Signature verification failed'\n case 'INVALIDATED_BY_PARENT':\n return 'Invalidated by parent suite'\n default:\n return status\n }\n}\n","import { readFile, writeFile, unlink, mkdir } from 'node:fs/promises'\nimport { join, dirname } from 'node:path'\n\n/**\n * Session state for interrupted run recovery.\n */\nexport interface Session {\n /** ISO timestamp when session started */\n started: string\n /** Suites selected by user for this session */\n selected: string[]\n /** Suites that completed successfully */\n completed: string[]\n /** Suites that failed */\n failed: string[]\n /** Suites not yet run (selected - completed - failed) */\n remaining: string[]\n}\n\n/**\n * Get the path to the session file.\n * Returns `.attest-it/session.json` relative to current working directory.\n */\nexport function getSessionPath(): string {\n return join(process.cwd(), '.attest-it', 'session.json')\n}\n\n/**\n * Load an existing session from disk.\n * Returns null if no session exists or session is invalid.\n */\nexport async function loadSession(): Promise<Session | null> {\n try {\n const content = await readFile(getSessionPath(), 'utf-8')\n const data: unknown = JSON.parse(content)\n\n // Validate session structure\n if (!isValidSession(data)) {\n return null\n }\n\n return data\n } catch {\n // File doesn't exist or is unreadable\n return null\n }\n}\n\n/**\n * Save session state to disk.\n * Creates .attest-it directory if it doesn't exist.\n */\nexport async function saveSession(session: Session): Promise<void> {\n const sessionPath = getSessionPath()\n const dir = dirname(sessionPath)\n\n // Create directory if it doesn't exist\n await mkdir(dir, { recursive: true })\n\n // Write session file\n await writeFile(sessionPath, JSON.stringify(session, null, 2), 'utf-8')\n}\n\n/**\n * Delete the session file.\n * Call this when a session completes successfully.\n */\nexport async function clearSession(): Promise<void> {\n try {\n await unlink(getSessionPath())\n } catch {\n // File doesn't exist - that's fine\n }\n}\n\n/**\n * Create a new session with the given selected suites.\n */\nexport function createSession(selected: string[]): Session {\n return {\n started: new Date().toISOString(),\n selected: [...selected],\n completed: [],\n failed: [],\n remaining: [...selected],\n }\n}\n\n/**\n * Update session after a suite completes.\n */\nexport function updateSessionAfterSuite(\n session: Session,\n suite: string,\n success: boolean,\n): Session {\n const remaining = session.remaining.filter((s) => s !== suite)\n return {\n ...session,\n completed: success ? [...session.completed, suite] : session.completed,\n failed: success ? session.failed : [...session.failed, suite],\n remaining,\n }\n}\n\n/**\n * Type guard to validate session structure.\n */\nfunction isValidSession(data: unknown): data is Session {\n if (typeof data !== 'object' || data === null) {\n return false\n }\n\n // We need to access properties of unknown object, so we check each property\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n const obj = data as Record<string, unknown>\n\n return (\n typeof obj.started === 'string' &&\n Array.isArray(obj.selected) &&\n obj.selected.every((item) => typeof item === 'string') &&\n Array.isArray(obj.completed) &&\n obj.completed.every((item) => typeof item === 'string') &&\n Array.isArray(obj.failed) &&\n obj.failed.every((item) => typeof item === 'string') &&\n Array.isArray(obj.remaining) &&\n obj.remaining.every((item) => typeof item === 'string')\n )\n}\n","/**\n * Entry point for interactive run mode.\n *\n * This module bridges the Commander.js CLI and the React-based interactive UI.\n * It handles:\n * - Loading configuration and suite statuses\n * - Checking for session resumption (--continue)\n * - Dry run mode (just show what would run)\n * - Rendering the InteractiveRun component with ink\n * - Providing test execution and attestation creation callbacks\n *\n * @packageDocumentation\n */\n\nimport * as React from 'react'\nimport { render } from 'ink'\nimport { spawn } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport { parse as parseShellCommand } from 'shell-quote'\nimport {\n loadConfig,\n computeFingerprint,\n readAttestations,\n writeSignedAttestations,\n upsertAttestation,\n createAttestation,\n getDefaultPrivateKeyPath,\n type Config,\n} from '@attest-it/core'\nimport { InteractiveRun } from '../components/InteractiveRun.js'\nimport { getAllSuiteStatuses, type SuiteStatus } from './run-utils.js'\nimport { loadSession, saveSession as persistSession, clearSession } from '../session/session.js'\nimport { error, log } from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\n/**\n * Options for interactive mode.\n * @public\n */\nexport interface InteractiveOptions {\n /** Show what would run without executing */\n dryRun?: boolean | undefined\n /** Resume from saved session */\n continue?: boolean | undefined\n /** Filter pattern for suite names */\n filter?: string | undefined\n}\n\n/**\n * Run the interactive mode UI.\n *\n * @param options - Interactive mode options\n * @public\n */\nexport async function runInteractive(options: InteractiveOptions): Promise<void> {\n // Load config\n const config = await loadConfig()\n\n // Get all suite statuses\n const allSuites = await getAllSuiteStatuses(config)\n\n // Check if resuming from session\n let preSelected: string[] | undefined\n if (options.continue) {\n const session = await loadSession()\n if (session && session.remaining.length > 0) {\n preSelected = session.remaining\n log(`Resuming session with ${String(preSelected.length)} remaining suite(s)`)\n }\n }\n\n // Dry run mode - just show what would run\n if (options.dryRun) {\n handleDryRun(allSuites, config, options.filter)\n return\n }\n\n // Check for pending suites\n const pendingSuites = allSuites.filter((s) => s.status !== 'VALID')\n if (pendingSuites.length === 0) {\n log('All suites are valid. Nothing to run.')\n process.exit(ExitCode.NO_WORK)\n }\n\n // Check for dirty working tree\n const isDirty = await checkDirtyWorkingTree()\n if (isDirty) {\n error('Working tree has uncommitted changes. Please commit or stash before attesting.')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Create test executor\n const executeTest = createTestExecutor(config)\n\n // Create attestation creator\n const createAttestationFn = createAttestationCreator(config)\n\n // Create session saver\n const saveSessionFn = createSessionSaver()\n\n // Render the interactive UI\n const interactiveRunProps = {\n allSuites,\n config,\n executeTest,\n createAttestation: createAttestationFn,\n saveSession: saveSessionFn,\n ...(preSelected !== undefined && { preSelected }),\n }\n\n const { waitUntilExit } = render(<InteractiveRun {...interactiveRunProps} />)\n\n // Wait for UI to exit\n await waitUntilExit()\n}\n\n/**\n * Handle dry run mode.\n * Shows what would run without actually executing.\n *\n * @param allSuites - All suite statuses\n * @param config - Configuration object\n * @param filterPattern - Optional filter pattern\n * @internal\n */\nfunction handleDryRun(allSuites: SuiteStatus[], config: Config, filterPattern?: string): void {\n let pendingSuites = allSuites.filter((s) => s.status !== 'VALID')\n\n if (filterPattern) {\n const regex = new RegExp('^' + filterPattern.replace(/\\*/g, '.*') + '$', 'i')\n pendingSuites = pendingSuites.filter((s) => regex.test(s.name))\n }\n\n if (pendingSuites.length === 0) {\n log('No suites would run (all valid or filtered out).')\n process.exit(ExitCode.NO_WORK)\n }\n\n log(`Would run ${String(pendingSuites.length)} suite(s):`)\n pendingSuites.forEach((s, i) => {\n log(` ${String(i + 1)}. ${s.name} (${s.status})`)\n })\n log('')\n log('Use `attest-it run` to execute.')\n process.exit(ExitCode.SUCCESS)\n}\n\n/**\n * Create a test executor function for a suite.\n *\n * @param config - Configuration object\n * @returns Function that executes a suite's test command\n * @internal\n */\nfunction createTestExecutor(config: Config): (suite: string) => Promise<boolean> {\n return async (suiteName: string): Promise<boolean> => {\n // eslint-disable-next-line security/detect-object-injection -- Safe access with validated suite name\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) {\n error(`Suite \"${suiteName}\" not found in config`)\n return false\n }\n\n // Build command\n let command = suiteConfig.command ?? config.settings.defaultCommand\n if (!command) {\n error(`No command specified for suite \"${suiteName}\"`)\n return false\n }\n\n // Substitute ${files} if present\n if (command.includes('${files}') && suiteConfig.files) {\n command = command.replaceAll('${files}', suiteConfig.files.join(' '))\n }\n\n log(`Running: ${command}`)\n\n // Execute command\n const exitCode = await executeCommand(command)\n return exitCode === 0\n }\n}\n\n/**\n * Create an attestation creator function.\n *\n * @param config - Configuration object\n * @returns Function that creates and saves an attestation for a suite\n * @internal\n */\nfunction createAttestationCreator(config: Config): (suite: string) => Promise<void> {\n return async (suiteName: string): Promise<void> => {\n // eslint-disable-next-line security/detect-object-injection -- Safe access with validated suite name\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) {\n throw new Error(`Suite \"${suiteName}\" not found`)\n }\n\n // Compute fingerprint\n const fingerprintResult = await computeFingerprint({\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n })\n\n // Create attestation\n const attestation = createAttestation({\n suite: suiteName,\n fingerprint: fingerprintResult.fingerprint,\n command: suiteConfig.command ?? config.settings.defaultCommand ?? '',\n attestedBy: os.userInfo().username,\n })\n\n // Load existing attestations\n const attestationsPath = config.settings.attestationsPath\n const existingFile = await readAttestations(attestationsPath).catch(() => null)\n const existingAttestations = existingFile?.attestations ?? []\n\n // Upsert the new attestation\n const newAttestations = upsertAttestation(existingAttestations, attestation)\n\n // Get private key path\n const privateKeyPath = getDefaultPrivateKeyPath()\n\n if (!fs.existsSync(privateKeyPath)) {\n throw new Error(`Private key not found: ${privateKeyPath}. Run \"attest-it keygen\" first.`)\n }\n\n // Write signed attestations\n await writeSignedAttestations({\n filePath: attestationsPath,\n attestations: newAttestations,\n privateKeyPath,\n })\n\n log(`✓ Attestation created for ${suiteName}`)\n }\n}\n\n/**\n * Create session saver function.\n *\n * @returns Function that saves or clears session state\n * @internal\n */\nfunction createSessionSaver(): (\n completed: string[],\n failed: string[],\n remaining: string[],\n) => Promise<void> {\n return async (completed: string[], failed: string[], remaining: string[]): Promise<void> => {\n if (completed.length === 0 && failed.length === 0 && remaining.length === 0) {\n // All done - clear session\n await clearSession()\n } else {\n // Save session for --continue\n await persistSession({\n started: new Date().toISOString(),\n selected: [...completed, ...failed, ...remaining],\n completed,\n failed,\n remaining,\n })\n }\n }\n}\n\n/**\n * Execute a shell command and return exit code.\n *\n * @param command - Shell command to execute\n * @returns Promise resolving to exit code\n * @internal\n */\nasync function executeCommand(command: string): Promise<number> {\n return new Promise((resolve) => {\n const parsed = parseShellCommand(command)\n const stringArgs = parsed.filter((t): t is string => typeof t === 'string')\n\n if (stringArgs.length === 0) {\n error('Empty command')\n resolve(1)\n return\n }\n\n const [executable, ...args] = stringArgs\n if (!executable) {\n resolve(1)\n return\n }\n\n const child = spawn(executable, args, { stdio: 'inherit' })\n\n child.on('close', (code) => {\n resolve(code ?? 1)\n })\n child.on('error', (err) => {\n error(`Command failed: ${err.message}`)\n resolve(1)\n })\n })\n}\n\n/**\n * Check for uncommitted changes in the working tree.\n *\n * @returns Promise resolving to true if there are uncommitted changes\n * @internal\n */\nasync function checkDirtyWorkingTree(): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn('git', ['status', '--porcelain'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let output = ''\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString()\n })\n\n child.on('close', () => {\n resolve(output.trim().length > 0)\n })\n child.on('error', () => {\n resolve(false)\n })\n })\n}\n","/**\n * Run command implementation for attest-it CLI.\n */\n\nimport { Command } from 'commander'\nimport { spawn } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as os from 'node:os'\nimport { parse as parseShellCommand } from 'shell-quote'\nimport {\n loadConfig,\n computeFingerprint,\n readAttestations,\n writeSignedAttestations,\n upsertAttestation,\n createAttestation,\n getDefaultPrivateKeyPath,\n type Config,\n} from '@attest-it/core'\nimport { log, success, error, warn, verbose } from '../utils/output.js'\nimport { confirmAction } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\nimport { runInteractive } from './run-interactive.js'\nimport { getAllSuiteStatuses } from './run-utils.js'\n\nexport const runCommand = new Command('run')\n .description('Execute tests and create attestation')\n .option('-s, --suite <name>', 'Run specific suite (required unless --all or interactive mode)')\n .option('-a, --all', 'Run all suites needing attestation')\n .option('--no-attest', 'Run tests without creating attestation')\n .option('-y, --yes', 'Skip confirmation prompt')\n .option('--dry-run', 'Show what would run without executing')\n .option('-c, --continue', 'Resume interrupted session')\n .option('--filter <pattern>', 'Filter suites by pattern (glob-style)')\n .action(async (options: RunOptions) => {\n await runTests(options)\n })\n\ninterface RunOptions {\n suite?: string\n all?: boolean\n attest?: boolean // Note: --no-attest sets this to false\n yes?: boolean\n dryRun?: boolean\n continue?: boolean\n filter?: string\n}\n\n/**\n * Run tests and create attestations.\n *\n * Routes to the appropriate execution mode based on options:\n * - Direct mode: --suite specified\n * - All pending mode: --all specified\n * - Interactive mode: no --suite and no --all\n *\n * @param options - Command options\n * @param options.suite - Run specific suite\n * @param options.all - Run all suites needing attestation\n * @param options.attest - Create attestation after tests (default: true)\n * @param options.yes - Skip confirmation prompt\n * @param options.dryRun - Show what would run without executing\n * @param options.continue - Resume interrupted session\n * @param options.filter - Filter suites by pattern\n * @public\n */\nasync function runTests(options: RunOptions): Promise<void> {\n try {\n // If --suite provided, use existing direct mode\n if (options.suite) {\n await runDirectMode(options)\n return\n }\n\n // If --all with no --suite, run all pending non-interactively\n if (options.all) {\n await runAllPending(options)\n return\n }\n\n // No --suite and no --all means interactive mode\n // This includes: no args, --dry-run, --continue, --filter\n await runInteractive({\n dryRun: options.dryRun,\n continue: options.continue,\n filter: options.filter,\n })\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\n/**\n * Build the test command to execute.\n *\n * Uses suite-specific command if provided, otherwise falls back to\n * default command from settings. Substitutes ${files} placeholder\n * with suite file patterns.\n *\n * @param config - Configuration object\n * @param suiteCommand - Suite-specific command (optional)\n * @param suiteFiles - File patterns for suite (optional)\n * @returns Constructed command string\n * @public\n */\nfunction buildCommand(config: Config, suiteCommand?: string, suiteFiles?: string[]): string {\n // Use suite command if specified, otherwise default\n let command = suiteCommand ?? config.settings.defaultCommand\n\n if (!command) {\n error('No command specified for suite and no defaultCommand in settings')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Substitute ${files} if present (replace all occurrences)\n if (command.includes('${files}') && suiteFiles) {\n const files = suiteFiles.join(' ')\n command = command.replaceAll('${files}', files)\n }\n\n return command\n}\n\n/**\n * Parsed command result.\n */\ninterface ParsedCommand {\n executable: string\n args: string[]\n}\n\n/**\n * Parse a command string into executable and arguments.\n *\n * Uses shell-quote to safely parse shell syntax without using shell: true.\n *\n * @param command - Command string to parse\n * @returns Parsed command with executable and arguments\n * @throws Error if command is empty or contains only control operators\n * @public\n */\nfunction parseCommand(command: string): ParsedCommand {\n const parsed = parseShellCommand(command)\n\n // shell-quote returns an array of strings and special control operators\n // We only want the string arguments\n const stringArgs = parsed.filter((token): token is string => {\n return typeof token === 'string'\n })\n\n if (stringArgs.length === 0) {\n throw new Error('Command string is empty or contains only control operators')\n }\n\n const [executable, ...args] = stringArgs\n // TypeScript doesn't know that stringArgs.length > 0 guarantees executable is defined\n // The check above ensures stringArgs[0] exists, but we assert it for type safety\n if (executable === undefined) {\n throw new Error('Command string is empty or contains only control operators')\n }\n\n return { executable, args }\n}\n\n/**\n * Execute a command and return its exit code.\n *\n * Spawns a child process and streams output to the terminal.\n *\n * @param command - Command string to execute\n * @returns Exit code from the command (0 for success)\n * @public\n */\nasync function executeCommand(command: string): Promise<number> {\n return new Promise((resolve) => {\n let parsed: ParsedCommand\n try {\n parsed = parseCommand(command)\n } catch (err) {\n if (err instanceof Error) {\n error(`Failed to parse command: ${err.message}`)\n } else {\n error('Failed to parse command: Unknown error')\n }\n resolve(1)\n return\n }\n\n const child = spawn(parsed.executable, parsed.args, {\n stdio: 'inherit', // Stream output to terminal\n })\n\n child.on('close', (code) => {\n resolve(code ?? 1)\n })\n\n child.on('error', (err) => {\n error(`Failed to execute command: ${err.message}`)\n resolve(1)\n })\n })\n}\n\n/**\n * Check if the git working tree has uncommitted changes.\n *\n * @returns True if there are uncommitted changes, false otherwise\n * @public\n */\nasync function checkDirtyWorkingTree(): Promise<boolean> {\n return new Promise((resolve) => {\n const child = spawn('git', ['status', '--porcelain'], {\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let output = ''\n child.stdout.on('data', (data: Buffer) => {\n output += data.toString()\n })\n\n child.on('close', () => {\n // If output is non-empty, there are uncommitted changes\n resolve(output.trim().length > 0)\n })\n\n child.on('error', () => {\n // If git not available, assume not dirty\n resolve(false)\n })\n })\n}\n\n/**\n * Run tests for a specific suite (direct mode with --suite).\n *\n * @param options - Run options with suite specified\n * @public\n */\nasync function runDirectMode(options: RunOptions): Promise<void> {\n if (!options.suite) {\n error('Suite name is required for direct mode')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Load config\n const config = await loadConfig()\n\n // Validate suite exists\n if (!config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Check for dirty working tree\n const isDirty = await checkDirtyWorkingTree()\n if (isDirty) {\n error('Working tree has uncommitted changes. Please commit or stash before attesting.')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Run the suite\n await runSingleSuite(options.suite, config, options)\n\n log('')\n success('Suite completed!')\n log(\n `\\nTo commit: git add ${config.settings.attestationsPath} && git commit -m \"Update attestations\"`,\n )\n}\n\n/**\n * Run all suites that need attestation (--all mode).\n *\n * @param options - Run options\n * @public\n */\nasync function runAllPending(options: RunOptions): Promise<void> {\n const config = await loadConfig()\n const allSuites = await getAllSuiteStatuses(config)\n const pendingSuites = allSuites.filter((s) => s.status !== 'VALID')\n\n if (pendingSuites.length === 0) {\n log('All suites are valid. Nothing to run.')\n process.exit(ExitCode.NO_WORK)\n }\n\n // Apply filter if specified\n let suitesToRun = pendingSuites\n if (options.filter) {\n const regex = new RegExp('^' + options.filter.replace(/\\*/g, '.*') + '$', 'i')\n suitesToRun = pendingSuites.filter((s) => regex.test(s.name))\n\n if (suitesToRun.length === 0) {\n log(`No suites match filter: ${options.filter}`)\n process.exit(ExitCode.NO_WORK)\n }\n }\n\n // Dry run - just show and exit\n if (options.dryRun) {\n log(`Would run ${String(suitesToRun.length)} suite(s):`)\n suitesToRun.forEach((s, i) => {\n log(` ${String(i + 1)}. ${s.name} (${s.status})`)\n })\n process.exit(ExitCode.SUCCESS)\n }\n\n // Check for dirty working tree\n const isDirty = await checkDirtyWorkingTree()\n if (isDirty) {\n error('Working tree has uncommitted changes. Please commit or stash before attesting.')\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n // Run each suite using existing direct mode logic\n for (const suite of suitesToRun) {\n await runSingleSuite(suite.name, config, options)\n }\n\n log('')\n success('All suites completed!')\n log(\n `\\nTo commit: git add ${config.settings.attestationsPath} && git commit -m \"Update attestations\"`,\n )\n}\n\n/**\n * Run a single suite's tests and optionally create an attestation.\n *\n * @param suiteName - Name of the suite to run\n * @param config - Configuration object\n * @param options - Run options\n * @public\n */\nasync function runSingleSuite(\n suiteName: string,\n config: Config,\n options: RunOptions,\n): Promise<void> {\n // eslint-disable-next-line security/detect-object-injection -- suiteName is from validated config keys\n const suiteConfig = config.suites[suiteName]\n if (!suiteConfig) {\n error(`Suite \"${suiteName}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n\n log(`\\n=== Running suite: ${suiteName} ===\\n`)\n\n // Compute fingerprint before running\n const fingerprintOptions = {\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const fingerprintResult = await computeFingerprint(fingerprintOptions)\n verbose(`Fingerprint: ${fingerprintResult.fingerprint}`)\n verbose(`Files: ${String(fingerprintResult.fileCount)}`)\n\n // Build the test command\n const command = buildCommand(config, suiteConfig.command, suiteConfig.files)\n log(`Running: ${command}`)\n log('')\n\n // Execute tests\n const exitCode = await executeCommand(command)\n\n if (exitCode !== 0) {\n error(`Tests failed with exit code ${String(exitCode)}`)\n process.exit(ExitCode.FAILURE)\n }\n\n success('Tests passed!')\n\n // Skip attestation if --no-attest\n if (options.attest === false) {\n log('Skipping attestation (--no-attest)')\n return\n }\n\n // Confirm attestation\n const shouldAttest =\n options.yes ??\n (await confirmAction({\n message: 'Create attestation?',\n default: true,\n }))\n\n if (!shouldAttest) {\n warn('Attestation cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n\n // Create attestation\n const attestation = createAttestation({\n suite: suiteName,\n fingerprint: fingerprintResult.fingerprint,\n command,\n attestedBy: os.userInfo().username,\n })\n\n // Load existing attestations\n const attestationsPath = config.settings.attestationsPath\n const existingFile = await readAttestations(attestationsPath)\n const existingAttestations = existingFile?.attestations ?? []\n\n // Upsert the new attestation\n const newAttestations = upsertAttestation(existingAttestations, attestation)\n\n // Get private key path (from config or default)\n const privateKeyPath = getDefaultPrivateKeyPath()\n\n // Check if private key exists\n if (!fs.existsSync(privateKeyPath)) {\n error(`Private key not found: ${privateKeyPath}`)\n error('Run \"attest-it keygen\" first to generate a keypair.')\n process.exit(ExitCode.MISSING_KEY)\n }\n\n // Write signed attestations\n await writeSignedAttestations({\n filePath: attestationsPath,\n attestations: newAttestations,\n privateKeyPath,\n })\n\n success(`Attestation created for ${suiteName}`)\n log(` Fingerprint: ${fingerprintResult.fingerprint}`)\n log(` Attested by: ${attestation.attestedBy}`)\n log(` Attested at: ${attestation.attestedAt}`)\n}\n\n// Export for testing\nexport { buildCommand, parseCommand, executeCommand, checkDirtyWorkingTree }\n","import { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport {\n checkOpenSSL,\n generateKeyPair,\n getDefaultPrivateKeyPath,\n getDefaultPublicKeyPath,\n setKeyPermissions,\n} from '@attest-it/core'\nimport { log, success, error, warn, info } from '../utils/output.js'\nimport { confirmAction } from '../utils/prompts.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const keygenCommand = new Command('keygen')\n .description('Generate a new RSA keypair for signing attestations')\n .option('-o, --output <path>', 'Private key output path')\n .option('-p, --public <path>', 'Public key output path')\n .option('-f, --force', 'Overwrite existing keys')\n .action(async (options: KeygenOptions) => {\n await runKeygen(options)\n })\n\ninterface KeygenOptions {\n output?: string\n public?: string\n force?: boolean\n}\n\n/**\n * Run the keygen command to generate a new cryptographic keypair.\n *\n * Generates an RSA-2048 keypair with SHA-256 signatures, which is universally\n * supported across all OpenSSL and LibreSSL versions.\n *\n * @param options - Command options\n * @param options.output - Private key output path\n * @param options.public - Public key output path\n * @param options.force - Overwrite existing keys without prompting\n * @public\n */\nasync function runKeygen(options: KeygenOptions): Promise<void> {\n try {\n // Check OpenSSL\n log('Checking OpenSSL...')\n const version = await checkOpenSSL()\n info(`OpenSSL: ${version}`)\n\n // Determine paths\n const privatePath = options.output ?? getDefaultPrivateKeyPath()\n const publicPath = options.public ?? getDefaultPublicKeyPath()\n\n log(`Private key: ${privatePath}`)\n log(`Public key: ${publicPath}`)\n\n // Check if keys already exist\n const privateExists = fs.existsSync(privatePath)\n const publicExists = fs.existsSync(publicPath)\n\n if ((privateExists || publicExists) && !options.force) {\n if (privateExists) {\n warn(`Private key already exists: ${privatePath}`)\n }\n if (publicExists) {\n warn(`Public key already exists: ${publicPath}`)\n }\n\n const shouldOverwrite = await confirmAction({\n message: 'Overwrite existing keys?',\n default: false,\n })\n\n if (!shouldOverwrite) {\n error('Keygen cancelled')\n process.exit(ExitCode.CANCELLED)\n }\n }\n\n // Generate keypair\n log('\\nGenerating RSA-2048 keypair...')\n\n const result = await generateKeyPair({\n privatePath,\n publicPath,\n force: true,\n })\n\n // Set permissions on private key\n await setKeyPermissions(result.privatePath)\n\n success('Keypair generated successfully!')\n log('')\n log('Private key (KEEP SECRET):')\n log(` ${result.privatePath}`)\n log('')\n log('Public key (commit to repo):')\n log(` ${result.publicPath}`)\n log('')\n info('Important: Back up your private key securely!')\n log('')\n log('Next steps:')\n log(` 1. git add ${result.publicPath}`)\n log(' 2. Update .attest-it/config.yaml publicKeyPath if needed')\n log(' 3. attest-it run --suite <suite-name>')\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\nexport { runKeygen }\n","/**\n * Prune command implementation for attest-it CLI.\n */\n\nimport { Command } from 'commander'\nimport * as fs from 'node:fs'\nimport {\n loadConfig,\n readAttestations,\n writeSignedAttestations,\n computeFingerprint,\n getDefaultPrivateKeyPath,\n type Attestation,\n} from '@attest-it/core'\nimport { log, success, error, info, verbose } from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const pruneCommand = new Command('prune')\n .description('Remove stale attestations')\n .option('-n, --dry-run', 'Show what would be removed without removing')\n .option('-k, --keep-days <n>', 'Keep attestations newer than n days', '30')\n .action(async (options: PruneOptions) => {\n await runPrune(options)\n })\n\ninterface PruneOptions {\n dryRun?: boolean\n keepDays: string\n}\n\n/**\n * Run the prune command to remove stale attestations.\n *\n * Removes attestations that are outdated (older than keepDays and\n * fingerprint doesn't match current code) or orphaned (suite no\n * longer exists in config). Re-signs the attestations file.\n *\n * @param options - Command options\n * @param options.dryRun - Show what would be removed without removing\n * @param options.keepDays - Keep attestations newer than n days\n * @public\n */\nasync function runPrune(options: PruneOptions): Promise<void> {\n try {\n const keepDays = parseInt(options.keepDays, 10)\n if (isNaN(keepDays) || keepDays < 1) {\n error('--keep-days must be a positive integer')\n process.exit(ExitCode.CONFIG_ERROR)\n return\n }\n\n // Load config\n const config = await loadConfig()\n\n // Load attestations\n const attestationsPath = config.settings.attestationsPath\n const file = await readAttestations(attestationsPath)\n\n if (!file || file.attestations.length === 0) {\n info('No attestations to prune')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n const now = Date.now()\n const keepMs = keepDays * 24 * 60 * 60 * 1000\n\n // Identify stale attestations\n const stale: Attestation[] = []\n const keep: Attestation[] = []\n\n for (const attestation of file.attestations) {\n const attestedAt = new Date(attestation.attestedAt).getTime()\n const ageMs = now - attestedAt\n const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24))\n\n // Check if suite still exists in config\n const suiteExists = attestation.suite in config.suites\n\n // Check if fingerprint still matches current code\n let fingerprintMatches = false\n if (suiteExists) {\n const suiteConfig = config.suites[attestation.suite]\n if (suiteConfig) {\n const fingerprintOptions = {\n packages: suiteConfig.packages,\n ...(suiteConfig.ignore && { ignore: suiteConfig.ignore }),\n }\n const result = await computeFingerprint(fingerprintOptions)\n fingerprintMatches = result.fingerprint === attestation.fingerprint\n }\n }\n\n // Keep if:\n // 1. Age is within keepDays AND fingerprint matches, OR\n // 2. Fingerprint matches current code (regardless of age)\n const isStale = !fingerprintMatches && ageMs > keepMs\n const orphaned = !suiteExists\n\n if (isStale || orphaned) {\n stale.push(attestation)\n const reason = orphaned\n ? 'suite removed'\n : !fingerprintMatches\n ? 'fingerprint changed'\n : 'expired'\n verbose(`Stale: ${attestation.suite} (${reason}, ${String(ageDays)} days old)`)\n } else {\n keep.push(attestation)\n }\n }\n\n // Report what will be pruned\n if (stale.length === 0) {\n success('No stale attestations found')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n log(`Found ${String(stale.length)} stale attestation(s):`)\n for (const attestation of stale) {\n const ageDays = Math.floor(\n (now - new Date(attestation.attestedAt).getTime()) / (1000 * 60 * 60 * 24),\n )\n log(` - ${attestation.suite} (${String(ageDays)} days old)`)\n }\n\n if (options.dryRun) {\n info('Dry run - no changes made')\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n // Check for private key\n const privateKeyPath = getDefaultPrivateKeyPath()\n if (!fs.existsSync(privateKeyPath)) {\n error(`Private key not found: ${privateKeyPath}`)\n error('Cannot re-sign attestations file.')\n process.exit(ExitCode.MISSING_KEY)\n return\n }\n\n // Write updated attestations\n await writeSignedAttestations({\n filePath: attestationsPath,\n attestations: keep,\n privateKeyPath,\n })\n\n success(`Pruned ${String(stale.length)} stale attestation(s)`)\n log(`Remaining: ${String(keep.length)} attestation(s)`)\n process.exit(ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n return\n }\n}\n\nexport { runPrune }\n","import { Command } from 'commander'\nimport {\n loadConfig,\n toAttestItConfig,\n verifyAttestations,\n type Config,\n type VerifyResult,\n type SuiteVerificationResult,\n} from '@attest-it/core'\nimport {\n log,\n success,\n error,\n warn,\n formatTable,\n colorizeStatus,\n outputJson,\n type TableRow,\n} from '../utils/output.js'\nimport { ExitCode } from '../utils/exit-codes.js'\n\nexport const verifyCommand = new Command('verify')\n .description('Verify all attestations (for CI)')\n .option('-s, --suite <name>', 'Verify specific suite only')\n .option('--json', 'Output JSON for machine parsing')\n .option('--strict', 'Fail on warnings (approaching expiry)')\n .action(async (options: VerifyOptions) => {\n await runVerify(options)\n })\n\ninterface VerifyOptions {\n suite?: string\n json?: boolean\n strict?: boolean\n}\n\n/**\n * Run the verify command to validate attestations.\n *\n * Verifies signature validity and checks attestation status for all suites\n * or a specific suite. Intended for CI/CD pipelines.\n *\n * @param options - Command options\n * @param options.suite - Verify specific suite only\n * @param options.json - Output JSON for machine parsing\n * @param options.strict - Fail on warnings (approaching expiry)\n * @public\n */\nasync function runVerify(options: VerifyOptions): Promise<void> {\n try {\n // Load config\n const config = await loadConfig()\n\n // Filter to specific suite if requested\n if (options.suite) {\n if (!config.suites[options.suite]) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n // Create filtered config\n const filteredSuiteEntry = config.suites[options.suite]\n if (!filteredSuiteEntry) {\n error(`Suite \"${options.suite}\" not found in config`)\n process.exit(ExitCode.CONFIG_ERROR)\n }\n const filteredConfig: Config = {\n version: config.version,\n settings: config.settings,\n suites: { [options.suite]: filteredSuiteEntry },\n }\n\n // Run verification with filtered config, converting from Zod Config to AttestItConfig\n const result = await verifyAttestations({ config: toAttestItConfig(filteredConfig) })\n\n // Output results\n if (options.json) {\n outputJson(result)\n } else {\n displayResults(result, filteredConfig.settings.maxAgeDays, options.strict)\n }\n\n // Determine exit code\n if (!result.success) {\n process.exit(ExitCode.FAILURE)\n return\n }\n\n if (options.strict && hasWarnings(result, filteredConfig.settings.maxAgeDays)) {\n process.exit(ExitCode.FAILURE)\n return\n }\n\n process.exit(ExitCode.SUCCESS)\n return\n }\n\n // Run verification with full config, converting from Zod Config to AttestItConfig\n const result = await verifyAttestations({ config: toAttestItConfig(config) })\n\n // Output results\n if (options.json) {\n outputJson(result)\n } else {\n displayResults(result, config.settings.maxAgeDays, options.strict)\n }\n\n // Determine exit code\n if (!result.success) {\n process.exit(ExitCode.FAILURE)\n }\n\n if (options.strict && hasWarnings(result, config.settings.maxAgeDays)) {\n process.exit(ExitCode.FAILURE)\n }\n\n process.exit(ExitCode.SUCCESS)\n } catch (err) {\n if (err instanceof Error) {\n error(err.message)\n } else {\n error('Unknown error occurred')\n }\n process.exit(ExitCode.CONFIG_ERROR)\n }\n}\n\n/**\n * Display verification results in a formatted table.\n *\n * Shows signature status, errors, suite results, and remediation steps.\n *\n * @param result - Verification result from verifyAttestations\n * @param maxAgeDays - Maximum age in days before expiry\n * @param strict - Whether to show warnings as errors\n * @public\n */\nfunction displayResults(result: VerifyResult, maxAgeDays: number, strict?: boolean): void {\n log('')\n\n // Signature status\n if (!result.signatureValid) {\n error('Signature verification FAILED')\n log('The attestations file may have been tampered with.')\n log('')\n }\n\n // Errors\n for (const errorMsg of result.errors) {\n error(errorMsg)\n }\n if (result.errors.length > 0) {\n log('')\n }\n\n // Suite results as table\n const tableRows: TableRow[] = result.suites.map((s) => ({\n suite: s.suite,\n status: colorizeStatus(s.status),\n fingerprint: s.fingerprint.slice(0, 16) + '...',\n age: formatAgeColumn(s),\n }))\n\n log(formatTable(tableRows))\n log('')\n\n // Summary\n if (result.success) {\n success('All attestations valid')\n } else {\n // Show remediation steps\n const needsAttestation = result.suites.filter((s) => s.status !== 'VALID')\n\n if (needsAttestation.length > 0) {\n log('Remediation:')\n for (const suite of needsAttestation) {\n log(` attest-it run --suite ${suite.suite}`)\n if (suite.message) {\n log(` ${suite.message}`)\n }\n }\n }\n }\n\n // Warnings (approaching expiry)\n const warningThreshold = 7 // days before expiry to warn\n const nearExpiry = result.suites.filter(\n (s) => s.status === 'VALID' && (s.age ?? 0) > maxAgeDays - warningThreshold,\n )\n\n if (nearExpiry.length > 0) {\n log('')\n for (const suite of nearExpiry) {\n warn(`${suite.suite} attestation approaching expiry (${String(suite.age)} days old)`)\n }\n if (strict) {\n log('(--strict mode: warnings are treated as errors)')\n }\n }\n}\n\nfunction formatAgeColumn(s: SuiteVerificationResult): string {\n if (s.status === 'VALID') {\n return `${String(s.age ?? 0)} days`\n }\n\n if (s.status === 'NEEDS_ATTESTATION') {\n return '(none)'\n }\n\n if (s.status === 'EXPIRED') {\n return `${String(s.age ?? 0)} days (expired)`\n }\n\n if (s.status === 'FINGERPRINT_CHANGED') {\n return '(changed)'\n }\n\n if (s.status === 'INVALIDATED_BY_PARENT') {\n return '(invalidated)'\n }\n\n return '-'\n}\n\n/**\n * Check if verification result has warnings.\n *\n * Returns true if any valid attestations are approaching expiry\n * (within 7 days of maxAgeDays).\n *\n * @param result - Verification result to check\n * @param maxAgeDays - Maximum age in days before expiry\n * @returns True if warnings exist, false otherwise\n * @public\n */\nfunction hasWarnings(result: VerifyResult, maxAgeDays: number): boolean {\n const warningThreshold = 7 // days before expiry to warn\n return result.suites.some(\n (s) => s.status === 'VALID' && (s.age ?? 0) > maxAgeDays - warningThreshold,\n )\n}\n\nexport { runVerify, displayResults, hasWarnings }\n","import { Command } from 'commander'\nimport { initCommand } from './commands/init.js'\nimport { statusCommand } from './commands/status.js'\nimport { runCommand } from './commands/run.js'\nimport { keygenCommand } from './commands/keygen.js'\nimport { pruneCommand } from './commands/prune.js'\nimport { verifyCommand } from './commands/verify.js'\nimport { setOutputOptions, initTheme } from './utils/output.js'\n\nconst program = new Command()\n\nprogram\n .name('attest-it')\n .description('Human-gated test attestation system')\n .version('0.0.1')\n .option('-c, --config <path>', 'Path to config file')\n .option('-v, --verbose', 'Verbose output')\n .option('-q, --quiet', 'Minimal output')\n\n// Register commands\nprogram.addCommand(initCommand)\nprogram.addCommand(statusCommand)\nprogram.addCommand(runCommand)\nprogram.addCommand(keygenCommand)\nprogram.addCommand(pruneCommand)\nprogram.addCommand(verifyCommand)\n\nexport async function run(): Promise<void> {\n // Initialize theme before any output\n await initTheme()\n\n // Parse options and set global output options\n program.parse()\n const options = program.opts<{ verbose?: boolean; quiet?: boolean }>()\n\n const outputOptions: { verbose?: boolean; quiet?: boolean } = {}\n if (options.verbose !== undefined) {\n outputOptions.verbose = options.verbose\n }\n if (options.quiet !== undefined) {\n outputOptions.quiet = options.quiet\n }\n\n setOutputOptions(outputOptions)\n}\n\nexport { program }\n","import { run } from '../src/index.js'\n\nvoid run()\n"]}
|