vaultkeeper 0.2.0 → 0.3.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/index.cjs +39 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -1
- package/dist/index.d.ts +30 -1
- package/dist/index.js +38 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/backend/registry.ts","../src/util/exec.ts","../src/backend/file-backend.ts","../src/backend/yubikey-backend.ts","../src/identity/hash.ts","../src/identity/manifest.ts","../src/identity/trust.ts","../src/identity/session.ts","../src/config.ts","../src/keys/manager.ts","../src/jwe/token.ts","../src/jwe/claims.ts","../src/access/delegated-fetch.ts","../src/access/delegated-exec.ts","../src/access/controlled-direct.ts","../src/doctor/checks.ts","../src/util/platform.ts","../src/doctor/runner.ts","../src/vault.ts"],"names":["spawn","path2","path3","crypto2","fs4","path4","fs5","updated","path5","os4","fs6","crypto3","CompactEncrypt","isObject","compactDecrypt","PLACEHOLDER","replacePlaceholder","replaceInRecord","crypto4"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKO,IAAM,UAAA,GAAN,cAAyB,KAAA,CAAM;AAAA,EACpC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AAAA,EACd;AACF;AASO,IAAM,kBAAA,GAAN,cAAiC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,WAAA;AAAA,EAET,WAAA,CAAY,SAAiB,WAAA,EAAsB;AACjD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAAA,EACrB;AACF;AAMO,IAAM,qBAAA,GAAN,cAAoC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3C,SAAA;AAAA,EAET,WAAA,CAAY,SAAiB,SAAA,EAAmB;AAC9C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAAA,EACnB;AACF;AAMO,IAAM,wBAAA,GAAN,cAAuC,UAAA,CAAW;AAAA,EACvD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,0BAAA;AAAA,EACd;AACF;AAOO,IAAM,uBAAA,GAAN,cAAsC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7C,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,SAAA,EAAqB;AAChE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAAA,EACnB;AACF;AAMO,IAAM,mBAAA,GAAN,cAAkC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAIzC,MAAA;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,UAAA,EAAoB;AAC/D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AACF;AAKO,IAAM,mBAAA,GAAN,cAAkC,UAAA,CAAW;AAAA,EAClD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAOO,IAAM,iBAAA,GAAN,cAAgC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvC,UAAA;AAAA,EAET,WAAA,CAAY,SAAiB,UAAA,EAAqB;AAChD,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AACF;AAMO,IAAM,eAAA,GAAN,cAA8B,UAAA,CAAW;AAAA,EAC9C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAMO,IAAM,eAAA,GAAN,cAA8B,UAAA,CAAW;AAAA,EAC9C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAMO,IAAM,iBAAA,GAAN,cAAgC,UAAA,CAAW;AAAA,EAChD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF;AAMO,IAAM,uBAAA,GAAN,cAAsC,UAAA,CAAW;AAAA,EACtD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;AAWO,IAAM,qBAAA,GAAN,cAAoC,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAI3C,YAAA;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,YAAA,EAAsB,WAAA,EAAqB;AACtE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,uBAAA;AACZ,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAAA,EACrB;AACF;AAQO,IAAM,UAAA,GAAN,cAAyB,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAIhC,UAAA;AAAA,EAET,WAAA,CAAY,SAAiB,UAAA,EAAoB;AAC/C,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AACF;AAMO,IAAM,eAAA,GAAN,cAA8B,UAAA,CAAW;AAAA;AAAA;AAAA;AAAA,EAIrC,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,QAAA,EAAkB,UAAA,EAAoB;AACjE,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,QAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAAA,EACpB;AACF;AAMO,IAAM,uBAAA,GAAN,cAAsC,UAAA,CAAW;AAAA,EACtD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;;;ACnPO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,OAAe,QAAA,mBAAW,IAAI,GAAA,EAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1D,OAAO,QAAA,CAAS,IAAA,EAAc,OAAA,EAA+B;AAC3D,IAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO,IAAA,EAA6B;AACzC,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA;AACtC,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,MAAM,IAAI,uBAAA;AAAA,QACR,CAAA,sBAAA,EAAyB,IAAI,CAAA,mBAAA,EACP,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,QACjE,cAAA;AAAA,QACA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAM;AAAA,OACjC;AAAA,IACF;AACA,IAAA,OAAO,OAAA,EAAQ;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,QAAA,GAAqB;AAC1B,IAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAM,CAAA;AAAA,EACxC;AACF;ACnCA,eAAsB,WAAA,CACpB,OAAA,EACA,IAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,OAAA,EAAS,IAAa,CAAA;AAC3D,EAAA,IAAI,MAAA,CAAO,aAAa,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiC,MAAA,CAAO,MAAA,CAAO,QAAQ,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,MAAM,CAAA,CAAE,CAAA;AAAA,EAC9F;AACA,EAAA,OAAO,MAAA,CAAO,OAAO,IAAA,EAAK;AAC5B;AAKO,SAAS,eAAA,CACd,OAAA,EACA,IAAA,EACA,OAAA,EAC4B;AAC5B,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,IAAA,GAAOA,mBAAA,CAAM,OAAA,EAAS,IAAA,EAAM;AAAA,MAChC,KAAA,EAAO,CAAyC,QAAA,EAAU,QAAQ,MAAM;AAAA,KACzE,CAAA;AACD,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAcD,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AACzB,MAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAA,IAAQ,GAAG,CAAA;AAAA,IACjD,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AAC1B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AC5D8BC,gBAAA,CAAA,IAAA,CAAK,cAAA,EAAgB,MAAM;ACH3BC,gBAAA,CAAA,IAAA,CAAK,cAAA,EAAgB,SAAS;ACHrD,SAAS,eAAe,QAAA,EAAmC;AAChE,EAAA,OAAO,IAAI,OAAA,CAAgB,CAAC,OAAA,EAAS,MAAA,KAAW;AAC9C,IAAA,MAAM,IAAA,GAAcC,8BAAW,QAAQ,CAAA;AACvC,IAAA,MAAM,MAAA,GAAYC,gCAAiB,QAAQ,CAAA;AAE3C,IAAA,MAAA,CAAO,EAAA,CAAG,MAAA,EAAQ,CAAC,KAAA,KAA2B;AAC5C,MAAA,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,IACnB,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,OAAO,MAAM;AACrB,MAAA,OAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IAC5B,CAAC,CAAA;AAED,IAAA,MAAA,CAAO,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAAe;AACjC,MAAA,MAAA,CAAO,GAAG,CAAA;AAAA,IACZ,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;ACvBA,IAAM,iBAAA,GAAoB,qBAAA;AAgB1B,SAAS,cAAc,KAAA,EAAsC;AAC3D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,KAAA;AACxD,EAAA,IAAI,EAAE,SAAA,IAAa,KAAA,CAAA,IAAU,OAAO,KAAA,CAAM,OAAA,KAAY,UAAU,OAAO,KAAA;AACvE,EAAA,IAAI,EAAE,SAAA,IAAa,KAAA,CAAA,IAAU,OAAO,KAAA,CAAM,YAAY,QAAA,IAAY,KAAA,CAAM,OAAA,KAAY,IAAA,EAAM,OAAO,KAAA;AACjG,EAAA,OAAO,IAAA;AACT;AAKA,SAAS,qBAAqB,KAAA,EAA6C;AACzE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,KAAA;AACxD,EAAA,IAAI,EAAE,YAAY,KAAA,CAAA,IAAU,CAAC,MAAM,OAAA,CAAQ,KAAA,CAAM,MAAM,CAAA,EAAG,OAAO,KAAA;AACjE,EAAA,IAAI,EAAE,WAAA,IAAe,KAAA,CAAA,EAAQ,OAAO,KAAA;AACpC,EAAA,MAAM,EAAE,WAAU,GAAI,KAAA;AACtB,EAAA,IAAI,cAAc,CAAA,IAAK,SAAA,KAAc,CAAA,IAAK,SAAA,KAAc,GAAG,OAAO,KAAA;AAClE,EAAA,OAAO,IAAA;AACT;AAOA,eAAsB,aAAa,SAAA,EAA2C;AAC5E,EAAA,MAAM,YAAA,GAAoBC,gBAAA,CAAA,IAAA,CAAK,SAAA,EAAW,iBAAiB,CAAA;AAC3D,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAASC,cAAA,CAAA,QAAA,CAAS,YAAA,EAAc,MAAM,CAAA;AAAA,EAClD,SAAS,GAAA,EAAK;AACZ,IAAA,IACE,OAAO,QAAQ,QAAA,IACf,GAAA,KAAQ,QACR,MAAA,IAAU,GAAA,IACV,GAAA,CAAI,IAAA,KAAS,QAAA,EACb;AACA,MAAA,2BAAW,GAAA,EAAI;AAAA,IACjB;AACA,IAAA,MAAM,GAAA;AAAA,EACR;AAEA,EAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAE1C,EAAA,IAAI,CAAC,aAAA,CAAc,MAAM,CAAA,EAAG;AAC1B,IAAA,2BAAW,GAAA,EAAI;AAAA,EACjB;AAEA,EAAA,MAAM,QAAA,uBAA8B,GAAA,EAAI;AACxC,EAAA,KAAA,MAAW,CAAC,WAAW,KAAK,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAA,EAAG;AAC/D,IAAA,IAAI,oBAAA,CAAqB,KAAK,CAAA,EAAG;AAC/B,MAAA,QAAA,CAAS,GAAA,CAAI,SAAA,EAAW,EAAE,MAAA,EAAQ,CAAC,GAAG,KAAA,CAAM,MAAM,CAAA,EAAG,SAAA,EAAW,KAAA,CAAM,SAAA,EAAW,CAAA;AAAA,IACnF;AAAA,EACF;AACA,EAAA,OAAO,QAAA;AACT;AAMA,eAAsB,YAAA,CAAa,WAAmB,QAAA,EAAwC;AAC5F,EAAA,MAASA,cAAA,CAAA,KAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAC7C,EAAA,MAAM,UAA8C,EAAC;AACrD,EAAA,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,CAAA,IAAK,QAAA,EAAU;AACzC,IAAA,OAAA,CAAQ,SAAS,CAAA,GAAI,KAAA;AAAA,EACvB;AACA,EAAA,MAAM,GAAA,GAAmB,EAAE,OAAA,EAAS,CAAA,EAAG,OAAA,EAAQ;AAC/C,EAAA,MAAM,YAAA,GAAoBD,gBAAA,CAAA,IAAA,CAAK,SAAA,EAAW,iBAAiB,CAAA;AAC3D,EAAA,MAASC,cAAA,CAAA,SAAA,CAAU,cAAc,IAAA,CAAK,SAAA,CAAU,KAAK,IAAA,EAAM,CAAC,GAAG,MAAM,CAAA;AACvE;AAQO,SAAS,cAAA,CAAe,QAAA,EAAyB,SAAA,EAAmB,IAAA,EAA6B;AACtG,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,QAAQ,CAAA;AAC7B,EAAA,MAAM,QAAA,GAAW,IAAA,CAAK,GAAA,CAAI,SAAS,CAAA;AACnC,EAAA,IAAI,aAAa,MAAA,EAAW;AAC1B,IAAA,IAAA,CAAK,GAAA,CAAI,WAAW,EAAE,MAAA,EAAQ,CAAC,IAAI,CAAA,EAAG,SAAA,EAAW,CAAA,EAAG,CAAA;AAAA,EACtD,WAAW,CAAC,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA,EAAG;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,SAAA,EAAW,EAAE,MAAA,EAAQ,CAAC,GAAG,QAAA,CAAS,MAAA,EAAQ,IAAI,CAAA,EAAG,SAAA,EAAW,QAAA,CAAS,WAAW,CAAA;AAAA,EAC3F;AACA,EAAA,OAAO,IAAA;AACT;AAMO,SAAS,SAAA,CAAU,QAAA,EAAyB,SAAA,EAAmB,IAAA,EAAuB;AAC3F,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AACpC,EAAA,IAAI,KAAA,KAAU,QAAW,OAAO,KAAA;AAChC,EAAA,OAAO,KAAA,CAAM,MAAA,CAAO,QAAA,CAAS,IAAI,CAAA;AACnC;;;ACpGA,eAAe,YAAY,QAAA,EAAoC;AAC7D,EAAA,IAAI;AAKF,IAAA,MAAM,QAAA,GAAoB,MAAM,OAAO,UAAU,CAAA;AAIjD,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AACrD,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,IAAI,EAAE,QAAA,IAAY,QAAA,CAAA,IAAa,OAAO,QAAA,CAAS,WAAW,UAAA,EAAY;AACpE,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,KAAK,QAAA;AACL,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AASA,eAAsB,WAAA,CACpB,UACA,OAAA,EACkC;AAElC,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,OAAO;AAAA,MACL,UAAU,EAAE,IAAA,EAAM,OAAO,SAAA,EAAW,CAAA,EAAG,UAAU,KAAA,EAAM;AAAA,MACvD,YAAA,EAAc,KAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,IAAa,cAAA;AACxC,EAAA,MAAM,SAAA,GAAY,SAAS,SAAA,IAAa,QAAA;AAGxC,EAAA,MAAM,WAAA,GAAc,MAAM,cAAA,CAAe,QAAQ,CAAA;AAGjD,EAAA,MAAM,QAAA,GAAW,MAAM,YAAA,CAAa,SAAS,CAAA;AAG7C,EAAA,IAAI,OAAA,EAAS,iBAAiB,IAAA,EAAM;AAClC,IAAA,MAAM,gBAAA,GAAmB,MAAM,WAAA,CAAY,QAAQ,CAAA;AACnD,IAAA,IAAI,gBAAA,EAAkB;AACpB,MAAA,MAAMC,QAAAA,GAAU,cAAA,CAAe,QAAA,EAAU,SAAA,EAAW,WAAW,CAAA;AAC/D,MAAA,MAAM,YAAA,CAAa,WAAWA,QAAO,CAAA;AACrC,MAAA,OAAO;AAAA,QACL,UAAU,EAAE,IAAA,EAAM,aAAa,SAAA,EAAW,CAAA,EAAG,UAAU,IAAA,EAAK;AAAA,QAC5D,YAAA,EAAc,KAAA;AAAA,QACd,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,SAAA,CAAU,QAAA,EAAU,SAAA,EAAW,WAAW,CAAA,EAAG;AAC/C,IAAA,OAAO;AAAA,MACL,UAAU,EAAE,IAAA,EAAM,aAAa,SAAA,EAAW,CAAA,EAAG,UAAU,IAAA,EAAK;AAAA,MAC5D,YAAA,EAAc,KAAA;AAAA,MACd,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AAGA,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,GAAA,CAAI,SAAS,CAAA;AACvC,EAAA,IAAI,QAAA,KAAa,MAAA,IAAa,QAAA,CAAS,MAAA,CAAO,SAAS,CAAA,EAAG;AAExD,IAAA,OAAO;AAAA,MACL,UAAU,EAAE,IAAA,EAAM,aAAa,SAAA,EAAW,CAAA,EAAG,UAAU,KAAA,EAAM;AAAA,MAC7D,YAAA,EAAc,IAAA;AAAA,MACd,MAAA,EAAQ,CAAA,yEAAA;AAAA,KACV;AAAA,EACF;AAGA,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,QAAA,EAAU,SAAA,EAAW,WAAW,CAAA;AAC/D,EAAA,MAAM,YAAA,CAAa,WAAW,OAAO,CAAA;AACrC,EAAA,OAAO;AAAA,IACL,UAAU,EAAE,IAAA,EAAM,aAAa,SAAA,EAAW,CAAA,EAAG,UAAU,KAAA,EAAM;AAAA,IAC7D,YAAA,EAAc,KAAA;AAAA,IACd,MAAA,EAAQ;AAAA,GACV;AACF;;;ACxGO,IAAM,kBAAN,MAAsB;AAAA;AAAA,EAElB,MAAA;AAAA,EAET,WAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAA,0BAAgB,iBAAiB,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAA,GAAmB;AACjB,IAAA,OAAO,CAAA,iBAAA,EAAoB,IAAA,CAAK,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,CAAA;AAAA,EACnD;AACF;AAGA,IAAM,WAAA,uBAAkB,OAAA,EAAsC;AAQvD,SAAS,sBAAsB,MAAA,EAAsC;AAC1E,EAAA,MAAM,KAAA,GAAQ,IAAI,eAAA,EAAgB;AAClC,EAAA,WAAA,CAAY,GAAA,CAAI,OAAO,MAAM,CAAA;AAC7B,EAAA,OAAO,KAAA;AACT;AAUO,SAAS,wBAAwB,KAAA,EAAqC;AAC3E,EAAA,MAAM,MAAA,GAAS,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AACpC,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,MAAM,IAAI,yBAAyB,0CAA0C,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,MAAA;AACT;AC7CO,SAAS,mBAAA,GAA8B;AAC5C,EAAA,IAAI,OAAA,CAAQ,aAAa,OAAA,EAAS;AAChC,IAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,CAAI,OAAA;AAC5B,IAAA,IAAI,YAAY,MAAA,EAAW;AACzB,MAAA,OAAYC,gBAAA,CAAA,IAAA,CAAK,SAAS,aAAa,CAAA;AAAA,IACzC;AACA,IAAA,OAAYA,gBAAA,CAAA,IAAA,CAAQC,cAAA,CAAA,OAAA,EAAQ,EAAG,SAAA,EAAW,WAAW,aAAa,CAAA;AAAA,EACpE;AACA,EAAA,OAAYD,gBAAA,CAAA,IAAA,CAAQC,cAAA,CAAA,OAAA,EAAQ,EAAG,SAAA,EAAW,aAAa,CAAA;AACzD;AAGA,SAAS,aAAA,GAA6B;AACpC,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,CAAA;AAAA,IACT,UAAU,CAAC,EAAE,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAA;AAAA,IAC1C,WAAA,EAAa,EAAE,eAAA,EAAiB,CAAA,EAAE;AAAA,IAClC,QAAA,EAAU,EAAE,UAAA,EAAY,EAAA,EAAI,WAAW,CAAA;AAAE,GAC3C;AACF;AAKA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAKA,SAAS,oBAAA,CAAqB,OAAgB,KAAA,EAA8B;AAC1E,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AACpB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAC,CAAA,mBAAA,CAAqB,CAAA;AAAA,EAChE;AACA,EAAA,IAAI,OAAO,MAAM,IAAA,KAAS,QAAA,IAAY,MAAM,IAAA,CAAK,IAAA,OAAW,EAAA,EAAI;AAC9D,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAC,CAAA,iCAAA,CAAmC,CAAA;AAAA,EAC9E;AACA,EAAA,IAAI,OAAO,KAAA,CAAM,OAAA,KAAY,SAAA,EAAW;AACtC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAC,CAAA,2BAAA,CAA6B,CAAA;AAAA,EACxE;AAEA,EAAA,MAAM,MAAA,GAAwB;AAAA,IAC5B,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,SAAS,KAAA,CAAM;AAAA,GACjB;AAEA,EAAA,IAAI,KAAA,CAAM,WAAW,MAAA,EAAW;AAC9B,IAAA,IAAI,OAAO,KAAA,CAAM,MAAA,KAAW,SAAA,EAAW;AACrC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAC,CAAA,0BAAA,CAA4B,CAAA;AAAA,IACvE;AACA,IAAA,MAAA,CAAO,SAAS,KAAA,CAAM,MAAA;AAAA,EACxB;AAEA,EAAA,IAAI,KAAA,CAAM,SAAS,MAAA,EAAW;AAC5B,IAAA,IAAI,OAAO,KAAA,CAAM,IAAA,KAAS,QAAA,EAAU;AAClC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,SAAA,EAAY,MAAA,CAAO,KAAK,CAAC,CAAA,uBAAA,CAAyB,CAAA;AAAA,IACpE;AACA,IAAA,MAAA,CAAO,OAAO,KAAA,CAAM,IAAA;AAAA,EACtB;AAEA,EAAA,OAAO,MAAA;AACT;AAMO,SAAS,eAAe,MAAA,EAA8B;AAC3D,EAAA,IAAI,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG;AACrB,IAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,OAAO,MAAA,CAAO,OAAA,KAAY,QAAA,IAAY,MAAA,CAAO,YAAY,CAAA,EAAG;AAC9D,IAAA,MAAM,IAAI,MAAM,0BAA0B,CAAA;AAAA,EAC5C;AAEA,EAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,IAAK,MAAA,CAAO,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AACnE,IAAA,MAAM,IAAI,MAAM,uCAAuC,CAAA;AAAA,EACzD;AAEA,EAAA,MAAM,QAAA,GAA4B,OAAO,QAAA,CAAS,GAAA;AAAA,IAAI,CAAC,KAAA,EAAgB,CAAA,KACrE,oBAAA,CAAqB,OAAO,CAAC;AAAA,GAC/B;AAEA,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,WAAW,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,MAAM,sCAAsC,CAAA;AAAA,EACxD;AACA,EAAA,IACE,OAAO,OAAO,WAAA,CAAY,eAAA,KAAoB,YAC9C,MAAA,CAAO,WAAA,CAAY,mBAAmB,CAAA,EACtC;AACA,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAChF;AAEA,EAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC9B,IAAA,MAAM,IAAI,MAAM,mCAAmC,CAAA;AAAA,EACrD;AACA,EAAA,IAAI,OAAO,OAAO,QAAA,CAAS,UAAA,KAAe,YAAY,MAAA,CAAO,QAAA,CAAS,cAAc,CAAA,EAAG;AACrF,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AACA,EAAA,MAAM,IAAA,GAAO,OAAO,QAAA,CAAS,SAAA;AAC7B,EAAA,IAAI,IAAA,KAAS,CAAA,IAAK,IAAA,KAAS,CAAA,IAAK,SAAS,CAAA,EAAG;AAC1C,IAAA,MAAM,IAAI,MAAM,8CAA8C,CAAA;AAAA,EAChE;AAEA,EAAA,MAAM,MAAA,GAAsB;AAAA,IAC1B,OAAA,EAAS,CAAA;AAAA,IACT,QAAA;AAAA,IACA,WAAA,EAAa;AAAA,MACX,eAAA,EAAiB,OAAO,WAAA,CAAY;AAAA,KACtC;AAAA,IACA,QAAA,EAAU;AAAA,MACR,UAAA,EAAY,OAAO,QAAA,CAAS,UAAA;AAAA,MAC5B,SAAA,EAAW;AAAA;AACb,GACF;AAEA,EAAA,IAAI,MAAA,CAAO,oBAAoB,MAAA,EAAW;AACxC,IAAA,IAAI,CAAC,QAAA,CAAS,MAAA,CAAO,eAAe,CAAA,EAAG;AACrC,MAAA,MAAM,IAAI,MAAM,0CAA0C,CAAA;AAAA,IAC5D;AACA,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,eAAA,CAAgB,WAAW,CAAA,EAAG;AACtD,MAAA,MAAM,IAAI,MAAM,qDAAqD,CAAA;AAAA,IACvE;AACA,IAAA,MAAM,cAAwB,EAAC;AAC/B,IAAA,KAAA,MAAW,CAAC,CAAA,EAAG,GAAG,CAAA,IAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,eAAA,CAAgB,WAAW,CAAA,CAAE,OAAA,EAAQ,EAAG;AAC/E,MAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mCAAA,EAAsC,MAAA,CAAO,CAAC,CAAC,CAAA,kBAAA,CAAoB,CAAA;AAAA,MACrF;AACA,MAAA,WAAA,CAAY,KAAK,GAAG,CAAA;AAAA,IACtB;AACA,IAAA,MAAA,CAAO,eAAA,GAAkB,EAAE,WAAA,EAAY;AAAA,EACzC;AAEA,EAAA,OAAO,MAAA;AACT;AASA,eAAsB,WAAW,SAAA,EAA0C;AACzE,EAAA,MAAM,GAAA,GAAM,aAAa,mBAAA,EAAoB;AAC7C,EAAA,MAAM,UAAA,GAAkBD,gBAAA,CAAA,IAAA,CAAK,GAAA,EAAK,aAAa,CAAA;AAE/C,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,MAASE,cAAA,CAAA,QAAA,CAAS,UAAA,EAAY,OAAO,CAAA;AAAA,EAC7C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,aAAA,EAAc;AAAA,EACvB;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,EACzB,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,+BAAA,EAAkC,UAAU,CAAA,CAAE,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,eAAe,MAAM,CAAA;AAC9B;ACpKO,IAAM,aAAN,MAAiB;AAAA,EACtB,MAAA,GAA+B,MAAA;AAAA,EAC/B,iBAAA,GAA+D,MAAA;AAAA,EAC/D,qBAAA,GAA4C,MAAA;AAAA,EAC5C,SAAA,GAAY,KAAA;AAAA;AAAA,EAGZ,WAAA,GAA2B;AACzB,IAAA,MAAM,YAAA,GAAsBC,kBAAA,CAAA,WAAA,CAAY,CAAC,CAAA,CAAE,SAAS,KAAK,CAAA;AACzD,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,KAAK,MAAA,CAAO,IAAA,CAAK,KAAK,CAAC,IAAI,YAAY,CAAA,CAAA;AAAA,MAC3C,GAAA,EAAK,IAAI,UAAA,CAAkBA,kBAAA,CAAA,WAAA,CAAY,EAAE,CAAC,CAAA;AAAA,MAC1C,SAAA,sBAAe,IAAA;AAAK,KACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAA,GAAsB;AACpB,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,MAAA,IAAA,CAAK,MAAA,GAAS,EAAE,OAAA,EAAS,IAAA,CAAK,aAAY,EAAE;AAAA,IAC9C;AACA,IAAA,OAAO,QAAQ,OAAA,EAAQ;AAAA,EACzB;AAAA;AAAA,EAGA,aAAA,GAA6B;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,EAAc;AACjC,IAAA,OAAO,KAAA,CAAM,OAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAA,GAA0C;AACxC,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,EAAc;AACjC,IAAA,OAAO,KAAA,CAAM,QAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,GAAA,EAAsC;AAChD,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,EAAc;AACjC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,EAAA,KAAO,GAAA,EAAK;AAC5B,MAAA,OAAO,KAAA,CAAM,OAAA;AAAA,IACf;AACA,IAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AACrB,IAAA,IAAI,QAAA,EAAU,OAAO,GAAA,EAAK;AAIxB,MAAA,OAAO,QAAA;AAAA,IACT;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,aAAA,EAA6B;AACrC,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,MAAM,IAAI,wBAAwB,uCAAuC,CAAA;AAAA,IAC3E;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,aAAA,EAAc;AACjC,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAGjB,IAAA,IAAA,CAAK,sBAAA,EAAuB;AAE5B,IAAA,MAAM,MAAA,GAAS,KAAK,WAAA,EAAY;AAChC,IAAA,IAAA,CAAK,SAAS,EAAE,OAAA,EAAS,MAAA,EAAQ,QAAA,EAAU,MAAM,OAAA,EAAQ;AACzD,IAAA,IAAA,CAAK,qBAAA,GAAwB,IAAA,CAAK,GAAA,EAAI,GAAI,aAAA;AAE1C,IAAA,IAAA,CAAK,iBAAA,GAAoB,WAAW,MAAM;AACxC,MAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAE7B,QAAA,IAAA,CAAK,MAAA,GAAS,EAAE,OAAA,EAAS,IAAA,CAAK,OAAO,OAAA,EAAQ;AAAA,MAC/C;AACA,MAAA,IAAA,CAAK,qBAAA,GAAwB,MAAA;AAC7B,MAAA,IAAA,CAAK,iBAAA,GAAoB,MAAA;AACzB,MAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AAAA,IACnB,GAAG,aAAa,CAAA;AAGhB,IAAA,IAAI,OAAO,IAAA,CAAK,iBAAA,CAAkB,KAAA,KAAU,UAAA,EAAY;AACtD,MAAA,IAAA,CAAK,kBAAkB,KAAA,EAAM;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAA,GAAkB;AAChB,IAAA,IAAA,CAAK,sBAAA,EAAuB;AAC5B,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AACjB,IAAA,IAAA,CAAK,qBAAA,GAAwB,MAAA;AAE7B,IAAA,MAAM,MAAA,GAAS,KAAK,WAAA,EAAY;AAChC,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,OAAA,EAAS,MAAA,EAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAA,GAA2B;AACzB,IAAA,IAAI,IAAA,CAAK,0BAA0B,MAAA,EAAW;AAC5C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,qBAAA;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAMA,aAAA,GAA0B;AACxB,IAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,MAAA,MAAM,IAAI,UAAA;AAAA,QACR,8DAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AACA,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,sBAAA,GAA+B;AAC7B,IAAA,IAAI,IAAA,CAAK,sBAAsB,MAAA,EAAW;AACxC,MAAA,YAAA,CAAa,KAAK,iBAAiB,CAAA;AACnC,MAAA,IAAA,CAAK,iBAAA,GAAoB,MAAA;AAAA,IAC3B;AAAA,EACF;AACF,CAAA;ACrJA,IAAM,SAAA,GAAY,KAAA;AAClB,IAAM,UAAA,GAAa,SAAA;AAuBnB,eAAsB,WAAA,CACpB,GAAA,EACA,MAAA,EACA,OAAA,EACiB;AACjB,EAAA,MAAM,SAAA,GAAY,IAAI,WAAA,EAAY,CAAE,OAAO,IAAA,CAAK,SAAA,CAAU,MAAM,CAAC,CAAA;AAEjE,EAAA,MAAM,MAAA,GAA0E;AAAA,IAC9E,GAAA,EAAK,SAAA;AAAA,IACL,GAAA,EAAK;AAAA,GACP;AAEA,EAAA,IAAI,OAAA,EAAS,QAAQ,MAAA,EAAW;AAC9B,IAAA,MAAA,CAAO,MAAM,OAAA,CAAQ,GAAA;AAAA,EACvB;AAEA,EAAA,OAAO,IAAIC,oBAAe,SAAS,CAAA,CAAE,mBAAmB,MAAM,CAAA,CAAE,QAAQ,GAAG,CAAA;AAC7E;AAKA,SAASC,UAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AAMA,SAAS,iBAAiB,GAAA,EAAuC;AAC/D,EAAA,IAAI,CAACA,SAAAA,CAAS,GAAG,CAAA,EAAG;AAClB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAI,GAAI,GAAA;AAE7D,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,GAAA,KAAQ,IAAA,IAAQ,OAAO,GAAA,KAAQ,UAAU,OAAO,MAAA;AACpD,EAAA,IAAI,QAAQ,CAAA,IAAK,GAAA,KAAQ,CAAA,IAAK,GAAA,KAAQ,GAAG,OAAO,MAAA;AAChD,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AACpC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,MAAA;AAEpC,EAAA,OAAO,EAAE,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,IAAO,IAAA,EAAM,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAI;AACzE;AAWA,eAAsB,YAAA,CAAa,KAAiB,GAAA,EAAmC;AACrF,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAMC,mBAAA,CAAe,GAAA,EAAK,GAAG,CAAA;AAC5C,IAAA,SAAA,GAAY,MAAA,CAAO,SAAA;AAAA,EACrB,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,uBAAA,EAA0B,OAAO,CAAA,CAAE,CAAA;AAAA,EAC1D;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,KAAK,KAAA,CAAM,IAAI,aAAY,CAAE,MAAA,CAAO,SAAS,CAAC,CAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,WAAW,+BAA+B,CAAA;AAAA,EACtD;AAEA,EAAA,MAAM,MAAA,GAAS,iBAAiB,MAAM,CAAA;AACtC,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,MAAM,IAAI,WAAW,+CAA+C,CAAA;AAAA,EACtE;AAEA,EAAA,OAAO,MAAA;AACT;AAYO,SAAS,WAAW,GAAA,EAAiC;AAC1D,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,WAAW,qDAAqD,CAAA;AAAA,EAC5E;AACA,EAAA,MAAM,aAAA,GAAgB,MAAM,CAAC,CAAA;AAC7B,EAAA,IAAI,aAAA,KAAkB,MAAA,IAAa,aAAA,KAAkB,EAAA,EAAI;AACvD,IAAA,MAAM,IAAI,WAAW,2DAA2D,CAAA;AAAA,EAClF;AACA,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI;AACF,IAAA,UAAA,GAAa,OAAO,IAAA,CAAK,aAAA,EAAe,WAAW,CAAA,CAAE,SAAS,OAAO,CAAA;AAAA,EACvE,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,WAAW,kEAAkE,CAAA;AAAA,EACzF;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,IAAA,CAAK,MAAM,UAAU,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,MAAM,IAAI,WAAW,6DAA6D,CAAA;AAAA,EACpF;AAEA,EAAA,IAAI,CAACD,SAAAA,CAAS,MAAM,CAAA,EAAG;AACrB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAM,MAAA,CAAO,GAAA;AACnB,EAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,GAAA;AACT;;;AC9IA,IAAM,kBAAA,GAAqB,GAAA;AAU3B,IAAM,SAAA,uBAAgB,GAAA,EAAkB;AASjC,SAAS,WAAW,GAAA,EAAmB;AAC5C,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA,EAAG;AAGtB,IAAA,SAAA,CAAU,OAAO,GAAG,CAAA;AAAA,EACtB,CAAA,MAAA,IAAW,SAAA,CAAU,IAAA,IAAQ,kBAAA,EAAoB;AAE/C,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,IAAA,EAAK,CAAE,MAAK,CAAE,KAAA;AAC1C,IAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,MAAA,SAAA,CAAU,OAAO,SAAS,CAAA;AAAA,IAC5B;AAAA,EACF;AACA,EAAA,SAAA,CAAU,GAAA,CAAI,KAAK,IAAI,CAAA;AACzB;AAQO,SAAS,UAAU,GAAA,EAAsB;AAC9C,EAAA,OAAO,SAAA,CAAU,IAAI,GAAG,CAAA;AAC1B;AA6BO,SAAS,cAAA,CAAe,MAAA,EAAqB,SAAA,GAAY,CAAA,EAAS;AAEvE,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AACA,EAAA,IAAI,MAAA,CAAO,GAAA,CAAI,IAAA,EAAK,KAAM,EAAA,EAAI;AAC5B,IAAA,MAAM,IAAI,WAAW,sCAAsC,CAAA;AAAA,EAC7D;AAGA,EAAA,IAAI,MAAA,CAAO,GAAA,GAAM,MAAA,CAAO,GAAA,EAAK;AAC3B,IAAA,MAAM,IAAI,WAAW,0CAA0C,CAAA;AAAA,EACjE;AAGA,EAAA,MAAM,SAAS,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAC3C,EAAA,IAAI,MAAA,IAAU,OAAO,GAAA,EAAK;AACxB,IAAA,MAAM,IAAI,iBAAA;AAAA,MACR,CAAA,iBAAA,EAAoB,OAAO,MAAA,CAAO,GAAG,CAAC,CAAA,OAAA,EAAU,MAAA,CAAO,MAAM,CAAC,CAAA,CAAA,CAAA;AAAA,MAC9D;AAAA,KACF;AAAA,EACF;AAGA,EAAA,IAAI,SAAA,CAAU,MAAA,CAAO,GAAG,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,iBAAA,CAAkB,CAAA,MAAA,EAAS,MAAA,CAAO,GAAG,CAAA,iBAAA,CAAmB,CAAA;AAAA,EACpE;AAGA,EAAA,IAAI,MAAA,CAAO,QAAQ,IAAA,EAAM;AACvB,IAAA,IAAI,MAAA,CAAO,OAAO,CAAA,EAAG;AACnB,MAAA,MAAM,IAAI,uBAAA;AAAA,QACR,SAAS,MAAA,CAAO,GAAG,oCAAoC,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OAC3E;AAAA,IACF;AACA,IAAA,IAAI,SAAA,IAAa,OAAO,GAAA,EAAK;AAC3B,MAAA,MAAM,IAAI,uBAAA;AAAA,QACR,CAAA,MAAA,EAAS,MAAA,CAAO,GAAG,CAAA,gBAAA,EAAmB,MAAA,CAAO,MAAA,CAAO,GAAG,CAAC,CAAA,iBAAA,EAAoB,MAAA,CAAO,SAAS,CAAC,CAAA,CAAA;AAAA,OAC/F;AAAA,IACF;AAAA,EACF;AACF;;;ACpIA,IAAM,WAAA,GAAc,YAAA;AAEpB,SAAS,kBAAA,CAAmB,OAAe,MAAA,EAAwB;AACjE,EAAA,OAAO,KAAA,CAAM,UAAA,CAAW,WAAA,EAAa,MAAM,CAAA;AAC7C;AAEA,SAAS,eAAA,CACP,QACA,MAAA,EACwB;AACxB,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,kBAAA,CAAmB,KAAA,EAAO,MAAM,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,MAAA;AACT;AAUA,eAAsB,cAAA,CACpB,QACA,OAAA,EACmB;AACnB,EAAA,MAAM,GAAA,GAAM,kBAAA,CAAmB,OAAA,CAAQ,GAAA,EAAK,MAAM,CAAA;AAClD,EAAA,MAAM,OAAA,GACJ,QAAQ,OAAA,KAAY,MAAA,GAChB,gBAAgB,OAAA,CAAQ,OAAA,EAAS,MAAM,CAAA,GACvC,MAAA;AACN,EAAA,MAAM,IAAA,GACJ,QAAQ,IAAA,KAAS,MAAA,GACb,mBAAmB,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,GACvC,MAAA;AAEN,EAAA,MAAM,OAAoB,EAAC;AAC3B,EAAA,IAAI,OAAA,CAAQ,WAAW,MAAA,EAAW;AAChC,IAAA,IAAA,CAAK,SAAS,OAAA,CAAQ,MAAA;AAAA,EACxB;AACA,EAAA,IAAI,YAAY,MAAA,EAAW;AACzB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACA,EAAA,IAAI,SAAS,MAAA,EAAW;AACtB,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EACd;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AClDA,IAAME,YAAAA,GAAc,YAAA;AAEpB,SAASC,mBAAAA,CAAmB,OAAe,MAAA,EAAwB;AACjE,EAAA,OAAO,KAAA,CAAM,UAAA,CAAWD,YAAAA,EAAa,MAAM,CAAA;AAC7C;AAEA,SAASE,gBAAAA,CACP,QACA,MAAA,EACwB;AACxB,EAAA,MAAM,SAAiC,EAAC;AACxC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AACjD,IAAA,MAAA,CAAO,GAAG,CAAA,GAAID,mBAAAA,CAAmB,KAAA,EAAO,MAAM,CAAA;AAAA,EAChD;AACA,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,aAAA,CACd,QACA,OAAA,EACqB;AACrB,EAAA,MAAM,IAAA,GAAA,CAAQ,OAAA,CAAQ,IAAA,IAAQ,EAAC,EAAG,GAAA,CAAI,CAAC,GAAA,KAAQA,mBAAAA,CAAmB,GAAA,EAAK,MAAM,CAAC,CAAA;AAC9E,EAAA,MAAM,GAAA,GACJ,QAAQ,GAAA,KAAQ,MAAA,GAAYC,iBAAgB,OAAA,CAAQ,GAAA,EAAK,MAAM,CAAA,GAAI,MAAA;AAErE,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,EAAS,MAAA,KAAW;AACtC,IAAA,MAAM,YAAA,GAA4C;AAAA,MAChD,KAAA,EAAO,CAAC,QAAA,EAAU,MAAA,EAAQ,MAAM;AAAA,KAClC;AACA,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,YAAA,CAAa,MAAM,EAAE,GAAG,OAAA,CAAQ,GAAA,EAAK,GAAG,GAAA,EAAI;AAAA,IAC9C;AACA,IAAA,IAAI,OAAA,CAAQ,QAAQ,MAAA,EAAW;AAC7B,MAAA,YAAA,CAAa,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC7B;AAEA,IAAA,MAAM,IAAA,GAAOjB,mBAAAA,CAAM,OAAA,CAAQ,OAAA,EAAS,MAAM,YAAY,CAAA;AACtD,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,MAAA,GAAS,EAAA;AAEb,IAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,MAAA,EAAQ,EAAA,CAAG,MAAA,EAAQ,CAAC,IAAA,KAAiB;AACxC,MAAA,MAAA,IAAU,KAAK,QAAA,EAAS;AAAA,IAC1B,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,CAAC,IAAA,KAAS;AACzB,MAAA,OAAA,CAAQ,EAAE,MAAA,EAAQ,MAAA,EAAQ,QAAA,EAAU,IAAA,IAAQ,GAAG,CAAA;AAAA,IACjD,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,EAAA,CAAG,OAAA,EAAS,CAAC,KAAA,KAAU;AAC1B,MAAA,MAAA,CAAO,KAAK,CAAA;AAAA,IACd,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;;;AC5DA,IAAM,cAAA,mBAAiB,MAAA,CAAO,GAAA,CAAI,4BAA4B,CAAA;AAgB9D,IAAM,uBAAN,MAA6D;AAAA,EAClD,IAAA;AAAA,EACT,CAAU,cAAc;AAAA,EAExB,WAAA,CACE,UACA,WAAA,EACA;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,QAAA;AACZ,IAAA,IAAA,CAAK,cAAc,CAAA,GAAI,WAAA;AAAA,EACzB;AACF,CAAA;AAcO,SAAS,qBAAqB,WAAA,EAAqC;AACxE,EAAA,IAAI,QAAA,GAAW,KAAA;AAEf,EAAA,MAAM,YAAA,GAAiD,EAAE,EAAA,EAAI,MAAA,EAAU;AAGvE,EAAA,SAAS,SAAS,QAAA,EAAuC;AACvD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,IAAI,MAAM,iGAA4F,CAAA;AAAA,IAC9G;AACA,IAAA,QAAA,GAAW,IAAA;AAEX,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,WAAA,EAAa,MAAM,CAAA;AAC3C,IAAA,IAAI;AACF,MAAA,QAAA,CAAS,GAAG,CAAA;AAAA,IACd,CAAA,SAAE;AACA,MAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AAEV,MAAA,YAAA,CAAa,EAAA,IAAK;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,SAAS,WAAA,GAAsB;AAC7B,IAAA,OAAO,kBAAA;AAAA,EACT;AAIA,EAAA,MAAM,MAAA,GAAS,IAAI,oBAAA,CAAqB,QAAA,EAAU,WAAW,CAAA;AAC7D,EAAA,MAAA,CAAO,cAAA,CAAe,QAAQ,IAAI,CAAA;AAClC,EAAA,MAAA,CAAO,kBAAkB,MAAM,CAAA;AAG/B,EAAA,MAAM,OAAA,GAA0D;AAAA,IAC9D,GAAA,CAAI,EAAA,EAAI,IAAA,EAAM,SAAA,EAAW;AACvB,MAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,QAAA;AAC5B,MAAA,IAAI,IAAA,KAAS,gBAAgB,OAAO,WAAA;AACpC,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,GAAA,CAAI,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,SAAA,EAAW;AAChC,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,GAAA,CAAI,IAAI,IAAA,EAAM;AACZ,MAAA,OAAO,IAAA,KAAS,UAAU,IAAA,KAAS,cAAA;AAAA,IACrC,CAAA;AAAA,IACA,cAAA,CAAe,IAAI,KAAA,EAAO;AACxB,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,KAAA,CAAM,EAAA,EAAI,QAAA,EAAU,KAAA,EAAO;AACzB,MAAA,MAAM,IAAI,UAAU,kCAAkC,CAAA;AAAA,IACxD,CAAA;AAAA,IACA,SAAA,CAAU,EAAA,EAAI,KAAA,EAAO,UAAA,EAAY;AAC/B,MAAA,MAAM,IAAI,UAAU,qCAAqC,CAAA;AAAA,IAC3D,CAAA;AAAA,IACA,cAAA,CAAe,EAAA,EAAI,KAAA,EAAO,WAAA,EAAa;AACrC,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,wBAAA,CAAyB,IAAI,IAAA,EAAM;AACjC,MAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,QAAA,OAAO,EAAE,cAAc,IAAA,EAAM,UAAA,EAAY,MAAM,QAAA,EAAU,KAAA,EAAO,OAAO,QAAA,EAAS;AAAA,MAClF;AACA,MAAA,IAAI,SAAS,cAAA,EAAgB;AAC3B,QAAA,OAAO,EAAE,cAAc,IAAA,EAAM,UAAA,EAAY,OAAO,QAAA,EAAU,KAAA,EAAO,OAAO,WAAA,EAAY;AAAA,MACtF;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IACA,eAAe,EAAA,EAAI;AAEjB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,cAAA,CAAe,IAAI,MAAA,EAAQ;AACzB,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,aAAa,EAAA,EAAI;AAEf,MAAA,OAAO,KAAA;AAAA,IACT,CAAA;AAAA,IACA,kBAAkB,EAAA,EAAI;AAEpB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IACA,QAAQ,EAAA,EAAI;AAGV,MAAA,OAAO,CAAC,QAAQ,cAAc,CAAA;AAAA,IAChC;AAAA,GACF;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,MAAA,KAAW,KAAA,CAAM,SAAA,CAAU,QAAQ,OAAO,CAAA;AAEzD,EAAA,YAAA,CAAa,EAAA,GAAK,MAAA;AAElB,EAAA,OAAO,KAAA;AACT;;;ACzIA,SAAS,aAAa,GAAA,EAA8C;AAClE,EAAA,MAAM,KAAA,GAAQ,qBAAA,CAAsB,IAAA,CAAK,GAAG,CAAA;AAC5C,EAAA,IAAI,CAAC,OAAO,OAAO,IAAA;AACnB,EAAA,MAAM,QAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AAC1C,EAAA,MAAM,QAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AAC1C,EAAA,MAAM,QAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,CAAA,IAAK,KAAK,EAAE,CAAA;AAC1C,EAAA,OAAO,CAAC,KAAA,EAAO,KAAA,EAAO,KAAK,CAAA;AAC7B;AAKA,SAAS,UAAA,CACP,GACA,CAAA,EACS;AACT,EAAA,IAAI,CAAA,CAAE,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,EAAG,OAAO,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AACpC,EAAA,IAAI,CAAA,CAAE,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,EAAG,OAAO,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA;AACpC,EAAA,OAAO,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA;AACpB;AAMA,eAAsB,YAAA,GAAwC;AAC5D,EAAA,MAAM,IAAA,GAAO,SAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,SAAA,EAAW,CAAC,SAAS,CAAC,CAAA;AACvD,IAAA,MAAM,MAAA,GAAS,aAAa,MAAM,CAAA;AAClC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,MAAA,EAAQ,qBAAA;AAAA,QACR,OAAA,EAAS,MAAA;AAAA,QACT,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AACA,IAAA,IAAI,CAAC,WAAW,MAAA,EAAQ,CAAC,GAAG,CAAA,EAAG,CAAC,CAAC,CAAA,EAAG;AAClC,MAAA,OAAO;AAAA,QACL,IAAA;AAAA,QACA,MAAA,EAAQ,qBAAA;AAAA,QACR,OAAA,EAAS,MAAA;AAAA,QACT,MAAA,EAAQ;AAAA,OACV;AAAA,IACF;AACA,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAS,MAAA,EAAO;AAAA,EAC/C,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,QAAQ,2BAAA,EAA4B;AAAA,EACxE;AACF;AAMA,eAAsB,SAAA,GAAqC;AACzD,EAAA,MAAM,IAAA,GAAO,MAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,MAAA,EAAQ,CAAC,WAAW,CAAC,CAAA;AACtD,IAAA,MAAM,YAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA,CAAE,CAAC,CAAA,IAAK,MAAA;AAC3C,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAS,SAAA,EAAU;AAAA,EAClD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,QAAQ,wBAAA,EAAyB;AAAA,EACrE;AACF;AAMA,eAAsB,eAAA,GAA2C;AAC/D,EAAA,MAAM,IAAA,GAAO,YAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,WAAA,CAAY,YAAA,EAAc;AAAA,MAC7C,UAAA;AAAA,MACA;AAAA,KACD,CAAA;AACD,IAAA,MAAM,OAAA,GAAU,OAAO,IAAA,EAAK;AAC5B,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAQ;AAAA,EACvC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,QAAQ,8BAAA,EAA+B;AAAA,EAC3E;AACF;AAMA,eAAsB,aAAA,GAAyC;AAC7D,EAAA,MAAM,IAAA,GAAO,UAAA;AACb,EAAA,IAAI;AAEF,IAAA,MAAM,WAAA,CAAY,UAAA,EAAY,CAAC,MAAM,CAAC,CAAA;AACtC,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAK;AAAA,EAC9B,SAAS,GAAA,EAAK;AAEZ,IAAA,MAAM,UAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC/D,IAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA,EAAG;AAEhC,MAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAK;AAAA,IAC9B;AACA,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AACF;AAMA,eAAsB,eAAA,GAA2C;AAC/D,EAAA,MAAM,IAAA,GAAO,aAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,aAAA,EAAe,CAAC,WAAW,CAAC,CAAA;AAC7D,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,OAAA,EAAS,MAAA,CAAO,MAAK,EAAE;AAAA,EACtD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AACF;AAMA,eAAsB,OAAA,GAAmC;AACvD,EAAA,MAAM,IAAA,GAAO,IAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,IAAA,EAAM,CAAC,WAAW,CAAC,CAAA;AACpD,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,OAAA,EAAS,MAAA,CAAO,MAAK,EAAE;AAAA,EACtD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AACF;AAMA,eAAsB,UAAA,GAAsC;AAC1D,EAAA,MAAM,IAAA,GAAO,OAAA;AACb,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,WAAA,CAAY,OAAA,EAAS,CAAC,WAAW,CAAC,CAAA;AACvD,IAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAM,OAAA,EAAS,MAAA,CAAO,MAAK,EAAE;AAAA,EACtD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,MAAA,EAAQ,SAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAAA,EACF;AACF;;;ACnKO,SAAS,eAAA,GAA4B;AAC1C,EAAA,MAAM,IAAI,OAAA,CAAQ,QAAA;AAClB,EAAA,IAAI,CAAA,KAAM,QAAA,IAAY,CAAA,KAAM,OAAA,IAAW,MAAM,OAAA,EAAS;AACpD,IAAA,OAAO,CAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAI,KAAA,CAAM,CAAA,sBAAA,EAAyB,CAAC,CAAA,CAAE,CAAA;AAC9C;;;AC0BA,eAAsB,UAAU,OAAA,EAAsD;AACpF,EAAA,MAAM,QAAA,GAAgC,eAAA,EAAgB;AAEtD,EAAA,MAAM,OAAA,GAAwB,eAAe,QAAQ,CAAA;AAErD,EAAA,MAAM,QAAA,GAA4B,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC9C,QAAQ,GAAA,CAAI,OAAO,EAAE,KAAA,EAAO,UAAS,KAAM;AACzC,MAAA,MAAM,MAAA,GAAS,MAAM,KAAA,EAAM;AAC3B,MAAA,OAAO,EAAE,UAAU,MAAA,EAAO;AAAA,IAC5B,CAAC;AAAA,GACH;AAEA,EAAA,MAAM,QAAQ,QAAA,CAAS,KAAA,CAAM,CAAC,EAAE,QAAA,EAAU,QAAO,KAAM;AACrD,IAAA,IAAI,CAAC,UAAU,OAAO,IAAA;AACtB,IAAA,OAAO,OAAO,MAAA,KAAW,IAAA;AAAA,EAC3B,CAAC,CAAA;AAED,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,MAAM,YAAsB,EAAC;AAE7B,EAAA,KAAA,MAAW,EAAE,QAAA,EAAU,MAAA,EAAO,IAAK,QAAA,EAAU;AAC3C,IAAA,IAAI,MAAA,CAAO,WAAW,SAAA,EAAW;AAC/B,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,SAAA,CAAU,IAAA,CAAK,CAAA,qCAAA,EAAwC,MAAA,CAAO,IAAI,CAAA,CAAE,CAAA;AAAA,MACtE,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,IAAA;AAAA,UACP,CAAA,+BAAA,EAAkC,MAAA,CAAO,IAAI,CAAA,EAAG,MAAA,CAAO,MAAA,KAAW,MAAA,GAAY,CAAA,QAAA,EAAM,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAE,CAAA;AAAA,SAC1G;AAAA,MACF;AAAA,IACF,CAAA,MAAA,IAAW,MAAA,CAAO,MAAA,KAAW,qBAAA,EAAuB;AAClD,MAAA,MAAM,GAAA,GAAM,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,uBAAA,EAA0B,MAAA,CAAO,MAAA,KAAW,MAAA,GAAY,CAAA,EAAA,EAAK,MAAA,CAAO,MAAM,CAAA,CAAA,GAAK,EAAE,CAAA,CAAA;AAC3G,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,SAAA,CAAU,IAAA,CAAK,CAAA,6BAAA,EAAgC,GAAG,CAAA,CAAE,CAAA;AAAA,MACtD,CAAA,MAAO;AACL,QAAA,QAAA,CAAS,IAAA,CAAK,CAAA,yCAAA,EAA4C,GAAG,CAAA,CAAE,CAAA;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,SAAS,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,MAAA,OAAa,MAAM,CAAA;AAElD,EAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,QAAA,EAAU,SAAA,EAAU;AAC9C;AAEA,SAAS,eAAe,QAAA,EAAkC;AACxD,EAAA,MAAM,UAAwB,CAAC,EAAE,OAAO,YAAA,EAAc,QAAA,EAAU,MAAM,CAAA;AAEtE,EAAA,IAAI,aAAa,QAAA,EAAU;AACzB,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,aAAA,EAAe,QAAA,EAAU,MAAM,CAAA;AACrD,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU,OAAO,CAAA;AAAA,EACpD,CAAA,MAAA,IAAW,aAAa,OAAA,EAAS;AAC/B,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,eAAA,EAAiB,QAAA,EAAU,MAAM,CAAA;AAAA,EACzD,CAAA,MAAO;AAEL,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAU,MAAM,CAAA;AACjD,IAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,eAAA,EAAiB,QAAA,EAAU,MAAM,CAAA;AAAA,EACzD;AAGA,EAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,OAAO,CAAA;AAChD,EAAA,OAAA,CAAQ,KAAK,EAAE,KAAA,EAAO,UAAA,EAAY,QAAA,EAAU,OAAO,CAAA;AAEnD,EAAA,OAAO,OAAA;AACT;;;AC1CA,IAAM,WAAA,uBAAkB,GAAA,EAAoB;AAMrC,IAAM,WAAA,GAAN,MAAM,YAAA,CAAY;AAAA,EACd,OAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACT,QAAA;AAAA,EAEQ,WAAA,CAAY,MAAA,EAAqB,UAAA,EAAwB,SAAA,EAAmB;AAClF,IAAA,IAAA,CAAK,OAAA,GAAU,MAAA;AACf,IAAA,IAAA,CAAK,WAAA,GAAc,UAAA;AACnB,IAAA,IAAA,CAAK,UAAA,GAAa,SAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,KAAK,OAAA,EAAoD;AACpE,IAAA,IAAI,OAAA,EAAS,eAAe,IAAA,EAAM;AAChC,MAAA,MAAM,YAAA,GAAe,MAAM,SAAA,EAAU;AACrC,MAAA,IAAI,CAAC,aAAa,KAAA,EAAO;AACvB,QAAA,MAAM,IAAI,UAAA;AAAA,UACR,CAAA,kBAAA,EAAqB,YAAA,CAAa,SAAA,CAAU,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,SACxD;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,SAAA,GAAY,OAAA,EAAS,SAAA,IAAa,mBAAA,EAAoB;AAC5D,IAAA,MAAM,MAAA,GAAS,OAAA,EAAS,MAAA,IAAW,MAAM,WAAW,SAAS,CAAA;AAE7D,IAAA,MAAM,UAAA,GAAa,IAAI,UAAA,EAAW;AAClC,IAAA,MAAM,WAAW,IAAA,EAAK;AAEtB,IAAA,MAAM,KAAA,GAAQ,IAAI,YAAA,CAAY,MAAA,EAAQ,YAAY,SAAS,CAAA;AAC3D,IAAA,KAAA,CAAM,QAAA,GAAW,MAAM,eAAA,EAAgB;AAEvC,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,MAAA,GAAmC;AAC9C,IAAA,OAAO,SAAA,EAAU;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAA,CAAM,UAAA,EAAoB,OAAA,EAAyC;AACvE,IAAA,MAAM,OAAA,GAAU,KAAK,eAAA,EAAgB;AACrC,IAAA,MAAM,WAAA,GAAc,OAAA,EAAS,WAAA,IAAe,OAAA,CAAQ,IAAA;AACpD,IAAA,MAAM,UAAA,GAAa,OAAA,EAAS,UAAA,IAAc,IAAA,CAAK,QAAQ,QAAA,CAAS,UAAA;AAChE,IAAA,MAAM,SAAA,GAAY,OAAA,EAAS,SAAA,IAAa,IAAA,CAAK,QAAQ,QAAA,CAAS,SAAA;AAC9D,IAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,IAAA;AACtC,IAAA,MAAM,cAAA,GAAiB,SAAS,cAAA,IAAkB,KAAA;AAElD,IAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ,QAAA,CAAS,UAAU,CAAA;AAErD,IAAA,IAAI,WAAA;AACJ,IAAA,IAAI,cAAA,KAAmB,KAAA,IAAS,IAAA,CAAK,oBAAA,CAAqB,cAAc,CAAA,EAAG;AACzE,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB,CAAA,MAAO;AACL,MAAA,MAAM,WAAA,GAAc,MAAM,WAAA,CAAY,cAAA,EAAgB;AAAA,QACpD,WAAW,IAAA,CAAK;AAAA,OACjB,CAAA;AACD,MAAA,IAAI,YAAY,YAAA,EAAc;AAC5B,QAAA,MAAM,IAAI,qBAAA;AAAA,UACR,qDAAA;AAAA,UACA,qBAAA;AAAA,UACA,YAAY,QAAA,CAAS;AAAA,SACvB;AAAA,MACF;AACA,MAAA,WAAA,GAAc,YAAY,QAAA,CAAS,IAAA;AAAA,IACrC;AAEA,IAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AACxC,IAAA,MAAM,MAAA,GAAsB;AAAA,MAC1B,KAAYkB,kBAAA,CAAA,UAAA,EAAW;AAAA,MACvB,GAAA,EAAK,MAAM,UAAA,GAAa,EAAA;AAAA,MACxB,GAAA,EAAK,GAAA;AAAA,MACL,GAAA,EAAK,UAAA;AAAA,MACL,GAAA,EAAK,WAAA;AAAA,MACL,GAAA,EAAK,QAAA;AAAA,MACL,GAAA,EAAK,SAAA;AAAA,MACL,GAAA,EAAK,WAAA;AAAA,MACL,GAAA,EAAK,WAAA;AAAA,MACL,GAAA,EAAK;AAAA,KACP;AAEA,IAAA,MAAM,UAAA,GAAa,IAAA,CAAK,WAAA,CAAY,aAAA,EAAc;AAClD,IAAA,OAAO,WAAA,CAAY,WAAW,GAAA,EAAK,MAAA,EAAQ,EAAE,GAAA,EAAK,UAAA,CAAW,IAAI,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAU,GAAA,EAA2E;AACzF,IAAA,MAAM,GAAA,GAAM,WAAW,GAAG,CAAA;AAC1B,IAAA,MAAM,EAAE,QAAQ,SAAA,EAAU,GAAI,MAAM,IAAA,CAAK,yBAAA,CAA0B,KAAK,GAAG,CAAA;AAG3E,IAAA,MAAM,MAAM,MAAA,CAAO,GAAA;AACnB,IAAA,MAAM,YAAA,GAAe,WAAA,CAAY,GAAA,CAAI,GAAG,CAAA,IAAK,CAAA;AAC7C,IAAA,cAAA,CAAe,QAAQ,YAAY,CAAA;AAGnC,IAAA,MAAM,WAAW,YAAA,GAAe,CAAA;AAChC,IAAA,IAAI,MAAA,CAAO,GAAA,KAAQ,IAAA,IAAQ,QAAA,IAAY,OAAO,GAAA,EAAK;AAGjD,MAAA,WAAA,CAAY,OAAO,GAAG,CAAA;AACtB,MAAA,UAAA,CAAW,GAAG,CAAA;AAAA,IAChB,CAAA,MAAO;AACL,MAAA,WAAA,CAAY,GAAA,CAAI,KAAK,QAAQ,CAAA;AAAA,IAC/B;AAEA,IAAA,MAAM,KAAA,GAAQ,sBAAsB,MAAM,CAAA;AAE1C,IAAA,MAAM,QAAA,GAA0B,EAAE,SAAA,EAAU;AAC5C,IAAA,IAAI,cAAc,UAAA,EAAY;AAE5B,MAAA,MAAM,UAAA,GAAa,IAAA,CAAK,WAAA,CAAY,aAAA,EAAc;AAClD,MAAA,MAAM,UAAA,GAAa,MAAM,WAAA,CAAY,UAAA,CAAW,GAAA,EAAK,QAAQ,EAAE,GAAA,EAAK,UAAA,CAAW,EAAA,EAAI,CAAA;AACnF,MAAA,QAAA,CAAS,UAAA,GAAa,UAAA;AAAA,IACxB;AAEA,IAAA,OAAO,EAAE,OAAO,QAAA,EAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,KAAA,CACJ,KAAA,EACA,OAAA,EAC+D;AAC/D,IAAA,MAAM,MAAA,GAAS,wBAAwB,KAAK,CAAA;AAC5C,IAAA,MAAM,QAAA,GAAW,MAAM,cAAA,CAAe,MAAA,CAAO,KAAK,OAAO,CAAA;AACzD,IAAA,OAAO;AAAA,MACL,QAAA;AAAA,MACA,aAAA,EAAe,EAAE,SAAA,EAAW,SAAA;AAAU,KACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,IAAA,CACJ,KAAA,EACA,OAAA,EAC+D;AAC/D,IAAA,MAAM,MAAA,GAAS,wBAAwB,KAAK,CAAA;AAC5C,IAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,MAAA,CAAO,KAAK,OAAO,CAAA;AACtD,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,aAAA,EAAe,EAAE,SAAA,EAAW,SAAA;AAAU,KACxC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UAAU,KAAA,EAAwC;AAChD,IAAA,MAAM,MAAA,GAAS,wBAAwB,KAAK,CAAA;AAC5C,IAAA,OAAO,oBAAA,CAAqB,OAAO,GAAG,CAAA;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAA,GAA2B;AAC/B,IAAA,MAAM,gBAAgB,IAAA,CAAK,OAAA,CAAQ,YAAY,eAAA,GAAkB,EAAA,GAAK,KAAK,EAAA,GAAK,GAAA;AAChF,IAAA,IAAA,CAAK,WAAA,CAAY,UAAU,aAAa,CAAA;AACxC,IAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,SAAA,GAA2B;AAC/B,IAAA,IAAA,CAAK,YAAY,SAAA,EAAU;AAC3B,IAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,kBAAA,CAAmB,cAAA,EAAwB,OAAA,EAAiC;AAChF,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,eAAA,KAAoB,MAAA,EAAW;AAC9C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,IAAA,CAAK,QAAQ,eAAA,GAAkB,EAAE,WAAA,EAAa,CAAC,cAAc,CAAA,EAAE;AAAA,MACjE;AACA,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,CAAgB,WAAA;AAC1C,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,OAAA,CAAQ,cAAc,CAAA;AAEvC,IAAA,IAAI,OAAA,IAAW,QAAQ,EAAA,EAAI;AACzB,MAAA,IAAA,CAAK,KAAK,cAAc,CAAA;AAAA,IAC1B,CAAA,MAAA,IAAW,CAAC,OAAA,IAAW,GAAA,KAAQ,EAAA,EAAI;AACjC,MAAA,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,IACpB;AAEA,IAAA,MAAM,QAAQ,OAAA,EAAQ;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAMA,eAAA,GAAiC;AAC/B,IAAA,MAAM,eAAA,GAAkB,KAAK,OAAA,CAAQ,QAAA,CAAS,OAAO,CAAC,CAAA,KAAM,EAAE,OAAO,CAAA;AACrE,IAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AAChC,MAAA,MAAM,IAAI,uBAAA;AAAA,QACR,gCAAA;AAAA,QACA,cAAA;AAAA,QACA,KAAK,OAAA,CAAQ,QAAA,CAAS,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,OACzC;AAAA,IACF;AAEA,IAAA,MAAM,YAAA,GAAe,gBAAgB,CAAC,CAAA;AACtC,IAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,MAAA,MAAM,IAAI,uBAAA;AAAA,QACR,gCAAA;AAAA,QACA,cAAA;AAAA,QACA;AAAC,OACH;AAAA,IACF;AAEA,IAAA,OAAO,eAAA,CAAgB,MAAA,CAAO,YAAA,CAAa,IAAI,CAAA;AAAA,EACjD;AAAA,EAEA,eAAA,GAAiC;AAC/B,IAAA,IAAI,IAAA,CAAK,aAAa,MAAA,EAAW;AAC/B,MAAA,MAAM,IAAI,WAAW,qCAAqC,CAAA;AAAA,IAC5D;AACA,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AAAA,EAEA,qBAAqB,cAAA,EAAiC;AACpD,IAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,eAAA,KAAoB,MAAA,EAAW;AAC9C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,CAAgB,WAAA,CAAY,SAAS,cAAc,CAAA;AAAA,EACzE;AAAA,EAEA,MAAM,yBAAA,CACJ,GAAA,EACA,GAAA,EACqE;AAErE,IAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,WAAA,CAAY,GAAG,CAAA;AAC5C,MAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,QAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,GAAA,CAAI,KAAK,GAAG,CAAA;AAC9C,QAAA,MAAM,YAAY,GAAA,CAAI,EAAA,KAAO,IAAA,CAAK,WAAA,CAAY,eAAc,CAAE,EAAA;AAC9D,QAAA,OAAO;AAAA,UACL,MAAA;AAAA,UACA,SAAA,EAAW,YAAY,SAAA,GAAY;AAAA,SACrC;AAAA,MACF;AAEA,MAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,IAAA,EAAO,GAAG,CAAA,uCAAA,CAAoC,CAAA;AAAA,IAC1E;AAGA,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,IAAA,CAAK,YAAY,aAAA,EAAc,CAAE,KAAK,GAAG,CAAA;AAC3E,MAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,SAAA,EAAU;AAAA,IACxC,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,WAAA,GAAc,IAAA,CAAK,WAAA,CAAY,cAAA,EAAe;AACpD,MAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,QAAA,MAAM,MAAA,GAAS,MAAM,YAAA,CAAa,WAAA,CAAY,KAAK,GAAG,CAAA;AACtD,QAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,UAAA,EAAW;AAAA,MACzC;AACA,MAAA,MAAM,IAAI,WAAW,8CAA8C,CAAA;AAAA,IACrE;AAAA,EACF;AACF","file":"index.cjs","sourcesContent":["/**\n * Error hierarchy for vaultkeeper.\n */\n\n/** Base error for all vaultkeeper errors. */\nexport class VaultError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'VaultError'\n }\n}\n\n// --- Backend Access Failures ---\n\n/**\n * Thrown when the backend keychain or credential store is locked and requires\n * user interaction (e.g. biometric prompt or password entry) before access can\n * be granted.\n */\nexport class BackendLockedError extends VaultError {\n /**\n * Whether the lock can be resolved through an interactive user prompt.\n * When `true`, callers may retry after prompting the user.\n */\n readonly interactive: boolean\n\n constructor(message: string, interactive: boolean) {\n super(message)\n this.name = 'BackendLockedError'\n this.interactive = interactive\n }\n}\n\n/**\n * Thrown when a hardware device (e.g. YubiKey or smart card) required for\n * authentication is not currently connected.\n */\nexport class DeviceNotPresentError extends VaultError {\n /**\n * How long (in milliseconds) the operation waited for the device before\n * giving up.\n */\n readonly timeoutMs: number\n\n constructor(message: string, timeoutMs: number) {\n super(message)\n this.name = 'DeviceNotPresentError'\n this.timeoutMs = timeoutMs\n }\n}\n\n/**\n * Thrown when the user explicitly denies an authorization request for a\n * secret access operation (e.g. cancels an OS permission dialog).\n */\nexport class AuthorizationDeniedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'AuthorizationDeniedError'\n }\n}\n\n/**\n * Thrown when no configured backend is available or reachable.\n * Inspect `reason` for a machine-readable cause and `attempted` for the list\n * of backend types that were tried.\n */\nexport class BackendUnavailableError extends VaultError {\n /**\n * Machine-readable reason code describing why the backend is unavailable\n * (e.g. `'none-enabled'`, `'all-failed'`).\n */\n readonly reason: string\n\n /**\n * The backend type identifiers that were attempted before this error was\n * thrown.\n */\n readonly attempted: string[]\n\n constructor(message: string, reason: string, attempted: string[]) {\n super(message)\n this.name = 'BackendUnavailableError'\n this.reason = reason\n this.attempted = attempted\n }\n}\n\n/**\n * Thrown when a required backend plugin (e.g. a third-party credential\n * manager) is not installed on the current system.\n */\nexport class PluginNotFoundError extends VaultError {\n /**\n * The plugin package or binary name that was not found.\n */\n readonly plugin: string\n\n /**\n * A URL pointing to installation instructions for the missing plugin.\n */\n readonly installUrl: string\n\n constructor(message: string, plugin: string, installUrl: string) {\n super(message)\n this.name = 'PluginNotFoundError'\n this.plugin = plugin\n this.installUrl = installUrl\n }\n}\n\n/**\n * Thrown when a requested secret does not exist in the backend store.\n */\nexport class SecretNotFoundError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'SecretNotFoundError'\n }\n}\n\n// --- JWE Lifecycle Failures ---\n\n/**\n * Thrown when a JWE token has passed its expiration time (`exp` claim).\n */\nexport class TokenExpiredError extends VaultError {\n /**\n * Whether the token can be refreshed by calling `setup()` again.\n * When `true`, the secret still exists in the backend and a new token can be\n * issued.\n */\n readonly canRefresh: boolean\n\n constructor(message: string, canRefresh: boolean) {\n super(message)\n this.name = 'TokenExpiredError'\n this.canRefresh = canRefresh\n }\n}\n\n/**\n * Thrown when the encryption key that was used to create a JWE has since been\n * rotated out of the grace period and can no longer be used for decryption.\n */\nexport class KeyRotatedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'KeyRotatedError'\n }\n}\n\n/**\n * Thrown when the encryption key referenced by a JWE's `kid` header has been\n * explicitly revoked and is no longer available for decryption.\n */\nexport class KeyRevokedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'KeyRevokedError'\n }\n}\n\n/**\n * Thrown when a JWE token has been explicitly blocked (e.g. after a single-use\n * token has already been consumed).\n */\nexport class TokenRevokedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'TokenRevokedError'\n }\n}\n\n/**\n * Thrown when a token with a finite `use` limit has been presented more times\n * than the limit allows.\n */\nexport class UsageLimitExceededError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'UsageLimitExceededError'\n }\n}\n\n// --- Identity and Trust Failures ---\n\n/**\n * Thrown when the hash of an executable no longer matches the previously\n * approved hash stored in the trust manifest (TOFU conflict).\n *\n * Callers must re-approve the executable before a new token can be issued for\n * it.\n */\nexport class IdentityMismatchError extends VaultError {\n /**\n * The hash that was recorded in the trust manifest at approval time.\n */\n readonly previousHash: string\n\n /**\n * The hash computed from the executable at the current moment.\n */\n readonly currentHash: string\n\n constructor(message: string, previousHash: string, currentHash: string) {\n super(message)\n this.name = 'IdentityMismatchError'\n this.previousHash = previousHash\n this.currentHash = currentHash\n }\n}\n\n// --- Infrastructure Failures ---\n\n/**\n * Thrown during initialization when a required system dependency (e.g. OpenSSL\n * or a native credential helper) is missing or incompatible.\n */\nexport class SetupError extends VaultError {\n /**\n * The name of the dependency that caused the setup failure.\n */\n readonly dependency: string\n\n constructor(message: string, dependency: string) {\n super(message)\n this.name = 'SetupError'\n this.dependency = dependency\n }\n}\n\n/**\n * Thrown when a filesystem operation fails due to a permission or access\n * problem (e.g. the config directory is not writable).\n */\nexport class FilesystemError extends VaultError {\n /**\n * The absolute path of the file or directory that caused the error.\n */\n readonly path: string\n\n /**\n * The permission level that was required but not available\n * (e.g. `'read'`, `'write'`, `'execute'`).\n */\n readonly permission: string\n\n constructor(message: string, filePath: string, permission: string) {\n super(message)\n this.name = 'FilesystemError'\n this.path = filePath\n this.permission = permission\n }\n}\n\n/**\n * Thrown when a key rotation is requested while a previous rotation is still\n * within its grace period (i.e. the previous key has not yet been retired).\n */\nexport class RotationInProgressError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'RotationInProgressError'\n }\n}\n","/**\n * Registry for secret backend implementations.\n *\n * @remarks\n * The registry maintains a mapping of backend types to factory functions,\n * allowing dynamic creation of backends based on configuration.\n */\n\nimport type { SecretBackend, BackendFactory } from './types.js'\nimport { BackendUnavailableError } from '../errors.js'\n\n/**\n * Registry for secret backend implementations.\n *\n * @remarks\n * The registry allows registration of custom backends and provides\n * a factory method to create backend instances from a type string.\n *\n * Note: This class is used as a namespace for static methods.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class BackendRegistry {\n private static backends = new Map<string, BackendFactory>()\n\n /**\n * Register a backend factory.\n * @param type - Backend type identifier\n * @param factory - Factory function to create backend instances\n */\n static register(type: string, factory: BackendFactory): void {\n this.backends.set(type, factory)\n }\n\n /**\n * Create a backend instance by type.\n * @param type - Backend type identifier\n * @returns A SecretBackend instance\n * @throws Error if the backend type is not registered\n */\n static create(type: string): SecretBackend {\n const factory = this.backends.get(type)\n if (factory === undefined) {\n throw new BackendUnavailableError(\n `Unknown backend type: ${type}. ` +\n `Available types: ${Array.from(this.backends.keys()).join(', ')}`,\n 'unknown-type',\n Array.from(this.backends.keys()),\n )\n }\n return factory()\n }\n\n /**\n * Get all registered backend type identifiers.\n * @returns Array of backend type identifiers\n */\n static getTypes(): string[] {\n return Array.from(this.backends.keys())\n }\n}\n","/**\n * CLI spawn wrapper for executing external commands.\n */\n\nimport { spawn } from 'node:child_process'\n\n/** Options for command execution. */\nexport interface ExecCommandOptions {\n /** Input to write to stdin */\n stdin?: string | undefined\n /** Timeout in milliseconds */\n timeoutMs?: number | undefined\n}\n\n/** Result of a command execution. */\nexport interface ExecCommandResult {\n stdout: string\n stderr: string\n exitCode: number\n}\n\n/**\n * Execute a command and return stdout.\n * @throws Error if the command exits with a non-zero code.\n */\nexport async function execCommand(\n command: string,\n args: string[],\n options?: ExecCommandOptions,\n): Promise<string> {\n const result = await execCommandFull(command, args, options)\n if (result.exitCode !== 0) {\n throw new Error(`Command failed with exit code ${String(result.exitCode)}: ${result.stderr}`)\n }\n return result.stdout.trim()\n}\n\n/**\n * Execute a command and return the full result.\n */\nexport function execCommandFull(\n command: string,\n args: string[],\n options?: ExecCommandOptions,\n): Promise<ExecCommandResult> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, {\n stdio: [options?.stdin !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],\n })\n let stdout = ''\n let stderr = ''\n\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n if (options?.stdin !== undefined && proc.stdin) {\n proc.stdin.write(options.stdin)\n proc.stdin.end()\n }\n\n if (options?.timeoutMs !== undefined) {\n setTimeout(() => {\n proc.kill('SIGTERM')\n reject(new Error(`Command timed out after ${String(options.timeoutMs)}ms`))\n }, options.timeoutMs)\n }\n\n proc.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code ?? 1 })\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * Encrypted file fallback backend implementation.\n *\n * @remarks\n * Stores secrets encrypted with AES-256-GCM using Node.js native crypto.\n * Each secret is stored as an individual encrypted file under\n * ~/.vaultkeeper/file/. A randomly generated key stored in a protected\n * file is used for encryption.\n *\n * Encrypted file format (all parts base64-encoded, colon-separated):\n * <iv>:<authTag>:<ciphertext>\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport * as crypto from 'node:crypto'\nimport { SecretNotFoundError, FilesystemError } from '../errors.js'\nimport type { SecretBackend } from './types.js'\n\nconst STORAGE_DIR_NAME = path.join('.vaultkeeper', 'file')\nconst KEY_FILE = '.key'\nconst GCM_IV_BYTES = 12\nconst GCM_KEY_BYTES = 32\nconst GCM_TAG_LENGTH = 128 // bits\n\nfunction getStorageDir(): string {\n return path.join(os.homedir(), STORAGE_DIR_NAME)\n}\n\nfunction getEntryPath(storageDir: string, id: string): string {\n const safeId = Buffer.from(id, 'utf8').toString('hex')\n return path.join(storageDir, `${safeId}.enc`)\n}\n\nasync function ensureStorageDir(storageDir: string): Promise<void> {\n try {\n await fs.mkdir(storageDir, { recursive: true, mode: 0o700 })\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code !== 'EEXIST') {\n throw new FilesystemError(\n `Failed to create storage directory: ${storageDir}`,\n storageDir,\n 'rwx',\n )\n }\n }\n}\n\nasync function getOrCreateKey(storageDir: string): Promise<Buffer> {\n const keyPath = path.join(storageDir, KEY_FILE)\n try {\n const data = await fs.readFile(keyPath)\n return data\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n // Generate a random 32-byte key\n const key = crypto.randomBytes(GCM_KEY_BYTES)\n await fs.writeFile(keyPath, key, { mode: 0o600 })\n return key\n }\n throw err\n }\n}\n\nfunction encryptGcm(key: Buffer, plaintext: string): string {\n const iv = crypto.randomBytes(GCM_IV_BYTES)\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH / 8,\n })\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])\n const authTag = cipher.getAuthTag()\n return [iv.toString('base64'), authTag.toString('base64'), encrypted.toString('base64')].join(':')\n}\n\nfunction decryptGcm(key: Buffer, encoded: string): string {\n const parts = encoded.split(':')\n if (parts.length !== 3) {\n throw new Error('Invalid encrypted file format: expected iv:authTag:ciphertext')\n }\n const [ivB64, authTagB64, ciphertextB64] = parts\n if (ivB64 === undefined || authTagB64 === undefined || ciphertextB64 === undefined) {\n throw new Error('Invalid encrypted file format: missing part')\n }\n const iv = Buffer.from(ivB64, 'base64')\n const authTag = Buffer.from(authTagB64, 'base64')\n const ciphertext = Buffer.from(ciphertextB64, 'base64')\n\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH / 8,\n })\n decipher.setAuthTag(authTag)\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])\n return decrypted.toString('utf8')\n}\n\n/**\n * Encrypted file fallback backend.\n *\n * @remarks\n * Available on all platforms. Stores secrets as AES-256-GCM encrypted files\n * using Node.js native crypto — no external tools required.\n * Not as secure as OS-native keystores, but provides a portable fallback.\n *\n * @internal\n */\nexport class FileBackend implements SecretBackend {\n readonly type = 'file'\n readonly displayName = 'Encrypted File Store'\n\n async isAvailable(): Promise<boolean> {\n // Node.js crypto is always available; check we can create the storage dir.\n try {\n const storageDir = getStorageDir()\n await ensureStorageDir(storageDir)\n return true\n } catch {\n return false\n }\n }\n\n async store(id: string, secret: string): Promise<void> {\n const storageDir = getStorageDir()\n await ensureStorageDir(storageDir)\n const key = await getOrCreateKey(storageDir)\n const entryPath = getEntryPath(storageDir, id)\n const encrypted = encryptGcm(key, secret)\n await fs.writeFile(entryPath, encrypted, { mode: 0o600 })\n }\n\n async retrieve(id: string): Promise<string> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n let encoded: string\n try {\n encoded = await fs.readFile(entryPath, 'utf8')\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in file store: ${id}`)\n }\n throw err\n }\n\n const key = await getOrCreateKey(storageDir)\n try {\n return decryptGcm(key, encoded)\n } catch (err) {\n throw new Error(\n `Failed to decrypt secret: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n async delete(id: string): Promise<void> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.unlink(entryPath)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in file store: ${id}`)\n }\n throw err\n }\n }\n\n async exists(id: string): Promise<boolean> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n return true\n } catch {\n return false\n }\n }\n}\n","/**\n * YubiKey backend implementation.\n *\n * @remarks\n * Stores secrets protected by a YubiKey using the `ykman` CLI tool.\n * Secrets are encrypted using the YubiKey's OATH TOTP/HOTP module\n * or PIV slot for hardware-backed protection.\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport { execCommand, execCommandFull } from '../util/exec.js'\nimport { SecretNotFoundError, PluginNotFoundError, DeviceNotPresentError } from '../errors.js'\nimport type { SecretBackend } from './types.js'\n\nconst YKMAN_INSTALL_URL = 'https://developers.yubico.com/yubikey-manager/'\nconst STORAGE_DIR_NAME = path.join('.vaultkeeper', 'yubikey')\nconst METADATA_FILE = 'metadata.json'\nconst DEVICE_TIMEOUT_MS = 5000\n\ninterface YubikeyMetadata {\n entries: Record<string, string>\n}\n\nfunction getStorageDir(): string {\n return path.join(os.homedir(), STORAGE_DIR_NAME)\n}\n\nfunction getEntryPath(storageDir: string, id: string): string {\n const safeId = Buffer.from(id, 'utf8').toString('hex')\n return path.join(storageDir, `${safeId}.enc`)\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n if (value === null || typeof value !== 'object') {\n return false\n }\n return Object.values(value).every((v) => typeof v === 'string')\n}\n\nasync function loadMetadata(storageDir: string): Promise<YubikeyMetadata> {\n const metaPath = path.join(storageDir, METADATA_FILE)\n try {\n const raw = await fs.readFile(metaPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n 'entries' in parsed &&\n isStringRecord(parsed.entries)\n ) {\n return { entries: parsed.entries }\n }\n return { entries: {} }\n } catch {\n return { entries: {} }\n }\n}\n\nasync function saveMetadata(storageDir: string, metadata: YubikeyMetadata): Promise<void> {\n const metaPath = path.join(storageDir, METADATA_FILE)\n await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), { mode: 0o600 })\n}\n\n/**\n * YubiKey backend via `ykman` CLI.\n *\n * @remarks\n * Requires ykman to be installed and a YubiKey to be connected.\n * Secrets are stored in files encrypted using the YubiKey's challenge-response\n * capability (HMAC-SHA1) via slot 2.\n *\n * @internal\n */\nexport class YubikeyBackend implements SecretBackend {\n readonly type = 'yubikey'\n readonly displayName = 'YubiKey'\n\n async isAvailable(): Promise<boolean> {\n try {\n const result = await execCommandFull('ykman', ['--version'])\n if (result.exitCode !== 0) {\n return false\n }\n // Also verify a YubiKey is connected\n const listResult = await execCommandFull('ykman', ['list'])\n return listResult.exitCode === 0 && listResult.stdout.trim() !== ''\n } catch {\n return false\n }\n }\n\n private async requireDevice(): Promise<void> {\n const available = await this.isAvailable()\n if (!available) {\n const hasYkman = await execCommandFull('ykman', ['--version']).then(\n (r) => r.exitCode === 0,\n () => false,\n )\n if (!hasYkman) {\n throw new PluginNotFoundError('ykman is not installed', 'ykman', YKMAN_INSTALL_URL)\n }\n throw new DeviceNotPresentError('No YubiKey device detected', DEVICE_TIMEOUT_MS)\n }\n }\n\n async store(id: string, secret: string): Promise<void> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n await fs.mkdir(storageDir, { recursive: true, mode: 0o700 })\n\n // Use ykman's OATH module to store a TOTP entry as the challenge key,\n // and store the actual secret encrypted with challenge-response in a file.\n // For a pragmatic implementation: use challenge-response slot 2 to derive\n // a key, then encrypt the secret with openssl using that key.\n const challenge = Buffer.from(`vaultkeeper:${id}`, 'utf8').toString('hex')\n const responseResult = await execCommandFull('ykman', [\n 'otp',\n 'calculate',\n '2',\n challenge,\n ])\n\n if (responseResult.exitCode !== 0) {\n throw new Error(`YubiKey challenge-response failed: ${responseResult.stderr}`)\n }\n\n const derivedKey = responseResult.stdout.trim()\n const entryPath = getEntryPath(storageDir, id)\n\n // Pass the derived key via stdin to avoid exposing it in the process table.\n // Input to openssl enc is read from stdin when -pass stdin is used;\n // we prepend the passphrase line followed by the secret via a two-pass approach.\n // openssl -pass stdin reads the first line as the passphrase and the rest as data.\n await execCommand(\n 'openssl',\n ['enc', '-aes-256-cbc', '-pbkdf2', '-pass', 'stdin', '-out', entryPath],\n { stdin: `${derivedKey}\\n${secret}` },\n )\n\n const metadata = await loadMetadata(storageDir)\n metadata.entries[id] = entryPath\n await saveMetadata(storageDir, metadata)\n }\n\n async retrieve(id: string): Promise<string> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n } catch {\n throw new SecretNotFoundError(`Secret not found in YubiKey store: ${id}`)\n }\n\n const challenge = Buffer.from(`vaultkeeper:${id}`, 'utf8').toString('hex')\n const responseResult = await execCommandFull('ykman', [\n 'otp',\n 'calculate',\n '2',\n challenge,\n ])\n\n if (responseResult.exitCode !== 0) {\n throw new Error(`YubiKey challenge-response failed: ${responseResult.stderr}`)\n }\n\n const derivedKey = responseResult.stdout.trim()\n\n // Pass the derived key via stdin to avoid exposing it in the process table.\n const result = await execCommandFull('openssl', [\n 'enc',\n '-d',\n '-aes-256-cbc',\n '-pbkdf2',\n '-pass',\n 'stdin',\n '-in',\n entryPath,\n ], { stdin: `${derivedKey}\\n` })\n\n if (result.exitCode !== 0) {\n throw new Error(`Failed to decrypt YubiKey-protected secret: ${result.stderr}`)\n }\n\n return result.stdout\n }\n\n async delete(id: string): Promise<void> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.unlink(entryPath)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in YubiKey store: ${id}`)\n }\n throw err\n }\n\n const metadata = await loadMetadata(storageDir)\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete metadata.entries[id]\n await saveMetadata(storageDir, metadata)\n }\n\n async exists(id: string): Promise<boolean> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n return true\n } catch {\n return false\n }\n }\n}\n","/**\n * Executable hashing utilities.\n */\n\nimport * as crypto from 'node:crypto'\nimport * as fs from 'node:fs'\n\n/**\n * Compute the SHA-256 digest of the file at `filePath`.\n *\n * @param filePath - Absolute or relative path to the binary to hash.\n * @returns Hex-encoded SHA-256 digest string.\n * @internal\n */\nexport function hashExecutable(filePath: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const hash = crypto.createHash('sha256')\n const stream = fs.createReadStream(filePath)\n\n stream.on('data', (chunk: Buffer | string) => {\n hash.update(chunk)\n })\n\n stream.on('end', () => {\n resolve(hash.digest('hex'))\n })\n\n stream.on('error', (err: Error) => {\n reject(err)\n })\n })\n}\n","/**\n * Trust manifest management — load, save, and query approved executable hashes.\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport type { TrustManifest, TrustManifestEntry } from './types.js'\n\nconst MANIFEST_FILENAME = 'trust-manifest.json'\n\n/** Raw shape persisted to disk (plain object, not a Map). */\ninterface RawManifest {\n version: number\n entries: Record<string, TrustManifestEntry>\n}\n\n/**\n * Type guard that checks `value` is an object with a `version: number` and\n * `entries` object property, matching {@link RawManifest}.\n *\n * We avoid type assertions by narrowing through the `in` operator and\n * `typeof` checks. The discriminated union `unknown → object` chain lets\n * TypeScript track narrowness without any `as` casts.\n */\nfunction isRawManifest(value: unknown): value is RawManifest {\n if (typeof value !== 'object' || value === null) return false\n if (!('version' in value) || typeof value.version !== 'number') return false\n if (!('entries' in value) || typeof value.entries !== 'object' || value.entries === null) return false\n return true\n}\n\n/**\n * Type guard for a single {@link TrustManifestEntry}.\n */\nfunction isTrustManifestEntry(value: unknown): value is TrustManifestEntry {\n if (typeof value !== 'object' || value === null) return false\n if (!('hashes' in value) || !Array.isArray(value.hashes)) return false\n if (!('trustTier' in value)) return false\n const { trustTier } = value\n if (trustTier !== 1 && trustTier !== 2 && trustTier !== 3) return false\n return true\n}\n\n/**\n * Load the trust manifest from `configDir`.\n * Returns an empty `Map` if the manifest file does not yet exist.\n * @internal\n */\nexport async function loadManifest(configDir: string): Promise<TrustManifest> {\n const manifestPath = path.join(configDir, MANIFEST_FILENAME)\n let rawText: string\n try {\n rawText = await fs.readFile(manifestPath, 'utf8')\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n err.code === 'ENOENT'\n ) {\n return new Map()\n }\n throw err\n }\n\n const parsed: unknown = JSON.parse(rawText)\n\n if (!isRawManifest(parsed)) {\n return new Map()\n }\n\n const manifest: TrustManifest = new Map()\n for (const [namespace, entry] of Object.entries(parsed.entries)) {\n if (isTrustManifestEntry(entry)) {\n manifest.set(namespace, { hashes: [...entry.hashes], trustTier: entry.trustTier })\n }\n }\n return manifest\n}\n\n/**\n * Persist `manifest` to `configDir`, creating the directory if necessary.\n * @internal\n */\nexport async function saveManifest(configDir: string, manifest: TrustManifest): Promise<void> {\n await fs.mkdir(configDir, { recursive: true })\n const entries: Record<string, TrustManifestEntry> = {}\n for (const [namespace, entry] of manifest) {\n entries[namespace] = entry\n }\n const raw: RawManifest = { version: 1, entries }\n const manifestPath = path.join(configDir, MANIFEST_FILENAME)\n await fs.writeFile(manifestPath, JSON.stringify(raw, null, 2), 'utf8')\n}\n\n/**\n * Return a new manifest that includes `hash` under `namespace`.\n * If the namespace does not yet exist it is created with tier 3 (Unverified).\n * The trust tier of an existing entry is not changed.\n * @internal\n */\nexport function addTrustedHash(manifest: TrustManifest, namespace: string, hash: string): TrustManifest {\n const next = new Map(manifest)\n const existing = next.get(namespace)\n if (existing === undefined) {\n next.set(namespace, { hashes: [hash], trustTier: 3 })\n } else if (!existing.hashes.includes(hash)) {\n next.set(namespace, { hashes: [...existing.hashes, hash], trustTier: existing.trustTier })\n }\n return next\n}\n\n/**\n * Return `true` if `hash` is in the approved list for `namespace`.\n * @internal\n */\nexport function isTrusted(manifest: TrustManifest, namespace: string, hash: string): boolean {\n const entry = manifest.get(namespace)\n if (entry === undefined) return false\n return entry.hashes.includes(hash)\n}\n","/**\n * Trust classification for executables.\n *\n * Tier 1 — Sigstore: cryptographic provenance verified via Sigstore (lazy import).\n * Tier 2 — Registry: hash found in the approved trust manifest.\n * Tier 3 — Unverified: default fallback when no stronger evidence is available.\n *\n * TOFU (Trust On First Use): on the first encounter with an executable the hash\n * is recorded. If the hash changes on a subsequent call a `tofuConflict` is\n * signalled so the caller can prompt for re-approval.\n *\n * Dev-mode bypass: when the executable path is the literal string `\"dev\"` all\n * hash verification is skipped and Tier 3 unverified is returned immediately.\n */\n\nimport { hashExecutable } from './hash.js'\nimport { loadManifest, saveManifest, addTrustedHash, isTrusted } from './manifest.js'\nimport type { TrustVerificationResult, TrustOptions } from './types.js'\n\n/** Attempt Sigstore bundle verification (Tier 1). Returns `true` on success. */\nasync function trySigstore(execPath: string): Promise<boolean> {\n try {\n // Dynamic import so the library works without sigstore installed.\n // @ts-expect-error — sigstore is an optional peer dependency not listed in\n // package.json; the import will fail at runtime if not installed, which is\n // the intended behaviour. We catch that case below.\n const sigstore: unknown = await import('sigstore')\n // sigstore.verify expects a bundle; for executable verification we check\n // whether the library is present and functional. If the import succeeds but\n // the verify function is not available we fall through gracefully.\n if (typeof sigstore !== 'object' || sigstore === null) {\n return false\n }\n if (!('verify' in sigstore) || typeof sigstore.verify !== 'function') {\n return false\n }\n // Executable bundles are not universally available; treat any error as a\n // Tier-1 failure rather than a hard error.\n void execPath // execPath would be used in a full Sigstore bundle lookup\n return false // Full Sigstore bundle verification not yet available for arbitrary binaries\n } catch {\n return false\n }\n}\n\n/**\n * Verify the trust tier of the executable at `execPath`.\n *\n * @param execPath - Path to the executable, or `\"dev\"` to enable dev-mode bypass.\n * @param options - Optional trust configuration.\n * @internal\n */\nexport async function verifyTrust(\n execPath: string,\n options?: TrustOptions,\n): Promise<TrustVerificationResult> {\n // Dev-mode bypass: skip all verification for the sentinel value \"dev\".\n if (execPath === 'dev') {\n return {\n identity: { hash: 'dev', trustTier: 3, verified: false },\n tofuConflict: false,\n reason: 'Dev mode — hash verification skipped',\n }\n }\n\n const configDir = options?.configDir ?? '.vaultkeeper'\n const namespace = options?.namespace ?? execPath\n\n // Compute the current hash of the executable.\n const currentHash = await hashExecutable(execPath)\n\n // Load the manifest for TOFU and registry checks.\n const manifest = await loadManifest(configDir)\n\n // --- Tier 1: Sigstore ---\n if (options?.skipSigstore !== true) {\n const sigstoreVerified = await trySigstore(execPath)\n if (sigstoreVerified) {\n const updated = addTrustedHash(manifest, namespace, currentHash)\n await saveManifest(configDir, updated)\n return {\n identity: { hash: currentHash, trustTier: 1, verified: true },\n tofuConflict: false,\n reason: 'Sigstore bundle verified',\n }\n }\n }\n\n // --- Tier 2: Registry (manifest) ---\n if (isTrusted(manifest, namespace, currentHash)) {\n return {\n identity: { hash: currentHash, trustTier: 2, verified: true },\n tofuConflict: false,\n reason: 'Hash found in trust manifest',\n }\n }\n\n // --- TOFU check ---\n const existing = manifest.get(namespace)\n if (existing !== undefined && existing.hashes.length > 0) {\n // The namespace is known but the current hash is not approved — TOFU conflict.\n return {\n identity: { hash: currentHash, trustTier: 3, verified: false },\n tofuConflict: true,\n reason: `Hash changed from a previously approved value — re-approval required`,\n }\n }\n\n // --- Tier 3: First encounter — record via TOFU ---\n const updated = addTrustedHash(manifest, namespace, currentHash)\n await saveManifest(configDir, updated)\n return {\n identity: { hash: currentHash, trustTier: 3, verified: false },\n tofuConflict: false,\n reason: 'First encounter — hash recorded via TOFU',\n }\n}\n","/**\n * Capability token management.\n *\n * Tokens are backed by a `WeakMap` whose keys are `CapabilityToken` instances,\n * so the actual claims are never reachable from outside this module. Private\n * class fields enforce that no property on the token object leaks data.\n */\n\nimport type { VaultClaims } from './types.js'\nimport { AuthorizationDeniedError } from '../errors.js'\n\n/** Opaque capability token. Claims are inaccessible without `validateCapabilityToken`. */\nexport class CapabilityToken {\n // Private field ensures no public surface leaks claims.\n readonly #brand: symbol\n\n constructor() {\n this.#brand = Symbol('CapabilityToken')\n }\n\n /**\n * Return a non-enumerable identifier for debugging purposes only.\n * Does NOT expose claims.\n */\n toString(): string {\n return `[CapabilityToken ${this.#brand.toString()}]`\n }\n}\n\n/** Internal storage for claims — inaccessible outside the module closure. */\nconst claimsStore = new WeakMap<CapabilityToken, VaultClaims>()\n\n/**\n * Create a capability token that wraps `claims`.\n * The claims are stored in a module-private `WeakMap` and cannot be reached\n * without calling `validateCapabilityToken`.\n * @internal\n */\nexport function createCapabilityToken(claims: VaultClaims): CapabilityToken {\n const token = new CapabilityToken()\n claimsStore.set(token, claims)\n return token\n}\n\n/**\n * Retrieve the `VaultClaims` associated with `token`.\n *\n * @throws {AuthorizationDeniedError} if the token was not created by\n * `createCapabilityToken` in this module (i.e. it has no claims entry\n * in the store).\n * @internal\n */\nexport function validateCapabilityToken(token: CapabilityToken): VaultClaims {\n const claims = claimsStore.get(token)\n if (claims === undefined) {\n throw new AuthorizationDeniedError('Invalid or unrecognized capability token')\n }\n return claims\n}\n","/**\n * Configuration loading, validation, and defaults for vaultkeeper.\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport type { VaultConfig, BackendConfig, TrustTier } from './types.js'\n\n/**\n * Return the platform-appropriate default config directory.\n * @internal\n */\nexport function getDefaultConfigDir(): string {\n if (process.platform === 'win32') {\n const appData = process.env.APPDATA\n if (appData !== undefined) {\n return path.join(appData, 'vaultkeeper')\n }\n return path.join(os.homedir(), 'AppData', 'Roaming', 'vaultkeeper')\n }\n return path.join(os.homedir(), '.config', 'vaultkeeper')\n}\n\n/** Default configuration when no config file exists. */\nfunction defaultConfig(): VaultConfig {\n return {\n version: 1,\n backends: [{ type: 'file', enabled: true }],\n keyRotation: { gracePeriodDays: 7 },\n defaults: { ttlMinutes: 60, trustTier: 3 },\n }\n}\n\n/**\n * Type guard for plain objects.\n */\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Validates a backend config entry.\n */\nfunction validateBackendEntry(entry: unknown, index: number): BackendConfig {\n if (!isObject(entry)) {\n throw new Error(`backends[${String(index)}] must be an object`)\n }\n if (typeof entry.type !== 'string' || entry.type.trim() === '') {\n throw new Error(`backends[${String(index)}].type must be a non-empty string`)\n }\n if (typeof entry.enabled !== 'boolean') {\n throw new Error(`backends[${String(index)}].enabled must be a boolean`)\n }\n\n const result: BackendConfig = {\n type: entry.type,\n enabled: entry.enabled,\n }\n\n if (entry.plugin !== undefined) {\n if (typeof entry.plugin !== 'boolean') {\n throw new Error(`backends[${String(index)}].plugin must be a boolean`)\n }\n result.plugin = entry.plugin\n }\n\n if (entry.path !== undefined) {\n if (typeof entry.path !== 'string') {\n throw new Error(`backends[${String(index)}].path must be a string`)\n }\n result.path = entry.path\n }\n\n return result\n}\n\n/**\n * Validate an unknown value as a VaultConfig, throwing on invalid structure.\n * @internal\n */\nexport function validateConfig(config: unknown): VaultConfig {\n if (!isObject(config)) {\n throw new Error('Config must be an object')\n }\n\n if (typeof config.version !== 'number' || config.version !== 1) {\n throw new Error('Config version must be 1')\n }\n\n if (!Array.isArray(config.backends) || config.backends.length === 0) {\n throw new Error('Config must have at least one backend')\n }\n\n const backends: BackendConfig[] = config.backends.map((entry: unknown, i: number) =>\n validateBackendEntry(entry, i),\n )\n\n if (!isObject(config.keyRotation)) {\n throw new Error('Config keyRotation must be an object')\n }\n if (\n typeof config.keyRotation.gracePeriodDays !== 'number' ||\n config.keyRotation.gracePeriodDays <= 0\n ) {\n throw new Error('Config keyRotation.gracePeriodDays must be a positive number')\n }\n\n if (!isObject(config.defaults)) {\n throw new Error('Config defaults must be an object')\n }\n if (typeof config.defaults.ttlMinutes !== 'number' || config.defaults.ttlMinutes <= 0) {\n throw new Error('Config defaults.ttlMinutes must be a positive number')\n }\n const tier = config.defaults.trustTier\n if (tier !== 1 && tier !== 2 && tier !== 3) {\n throw new Error('Config defaults.trustTier must be 1, 2, or 3')\n }\n\n const result: VaultConfig = {\n version: 1,\n backends,\n keyRotation: {\n gracePeriodDays: config.keyRotation.gracePeriodDays,\n },\n defaults: {\n ttlMinutes: config.defaults.ttlMinutes,\n trustTier: tier satisfies TrustTier,\n },\n }\n\n if (config.developmentMode !== undefined) {\n if (!isObject(config.developmentMode)) {\n throw new Error('Config developmentMode must be an object')\n }\n if (!Array.isArray(config.developmentMode.executables)) {\n throw new Error('Config developmentMode.executables must be an array')\n }\n const executables: string[] = []\n for (const [i, exe] of Array.from(config.developmentMode.executables).entries()) {\n if (typeof exe !== 'string') {\n throw new Error(`Config developmentMode.executables[${String(i)}] must be a string`)\n }\n executables.push(exe)\n }\n result.developmentMode = { executables }\n }\n\n return result\n}\n\n/**\n * Load the vaultkeeper config from disk, falling back to defaults if the file\n * does not exist.\n *\n * @param configDir - Directory containing config.json. Defaults to platform-appropriate path.\n * @internal\n */\nexport async function loadConfig(configDir?: string): Promise<VaultConfig> {\n const dir = configDir ?? getDefaultConfigDir()\n const configPath = path.join(dir, 'config.json')\n\n let raw: string\n try {\n raw = await fs.readFile(configPath, 'utf-8')\n } catch {\n return defaultConfig()\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new Error(`Failed to parse config file at ${configPath}`)\n }\n\n return validateConfig(parsed)\n}\n","/**\n * Key management for vaultkeeper, including generation, rotation, revocation,\n * and grace-period tracking.\n */\n\nimport * as crypto from 'node:crypto'\nimport { RotationInProgressError, SetupError } from '../errors.js'\nimport type { KeyMaterial, KeyState } from './types.js'\n\n/**\n * Manage cryptographic keys with rotation and grace-period semantics.\n * @internal\n */\nexport class KeyManager {\n #state: KeyState | undefined = undefined\n #gracePeriodTimer: ReturnType<typeof setTimeout> | undefined = undefined\n #gracePeriodExpiresAt: number | undefined = undefined\n #rotating = false\n\n /** Generate a new 32-byte key with a timestamp-based id. */\n generateKey(): KeyMaterial {\n const randomSuffix = crypto.randomBytes(4).toString('hex')\n return {\n id: `k-${String(Date.now())}-${randomSuffix}`,\n key: new Uint8Array(crypto.randomBytes(32)),\n createdAt: new Date(),\n }\n }\n\n /**\n * Initialize the manager with a freshly generated key.\n * Safe to call multiple times; subsequent calls are no-ops.\n */\n init(): Promise<void> {\n if (this.#state === undefined) {\n this.#state = { current: this.generateKey() }\n }\n return Promise.resolve()\n }\n\n /** Return the current (encryption) key. Throws if not initialized. */\n getCurrentKey(): KeyMaterial {\n const state = this.#requireState()\n return state.current\n }\n\n /**\n * Return the previous key if we are still inside a grace period,\n * otherwise `undefined`.\n */\n getPreviousKey(): KeyMaterial | undefined {\n const state = this.#requireState()\n return state.previous\n }\n\n /**\n * Find a key by its id, searching current then previous.\n * Returns `undefined` if the key is not found (or the previous key's\n * grace period has expired).\n */\n findKeyById(kid: string): KeyMaterial | undefined {\n const state = this.#requireState()\n if (state.current.id === kid) {\n return state.current\n }\n const { previous } = state\n if (previous?.id === kid) {\n // previous?.id === kid is only true when previous is defined and its id\n // matches, so we can safely return it here. TypeScript does not narrow\n // the optional-chain result back to KeyMaterial, so we guard explicitly.\n return previous\n }\n return undefined\n }\n\n /**\n * Rotate the current key: the current key becomes previous, a new key\n * becomes current. A grace-period timer is started; when it fires the\n * previous key is cleared automatically.\n *\n * @throws {RotationInProgressError} if a rotation is already underway.\n */\n rotateKey(gracePeriodMs: number): void {\n if (this.#rotating) {\n throw new RotationInProgressError('A key rotation is already in progress')\n }\n\n const state = this.#requireState()\n this.#rotating = true\n\n // Cancel any existing grace-period timer before starting a new rotation.\n this.#clearGracePeriodTimer()\n\n const newKey = this.generateKey()\n this.#state = { current: newKey, previous: state.current }\n this.#gracePeriodExpiresAt = Date.now() + gracePeriodMs\n\n this.#gracePeriodTimer = setTimeout(() => {\n if (this.#state !== undefined) {\n // Remove the previous key once the grace period elapses.\n this.#state = { current: this.#state.current }\n }\n this.#gracePeriodExpiresAt = undefined\n this.#gracePeriodTimer = undefined\n this.#rotating = false\n }, gracePeriodMs)\n\n // Allow the timer to be GC'd without keeping the process alive.\n if (typeof this.#gracePeriodTimer.unref === 'function') {\n this.#gracePeriodTimer.unref()\n }\n }\n\n /**\n * Emergency revocation: immediately clear the previous key and generate\n * a brand-new current key. Any in-flight grace period is cancelled.\n */\n revokeKey(): void {\n this.#clearGracePeriodTimer()\n this.#rotating = false\n this.#gracePeriodExpiresAt = undefined\n\n const newKey = this.generateKey()\n this.#state = { current: newKey }\n }\n\n /**\n * Return `true` while a rotation grace period is active (i.e. the previous\n * key is still accessible).\n */\n isInGracePeriod(): boolean {\n if (this.#gracePeriodExpiresAt === undefined) {\n return false\n }\n return Date.now() < this.#gracePeriodExpiresAt\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n #requireState(): KeyState {\n if (this.#state === undefined) {\n throw new SetupError(\n 'KeyManager has not been initialized — call init() first',\n 'KeyManager',\n )\n }\n return this.#state\n }\n\n #clearGracePeriodTimer(): void {\n if (this.#gracePeriodTimer !== undefined) {\n clearTimeout(this.#gracePeriodTimer)\n this.#gracePeriodTimer = undefined\n }\n }\n}\n","/**\n * JWE token creation and decryption using `jose` with `dir` + `A256GCM`.\n */\n\nimport { CompactEncrypt, compactDecrypt } from 'jose'\nimport type { VaultClaims } from '../types.js'\nimport { VaultError } from '../errors.js'\n\nconst ALGORITHM = 'dir'\nconst ENCRYPTION = 'A256GCM'\n\n/**\n * Options for token creation.\n * @internal\n */\nexport interface CreateTokenOptions {\n /** Optional key ID to embed in the JWE header for rotation tracking. */\n kid?: string | undefined\n}\n\n/**\n * Creates a compact JWE string from the given claims.\n *\n * Uses `dir` (direct key agreement) with `A256GCM` content encryption.\n * The 256-bit key must be exactly 32 bytes.\n *\n * @param key - 32-byte symmetric key (AES-256)\n * @param claims - VaultClaims payload to encrypt\n * @param options - Optional token creation options\n * @returns Compact JWE string\n * @internal\n */\nexport async function createToken(\n key: Uint8Array,\n claims: VaultClaims,\n options?: CreateTokenOptions,\n): Promise<string> {\n const plaintext = new TextEncoder().encode(JSON.stringify(claims))\n\n const header: { alg: typeof ALGORITHM; enc: typeof ENCRYPTION; kid?: string } = {\n alg: ALGORITHM,\n enc: ENCRYPTION,\n }\n\n if (options?.kid !== undefined) {\n header.kid = options.kid\n }\n\n return new CompactEncrypt(plaintext).setProtectedHeader(header).encrypt(key)\n}\n\n/**\n * Type guard that checks whether an unknown value is a non-null object.\n */\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Parses a raw JSON payload object into VaultClaims, validating that all required fields\n * are present and of the correct types. Returns `undefined` if validation fails.\n */\nfunction parseVaultClaims(raw: unknown): VaultClaims | undefined {\n if (!isObject(raw)) {\n return undefined\n }\n\n const { jti, exp, iat, sub, exe, use, tid, bkd, val, ref } = raw\n\n if (typeof jti !== 'string') return undefined\n if (typeof exp !== 'number') return undefined\n if (typeof iat !== 'number') return undefined\n if (typeof sub !== 'string') return undefined\n if (typeof exe !== 'string') return undefined\n if (use !== null && typeof use !== 'number') return undefined\n if (tid !== 1 && tid !== 2 && tid !== 3) return undefined\n if (typeof bkd !== 'string') return undefined\n if (typeof val !== 'string') return undefined\n if (typeof ref !== 'string') return undefined\n\n return { jti, exp, iat, sub, exe, use: use ?? null, tid, bkd, val, ref }\n}\n\n/**\n * Decrypts a compact JWE string and returns the VaultClaims payload.\n *\n * @param key - 32-byte symmetric key (AES-256)\n * @param jwe - Compact JWE string to decrypt\n * @returns Decrypted VaultClaims\n * @throws VaultError if decryption fails or the payload is malformed\n * @internal\n */\nexport async function decryptToken(key: Uint8Array, jwe: string): Promise<VaultClaims> {\n let plaintext: Uint8Array\n try {\n const result = await compactDecrypt(jwe, key)\n plaintext = result.plaintext\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new VaultError(`JWE decryption failed: ${message}`)\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(new TextDecoder().decode(plaintext))\n } catch {\n throw new VaultError('JWE payload is not valid JSON')\n }\n\n const claims = parseVaultClaims(parsed)\n if (claims === undefined) {\n throw new VaultError('JWE payload does not match VaultClaims schema')\n }\n\n return claims\n}\n\n/**\n * Extracts the `kid` header from a compact JWE without decrypting it.\n *\n * The protected header in compact JWE is the first Base64URL-encoded segment.\n *\n * @param jwe - Compact JWE string\n * @returns The kid value, or undefined if not present\n * @throws VaultError if the JWE structure is invalid\n * @internal\n */\nexport function extractKid(jwe: string): string | undefined {\n const parts = jwe.split('.')\n if (parts.length !== 5) {\n throw new VaultError('Invalid JWE compact serialization: expected 5 parts')\n }\n const headerSegment = parts[0]\n if (headerSegment === undefined || headerSegment === '') {\n throw new VaultError('Invalid JWE compact serialization: missing header segment')\n }\n let headerJson: string\n try {\n headerJson = Buffer.from(headerSegment, 'base64url').toString('utf-8')\n } catch {\n throw new VaultError('Invalid JWE compact serialization: header is not valid Base64URL')\n }\n\n let header: unknown\n try {\n header = JSON.parse(headerJson)\n } catch {\n throw new VaultError('Invalid JWE compact serialization: header is not valid JSON')\n }\n\n if (!isObject(header)) {\n return undefined\n }\n\n const kid = header.kid\n if (typeof kid !== 'string') {\n return undefined\n }\n return kid\n}\n","/**\n * VaultClaims validation and in-memory token blocklist.\n */\n\nimport type { VaultClaims } from '../types.js'\nimport {\n TokenExpiredError,\n TokenRevokedError,\n UsageLimitExceededError,\n VaultError,\n} from '../errors.js'\n\n/**\n * Maximum number of JTIs the in-memory blocklist will retain.\n * When the cap is reached, the oldest inserted entry is evicted (FIFO/LRU).\n * This prevents unbounded growth for long-running processes.\n */\nconst BLOCKLIST_MAX_SIZE = 10_000\n\n/**\n * In-memory blocklist for revoked token JTIs. This is process-local and non-persistent.\n * For production use, a distributed blocklist (e.g., Redis) should be layered on top.\n *\n * A Map is used instead of a Set because Map preserves insertion order, which\n * allows O(1) eviction of the oldest entry (first key in iteration order).\n * The map values are always `true` — only the keys matter for lookup.\n */\nconst blocklist = new Map<string, true>()\n\n/**\n * Adds a JTI to the in-memory blocklist, preventing further use of that token.\n * If the blocklist has reached its maximum size, the oldest entry is evicted first.\n *\n * @param jti - The unique token ID to block\n * @internal\n */\nexport function blockToken(jti: string): void {\n if (blocklist.has(jti)) {\n // Already blocked — re-inserting would not change insertion order in Map,\n // so we delete and re-add to refresh the recency position.\n blocklist.delete(jti)\n } else if (blocklist.size >= BLOCKLIST_MAX_SIZE) {\n // Evict the oldest entry (first key in insertion-order iteration).\n const oldestKey = blocklist.keys().next().value\n if (oldestKey !== undefined) {\n blocklist.delete(oldestKey)\n }\n }\n blocklist.set(jti, true)\n}\n\n/**\n * Returns true if the given JTI has been blocked.\n *\n * @param jti - The unique token ID to check\n * @internal\n */\nexport function isBlocked(jti: string): boolean {\n return blocklist.has(jti)\n}\n\n/**\n * Clears all blocked JTIs from the in-memory blocklist.\n * Primarily intended for use in tests.\n * @internal\n */\nexport function clearBlocklist(): void {\n blocklist.clear()\n}\n\n/**\n * Validates all claims in a VaultClaims payload.\n * @internal\n *\n * Checks performed:\n * - Required fields present (jti, exp, iat, sub, exe, tid, bkd, val, ref)\n * - Token is not expired (exp vs. current time)\n * - Token is not on the blocklist\n * - Usage limit (use) is not exceeded if a positive limit is set\n * - Trust tier (tid) is valid (1, 2, or 3)\n *\n * @param claims - VaultClaims payload to validate\n * @param usedCount - How many times the token has been used already (for `use` limit checking)\n * @throws TokenExpiredError if the token is expired\n * @throws TokenRevokedError if the token has been blocked\n * @throws UsageLimitExceededError if the usage count has been exhausted\n * @throws VaultError for missing or malformed required fields\n */\nexport function validateClaims(claims: VaultClaims, usedCount = 0): void {\n // Validate required string fields are non-empty\n if (claims.jti.trim() === '') {\n throw new VaultError('Invalid token: jti must not be empty')\n }\n if (claims.sub.trim() === '') {\n throw new VaultError('Invalid token: sub must not be empty')\n }\n if (claims.exe.trim() === '') {\n throw new VaultError('Invalid token: exe must not be empty')\n }\n if (claims.bkd.trim() === '') {\n throw new VaultError('Invalid token: bkd must not be empty')\n }\n if (claims.val.trim() === '') {\n throw new VaultError('Invalid token: val must not be empty')\n }\n if (claims.ref.trim() === '') {\n throw new VaultError('Invalid token: ref must not be empty')\n }\n\n // Validate timestamp ordering\n if (claims.iat > claims.exp) {\n throw new VaultError('Invalid token: iat must not be after exp')\n }\n\n // Check expiration\n const nowSec = Math.floor(Date.now() / 1000)\n if (nowSec >= claims.exp) {\n throw new TokenExpiredError(\n `Token expired at ${String(claims.exp)} (now: ${String(nowSec)})`,\n false,\n )\n }\n\n // Check blocklist\n if (isBlocked(claims.jti)) {\n throw new TokenRevokedError(`Token ${claims.jti} has been revoked`)\n }\n\n // Check usage limit\n if (claims.use !== null) {\n if (claims.use <= 0) {\n throw new UsageLimitExceededError(\n `Token ${claims.jti} has a non-positive usage limit: ${String(claims.use)}`,\n )\n }\n if (usedCount >= claims.use) {\n throw new UsageLimitExceededError(\n `Token ${claims.jti} usage limit of ${String(claims.use)} exceeded (used: ${String(usedCount)})`,\n )\n }\n }\n}\n","/**\n * Delegated HTTP fetch access pattern.\n *\n * Replaces `{{secret}}` placeholders in the request URL, headers, and body\n * with the actual secret value, then executes the fetch.\n */\n\nimport type { FetchRequest } from '../types.js'\n\nconst PLACEHOLDER = '{{secret}}'\n\nfunction replacePlaceholder(value: string, secret: string): string {\n return value.replaceAll(PLACEHOLDER, secret)\n}\n\nfunction replaceInRecord(\n record: Record<string, string>,\n secret: string,\n): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = replacePlaceholder(value, secret)\n }\n return result\n}\n\n/**\n * Execute a delegated HTTP fetch with the secret injected into the request.\n *\n * @param secret - The secret value to inject\n * @param request - The fetch request template with `{{secret}}` placeholders\n * @returns The fetch Response\n * @internal\n */\nexport async function delegatedFetch(\n secret: string,\n request: FetchRequest,\n): Promise<Response> {\n const url = replacePlaceholder(request.url, secret)\n const headers =\n request.headers !== undefined\n ? replaceInRecord(request.headers, secret)\n : undefined\n const body =\n request.body !== undefined\n ? replacePlaceholder(request.body, secret)\n : undefined\n\n const init: RequestInit = {}\n if (request.method !== undefined) {\n init.method = request.method\n }\n if (headers !== undefined) {\n init.headers = headers\n }\n if (body !== undefined) {\n init.body = body\n }\n\n return fetch(url, init)\n}\n","/**\n * Delegated command execution access pattern.\n *\n * Replaces `{{secret}}` placeholders in command args and environment values,\n * then executes the command.\n */\n\nimport { spawn } from 'node:child_process'\nimport type { ExecRequest, ExecResult } from '../types.js'\n\nconst PLACEHOLDER = '{{secret}}'\n\nfunction replacePlaceholder(value: string, secret: string): string {\n return value.replaceAll(PLACEHOLDER, secret)\n}\n\nfunction replaceInRecord(\n record: Record<string, string>,\n secret: string,\n): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = replacePlaceholder(value, secret)\n }\n return result\n}\n\n/**\n * Execute a delegated command with the secret injected into args and env.\n *\n * @param secret - The secret value to inject\n * @param request - The exec request template with `{{secret}}` placeholders\n * @returns The command result (stdout, stderr, exitCode)\n * @internal\n */\nexport function delegatedExec(\n secret: string,\n request: ExecRequest,\n): Promise<ExecResult> {\n const args = (request.args ?? []).map((arg) => replacePlaceholder(arg, secret))\n const env =\n request.env !== undefined ? replaceInRecord(request.env, secret) : undefined\n\n return new Promise((resolve, reject) => {\n const spawnOptions: Parameters<typeof spawn>[2] = {\n stdio: ['ignore', 'pipe', 'pipe'],\n }\n if (env !== undefined) {\n spawnOptions.env = { ...process.env, ...env }\n }\n if (request.cwd !== undefined) {\n spawnOptions.cwd = request.cwd\n }\n\n const proc = spawn(request.command, args, spawnOptions)\n let stdout = ''\n let stderr = ''\n\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n proc.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code ?? 1 })\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * Controlled direct access pattern.\n *\n * Provides a `SecretAccessor` backed by a revocable Proxy that:\n * - Exposes a single `.read()` method\n * - Passes a Buffer containing the secret to the callback\n * - Zeros the buffer after the callback returns\n * - Prevents double-read (throws on second call)\n * - Revokes the proxy synchronously after the first `read()` call completes\n * - Redacts itself from Node.js inspect output\n */\n\nimport type { SecretAccessor } from '../types.js'\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom')\n\n/** Extended accessor that also supports custom inspect. */\ninterface SecretAccessorInternal extends SecretAccessor {\n [INSPECT_CUSTOM](): string\n}\n\n/**\n * Proxy target class that satisfies SecretAccessorInternal.\n *\n * Instances have their prototype set to null and are made non-extensible\n * after construction, so all proxy invariants can be met consistently:\n * - getPrototypeOf trap returns null (matches actual prototype)\n * - isExtensible trap returns false (matches actual extensibility)\n * - ownKeys trap includes all own keys (matches non-extensible contract)\n */\nclass SecretAccessorTarget implements SecretAccessorInternal {\n readonly read: (callback: (buf: Buffer) => void) => void\n readonly [INSPECT_CUSTOM]: () => string\n\n constructor(\n readImpl: (callback: (buf: Buffer) => void) => void,\n inspectImpl: () => string,\n ) {\n this.read = readImpl\n this[INSPECT_CUSTOM] = inspectImpl\n }\n}\n\n/**\n * Create a `SecretAccessor` for the given secret value.\n * @internal\n *\n * The accessor is backed by a revocable Proxy with all 13 traps implemented.\n * The proxy is revoked synchronously after the first `read()` call completes\n * (in the `finally` block, after zeroing the buffer). Any subsequent property\n * access will throw a TypeError.\n *\n * This avoids the `queueMicrotask(revoke)` approach which breaks async callers\n * that `await` between receiving the accessor and calling `.read()`.\n */\nexport function createSecretAccessor(secretValue: string): SecretAccessor {\n let consumed = false\n // Holder allows readImpl to close over the revoke function without a let/reassignment.\n const revokeHolder: { fn: (() => void) | undefined } = { fn: undefined }\n\n // Close over the actual read logic.\n function readImpl(callback: (buf: Buffer) => void): void {\n if (consumed) {\n throw new Error('SecretAccessor has already been consumed — call getSecret() again to obtain a new accessor')\n }\n consumed = true\n\n const buf = Buffer.from(secretValue, 'utf8')\n try {\n callback(buf)\n } finally {\n buf.fill(0)\n // Revoke the proxy synchronously so no further property access is possible.\n revokeHolder.fn?.()\n }\n }\n\n function inspectImpl(): string {\n return '[SecretAccessor]'\n }\n\n // Build the proxy target: a class instance with null prototype and\n // non-extensible to satisfy V8's proxy invariants for those traps.\n const target = new SecretAccessorTarget(readImpl, inspectImpl)\n Object.setPrototypeOf(target, null)\n Object.preventExtensions(target)\n\n // All 13 proxy handler traps.\n const handler: Required<ProxyHandler<SecretAccessorInternal>> = {\n get(_t, prop, _receiver) {\n if (prop === 'read') return readImpl\n if (prop === INSPECT_CUSTOM) return inspectImpl\n return undefined\n },\n set(_t, _prop, _value, _receiver) {\n return false\n },\n has(_t, prop) {\n return prop === 'read' || prop === INSPECT_CUSTOM\n },\n deleteProperty(_t, _prop) {\n return false\n },\n apply(_t, _thisArg, _args) {\n throw new TypeError('SecretAccessor is not a function')\n },\n construct(_t, _args, _newTarget) {\n throw new TypeError('SecretAccessor is not a constructor')\n },\n defineProperty(_t, _prop, _descriptor) {\n return false\n },\n getOwnPropertyDescriptor(_t, prop) {\n if (prop === 'read') {\n return { configurable: true, enumerable: true, writable: false, value: readImpl }\n }\n if (prop === INSPECT_CUSTOM) {\n return { configurable: true, enumerable: false, writable: false, value: inspectImpl }\n }\n return undefined\n },\n getPrototypeOf(_t) {\n // Null prototype — matches the actual target prototype after setPrototypeOf(target, null).\n return null\n },\n setPrototypeOf(_t, _proto) {\n return false\n },\n isExtensible(_t) {\n // Non-extensible — matches the actual target extensibility.\n return false\n },\n preventExtensions(_t) {\n // Already non-extensible — trap returns true (success) matching target state.\n return true\n },\n ownKeys(_t) {\n // Must include all own keys of the non-extensible target.\n // The target has 'read' and INSPECT_CUSTOM as own properties.\n return ['read', INSPECT_CUSTOM]\n },\n }\n\n const { proxy, revoke } = Proxy.revocable(target, handler)\n // Wire up the revoke function so readImpl can call it after the callback returns.\n revokeHolder.fn = revoke\n\n return proxy\n}\n","/**\n * Individual preflight check functions for each system dependency.\n */\n\nimport { execCommand } from '../util/exec.js'\nimport type { PreflightCheck } from '../types.js'\n\n/**\n * Parse a semver-like version string and return [major, minor, patch].\n * Returns null if unparseable.\n */\nfunction parseVersion(raw: string): [number, number, number] | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)/.exec(raw)\n if (!match) return null\n const major = parseInt(match[1] ?? '0', 10)\n const minor = parseInt(match[2] ?? '0', 10)\n const patch = parseInt(match[3] ?? '0', 10)\n return [major, minor, patch]\n}\n\n/**\n * Returns true if [aMajor, aMinor, aPatch] >= [bMajor, bMinor, bPatch].\n */\nfunction versionGte(\n a: [number, number, number],\n b: [number, number, number],\n): boolean {\n if (a[0] !== b[0]) return a[0] > b[0]\n if (a[1] !== b[1]) return a[1] > b[1]\n return a[2] >= b[2]\n}\n\n/**\n * Check that openssl is present and >= 1.1.1.\n * @internal\n */\nexport async function checkOpenssl(): Promise<PreflightCheck> {\n const name = 'openssl'\n try {\n const output = await execCommand('openssl', ['version'])\n const parsed = parseVersion(output)\n if (!parsed) {\n return {\n name,\n status: 'version-unsupported',\n version: output,\n reason: 'Could not parse openssl version',\n }\n }\n if (!versionGte(parsed, [1, 1, 1])) {\n return {\n name,\n status: 'version-unsupported',\n version: output,\n reason: 'openssl >= 1.1.1 is required',\n }\n }\n return { name, status: 'ok', version: output }\n } catch {\n return { name, status: 'missing', reason: 'openssl not found in PATH' }\n }\n}\n\n/**\n * Check that bash is present.\n * @internal\n */\nexport async function checkBash(): Promise<PreflightCheck> {\n const name = 'bash'\n try {\n const output = await execCommand('bash', ['--version'])\n const firstLine = output.split('\\n')[0] ?? output\n return { name, status: 'ok', version: firstLine }\n } catch {\n return { name, status: 'missing', reason: 'bash not found in PATH' }\n }\n}\n\n/**\n * Check that PowerShell is present (Windows only).\n * @internal\n */\nexport async function checkPowershell(): Promise<PreflightCheck> {\n const name = 'powershell'\n try {\n const output = await execCommand('powershell', [\n '-Command',\n '$PSVersionTable.PSVersion',\n ])\n const version = output.trim()\n return { name, status: 'ok', version }\n } catch {\n return { name, status: 'missing', reason: 'powershell not found in PATH' }\n }\n}\n\n/**\n * Check that macOS security CLI is present (macOS only, for Keychain access).\n * @internal\n */\nexport async function checkSecurity(): Promise<PreflightCheck> {\n const name = 'security'\n try {\n // `security help` exits with non-zero but writes to stderr; we only need it to exist\n await execCommand('security', ['help'])\n return { name, status: 'ok' }\n } catch (err) {\n // security help exits non-zero intentionally — if we got stderr output, it's present\n const message = err instanceof Error ? err.message : String(err)\n if (message.includes('security')) {\n // The command exists but help exits with a non-zero code\n return { name, status: 'ok' }\n }\n return {\n name,\n status: 'missing',\n reason: 'security command not found in PATH',\n }\n }\n}\n\n/**\n * Check that secret-tool is present (Linux only).\n * @internal\n */\nexport async function checkSecretTool(): Promise<PreflightCheck> {\n const name = 'secret-tool'\n try {\n const output = await execCommand('secret-tool', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'secret-tool not found in PATH (install libsecret-tools)',\n }\n }\n}\n\n/**\n * Check that 1Password CLI (op) is present (optional).\n * @internal\n */\nexport async function checkOp(): Promise<PreflightCheck> {\n const name = 'op'\n try {\n const output = await execCommand('op', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'op (1Password CLI) not found in PATH',\n }\n }\n}\n\n/**\n * Check that ykman (YubiKey Manager CLI) is present (optional).\n * @internal\n */\nexport async function checkYkman(): Promise<PreflightCheck> {\n const name = 'ykman'\n try {\n const output = await execCommand('ykman', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'ykman (YubiKey Manager) not found in PATH',\n }\n }\n}\n","/**\n * Platform detection utilities.\n */\n\n/**\n * @internal\n */\nexport type Platform = 'darwin' | 'win32' | 'linux'\n\n/** Get the current platform. */\nexport function currentPlatform(): Platform {\n const p = process.platform\n if (p === 'darwin' || p === 'win32' || p === 'linux') {\n return p\n }\n throw new Error(`Unsupported platform: ${p}`)\n}\n\n/** Check if running on macOS. */\nexport function isDarwin(): boolean {\n return process.platform === 'darwin'\n}\n\n/** Check if running on Windows. */\nexport function isWindows(): boolean {\n return process.platform === 'win32'\n}\n\n/** Check if running on Linux. */\nexport function isLinux(): boolean {\n return process.platform === 'linux'\n}\n","/**\n * Doctor runner: orchestrates platform-appropriate checks and aggregates results.\n */\n\nimport {\n checkOpenssl,\n checkBash,\n checkPowershell,\n checkSecurity,\n checkSecretTool,\n checkOp,\n checkYkman,\n} from './checks.js'\nimport { currentPlatform } from '../util/platform.js'\nimport type { PreflightCheck, PreflightResult } from '../types.js'\nimport type { Platform } from '../util/platform.js'\n\n/**\n * Options for running the doctor.\n * @internal\n */\nexport interface RunDoctorOptions {\n /** Override the platform detection (useful for testing). */\n platform?: Platform\n}\n\n/** A doctor check entry pairing the check function with whether it is required. */\ninterface CheckEntry {\n check: () => Promise<PreflightCheck>\n required: boolean\n}\n\n/** Aggregated check entry with its result. */\ninterface ResolvedEntry {\n required: boolean\n result: PreflightCheck\n}\n\n/**\n * Run all platform-appropriate preflight checks and aggregate the results.\n * @internal\n */\nexport async function runDoctor(options?: RunDoctorOptions): Promise<PreflightResult> {\n const platform = options?.platform ?? currentPlatform()\n\n const entries: CheckEntry[] = buildCheckList(platform)\n\n const resolved: ResolvedEntry[] = await Promise.all(\n entries.map(async ({ check, required }) => {\n const result = await check()\n return { required, result }\n }),\n )\n\n const ready = resolved.every(({ required, result }) => {\n if (!required) return true\n return result.status === 'ok'\n })\n\n const warnings: string[] = []\n const nextSteps: string[] = []\n\n for (const { required, result } of resolved) {\n if (result.status === 'missing') {\n if (required) {\n nextSteps.push(`Install missing required dependency: ${result.name}`)\n } else {\n warnings.push(\n `Optional dependency not found: ${result.name}${result.reason !== undefined ? ` — ${result.reason}` : ''}`,\n )\n }\n } else if (result.status === 'version-unsupported') {\n const msg = `${result.name} version is unsupported${result.reason !== undefined ? `: ${result.reason}` : ''}`\n if (required) {\n nextSteps.push(`Upgrade required dependency: ${msg}`)\n } else {\n warnings.push(`Optional dependency version unsupported: ${msg}`)\n }\n }\n }\n\n const checks = resolved.map(({ result }) => result)\n\n return { checks, ready, warnings, nextSteps }\n}\n\nfunction buildCheckList(platform: Platform): CheckEntry[] {\n const entries: CheckEntry[] = [{ check: checkOpenssl, required: true }]\n\n if (platform === 'darwin') {\n entries.push({ check: checkSecurity, required: true })\n entries.push({ check: checkBash, required: false })\n } else if (platform === 'win32') {\n entries.push({ check: checkPowershell, required: true })\n } else {\n // linux\n entries.push({ check: checkBash, required: true })\n entries.push({ check: checkSecretTool, required: true })\n }\n\n // Optional tools on all platforms\n entries.push({ check: checkOp, required: false })\n entries.push({ check: checkYkman, required: false })\n\n return entries\n}\n","/**\n * VaultKeeper main class — wires together all vaultkeeper subsystems.\n */\n\nimport * as crypto from 'node:crypto'\nimport type {\n VaultConfig,\n VaultClaims,\n VaultResponse,\n FetchRequest,\n ExecRequest,\n ExecResult,\n SecretAccessor,\n PreflightResult,\n TrustTier,\n} from './types.js'\nimport { loadConfig, getDefaultConfigDir } from './config.js'\nimport { KeyManager } from './keys/manager.js'\nimport { BackendRegistry } from './backend/registry.js'\nimport type { SecretBackend } from './backend/types.js'\nimport { createToken, decryptToken, extractKid, validateClaims, blockToken } from './jwe/index.js'\nimport { verifyTrust } from './identity/trust.js'\nimport {\n CapabilityToken,\n createCapabilityToken,\n validateCapabilityToken,\n} from './identity/session.js'\nimport { delegatedFetch } from './access/delegated-fetch.js'\nimport { delegatedExec } from './access/delegated-exec.js'\nimport { createSecretAccessor } from './access/controlled-direct.js'\nimport { runDoctor } from './doctor/runner.js'\nimport {\n IdentityMismatchError,\n BackendUnavailableError,\n VaultError,\n KeyRevokedError,\n} from './errors.js'\n\n/** Options for initializing VaultKeeper. */\nexport interface VaultKeeperOptions {\n /** Override the config directory. */\n configDir?: string | undefined\n /** Supply config directly, skipping file load. */\n config?: VaultConfig | undefined\n /** Skip the doctor preflight check. */\n skipDoctor?: boolean | undefined\n}\n\n/** Options for the setup operation. */\nexport interface SetupOptions {\n /** TTL in minutes for the JWE. */\n ttlMinutes?: number | undefined\n /** Usage limit (null for unlimited). */\n useLimit?: number | null | undefined\n /** Executable path for identity binding. Use \"dev\" for dev mode. */\n executablePath?: string | undefined\n /** Trust tier override. */\n trustTier?: TrustTier | undefined\n /** Backend type to use. */\n backendType?: string | undefined\n}\n\n/** Usage tracking for tokens with use limits. */\nconst usageCounts = new Map<string, number>()\n\n/**\n * Main entry point for vaultkeeper. Orchestrates backends, keys, JWE tokens,\n * identity verification, and access patterns.\n */\nexport class VaultKeeper {\n readonly #config: VaultConfig\n readonly #keyManager: KeyManager\n readonly #configDir: string\n #backend: SecretBackend | undefined\n\n private constructor(config: VaultConfig, keyManager: KeyManager, configDir: string) {\n this.#config = config\n this.#keyManager = keyManager\n this.#configDir = configDir\n }\n\n /**\n * Initialize a new VaultKeeper instance.\n * Runs doctor checks (unless skipped), loads config, and sets up the key manager.\n */\n static async init(options?: VaultKeeperOptions): Promise<VaultKeeper> {\n if (options?.skipDoctor !== true) {\n const doctorResult = await runDoctor()\n if (!doctorResult.ready) {\n throw new VaultError(\n `System not ready: ${doctorResult.nextSteps.join('; ')}`,\n )\n }\n }\n\n const configDir = options?.configDir ?? getDefaultConfigDir()\n const config = options?.config ?? (await loadConfig(configDir))\n\n const keyManager = new KeyManager()\n await keyManager.init()\n\n const vault = new VaultKeeper(config, keyManager, configDir)\n vault.#backend = vault.#resolveBackend()\n\n return vault\n }\n\n /** Run doctor checks without full initialization. */\n static async doctor(): Promise<PreflightResult> {\n return runDoctor()\n }\n\n /**\n * Store a secret and return a JWE token that encapsulates it.\n *\n * @param secretName - Identifier for the secret\n * @param options - Setup options\n * @returns Compact JWE string\n */\n async setup(secretName: string, options?: SetupOptions): Promise<string> {\n const backend = this.#requireBackend()\n const backendType = options?.backendType ?? backend.type\n const ttlMinutes = options?.ttlMinutes ?? this.#config.defaults.ttlMinutes\n const trustTier = options?.trustTier ?? this.#config.defaults.trustTier\n const useLimit = options?.useLimit ?? null\n const executablePath = options?.executablePath ?? 'dev'\n\n const secretValue = await backend.retrieve(secretName)\n\n let exeIdentity: string\n if (executablePath === 'dev' || this.#isDevModeExecutable(executablePath)) {\n exeIdentity = 'dev'\n } else {\n const trustResult = await verifyTrust(executablePath, {\n configDir: this.#configDir,\n })\n if (trustResult.tofuConflict) {\n throw new IdentityMismatchError(\n 'Executable hash changed — re-approval required',\n 'previously-approved',\n trustResult.identity.hash,\n )\n }\n exeIdentity = trustResult.identity.hash\n }\n\n const now = Math.floor(Date.now() / 1000)\n const claims: VaultClaims = {\n jti: crypto.randomUUID(),\n exp: now + ttlMinutes * 60,\n iat: now,\n sub: secretName,\n exe: exeIdentity,\n use: useLimit,\n tid: trustTier,\n bkd: backendType,\n val: secretValue,\n ref: secretName,\n }\n\n const currentKey = this.#keyManager.getCurrentKey()\n return createToken(currentKey.key, claims, { kid: currentKey.id })\n }\n\n /**\n * Decrypt a JWE, validate claims, verify executable identity, and return\n * an opaque CapabilityToken.\n *\n * @param jwe - Compact JWE string from setup()\n * @returns Opaque capability token for use with fetch/exec/getSecret\n */\n async authorize(jwe: string): Promise<{ token: CapabilityToken; response: VaultResponse }> {\n const kid = extractKid(jwe)\n const { claims, keyStatus } = await this.#decryptWithKeyResolution(jwe, kid)\n\n // Validate claims (expiry, blocklist, usage)\n const jti = claims.jti\n const currentCount = usageCounts.get(jti) ?? 0\n validateClaims(claims, currentCount)\n\n // Track usage and evict finished tokens to prevent unbounded map growth.\n const newCount = currentCount + 1\n if (claims.use !== null && newCount >= claims.use) {\n // Token has reached its usage limit — remove from tracking and block it\n // so future attempts hit the blocklist rather than the usageCounts map.\n usageCounts.delete(jti)\n blockToken(jti)\n } else {\n usageCounts.set(jti, newCount)\n }\n\n const token = createCapabilityToken(claims)\n\n const response: VaultResponse = { keyStatus }\n if (keyStatus === 'previous') {\n // Re-encrypt with current key\n const currentKey = this.#keyManager.getCurrentKey()\n const rotatedJwt = await createToken(currentKey.key, claims, { kid: currentKey.id })\n response.rotatedJwt = rotatedJwt\n }\n\n return { token, response }\n }\n\n /**\n * Execute a delegated HTTP fetch, injecting the secret from the token.\n *\n * The secret value is substituted for every `{{secret}}` placeholder found\n * in `request.url`, `request.headers`, and `request.body` before the fetch\n * is executed. The raw secret is never exposed in the return value.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @param request - The fetch request template. Use `{{secret}}` as a\n * placeholder wherever the secret value should be injected.\n * @returns The `Response` from the underlying `fetch()` call, together with\n * the vault metadata (`vaultResponse`).\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n async fetch(\n token: CapabilityToken,\n request: FetchRequest,\n ): Promise<{ response: Response; vaultResponse: VaultResponse }> {\n const claims = validateCapabilityToken(token)\n const response = await delegatedFetch(claims.val, request)\n return {\n response,\n vaultResponse: { keyStatus: 'current' },\n }\n }\n\n /**\n * Execute a delegated command, injecting the secret from the token.\n *\n * The secret value is substituted for every `{{secret}}` placeholder found\n * in `request.args` and `request.env` values before the process is spawned.\n * The raw secret is never exposed in the return value.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @param request - The exec request template. Use `{{secret}}` as a\n * placeholder wherever the secret value should be injected.\n * @returns The command result (`stdout`, `stderr`, `exitCode`) together with\n * the vault metadata (`vaultResponse`).\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n async exec(\n token: CapabilityToken,\n request: ExecRequest,\n ): Promise<{ result: ExecResult; vaultResponse: VaultResponse }> {\n const claims = validateCapabilityToken(token)\n const result = await delegatedExec(claims.val, request)\n return {\n result,\n vaultResponse: { keyStatus: 'current' },\n }\n }\n\n /**\n * Create a controlled-direct `SecretAccessor` from a capability token.\n *\n * The accessor wraps the secret in a single-use, auto-zeroing `Buffer`. The\n * secret is accessible only through the `read()` callback and is zeroed\n * immediately after the callback returns.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @returns A `SecretAccessor` that can be read exactly once.\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n getSecret(token: CapabilityToken): SecretAccessor {\n const claims = validateCapabilityToken(token)\n return createSecretAccessor(claims.val)\n }\n\n /**\n * Rotate the current encryption key.\n *\n * The previous key remains valid for decryption during the grace period\n * configured in `keyRotation.gracePeriodDays`. JWEs presented during the\n * grace period return a `rotatedJwt` in the `VaultResponse` so callers can\n * persist the updated token.\n *\n * @throws {RotationInProgressError} If a rotation is already in progress\n * (i.e. a previous key is still within its grace period).\n */\n async rotateKey(): Promise<void> {\n const gracePeriodMs = this.#config.keyRotation.gracePeriodDays * 24 * 60 * 60 * 1000\n this.#keyManager.rotateKey(gracePeriodMs)\n await Promise.resolve()\n }\n\n /**\n * Emergency key revocation — invalidates the previous key immediately.\n *\n * After revocation, any JWE that was encrypted with the revoked key will\n * be permanently unreadable. A new encryption key is generated automatically\n * so that `setup()` can be called immediately after revocation.\n */\n async revokeKey(): Promise<void> {\n this.#keyManager.revokeKey()\n await Promise.resolve()\n }\n\n /**\n * Add or remove an executable from the development-mode whitelist.\n *\n * When an executable is in the development-mode list, identity verification\n * (TOFU hash checking) is skipped for that executable during `setup()`. This\n * is intended for local development workflows where the binary changes\n * frequently.\n *\n * @param executablePath - Absolute path to the executable to add or remove.\n * @param enabled - Pass `true` to add the executable to the list, `false`\n * to remove it.\n */\n async setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void> {\n if (this.#config.developmentMode === undefined) {\n if (enabled) {\n this.#config.developmentMode = { executables: [executablePath] }\n }\n return\n }\n\n const exes = this.#config.developmentMode.executables\n const idx = exes.indexOf(executablePath)\n\n if (enabled && idx === -1) {\n exes.push(executablePath)\n } else if (!enabled && idx !== -1) {\n exes.splice(idx, 1)\n }\n\n await Promise.resolve()\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n #resolveBackend(): SecretBackend {\n const enabledBackends = this.#config.backends.filter((b) => b.enabled)\n if (enabledBackends.length === 0) {\n throw new BackendUnavailableError(\n 'No enabled backends configured',\n 'none-enabled',\n this.#config.backends.map((b) => b.type),\n )\n }\n\n const firstEnabled = enabledBackends[0]\n if (firstEnabled === undefined) {\n throw new BackendUnavailableError(\n 'No enabled backends configured',\n 'none-enabled',\n [],\n )\n }\n\n return BackendRegistry.create(firstEnabled.type)\n }\n\n #requireBackend(): SecretBackend {\n if (this.#backend === undefined) {\n throw new VaultError('VaultKeeper backend not initialized')\n }\n return this.#backend\n }\n\n #isDevModeExecutable(executablePath: string): boolean {\n if (this.#config.developmentMode === undefined) {\n return false\n }\n return this.#config.developmentMode.executables.includes(executablePath)\n }\n\n async #decryptWithKeyResolution(\n jwe: string,\n kid: string | undefined,\n ): Promise<{ claims: VaultClaims; keyStatus: 'current' | 'previous' }> {\n // Try to find key by kid\n if (kid !== undefined) {\n const key = this.#keyManager.findKeyById(kid)\n if (key !== undefined) {\n const claims = await decryptToken(key.key, jwe)\n const isCurrent = key.id === this.#keyManager.getCurrentKey().id\n return {\n claims,\n keyStatus: isCurrent ? 'current' : 'previous',\n }\n }\n // kid not found — key may have been revoked\n throw new KeyRevokedError(`Key ${kid} not found — may have been revoked`)\n }\n\n // No kid — try current key first, then previous\n try {\n const claims = await decryptToken(this.#keyManager.getCurrentKey().key, jwe)\n return { claims, keyStatus: 'current' }\n } catch {\n const previousKey = this.#keyManager.getPreviousKey()\n if (previousKey !== undefined) {\n const claims = await decryptToken(previousKey.key, jwe)\n return { claims, keyStatus: 'previous' }\n }\n throw new VaultError('Failed to decrypt JWE with any available key')\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/backend/types.ts","../src/backend/registry.ts","../src/util/exec.ts","../src/backend/file-backend.ts","../src/backend/yubikey-backend.ts","../src/identity/hash.ts","../src/identity/manifest.ts","../src/identity/trust.ts","../src/identity/session.ts","../src/config.ts","../src/keys/manager.ts","../src/jwe/token.ts","../src/jwe/claims.ts","../src/access/delegated-fetch.ts","../src/access/delegated-exec.ts","../src/access/controlled-direct.ts","../src/doctor/checks.ts","../src/util/platform.ts","../src/doctor/runner.ts","../src/vault.ts"],"names":["spawn","path2","path3","crypto3","fs4","path4","fs5","updated","path5","os4","fs6","crypto4","CompactEncrypt","isObject","compactDecrypt","PLACEHOLDER","replacePlaceholder","replaceInRecord","crypto5"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Error hierarchy for vaultkeeper.\n */\n\n/** Base error for all vaultkeeper errors. */\nexport class VaultError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'VaultError'\n }\n}\n\n// --- Backend Access Failures ---\n\n/**\n * Thrown when the backend keychain or credential store is locked and requires\n * user interaction (e.g. biometric prompt or password entry) before access can\n * be granted.\n */\nexport class BackendLockedError extends VaultError {\n /**\n * Whether the lock can be resolved through an interactive user prompt.\n * When `true`, callers may retry after prompting the user.\n */\n readonly interactive: boolean\n\n constructor(message: string, interactive: boolean) {\n super(message)\n this.name = 'BackendLockedError'\n this.interactive = interactive\n }\n}\n\n/**\n * Thrown when a hardware device (e.g. YubiKey or smart card) required for\n * authentication is not currently connected.\n */\nexport class DeviceNotPresentError extends VaultError {\n /**\n * How long (in milliseconds) the operation waited for the device before\n * giving up.\n */\n readonly timeoutMs: number\n\n constructor(message: string, timeoutMs: number) {\n super(message)\n this.name = 'DeviceNotPresentError'\n this.timeoutMs = timeoutMs\n }\n}\n\n/**\n * Thrown when the user explicitly denies an authorization request for a\n * secret access operation (e.g. cancels an OS permission dialog).\n */\nexport class AuthorizationDeniedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'AuthorizationDeniedError'\n }\n}\n\n/**\n * Thrown when no configured backend is available or reachable.\n * Inspect `reason` for a machine-readable cause and `attempted` for the list\n * of backend types that were tried.\n */\nexport class BackendUnavailableError extends VaultError {\n /**\n * Machine-readable reason code describing why the backend is unavailable\n * (e.g. `'none-enabled'`, `'all-failed'`).\n */\n readonly reason: string\n\n /**\n * The backend type identifiers that were attempted before this error was\n * thrown.\n */\n readonly attempted: string[]\n\n constructor(message: string, reason: string, attempted: string[]) {\n super(message)\n this.name = 'BackendUnavailableError'\n this.reason = reason\n this.attempted = attempted\n }\n}\n\n/**\n * Thrown when a required backend plugin (e.g. a third-party credential\n * manager) is not installed on the current system.\n */\nexport class PluginNotFoundError extends VaultError {\n /**\n * The plugin package or binary name that was not found.\n */\n readonly plugin: string\n\n /**\n * A URL pointing to installation instructions for the missing plugin.\n */\n readonly installUrl: string\n\n constructor(message: string, plugin: string, installUrl: string) {\n super(message)\n this.name = 'PluginNotFoundError'\n this.plugin = plugin\n this.installUrl = installUrl\n }\n}\n\n/**\n * Thrown when a requested secret does not exist in the backend store.\n */\nexport class SecretNotFoundError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'SecretNotFoundError'\n }\n}\n\n// --- JWE Lifecycle Failures ---\n\n/**\n * Thrown when a JWE token has passed its expiration time (`exp` claim).\n */\nexport class TokenExpiredError extends VaultError {\n /**\n * Whether the token can be refreshed by calling `setup()` again.\n * When `true`, the secret still exists in the backend and a new token can be\n * issued.\n */\n readonly canRefresh: boolean\n\n constructor(message: string, canRefresh: boolean) {\n super(message)\n this.name = 'TokenExpiredError'\n this.canRefresh = canRefresh\n }\n}\n\n/**\n * Thrown when the encryption key that was used to create a JWE has since been\n * rotated out of the grace period and can no longer be used for decryption.\n */\nexport class KeyRotatedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'KeyRotatedError'\n }\n}\n\n/**\n * Thrown when the encryption key referenced by a JWE's `kid` header has been\n * explicitly revoked and is no longer available for decryption.\n */\nexport class KeyRevokedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'KeyRevokedError'\n }\n}\n\n/**\n * Thrown when a JWE token has been explicitly blocked (e.g. after a single-use\n * token has already been consumed).\n */\nexport class TokenRevokedError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'TokenRevokedError'\n }\n}\n\n/**\n * Thrown when a token with a finite `use` limit has been presented more times\n * than the limit allows.\n */\nexport class UsageLimitExceededError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'UsageLimitExceededError'\n }\n}\n\n// --- Identity and Trust Failures ---\n\n/**\n * Thrown when the hash of an executable no longer matches the previously\n * approved hash stored in the trust manifest (TOFU conflict).\n *\n * Callers must re-approve the executable before a new token can be issued for\n * it.\n */\nexport class IdentityMismatchError extends VaultError {\n /**\n * The hash that was recorded in the trust manifest at approval time.\n */\n readonly previousHash: string\n\n /**\n * The hash computed from the executable at the current moment.\n */\n readonly currentHash: string\n\n constructor(message: string, previousHash: string, currentHash: string) {\n super(message)\n this.name = 'IdentityMismatchError'\n this.previousHash = previousHash\n this.currentHash = currentHash\n }\n}\n\n// --- Infrastructure Failures ---\n\n/**\n * Thrown during initialization when a required system dependency (e.g. OpenSSL\n * or a native credential helper) is missing or incompatible.\n */\nexport class SetupError extends VaultError {\n /**\n * The name of the dependency that caused the setup failure.\n */\n readonly dependency: string\n\n constructor(message: string, dependency: string) {\n super(message)\n this.name = 'SetupError'\n this.dependency = dependency\n }\n}\n\n/**\n * Thrown when a filesystem operation fails due to a permission or access\n * problem (e.g. the config directory is not writable).\n */\nexport class FilesystemError extends VaultError {\n /**\n * The absolute path of the file or directory that caused the error.\n */\n readonly path: string\n\n /**\n * The permission level that was required but not available\n * (e.g. `'read'`, `'write'`, `'execute'`).\n */\n readonly permission: string\n\n constructor(message: string, filePath: string, permission: string) {\n super(message)\n this.name = 'FilesystemError'\n this.path = filePath\n this.permission = permission\n }\n}\n\n/**\n * Thrown when a key rotation is requested while a previous rotation is still\n * within its grace period (i.e. the previous key has not yet been retired).\n */\nexport class RotationInProgressError extends VaultError {\n constructor(message: string) {\n super(message)\n this.name = 'RotationInProgressError'\n }\n}\n","/**\n * Backend abstraction layer types for vaultkeeper.\n */\n\n/**\n * Factory function for creating a SecretBackend instance.\n * @public\n */\nexport type BackendFactory = () => SecretBackend\n\n/**\n * Abstraction interface for all secret storage backends.\n *\n * @remarks\n * Each backend implementation must handle its own availability check and\n * secret lifecycle (store, retrieve, delete, exists).\n *\n * @public\n */\nexport interface SecretBackend {\n /** Unique type identifier for this backend. */\n readonly type: string\n\n /** Human-readable display name for this backend. */\n readonly displayName: string\n\n /**\n * Check whether this backend is available on the current system.\n * @returns true if the backend can be used, false otherwise\n */\n isAvailable(): Promise<boolean>\n\n /**\n * Store a secret under the given id.\n * @param id - Unique identifier for the secret\n * @param secret - The secret value to store\n */\n store(id: string, secret: string): Promise<void>\n\n /**\n * Retrieve a secret by id.\n * @param id - Unique identifier for the secret\n * @returns The stored secret value\n * @throws SecretNotFoundError if the secret does not exist\n */\n retrieve(id: string): Promise<string>\n\n /**\n * Delete a secret by id.\n * @param id - Unique identifier for the secret\n * @throws SecretNotFoundError if the secret does not exist\n */\n delete(id: string): Promise<void>\n\n /**\n * Check whether a secret exists for the given id.\n * @param id - Unique identifier for the secret\n * @returns true if the secret exists, false otherwise\n */\n exists(id: string): Promise<boolean>\n}\n\n/**\n * Backend that can enumerate stored secret IDs.\n * @public\n */\nexport interface ListableBackend extends SecretBackend {\n /**\n * List IDs of all secrets managed by this backend.\n * @returns Array of secret identifiers\n */\n list(): Promise<string[]>\n}\n\n/**\n * Type guard for backends that support listing.\n * @public\n */\nexport function isListableBackend(backend: SecretBackend): backend is ListableBackend {\n return 'list' in backend && typeof backend.list === 'function'\n}\n","/**\n * Registry for secret backend implementations.\n *\n * @remarks\n * The registry maintains a mapping of backend types to factory functions,\n * allowing dynamic creation of backends based on configuration.\n */\n\nimport type { SecretBackend, BackendFactory } from './types.js'\nimport { BackendUnavailableError } from '../errors.js'\n\n/**\n * Registry for secret backend implementations.\n *\n * @remarks\n * The registry allows registration of custom backends and provides\n * a factory method to create backend instances from a type string.\n *\n * Note: This class is used as a namespace for static methods.\n * @public\n */\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class BackendRegistry {\n private static backends = new Map<string, BackendFactory>()\n\n /**\n * Register a backend factory.\n * @param type - Backend type identifier\n * @param factory - Factory function to create backend instances\n */\n static register(type: string, factory: BackendFactory): void {\n this.backends.set(type, factory)\n }\n\n /**\n * Create a backend instance by type.\n * @param type - Backend type identifier\n * @returns A SecretBackend instance\n * @throws Error if the backend type is not registered\n */\n static create(type: string): SecretBackend {\n const factory = this.backends.get(type)\n if (factory === undefined) {\n throw new BackendUnavailableError(\n `Unknown backend type: ${type}. ` +\n `Available types: ${Array.from(this.backends.keys()).join(', ')}`,\n 'unknown-type',\n Array.from(this.backends.keys()),\n )\n }\n return factory()\n }\n\n /**\n * Get all registered backend type identifiers.\n * @returns Array of backend type identifiers\n */\n static getTypes(): string[] {\n return Array.from(this.backends.keys())\n }\n\n /**\n * Returns backend types that are available on the current system.\n *\n * @remarks\n * Creates each registered backend via its factory, calls `isAvailable()`,\n * and returns only the type identifiers whose backend reports availability.\n * If a backend's `isAvailable()` call throws, that backend is excluded from\n * the result rather than propagating the error.\n *\n * @returns Promise resolving to an array of available backend type identifiers\n * @public\n */\n static async getAvailableTypes(): Promise<string[]> {\n const entries = Array.from(this.backends.entries())\n const results = await Promise.all(\n entries.map(async ([type, factory]) => {\n try {\n const backend = factory()\n const available = await backend.isAvailable()\n return available ? type : null\n } catch {\n return null\n }\n }),\n )\n return results.filter((type): type is string => type !== null)\n }\n}\n","/**\n * CLI spawn wrapper for executing external commands.\n */\n\nimport { spawn } from 'node:child_process'\n\n/** Options for command execution. */\nexport interface ExecCommandOptions {\n /** Input to write to stdin */\n stdin?: string | undefined\n /** Timeout in milliseconds */\n timeoutMs?: number | undefined\n}\n\n/** Result of a command execution. */\nexport interface ExecCommandResult {\n stdout: string\n stderr: string\n exitCode: number\n}\n\n/**\n * Execute a command and return stdout.\n * @throws Error if the command exits with a non-zero code.\n */\nexport async function execCommand(\n command: string,\n args: string[],\n options?: ExecCommandOptions,\n): Promise<string> {\n const result = await execCommandFull(command, args, options)\n if (result.exitCode !== 0) {\n throw new Error(`Command failed with exit code ${String(result.exitCode)}: ${result.stderr}`)\n }\n return result.stdout.trim()\n}\n\n/**\n * Execute a command and return the full result.\n */\nexport function execCommandFull(\n command: string,\n args: string[],\n options?: ExecCommandOptions,\n): Promise<ExecCommandResult> {\n return new Promise((resolve, reject) => {\n const proc = spawn(command, args, {\n stdio: [options?.stdin !== undefined ? 'pipe' : 'ignore', 'pipe', 'pipe'],\n })\n let stdout = ''\n let stderr = ''\n\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n if (options?.stdin !== undefined && proc.stdin) {\n proc.stdin.write(options.stdin)\n proc.stdin.end()\n }\n\n if (options?.timeoutMs !== undefined) {\n setTimeout(() => {\n proc.kill('SIGTERM')\n reject(new Error(`Command timed out after ${String(options.timeoutMs)}ms`))\n }, options.timeoutMs)\n }\n\n proc.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code ?? 1 })\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * Encrypted file fallback backend implementation.\n *\n * @remarks\n * Stores secrets encrypted with AES-256-GCM using Node.js native crypto.\n * Each secret is stored as an individual encrypted file under\n * ~/.vaultkeeper/file/. A randomly generated key stored in a protected\n * file is used for encryption.\n *\n * Encrypted file format (all parts base64-encoded, colon-separated):\n * <iv>:<authTag>:<ciphertext>\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport * as crypto from 'node:crypto'\nimport { SecretNotFoundError, FilesystemError } from '../errors.js'\nimport type { ListableBackend } from './types.js'\n\nconst STORAGE_DIR_NAME = path.join('.vaultkeeper', 'file')\nconst KEY_FILE = '.key'\nconst GCM_IV_BYTES = 12\nconst GCM_KEY_BYTES = 32\nconst GCM_TAG_LENGTH = 128 // bits\n\nfunction getStorageDir(): string {\n return path.join(os.homedir(), STORAGE_DIR_NAME)\n}\n\nfunction getEntryPath(storageDir: string, id: string): string {\n const safeId = Buffer.from(id, 'utf8').toString('hex')\n return path.join(storageDir, `${safeId}.enc`)\n}\n\nasync function ensureStorageDir(storageDir: string): Promise<void> {\n try {\n await fs.mkdir(storageDir, { recursive: true, mode: 0o700 })\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code !== 'EEXIST') {\n throw new FilesystemError(\n `Failed to create storage directory: ${storageDir}`,\n storageDir,\n 'rwx',\n )\n }\n }\n}\n\nasync function getOrCreateKey(storageDir: string): Promise<Buffer> {\n const keyPath = path.join(storageDir, KEY_FILE)\n try {\n const data = await fs.readFile(keyPath)\n return data\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n // Generate a random 32-byte key\n const key = crypto.randomBytes(GCM_KEY_BYTES)\n await fs.writeFile(keyPath, key, { mode: 0o600 })\n return key\n }\n throw err\n }\n}\n\nfunction encryptGcm(key: Buffer, plaintext: string): string {\n const iv = crypto.randomBytes(GCM_IV_BYTES)\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH / 8,\n })\n const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])\n const authTag = cipher.getAuthTag()\n return [iv.toString('base64'), authTag.toString('base64'), encrypted.toString('base64')].join(':')\n}\n\nfunction decryptGcm(key: Buffer, encoded: string): string {\n const parts = encoded.split(':')\n if (parts.length !== 3) {\n throw new Error('Invalid encrypted file format: expected iv:authTag:ciphertext')\n }\n const [ivB64, authTagB64, ciphertextB64] = parts\n if (ivB64 === undefined || authTagB64 === undefined || ciphertextB64 === undefined) {\n throw new Error('Invalid encrypted file format: missing part')\n }\n const iv = Buffer.from(ivB64, 'base64')\n const authTag = Buffer.from(authTagB64, 'base64')\n const ciphertext = Buffer.from(ciphertextB64, 'base64')\n\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH / 8,\n })\n decipher.setAuthTag(authTag)\n const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])\n return decrypted.toString('utf8')\n}\n\n/**\n * Encrypted file fallback backend.\n *\n * @remarks\n * Available on all platforms. Stores secrets as AES-256-GCM encrypted files\n * using Node.js native crypto — no external tools required.\n * Not as secure as OS-native keystores, but provides a portable fallback.\n *\n * @internal\n */\nexport class FileBackend implements ListableBackend {\n readonly type = 'file'\n readonly displayName = 'Encrypted File Store'\n\n async isAvailable(): Promise<boolean> {\n // Node.js crypto is always available; check we can create the storage dir.\n try {\n const storageDir = getStorageDir()\n await ensureStorageDir(storageDir)\n return true\n } catch {\n return false\n }\n }\n\n async store(id: string, secret: string): Promise<void> {\n const storageDir = getStorageDir()\n await ensureStorageDir(storageDir)\n const key = await getOrCreateKey(storageDir)\n const entryPath = getEntryPath(storageDir, id)\n const encrypted = encryptGcm(key, secret)\n await fs.writeFile(entryPath, encrypted, { mode: 0o600 })\n }\n\n async retrieve(id: string): Promise<string> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n let encoded: string\n try {\n encoded = await fs.readFile(entryPath, 'utf8')\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in file store: ${id}`)\n }\n throw err\n }\n\n const key = await getOrCreateKey(storageDir)\n try {\n return decryptGcm(key, encoded)\n } catch (err) {\n throw new Error(\n `Failed to decrypt secret: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n async delete(id: string): Promise<void> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.unlink(entryPath)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in file store: ${id}`)\n }\n throw err\n }\n }\n\n async exists(id: string): Promise<boolean> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n return true\n } catch {\n return false\n }\n }\n\n async list(): Promise<string[]> {\n const storageDir = getStorageDir()\n let entries: string[]\n try {\n entries = await fs.readdir(storageDir)\n } catch {\n return []\n }\n return entries\n .filter((f) => f.endsWith('.enc'))\n .map((f) => Buffer.from(f.slice(0, -4), 'hex').toString('utf8'))\n }\n}\n","/**\n * YubiKey backend implementation.\n *\n * @remarks\n * Stores secrets protected by a YubiKey using the `ykman` CLI tool.\n * Secrets are encrypted using AES-256-GCM with a key derived from the\n * YubiKey's HMAC-SHA1 challenge-response (slot 2) via HKDF-SHA-256.\n *\n * Encrypted file format (version 1, all parts base64-encoded, colon-separated):\n * 1:<iv>:<authTag>:<ciphertext>\n *\n * The leading \"1:\" version prefix allows future format migrations and enables\n * detection of legacy CBC files (which lack this prefix).\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport * as crypto from 'node:crypto'\nimport { execCommandFull } from '../util/exec.js'\nimport { SecretNotFoundError, PluginNotFoundError, DeviceNotPresentError } from '../errors.js'\nimport type { ListableBackend } from './types.js'\n\nconst YKMAN_INSTALL_URL = 'https://developers.yubico.com/yubikey-manager/'\nconst STORAGE_DIR_NAME = path.join('.vaultkeeper', 'yubikey')\nconst METADATA_FILE = 'metadata.json'\nconst DEVICE_TIMEOUT_MS = 5000\n\n/** AES-256-GCM constants */\nconst GCM_IV_BYTES = 12\nconst GCM_KEY_BYTES = 32\nconst GCM_TAG_LENGTH_BITS = 128\n\n/** Version prefix written at the start of every encrypted file. */\nconst FORMAT_VERSION = '1'\n\ninterface YubikeyMetadata {\n entries: Record<string, string>\n}\n\nfunction getStorageDir(): string {\n return path.join(os.homedir(), STORAGE_DIR_NAME)\n}\n\nfunction getEntryPath(storageDir: string, id: string): string {\n const safeId = Buffer.from(id, 'utf8').toString('hex')\n return path.join(storageDir, `${safeId}.enc`)\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n if (value === null || typeof value !== 'object') {\n return false\n }\n return Object.values(value).every((v) => typeof v === 'string')\n}\n\nasync function loadMetadata(storageDir: string): Promise<YubikeyMetadata> {\n const metaPath = path.join(storageDir, METADATA_FILE)\n try {\n const raw = await fs.readFile(metaPath, 'utf8')\n const parsed: unknown = JSON.parse(raw)\n if (\n parsed !== null &&\n typeof parsed === 'object' &&\n 'entries' in parsed &&\n isStringRecord(parsed.entries)\n ) {\n return { entries: parsed.entries }\n }\n return { entries: {} }\n } catch {\n return { entries: {} }\n }\n}\n\nasync function saveMetadata(storageDir: string, metadata: YubikeyMetadata): Promise<void> {\n const metaPath = path.join(storageDir, METADATA_FILE)\n await fs.writeFile(metaPath, JSON.stringify(metadata, null, 2), { mode: 0o600 })\n}\n\n/** Expected byte length of a YubiKey HMAC-SHA1 response (20 bytes = 40 hex chars). */\nconst HMAC_RESPONSE_HEX_LENGTH = 40\n\n/** Regex for a valid HMAC-SHA1 hex response: exactly 40 lowercase or uppercase hex digits. */\nconst HMAC_RESPONSE_RE = /^[0-9a-fA-F]{40}$/\n\n/**\n * Derive a 256-bit AES key from the YubiKey HMAC-SHA1 response using HKDF-SHA-256.\n *\n * The HMAC-SHA1 response is 20 bytes — too short and too biased to use\n * directly as an AES-256 key. HKDF expands it to exactly 32 bytes while\n * binding the key to the secret `id` via the `info` field.\n *\n * Throws if `hmacResponse` is not exactly 40 hex characters (20 bytes), which\n * would indicate a malformed or truncated ykman response.\n */\nfunction deriveKey(hmacResponse: string, id: string): Buffer {\n const trimmed = hmacResponse.trim()\n if (!HMAC_RESPONSE_RE.test(trimmed)) {\n throw new Error(\n `Invalid YubiKey HMAC response: expected exactly ${String(HMAC_RESPONSE_HEX_LENGTH)} hex characters (20 bytes), got ${String(trimmed.length)} characters`,\n )\n }\n // The ykman response is a hex string; convert to raw bytes as the IKM.\n const ikm = Buffer.from(trimmed, 'hex')\n const info = Buffer.from(`vaultkeeper-yubikey:${id}`, 'utf8')\n // Node's hkdfSync returns an ArrayBuffer; wrap without copying.\n const keyMaterial = crypto.hkdfSync('sha256', ikm, Buffer.alloc(0), info, GCM_KEY_BYTES)\n return Buffer.from(keyMaterial)\n}\n\n/**\n * Encrypt `plaintext` with AES-256-GCM using `key`.\n * Returns a versioned, colon-separated string: `1:<iv>:<authTag>:<ciphertext>`\n * (all binary fields base64-encoded).\n *\n * The key and all intermediate buffers are zeroed in the finally block,\n * guaranteeing cleanup even if `createCipheriv` or `cipher.final()` throws.\n */\nfunction encryptGcm(key: Buffer, plaintext: string): string {\n const iv = crypto.randomBytes(GCM_IV_BYTES)\n let encrypted: Buffer | undefined\n let authTag: Buffer | undefined\n try {\n const cipher = crypto.createCipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH_BITS / 8,\n })\n encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])\n authTag = cipher.getAuthTag()\n\n return [\n FORMAT_VERSION,\n iv.toString('base64'),\n authTag.toString('base64'),\n encrypted.toString('base64'),\n ].join(':')\n } finally {\n // Zero all secret material regardless of success or failure.\n key.fill(0)\n iv.fill(0)\n encrypted?.fill(0)\n authTag?.fill(0)\n }\n}\n\n/**\n * Decrypt a versioned GCM blob produced by `encryptGcm`.\n *\n * Version detection distinguishes three cases:\n * - First segment is a number matching `FORMAT_VERSION` → current format, proceed.\n * - First segment is a different number → unsupported future version, throw a\n * clear \"unsupported version N\" error.\n * - First segment is not a number at all → legacy/corrupt format (e.g. an\n * AES-256-CBC file written before this implementation), throw a migration error.\n *\n * The key buffer is always zeroed in a finally block, guaranteeing cleanup even\n * if `createDecipheriv` or `setAuthTag` throws before the decrypt attempt.\n */\nfunction decryptGcm(key: Buffer, encoded: string): string {\n const parts = encoded.split(':')\n const versionSegment = parts[0] ?? ''\n\n // Determine whether the first segment is a numeric version prefix at all.\n const parsedVersion = parseInt(versionSegment, 10)\n const isNumericVersion =\n String(parsedVersion) === versionSegment && !Number.isNaN(parsedVersion)\n\n if (!isNumericVersion) {\n // No recognisable version prefix — treat as legacy CBC or corrupt file.\n key.fill(0)\n throw new Error(\n 'Encrypted file uses a legacy format (AES-256-CBC). ' +\n 'Delete the secret and re-store it to migrate to AES-256-GCM.',\n )\n }\n\n if (versionSegment !== FORMAT_VERSION) {\n // A future format version this binary does not know how to decode.\n key.fill(0)\n throw new Error(\n `Unsupported encrypted file version: ${versionSegment}. ` +\n `This vaultkeeper build only supports version ${FORMAT_VERSION}. ` +\n 'Upgrade vaultkeeper to read this secret.',\n )\n }\n\n if (parts.length !== 4) {\n key.fill(0)\n throw new Error(\n `Invalid encrypted file format: expected ${FORMAT_VERSION}:iv:authTag:ciphertext`,\n )\n }\n\n const [_version, ivB64, authTagB64, ciphertextB64] = parts\n if (ivB64 === undefined || authTagB64 === undefined || ciphertextB64 === undefined) {\n key.fill(0)\n throw new Error('Invalid encrypted file format: missing part')\n }\n\n let decrypted: Buffer | undefined\n try {\n const iv = Buffer.from(ivB64, 'base64')\n const authTag = Buffer.from(authTagB64, 'base64')\n const ciphertext = Buffer.from(ciphertextB64, 'base64')\n\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv, {\n authTagLength: GCM_TAG_LENGTH_BITS / 8,\n })\n decipher.setAuthTag(authTag)\n\n try {\n decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()])\n } catch (err) {\n throw new Error(\n `GCM authentication failed — ciphertext may be tampered: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n\n const plaintext = decrypted.toString('utf8')\n return plaintext\n } finally {\n // Zero all secret material regardless of success or failure.\n key.fill(0)\n decrypted?.fill(0)\n }\n}\n\n/**\n * YubiKey backend via `ykman` CLI.\n *\n * @remarks\n * Requires ykman to be installed and a YubiKey to be connected.\n * Secrets are stored in files encrypted using AES-256-GCM. The encryption\n * key is derived from the YubiKey's HMAC-SHA1 challenge-response (slot 2)\n * via HKDF-SHA-256, binding each secret to its `id`.\n *\n * @internal\n */\nexport class YubikeyBackend implements ListableBackend {\n readonly type = 'yubikey'\n readonly displayName = 'YubiKey'\n\n async isAvailable(): Promise<boolean> {\n try {\n const result = await execCommandFull('ykman', ['--version'])\n if (result.exitCode !== 0) {\n return false\n }\n // Also verify a YubiKey is connected\n const listResult = await execCommandFull('ykman', ['list'])\n return listResult.exitCode === 0 && listResult.stdout.trim() !== ''\n } catch {\n return false\n }\n }\n\n private async requireDevice(): Promise<void> {\n const available = await this.isAvailable()\n if (!available) {\n const hasYkman = await execCommandFull('ykman', ['--version']).then(\n (r) => r.exitCode === 0,\n () => false,\n )\n if (!hasYkman) {\n throw new PluginNotFoundError('ykman is not installed', 'ykman', YKMAN_INSTALL_URL)\n }\n throw new DeviceNotPresentError('No YubiKey device detected', DEVICE_TIMEOUT_MS)\n }\n }\n\n /**\n * Perform the YubiKey HMAC-SHA1 challenge-response for `id` and return the\n * raw hex response string. Throws on device failure.\n */\n private async challengeResponse(id: string): Promise<string> {\n const challenge = Buffer.from(`vaultkeeper:${id}`, 'utf8').toString('hex')\n const responseResult = await execCommandFull('ykman', ['otp', 'calculate', '2', challenge])\n if (responseResult.exitCode !== 0) {\n throw new Error(`YubiKey challenge-response failed: ${responseResult.stderr}`)\n }\n return responseResult.stdout.trim()\n }\n\n async store(id: string, secret: string): Promise<void> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n await fs.mkdir(storageDir, { recursive: true, mode: 0o700 })\n\n const hmacResponse = await this.challengeResponse(id)\n const key = deriveKey(hmacResponse, id)\n const encrypted = encryptGcm(key, secret)\n\n const entryPath = getEntryPath(storageDir, id)\n await fs.writeFile(entryPath, encrypted, { mode: 0o600 })\n\n const metadata = await loadMetadata(storageDir)\n metadata.entries[id] = entryPath\n await saveMetadata(storageDir, metadata)\n }\n\n async retrieve(id: string): Promise<string> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n } catch {\n throw new SecretNotFoundError(`Secret not found in YubiKey store: ${id}`)\n }\n\n const encoded = await fs.readFile(entryPath, 'utf8')\n const hmacResponse = await this.challengeResponse(id)\n const key = deriveKey(hmacResponse, id)\n\n return decryptGcm(key, encoded)\n }\n\n async delete(id: string): Promise<void> {\n await this.requireDevice()\n\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.unlink(entryPath)\n } catch (err) {\n if (err instanceof Error && 'code' in err && err.code === 'ENOENT') {\n throw new SecretNotFoundError(`Secret not found in YubiKey store: ${id}`)\n }\n throw err\n }\n\n const metadata = await loadMetadata(storageDir)\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete metadata.entries[id]\n await saveMetadata(storageDir, metadata)\n }\n\n async exists(id: string): Promise<boolean> {\n const storageDir = getStorageDir()\n const entryPath = getEntryPath(storageDir, id)\n\n try {\n await fs.access(entryPath)\n return true\n } catch {\n return false\n }\n }\n\n async list(): Promise<string[]> {\n const storageDir = getStorageDir()\n const metadata = await loadMetadata(storageDir)\n return Object.keys(metadata.entries)\n }\n}\n","/**\n * Executable hashing utilities.\n */\n\nimport * as crypto from 'node:crypto'\nimport * as fs from 'node:fs'\n\n/**\n * Compute the SHA-256 digest of the file at `filePath`.\n *\n * @param filePath - Absolute or relative path to the binary to hash.\n * @returns Hex-encoded SHA-256 digest string.\n * @internal\n */\nexport function hashExecutable(filePath: string): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const hash = crypto.createHash('sha256')\n const stream = fs.createReadStream(filePath)\n\n stream.on('data', (chunk: Buffer | string) => {\n hash.update(chunk)\n })\n\n stream.on('end', () => {\n resolve(hash.digest('hex'))\n })\n\n stream.on('error', (err: Error) => {\n reject(err)\n })\n })\n}\n","/**\n * Trust manifest management — load, save, and query approved executable hashes.\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport type { TrustManifest, TrustManifestEntry } from './types.js'\n\nconst MANIFEST_FILENAME = 'trust-manifest.json'\n\n/** Raw shape persisted to disk (plain object, not a Map). */\ninterface RawManifest {\n version: number\n entries: Record<string, TrustManifestEntry>\n}\n\n/**\n * Type guard that checks `value` is an object with a `version: number` and\n * `entries` object property, matching {@link RawManifest}.\n *\n * We avoid type assertions by narrowing through the `in` operator and\n * `typeof` checks. The discriminated union `unknown → object` chain lets\n * TypeScript track narrowness without any `as` casts.\n */\nfunction isRawManifest(value: unknown): value is RawManifest {\n if (typeof value !== 'object' || value === null) return false\n if (!('version' in value) || typeof value.version !== 'number') return false\n if (!('entries' in value) || typeof value.entries !== 'object' || value.entries === null) return false\n return true\n}\n\n/**\n * Type guard for a single {@link TrustManifestEntry}.\n */\nfunction isTrustManifestEntry(value: unknown): value is TrustManifestEntry {\n if (typeof value !== 'object' || value === null) return false\n if (!('hashes' in value) || !Array.isArray(value.hashes)) return false\n if (!('trustTier' in value)) return false\n const { trustTier } = value\n if (trustTier !== 1 && trustTier !== 2 && trustTier !== 3) return false\n return true\n}\n\n/**\n * Load the trust manifest from `configDir`.\n * Returns an empty `Map` if the manifest file does not yet exist.\n * @internal\n */\nexport async function loadManifest(configDir: string): Promise<TrustManifest> {\n const manifestPath = path.join(configDir, MANIFEST_FILENAME)\n let rawText: string\n try {\n rawText = await fs.readFile(manifestPath, 'utf8')\n } catch (err) {\n if (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n err.code === 'ENOENT'\n ) {\n return new Map()\n }\n throw err\n }\n\n const parsed: unknown = JSON.parse(rawText)\n\n if (!isRawManifest(parsed)) {\n return new Map()\n }\n\n const manifest: TrustManifest = new Map()\n for (const [namespace, entry] of Object.entries(parsed.entries)) {\n if (isTrustManifestEntry(entry)) {\n manifest.set(namespace, { hashes: [...entry.hashes], trustTier: entry.trustTier })\n }\n }\n return manifest\n}\n\n/**\n * Persist `manifest` to `configDir`, creating the directory if necessary.\n * @internal\n */\nexport async function saveManifest(configDir: string, manifest: TrustManifest): Promise<void> {\n await fs.mkdir(configDir, { recursive: true })\n const entries: Record<string, TrustManifestEntry> = {}\n for (const [namespace, entry] of manifest) {\n entries[namespace] = entry\n }\n const raw: RawManifest = { version: 1, entries }\n const manifestPath = path.join(configDir, MANIFEST_FILENAME)\n await fs.writeFile(manifestPath, JSON.stringify(raw, null, 2), 'utf8')\n}\n\n/**\n * Return a new manifest that includes `hash` under `namespace`.\n * If the namespace does not yet exist it is created with tier 3 (Unverified).\n * The trust tier of an existing entry is not changed.\n * @internal\n */\nexport function addTrustedHash(manifest: TrustManifest, namespace: string, hash: string): TrustManifest {\n const next = new Map(manifest)\n const existing = next.get(namespace)\n if (existing === undefined) {\n next.set(namespace, { hashes: [hash], trustTier: 3 })\n } else if (!existing.hashes.includes(hash)) {\n next.set(namespace, { hashes: [...existing.hashes, hash], trustTier: existing.trustTier })\n }\n return next\n}\n\n/**\n * Return `true` if `hash` is in the approved list for `namespace`.\n * @internal\n */\nexport function isTrusted(manifest: TrustManifest, namespace: string, hash: string): boolean {\n const entry = manifest.get(namespace)\n if (entry === undefined) return false\n return entry.hashes.includes(hash)\n}\n","/**\n * Trust classification for executables.\n *\n * Tier 1 — Sigstore: cryptographic provenance verified via Sigstore (lazy import).\n * Tier 2 — Registry: hash found in the approved trust manifest.\n * Tier 3 — Unverified: default fallback when no stronger evidence is available.\n *\n * TOFU (Trust On First Use): on the first encounter with an executable the hash\n * is recorded. If the hash changes on a subsequent call a `tofuConflict` is\n * signalled so the caller can prompt for re-approval.\n *\n * Dev-mode bypass: when the executable path is the literal string `\"dev\"` all\n * hash verification is skipped and Tier 3 unverified is returned immediately.\n */\n\nimport { hashExecutable } from './hash.js'\nimport { loadManifest, saveManifest, addTrustedHash, isTrusted } from './manifest.js'\nimport type { TrustVerificationResult, TrustOptions } from './types.js'\n\n/** Attempt Sigstore bundle verification (Tier 1). Returns `true` on success. */\nasync function trySigstore(execPath: string): Promise<boolean> {\n try {\n // Dynamic import so the library works without sigstore installed.\n // @ts-expect-error — sigstore is an optional peer dependency not listed in\n // package.json; the import will fail at runtime if not installed, which is\n // the intended behaviour. We catch that case below.\n const sigstore: unknown = await import('sigstore')\n // sigstore.verify expects a bundle; for executable verification we check\n // whether the library is present and functional. If the import succeeds but\n // the verify function is not available we fall through gracefully.\n if (typeof sigstore !== 'object' || sigstore === null) {\n return false\n }\n if (!('verify' in sigstore) || typeof sigstore.verify !== 'function') {\n return false\n }\n // Executable bundles are not universally available; treat any error as a\n // Tier-1 failure rather than a hard error.\n void execPath // execPath would be used in a full Sigstore bundle lookup\n return false // Full Sigstore bundle verification not yet available for arbitrary binaries\n } catch {\n return false\n }\n}\n\n/**\n * Verify the trust tier of the executable at `execPath`.\n *\n * @param execPath - Path to the executable, or `\"dev\"` to enable dev-mode bypass.\n * @param options - Optional trust configuration.\n * @internal\n */\nexport async function verifyTrust(\n execPath: string,\n options?: TrustOptions,\n): Promise<TrustVerificationResult> {\n // Dev-mode bypass: skip all verification for the sentinel value \"dev\".\n if (execPath === 'dev') {\n return {\n identity: { hash: 'dev', trustTier: 3, verified: false },\n tofuConflict: false,\n reason: 'Dev mode — hash verification skipped',\n }\n }\n\n const configDir = options?.configDir ?? '.vaultkeeper'\n const namespace = options?.namespace ?? execPath\n\n // Compute the current hash of the executable.\n const currentHash = await hashExecutable(execPath)\n\n // Load the manifest for TOFU and registry checks.\n const manifest = await loadManifest(configDir)\n\n // --- Tier 1: Sigstore ---\n if (options?.skipSigstore !== true) {\n const sigstoreVerified = await trySigstore(execPath)\n if (sigstoreVerified) {\n const updated = addTrustedHash(manifest, namespace, currentHash)\n await saveManifest(configDir, updated)\n return {\n identity: { hash: currentHash, trustTier: 1, verified: true },\n tofuConflict: false,\n reason: 'Sigstore bundle verified',\n }\n }\n }\n\n // --- Tier 2: Registry (manifest) ---\n if (isTrusted(manifest, namespace, currentHash)) {\n return {\n identity: { hash: currentHash, trustTier: 2, verified: true },\n tofuConflict: false,\n reason: 'Hash found in trust manifest',\n }\n }\n\n // --- TOFU check ---\n const existing = manifest.get(namespace)\n if (existing !== undefined && existing.hashes.length > 0) {\n // The namespace is known but the current hash is not approved — TOFU conflict.\n return {\n identity: { hash: currentHash, trustTier: 3, verified: false },\n tofuConflict: true,\n reason: `Hash changed from a previously approved value — re-approval required`,\n }\n }\n\n // --- Tier 3: First encounter — record via TOFU ---\n const updated = addTrustedHash(manifest, namespace, currentHash)\n await saveManifest(configDir, updated)\n return {\n identity: { hash: currentHash, trustTier: 3, verified: false },\n tofuConflict: false,\n reason: 'First encounter — hash recorded via TOFU',\n }\n}\n","/**\n * Capability token management.\n *\n * Tokens are backed by a `WeakMap` whose keys are `CapabilityToken` instances,\n * so the actual claims are never reachable from outside this module. Private\n * class fields enforce that no property on the token object leaks data.\n */\n\nimport type { VaultClaims } from './types.js'\nimport { AuthorizationDeniedError } from '../errors.js'\n\n/** Opaque capability token. Claims are inaccessible without `validateCapabilityToken`. */\nexport class CapabilityToken {\n // Private field ensures no public surface leaks claims.\n readonly #brand: symbol\n\n constructor() {\n this.#brand = Symbol('CapabilityToken')\n }\n\n /**\n * Return a non-enumerable identifier for debugging purposes only.\n * Does NOT expose claims.\n */\n toString(): string {\n return `[CapabilityToken ${this.#brand.toString()}]`\n }\n}\n\n/** Internal storage for claims — inaccessible outside the module closure. */\nconst claimsStore = new WeakMap<CapabilityToken, VaultClaims>()\n\n/**\n * Create a capability token that wraps `claims`.\n * The claims are stored in a module-private `WeakMap` and cannot be reached\n * without calling `validateCapabilityToken`.\n * @internal\n */\nexport function createCapabilityToken(claims: VaultClaims): CapabilityToken {\n const token = new CapabilityToken()\n claimsStore.set(token, claims)\n return token\n}\n\n/**\n * Retrieve the `VaultClaims` associated with `token`.\n *\n * @throws {AuthorizationDeniedError} if the token was not created by\n * `createCapabilityToken` in this module (i.e. it has no claims entry\n * in the store).\n * @internal\n */\nexport function validateCapabilityToken(token: CapabilityToken): VaultClaims {\n const claims = claimsStore.get(token)\n if (claims === undefined) {\n throw new AuthorizationDeniedError('Invalid or unrecognized capability token')\n }\n return claims\n}\n","/**\n * Configuration loading, validation, and defaults for vaultkeeper.\n */\n\nimport * as fs from 'node:fs/promises'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport type { VaultConfig, BackendConfig, TrustTier } from './types.js'\n\n/**\n * Return the platform-appropriate default config directory.\n * @internal\n */\nexport function getDefaultConfigDir(): string {\n if (process.platform === 'win32') {\n const appData = process.env.APPDATA\n if (appData !== undefined) {\n return path.join(appData, 'vaultkeeper')\n }\n return path.join(os.homedir(), 'AppData', 'Roaming', 'vaultkeeper')\n }\n return path.join(os.homedir(), '.config', 'vaultkeeper')\n}\n\n/** Default configuration when no config file exists. */\nfunction defaultConfig(): VaultConfig {\n return {\n version: 1,\n backends: [{ type: 'file', enabled: true }],\n keyRotation: { gracePeriodDays: 7 },\n defaults: { ttlMinutes: 60, trustTier: 3 },\n }\n}\n\n/**\n * Type guard for plain objects.\n */\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Validates a backend config entry.\n */\nfunction validateBackendEntry(entry: unknown, index: number): BackendConfig {\n if (!isObject(entry)) {\n throw new Error(`backends[${String(index)}] must be an object`)\n }\n if (typeof entry.type !== 'string' || entry.type.trim() === '') {\n throw new Error(`backends[${String(index)}].type must be a non-empty string`)\n }\n if (typeof entry.enabled !== 'boolean') {\n throw new Error(`backends[${String(index)}].enabled must be a boolean`)\n }\n\n const result: BackendConfig = {\n type: entry.type,\n enabled: entry.enabled,\n }\n\n if (entry.plugin !== undefined) {\n if (typeof entry.plugin !== 'boolean') {\n throw new Error(`backends[${String(index)}].plugin must be a boolean`)\n }\n result.plugin = entry.plugin\n }\n\n if (entry.path !== undefined) {\n if (typeof entry.path !== 'string') {\n throw new Error(`backends[${String(index)}].path must be a string`)\n }\n result.path = entry.path\n }\n\n return result\n}\n\n/**\n * Validate an unknown value as a VaultConfig, throwing on invalid structure.\n * @internal\n */\nexport function validateConfig(config: unknown): VaultConfig {\n if (!isObject(config)) {\n throw new Error('Config must be an object')\n }\n\n if (typeof config.version !== 'number' || config.version !== 1) {\n throw new Error('Config version must be 1')\n }\n\n if (!Array.isArray(config.backends) || config.backends.length === 0) {\n throw new Error('Config must have at least one backend')\n }\n\n const backends: BackendConfig[] = config.backends.map((entry: unknown, i: number) =>\n validateBackendEntry(entry, i),\n )\n\n if (!isObject(config.keyRotation)) {\n throw new Error('Config keyRotation must be an object')\n }\n if (\n typeof config.keyRotation.gracePeriodDays !== 'number' ||\n config.keyRotation.gracePeriodDays <= 0\n ) {\n throw new Error('Config keyRotation.gracePeriodDays must be a positive number')\n }\n\n if (!isObject(config.defaults)) {\n throw new Error('Config defaults must be an object')\n }\n if (typeof config.defaults.ttlMinutes !== 'number' || config.defaults.ttlMinutes <= 0) {\n throw new Error('Config defaults.ttlMinutes must be a positive number')\n }\n const tier = config.defaults.trustTier\n if (tier !== 1 && tier !== 2 && tier !== 3) {\n throw new Error('Config defaults.trustTier must be 1, 2, or 3')\n }\n\n const result: VaultConfig = {\n version: 1,\n backends,\n keyRotation: {\n gracePeriodDays: config.keyRotation.gracePeriodDays,\n },\n defaults: {\n ttlMinutes: config.defaults.ttlMinutes,\n trustTier: tier satisfies TrustTier,\n },\n }\n\n if (config.developmentMode !== undefined) {\n if (!isObject(config.developmentMode)) {\n throw new Error('Config developmentMode must be an object')\n }\n if (!Array.isArray(config.developmentMode.executables)) {\n throw new Error('Config developmentMode.executables must be an array')\n }\n const executables: string[] = []\n for (const [i, exe] of Array.from(config.developmentMode.executables).entries()) {\n if (typeof exe !== 'string') {\n throw new Error(`Config developmentMode.executables[${String(i)}] must be a string`)\n }\n executables.push(exe)\n }\n result.developmentMode = { executables }\n }\n\n return result\n}\n\n/**\n * Load the vaultkeeper config from disk, falling back to defaults if the file\n * does not exist.\n *\n * @param configDir - Directory containing config.json. Defaults to platform-appropriate path.\n * @internal\n */\nexport async function loadConfig(configDir?: string): Promise<VaultConfig> {\n const dir = configDir ?? getDefaultConfigDir()\n const configPath = path.join(dir, 'config.json')\n\n let raw: string\n try {\n raw = await fs.readFile(configPath, 'utf-8')\n } catch {\n return defaultConfig()\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new Error(`Failed to parse config file at ${configPath}`)\n }\n\n return validateConfig(parsed)\n}\n","/**\n * Key management for vaultkeeper, including generation, rotation, revocation,\n * and grace-period tracking.\n */\n\nimport * as crypto from 'node:crypto'\nimport { RotationInProgressError, SetupError } from '../errors.js'\nimport type { KeyMaterial, KeyState } from './types.js'\n\n/**\n * Manage cryptographic keys with rotation and grace-period semantics.\n * @internal\n */\nexport class KeyManager {\n #state: KeyState | undefined = undefined\n #gracePeriodTimer: ReturnType<typeof setTimeout> | undefined = undefined\n #gracePeriodExpiresAt: number | undefined = undefined\n #rotating = false\n\n /** Generate a new 32-byte key with a timestamp-based id. */\n generateKey(): KeyMaterial {\n const randomSuffix = crypto.randomBytes(4).toString('hex')\n return {\n id: `k-${String(Date.now())}-${randomSuffix}`,\n key: new Uint8Array(crypto.randomBytes(32)),\n createdAt: new Date(),\n }\n }\n\n /**\n * Initialize the manager with a freshly generated key.\n * Safe to call multiple times; subsequent calls are no-ops.\n */\n init(): Promise<void> {\n if (this.#state === undefined) {\n this.#state = { current: this.generateKey() }\n }\n return Promise.resolve()\n }\n\n /** Return the current (encryption) key. Throws if not initialized. */\n getCurrentKey(): KeyMaterial {\n const state = this.#requireState()\n return state.current\n }\n\n /**\n * Return the previous key if we are still inside a grace period,\n * otherwise `undefined`.\n */\n getPreviousKey(): KeyMaterial | undefined {\n const state = this.#requireState()\n return state.previous\n }\n\n /**\n * Find a key by its id, searching current then previous.\n * Returns `undefined` if the key is not found (or the previous key's\n * grace period has expired).\n */\n findKeyById(kid: string): KeyMaterial | undefined {\n const state = this.#requireState()\n if (state.current.id === kid) {\n return state.current\n }\n const { previous } = state\n if (previous?.id === kid) {\n // previous?.id === kid is only true when previous is defined and its id\n // matches, so we can safely return it here. TypeScript does not narrow\n // the optional-chain result back to KeyMaterial, so we guard explicitly.\n return previous\n }\n return undefined\n }\n\n /**\n * Rotate the current key: the current key becomes previous, a new key\n * becomes current. A grace-period timer is started; when it fires the\n * previous key is cleared automatically.\n *\n * @throws {RotationInProgressError} if a rotation is already underway.\n */\n rotateKey(gracePeriodMs: number): void {\n if (this.#rotating) {\n throw new RotationInProgressError('A key rotation is already in progress')\n }\n\n const state = this.#requireState()\n this.#rotating = true\n\n // Cancel any existing grace-period timer before starting a new rotation.\n this.#clearGracePeriodTimer()\n\n const newKey = this.generateKey()\n this.#state = { current: newKey, previous: state.current }\n this.#gracePeriodExpiresAt = Date.now() + gracePeriodMs\n\n this.#gracePeriodTimer = setTimeout(() => {\n if (this.#state !== undefined) {\n // Remove the previous key once the grace period elapses.\n this.#state = { current: this.#state.current }\n }\n this.#gracePeriodExpiresAt = undefined\n this.#gracePeriodTimer = undefined\n this.#rotating = false\n }, gracePeriodMs)\n\n // Allow the timer to be GC'd without keeping the process alive.\n if (typeof this.#gracePeriodTimer.unref === 'function') {\n this.#gracePeriodTimer.unref()\n }\n }\n\n /**\n * Emergency revocation: immediately clear the previous key and generate\n * a brand-new current key. Any in-flight grace period is cancelled.\n */\n revokeKey(): void {\n this.#clearGracePeriodTimer()\n this.#rotating = false\n this.#gracePeriodExpiresAt = undefined\n\n const newKey = this.generateKey()\n this.#state = { current: newKey }\n }\n\n /**\n * Return `true` while a rotation grace period is active (i.e. the previous\n * key is still accessible).\n */\n isInGracePeriod(): boolean {\n if (this.#gracePeriodExpiresAt === undefined) {\n return false\n }\n return Date.now() < this.#gracePeriodExpiresAt\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n #requireState(): KeyState {\n if (this.#state === undefined) {\n throw new SetupError(\n 'KeyManager has not been initialized — call init() first',\n 'KeyManager',\n )\n }\n return this.#state\n }\n\n #clearGracePeriodTimer(): void {\n if (this.#gracePeriodTimer !== undefined) {\n clearTimeout(this.#gracePeriodTimer)\n this.#gracePeriodTimer = undefined\n }\n }\n}\n","/**\n * JWE token creation and decryption using `jose` with `dir` + `A256GCM`.\n */\n\nimport { CompactEncrypt, compactDecrypt } from 'jose'\nimport type { VaultClaims } from '../types.js'\nimport { VaultError } from '../errors.js'\n\nconst ALGORITHM = 'dir'\nconst ENCRYPTION = 'A256GCM'\n\n/**\n * Options for token creation.\n * @internal\n */\nexport interface CreateTokenOptions {\n /** Optional key ID to embed in the JWE header for rotation tracking. */\n kid?: string | undefined\n}\n\n/**\n * Creates a compact JWE string from the given claims.\n *\n * Uses `dir` (direct key agreement) with `A256GCM` content encryption.\n * The 256-bit key must be exactly 32 bytes.\n *\n * @param key - 32-byte symmetric key (AES-256)\n * @param claims - VaultClaims payload to encrypt\n * @param options - Optional token creation options\n * @returns Compact JWE string\n * @internal\n */\nexport async function createToken(\n key: Uint8Array,\n claims: VaultClaims,\n options?: CreateTokenOptions,\n): Promise<string> {\n const plaintext = new TextEncoder().encode(JSON.stringify(claims))\n\n const header: { alg: typeof ALGORITHM; enc: typeof ENCRYPTION; kid?: string } = {\n alg: ALGORITHM,\n enc: ENCRYPTION,\n }\n\n if (options?.kid !== undefined) {\n header.kid = options.kid\n }\n\n return new CompactEncrypt(plaintext).setProtectedHeader(header).encrypt(key)\n}\n\n/**\n * Type guard that checks whether an unknown value is a non-null object.\n */\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * Parses a raw JSON payload object into VaultClaims, validating that all required fields\n * are present and of the correct types. Returns `undefined` if validation fails.\n */\nfunction parseVaultClaims(raw: unknown): VaultClaims | undefined {\n if (!isObject(raw)) {\n return undefined\n }\n\n const { jti, exp, iat, sub, exe, use, tid, bkd, val, ref } = raw\n\n if (typeof jti !== 'string') return undefined\n if (typeof exp !== 'number') return undefined\n if (typeof iat !== 'number') return undefined\n if (typeof sub !== 'string') return undefined\n if (typeof exe !== 'string') return undefined\n if (use !== null && typeof use !== 'number') return undefined\n if (tid !== 1 && tid !== 2 && tid !== 3) return undefined\n if (typeof bkd !== 'string') return undefined\n if (typeof val !== 'string') return undefined\n if (typeof ref !== 'string') return undefined\n\n return { jti, exp, iat, sub, exe, use: use ?? null, tid, bkd, val, ref }\n}\n\n/**\n * Decrypts a compact JWE string and returns the VaultClaims payload.\n *\n * @param key - 32-byte symmetric key (AES-256)\n * @param jwe - Compact JWE string to decrypt\n * @returns Decrypted VaultClaims\n * @throws VaultError if decryption fails or the payload is malformed\n * @internal\n */\nexport async function decryptToken(key: Uint8Array, jwe: string): Promise<VaultClaims> {\n let plaintext: Uint8Array\n try {\n const result = await compactDecrypt(jwe, key)\n plaintext = result.plaintext\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new VaultError(`JWE decryption failed: ${message}`)\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(new TextDecoder().decode(plaintext))\n } catch {\n throw new VaultError('JWE payload is not valid JSON')\n }\n\n const claims = parseVaultClaims(parsed)\n if (claims === undefined) {\n throw new VaultError('JWE payload does not match VaultClaims schema')\n }\n\n return claims\n}\n\n/**\n * Extracts the `kid` header from a compact JWE without decrypting it.\n *\n * The protected header in compact JWE is the first Base64URL-encoded segment.\n *\n * @param jwe - Compact JWE string\n * @returns The kid value, or undefined if not present\n * @throws VaultError if the JWE structure is invalid\n * @internal\n */\nexport function extractKid(jwe: string): string | undefined {\n const parts = jwe.split('.')\n if (parts.length !== 5) {\n throw new VaultError('Invalid JWE compact serialization: expected 5 parts')\n }\n const headerSegment = parts[0]\n if (headerSegment === undefined || headerSegment === '') {\n throw new VaultError('Invalid JWE compact serialization: missing header segment')\n }\n let headerJson: string\n try {\n headerJson = Buffer.from(headerSegment, 'base64url').toString('utf-8')\n } catch {\n throw new VaultError('Invalid JWE compact serialization: header is not valid Base64URL')\n }\n\n let header: unknown\n try {\n header = JSON.parse(headerJson)\n } catch {\n throw new VaultError('Invalid JWE compact serialization: header is not valid JSON')\n }\n\n if (!isObject(header)) {\n return undefined\n }\n\n const kid = header.kid\n if (typeof kid !== 'string') {\n return undefined\n }\n return kid\n}\n","/**\n * VaultClaims validation and in-memory token blocklist.\n */\n\nimport type { VaultClaims } from '../types.js'\nimport {\n TokenExpiredError,\n TokenRevokedError,\n UsageLimitExceededError,\n VaultError,\n} from '../errors.js'\n\n/**\n * Maximum number of JTIs the in-memory blocklist will retain.\n * When the cap is reached, the oldest inserted entry is evicted (FIFO/LRU).\n * This prevents unbounded growth for long-running processes.\n */\nconst BLOCKLIST_MAX_SIZE = 10_000\n\n/**\n * In-memory blocklist for revoked token JTIs. This is process-local and non-persistent.\n * For production use, a distributed blocklist (e.g., Redis) should be layered on top.\n *\n * A Map is used instead of a Set because Map preserves insertion order, which\n * allows O(1) eviction of the oldest entry (first key in iteration order).\n * The map values are always `true` — only the keys matter for lookup.\n */\nconst blocklist = new Map<string, true>()\n\n/**\n * Adds a JTI to the in-memory blocklist, preventing further use of that token.\n * If the blocklist has reached its maximum size, the oldest entry is evicted first.\n *\n * @param jti - The unique token ID to block\n * @internal\n */\nexport function blockToken(jti: string): void {\n if (blocklist.has(jti)) {\n // Already blocked — re-inserting would not change insertion order in Map,\n // so we delete and re-add to refresh the recency position.\n blocklist.delete(jti)\n } else if (blocklist.size >= BLOCKLIST_MAX_SIZE) {\n // Evict the oldest entry (first key in insertion-order iteration).\n const oldestKey = blocklist.keys().next().value\n if (oldestKey !== undefined) {\n blocklist.delete(oldestKey)\n }\n }\n blocklist.set(jti, true)\n}\n\n/**\n * Returns true if the given JTI has been blocked.\n *\n * @param jti - The unique token ID to check\n * @internal\n */\nexport function isBlocked(jti: string): boolean {\n return blocklist.has(jti)\n}\n\n/**\n * Clears all blocked JTIs from the in-memory blocklist.\n * Primarily intended for use in tests.\n * @internal\n */\nexport function clearBlocklist(): void {\n blocklist.clear()\n}\n\n/**\n * Validates all claims in a VaultClaims payload.\n * @internal\n *\n * Checks performed:\n * - Required fields present (jti, exp, iat, sub, exe, tid, bkd, val, ref)\n * - Token is not expired (exp vs. current time)\n * - Token is not on the blocklist\n * - Usage limit (use) is not exceeded if a positive limit is set\n * - Trust tier (tid) is valid (1, 2, or 3)\n *\n * @param claims - VaultClaims payload to validate\n * @param usedCount - How many times the token has been used already (for `use` limit checking)\n * @throws TokenExpiredError if the token is expired\n * @throws TokenRevokedError if the token has been blocked\n * @throws UsageLimitExceededError if the usage count has been exhausted\n * @throws VaultError for missing or malformed required fields\n */\nexport function validateClaims(claims: VaultClaims, usedCount = 0): void {\n // Validate required string fields are non-empty\n if (claims.jti.trim() === '') {\n throw new VaultError('Invalid token: jti must not be empty')\n }\n if (claims.sub.trim() === '') {\n throw new VaultError('Invalid token: sub must not be empty')\n }\n if (claims.exe.trim() === '') {\n throw new VaultError('Invalid token: exe must not be empty')\n }\n if (claims.bkd.trim() === '') {\n throw new VaultError('Invalid token: bkd must not be empty')\n }\n if (claims.val.trim() === '') {\n throw new VaultError('Invalid token: val must not be empty')\n }\n if (claims.ref.trim() === '') {\n throw new VaultError('Invalid token: ref must not be empty')\n }\n\n // Validate timestamp ordering\n if (claims.iat > claims.exp) {\n throw new VaultError('Invalid token: iat must not be after exp')\n }\n\n // Check expiration\n const nowSec = Math.floor(Date.now() / 1000)\n if (nowSec >= claims.exp) {\n throw new TokenExpiredError(\n `Token expired at ${String(claims.exp)} (now: ${String(nowSec)})`,\n false,\n )\n }\n\n // Check blocklist\n if (isBlocked(claims.jti)) {\n throw new TokenRevokedError(`Token ${claims.jti} has been revoked`)\n }\n\n // Check usage limit\n if (claims.use !== null) {\n if (claims.use <= 0) {\n throw new UsageLimitExceededError(\n `Token ${claims.jti} has a non-positive usage limit: ${String(claims.use)}`,\n )\n }\n if (usedCount >= claims.use) {\n throw new UsageLimitExceededError(\n `Token ${claims.jti} usage limit of ${String(claims.use)} exceeded (used: ${String(usedCount)})`,\n )\n }\n }\n}\n","/**\n * Delegated HTTP fetch access pattern.\n *\n * Replaces `{{secret}}` placeholders in the request URL, headers, and body\n * with the actual secret value, then executes the fetch.\n */\n\nimport type { FetchRequest } from '../types.js'\n\nconst PLACEHOLDER = '{{secret}}'\n\nfunction replacePlaceholder(value: string, secret: string): string {\n return value.replaceAll(PLACEHOLDER, secret)\n}\n\nfunction replaceInRecord(\n record: Record<string, string>,\n secret: string,\n): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = replacePlaceholder(value, secret)\n }\n return result\n}\n\n/**\n * Execute a delegated HTTP fetch with the secret injected into the request.\n *\n * @param secret - The secret value to inject\n * @param request - The fetch request template with `{{secret}}` placeholders\n * @returns The fetch Response\n * @internal\n */\nexport async function delegatedFetch(\n secret: string,\n request: FetchRequest,\n): Promise<Response> {\n const url = replacePlaceholder(request.url, secret)\n const headers =\n request.headers !== undefined\n ? replaceInRecord(request.headers, secret)\n : undefined\n const body =\n request.body !== undefined\n ? replacePlaceholder(request.body, secret)\n : undefined\n\n const init: RequestInit = {}\n if (request.method !== undefined) {\n init.method = request.method\n }\n if (headers !== undefined) {\n init.headers = headers\n }\n if (body !== undefined) {\n init.body = body\n }\n\n return fetch(url, init)\n}\n","/**\n * Delegated command execution access pattern.\n *\n * Replaces `{{secret}}` placeholders in command args and environment values,\n * then executes the command.\n */\n\nimport { spawn } from 'node:child_process'\nimport type { ExecRequest, ExecResult } from '../types.js'\n\nconst PLACEHOLDER = '{{secret}}'\n\nfunction replacePlaceholder(value: string, secret: string): string {\n return value.replaceAll(PLACEHOLDER, secret)\n}\n\nfunction replaceInRecord(\n record: Record<string, string>,\n secret: string,\n): Record<string, string> {\n const result: Record<string, string> = {}\n for (const [key, value] of Object.entries(record)) {\n result[key] = replacePlaceholder(value, secret)\n }\n return result\n}\n\n/**\n * Execute a delegated command with the secret injected into args and env.\n *\n * @param secret - The secret value to inject\n * @param request - The exec request template with `{{secret}}` placeholders\n * @returns The command result (stdout, stderr, exitCode)\n * @internal\n */\nexport function delegatedExec(\n secret: string,\n request: ExecRequest,\n): Promise<ExecResult> {\n const args = (request.args ?? []).map((arg) => replacePlaceholder(arg, secret))\n const env =\n request.env !== undefined ? replaceInRecord(request.env, secret) : undefined\n\n return new Promise((resolve, reject) => {\n const spawnOptions: Parameters<typeof spawn>[2] = {\n stdio: ['ignore', 'pipe', 'pipe'],\n }\n if (env !== undefined) {\n spawnOptions.env = { ...process.env, ...env }\n }\n if (request.cwd !== undefined) {\n spawnOptions.cwd = request.cwd\n }\n\n const proc = spawn(request.command, args, spawnOptions)\n let stdout = ''\n let stderr = ''\n\n proc.stdout?.on('data', (data: Buffer) => {\n stdout += data.toString()\n })\n\n proc.stderr?.on('data', (data: Buffer) => {\n stderr += data.toString()\n })\n\n proc.on('close', (code) => {\n resolve({ stdout, stderr, exitCode: code ?? 1 })\n })\n\n proc.on('error', (error) => {\n reject(error)\n })\n })\n}\n","/**\n * Controlled direct access pattern.\n *\n * Provides a `SecretAccessor` backed by a revocable Proxy that:\n * - Exposes a single `.read()` method\n * - Passes a Buffer containing the secret to the callback\n * - Zeros the buffer after the callback returns\n * - Prevents double-read (throws on second call)\n * - Revokes the proxy synchronously after the first `read()` call completes\n * - Redacts itself from Node.js inspect output\n */\n\nimport type { SecretAccessor } from '../types.js'\n\nconst INSPECT_CUSTOM = Symbol.for('nodejs.util.inspect.custom')\n\n/** Extended accessor that also supports custom inspect. */\ninterface SecretAccessorInternal extends SecretAccessor {\n [INSPECT_CUSTOM](): string\n}\n\n/**\n * Proxy target class that satisfies SecretAccessorInternal.\n *\n * Instances have their prototype set to null and are made non-extensible\n * after construction, so all proxy invariants can be met consistently:\n * - getPrototypeOf trap returns null (matches actual prototype)\n * - isExtensible trap returns false (matches actual extensibility)\n * - ownKeys trap includes all own keys (matches non-extensible contract)\n */\nclass SecretAccessorTarget implements SecretAccessorInternal {\n readonly read: (callback: (buf: Buffer) => void) => void\n readonly [INSPECT_CUSTOM]: () => string\n\n constructor(\n readImpl: (callback: (buf: Buffer) => void) => void,\n inspectImpl: () => string,\n ) {\n this.read = readImpl\n this[INSPECT_CUSTOM] = inspectImpl\n }\n}\n\n/**\n * Create a `SecretAccessor` for the given secret value.\n * @internal\n *\n * The accessor is backed by a revocable Proxy with all 13 traps implemented.\n * The proxy is revoked synchronously after the first `read()` call completes\n * (in the `finally` block, after zeroing the buffer). Any subsequent property\n * access will throw a TypeError.\n *\n * This avoids the `queueMicrotask(revoke)` approach which breaks async callers\n * that `await` between receiving the accessor and calling `.read()`.\n */\nexport function createSecretAccessor(secretValue: string): SecretAccessor {\n let consumed = false\n // Holder allows readImpl to close over the revoke function without a let/reassignment.\n const revokeHolder: { fn: (() => void) | undefined } = { fn: undefined }\n\n // Close over the actual read logic.\n function readImpl(callback: (buf: Buffer) => void): void {\n if (consumed) {\n throw new Error('SecretAccessor has already been consumed — call getSecret() again to obtain a new accessor')\n }\n consumed = true\n\n const buf = Buffer.from(secretValue, 'utf8')\n try {\n callback(buf)\n } finally {\n buf.fill(0)\n // Revoke the proxy synchronously so no further property access is possible.\n revokeHolder.fn?.()\n }\n }\n\n function inspectImpl(): string {\n return '[SecretAccessor]'\n }\n\n // Build the proxy target: a class instance with null prototype and\n // non-extensible to satisfy V8's proxy invariants for those traps.\n const target = new SecretAccessorTarget(readImpl, inspectImpl)\n Object.setPrototypeOf(target, null)\n Object.preventExtensions(target)\n\n // All 13 proxy handler traps.\n const handler: Required<ProxyHandler<SecretAccessorInternal>> = {\n get(_t, prop, _receiver) {\n if (prop === 'read') return readImpl\n if (prop === INSPECT_CUSTOM) return inspectImpl\n return undefined\n },\n set(_t, _prop, _value, _receiver) {\n return false\n },\n has(_t, prop) {\n return prop === 'read' || prop === INSPECT_CUSTOM\n },\n deleteProperty(_t, _prop) {\n return false\n },\n apply(_t, _thisArg, _args) {\n throw new TypeError('SecretAccessor is not a function')\n },\n construct(_t, _args, _newTarget) {\n throw new TypeError('SecretAccessor is not a constructor')\n },\n defineProperty(_t, _prop, _descriptor) {\n return false\n },\n getOwnPropertyDescriptor(_t, prop) {\n if (prop === 'read') {\n return { configurable: true, enumerable: true, writable: false, value: readImpl }\n }\n if (prop === INSPECT_CUSTOM) {\n return { configurable: true, enumerable: false, writable: false, value: inspectImpl }\n }\n return undefined\n },\n getPrototypeOf(_t) {\n // Null prototype — matches the actual target prototype after setPrototypeOf(target, null).\n return null\n },\n setPrototypeOf(_t, _proto) {\n return false\n },\n isExtensible(_t) {\n // Non-extensible — matches the actual target extensibility.\n return false\n },\n preventExtensions(_t) {\n // Already non-extensible — trap returns true (success) matching target state.\n return true\n },\n ownKeys(_t) {\n // Must include all own keys of the non-extensible target.\n // The target has 'read' and INSPECT_CUSTOM as own properties.\n return ['read', INSPECT_CUSTOM]\n },\n }\n\n const { proxy, revoke } = Proxy.revocable(target, handler)\n // Wire up the revoke function so readImpl can call it after the callback returns.\n revokeHolder.fn = revoke\n\n return proxy\n}\n","/**\n * Individual preflight check functions for each system dependency.\n */\n\nimport { execCommand } from '../util/exec.js'\nimport type { PreflightCheck } from '../types.js'\n\n/**\n * Parse a semver-like version string and return [major, minor, patch].\n * Returns null if unparseable.\n */\nfunction parseVersion(raw: string): [number, number, number] | null {\n const match = /(\\d+)\\.(\\d+)\\.(\\d+)/.exec(raw)\n if (!match) return null\n const major = parseInt(match[1] ?? '0', 10)\n const minor = parseInt(match[2] ?? '0', 10)\n const patch = parseInt(match[3] ?? '0', 10)\n return [major, minor, patch]\n}\n\n/**\n * Returns true if [aMajor, aMinor, aPatch] >= [bMajor, bMinor, bPatch].\n */\nfunction versionGte(\n a: [number, number, number],\n b: [number, number, number],\n): boolean {\n if (a[0] !== b[0]) return a[0] > b[0]\n if (a[1] !== b[1]) return a[1] > b[1]\n return a[2] >= b[2]\n}\n\n/**\n * Check that openssl is present and >= 1.1.1.\n * @internal\n */\nexport async function checkOpenssl(): Promise<PreflightCheck> {\n const name = 'openssl'\n try {\n const output = await execCommand('openssl', ['version'])\n const parsed = parseVersion(output)\n if (!parsed) {\n return {\n name,\n status: 'version-unsupported',\n version: output,\n reason: 'Could not parse openssl version',\n }\n }\n if (!versionGte(parsed, [1, 1, 1])) {\n return {\n name,\n status: 'version-unsupported',\n version: output,\n reason: 'openssl >= 1.1.1 is required',\n }\n }\n return { name, status: 'ok', version: output }\n } catch {\n return { name, status: 'missing', reason: 'openssl not found in PATH' }\n }\n}\n\n/**\n * Check that bash is present.\n * @internal\n */\nexport async function checkBash(): Promise<PreflightCheck> {\n const name = 'bash'\n try {\n const output = await execCommand('bash', ['--version'])\n const firstLine = output.split('\\n')[0] ?? output\n return { name, status: 'ok', version: firstLine }\n } catch {\n return { name, status: 'missing', reason: 'bash not found in PATH' }\n }\n}\n\n/**\n * Check that PowerShell is present (Windows only).\n * @internal\n */\nexport async function checkPowershell(): Promise<PreflightCheck> {\n const name = 'powershell'\n try {\n const output = await execCommand('powershell', [\n '-Command',\n '$PSVersionTable.PSVersion',\n ])\n const version = output.trim()\n return { name, status: 'ok', version }\n } catch {\n return { name, status: 'missing', reason: 'powershell not found in PATH' }\n }\n}\n\n/**\n * Check that macOS security CLI is present (macOS only, for Keychain access).\n * @internal\n */\nexport async function checkSecurity(): Promise<PreflightCheck> {\n const name = 'security'\n try {\n // `security help` exits with non-zero but writes to stderr; we only need it to exist\n await execCommand('security', ['help'])\n return { name, status: 'ok' }\n } catch (err) {\n // security help exits non-zero intentionally — if we got stderr output, it's present\n const message = err instanceof Error ? err.message : String(err)\n if (message.includes('security')) {\n // The command exists but help exits with a non-zero code\n return { name, status: 'ok' }\n }\n return {\n name,\n status: 'missing',\n reason: 'security command not found in PATH',\n }\n }\n}\n\n/**\n * Check that secret-tool is present (Linux only).\n * @internal\n */\nexport async function checkSecretTool(): Promise<PreflightCheck> {\n const name = 'secret-tool'\n try {\n const output = await execCommand('secret-tool', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'secret-tool not found in PATH (install libsecret-tools)',\n }\n }\n}\n\n/**\n * Check that 1Password CLI (op) is present (optional).\n * @internal\n */\nexport async function checkOp(): Promise<PreflightCheck> {\n const name = 'op'\n try {\n const output = await execCommand('op', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'op (1Password CLI) not found in PATH',\n }\n }\n}\n\n/**\n * Check that ykman (YubiKey Manager CLI) is present (optional).\n * @internal\n */\nexport async function checkYkman(): Promise<PreflightCheck> {\n const name = 'ykman'\n try {\n const output = await execCommand('ykman', ['--version'])\n return { name, status: 'ok', version: output.trim() }\n } catch {\n return {\n name,\n status: 'missing',\n reason: 'ykman (YubiKey Manager) not found in PATH',\n }\n }\n}\n","/**\n * Platform detection utilities.\n */\n\n/**\n * @internal\n */\nexport type Platform = 'darwin' | 'win32' | 'linux'\n\n/** Get the current platform. */\nexport function currentPlatform(): Platform {\n const p = process.platform\n if (p === 'darwin' || p === 'win32' || p === 'linux') {\n return p\n }\n throw new Error(`Unsupported platform: ${p}`)\n}\n\n/** Check if running on macOS. */\nexport function isDarwin(): boolean {\n return process.platform === 'darwin'\n}\n\n/** Check if running on Windows. */\nexport function isWindows(): boolean {\n return process.platform === 'win32'\n}\n\n/** Check if running on Linux. */\nexport function isLinux(): boolean {\n return process.platform === 'linux'\n}\n","/**\n * Doctor runner: orchestrates platform-appropriate checks and aggregates results.\n */\n\nimport {\n checkOpenssl,\n checkBash,\n checkPowershell,\n checkSecurity,\n checkSecretTool,\n checkOp,\n checkYkman,\n} from './checks.js'\nimport { currentPlatform } from '../util/platform.js'\nimport type { PreflightCheck, PreflightResult } from '../types.js'\nimport type { Platform } from '../util/platform.js'\n\n/**\n * Options for running the doctor.\n * @internal\n */\nexport interface RunDoctorOptions {\n /** Override the platform detection (useful for testing). */\n platform?: Platform\n}\n\n/** A doctor check entry pairing the check function with whether it is required. */\ninterface CheckEntry {\n check: () => Promise<PreflightCheck>\n required: boolean\n}\n\n/** Aggregated check entry with its result. */\ninterface ResolvedEntry {\n required: boolean\n result: PreflightCheck\n}\n\n/**\n * Run all platform-appropriate preflight checks and aggregate the results.\n * @internal\n */\nexport async function runDoctor(options?: RunDoctorOptions): Promise<PreflightResult> {\n const platform = options?.platform ?? currentPlatform()\n\n const entries: CheckEntry[] = buildCheckList(platform)\n\n const resolved: ResolvedEntry[] = await Promise.all(\n entries.map(async ({ check, required }) => {\n const result = await check()\n return { required, result }\n }),\n )\n\n const ready = resolved.every(({ required, result }) => {\n if (!required) return true\n return result.status === 'ok'\n })\n\n const warnings: string[] = []\n const nextSteps: string[] = []\n\n for (const { required, result } of resolved) {\n if (result.status === 'missing') {\n if (required) {\n nextSteps.push(`Install missing required dependency: ${result.name}`)\n } else {\n warnings.push(\n `Optional dependency not found: ${result.name}${result.reason !== undefined ? ` — ${result.reason}` : ''}`,\n )\n }\n } else if (result.status === 'version-unsupported') {\n const msg = `${result.name} version is unsupported${result.reason !== undefined ? `: ${result.reason}` : ''}`\n if (required) {\n nextSteps.push(`Upgrade required dependency: ${msg}`)\n } else {\n warnings.push(`Optional dependency version unsupported: ${msg}`)\n }\n }\n }\n\n const checks = resolved.map(({ result }) => result)\n\n return { checks, ready, warnings, nextSteps }\n}\n\nfunction buildCheckList(platform: Platform): CheckEntry[] {\n const entries: CheckEntry[] = [{ check: checkOpenssl, required: true }]\n\n if (platform === 'darwin') {\n entries.push({ check: checkSecurity, required: true })\n entries.push({ check: checkBash, required: false })\n } else if (platform === 'win32') {\n entries.push({ check: checkPowershell, required: true })\n } else {\n // linux\n entries.push({ check: checkBash, required: true })\n entries.push({ check: checkSecretTool, required: true })\n }\n\n // Optional tools on all platforms\n entries.push({ check: checkOp, required: false })\n entries.push({ check: checkYkman, required: false })\n\n return entries\n}\n","/**\n * VaultKeeper main class — wires together all vaultkeeper subsystems.\n */\n\nimport * as crypto from 'node:crypto'\nimport type {\n VaultConfig,\n VaultClaims,\n VaultResponse,\n FetchRequest,\n ExecRequest,\n ExecResult,\n SecretAccessor,\n PreflightResult,\n TrustTier,\n} from './types.js'\nimport { loadConfig, getDefaultConfigDir } from './config.js'\nimport { KeyManager } from './keys/manager.js'\nimport { BackendRegistry } from './backend/registry.js'\nimport type { SecretBackend } from './backend/types.js'\nimport { createToken, decryptToken, extractKid, validateClaims, blockToken } from './jwe/index.js'\nimport { verifyTrust } from './identity/trust.js'\nimport {\n CapabilityToken,\n createCapabilityToken,\n validateCapabilityToken,\n} from './identity/session.js'\nimport { delegatedFetch } from './access/delegated-fetch.js'\nimport { delegatedExec } from './access/delegated-exec.js'\nimport { createSecretAccessor } from './access/controlled-direct.js'\nimport { runDoctor } from './doctor/runner.js'\nimport {\n IdentityMismatchError,\n BackendUnavailableError,\n VaultError,\n KeyRevokedError,\n} from './errors.js'\n\n/** Options for initializing VaultKeeper. */\nexport interface VaultKeeperOptions {\n /** Override the config directory. */\n configDir?: string | undefined\n /** Supply config directly, skipping file load. */\n config?: VaultConfig | undefined\n /** Skip the doctor preflight check. */\n skipDoctor?: boolean | undefined\n}\n\n/** Options for the setup operation. */\nexport interface SetupOptions {\n /** TTL in minutes for the JWE. */\n ttlMinutes?: number | undefined\n /** Usage limit (null for unlimited). */\n useLimit?: number | null | undefined\n /** Executable path for identity binding. Use \"dev\" for dev mode. */\n executablePath?: string | undefined\n /** Trust tier override. */\n trustTier?: TrustTier | undefined\n /** Backend type to use. */\n backendType?: string | undefined\n}\n\n/** Usage tracking for tokens with use limits. */\nconst usageCounts = new Map<string, number>()\n\n/**\n * Main entry point for vaultkeeper. Orchestrates backends, keys, JWE tokens,\n * identity verification, and access patterns.\n */\nexport class VaultKeeper {\n readonly #config: VaultConfig\n readonly #keyManager: KeyManager\n readonly #configDir: string\n #backend: SecretBackend | undefined\n\n private constructor(config: VaultConfig, keyManager: KeyManager, configDir: string) {\n this.#config = config\n this.#keyManager = keyManager\n this.#configDir = configDir\n }\n\n /**\n * Initialize a new VaultKeeper instance.\n * Runs doctor checks (unless skipped), loads config, and sets up the key manager.\n */\n static async init(options?: VaultKeeperOptions): Promise<VaultKeeper> {\n if (options?.skipDoctor !== true) {\n const doctorResult = await runDoctor()\n if (!doctorResult.ready) {\n throw new VaultError(\n `System not ready: ${doctorResult.nextSteps.join('; ')}`,\n )\n }\n }\n\n const configDir = options?.configDir ?? getDefaultConfigDir()\n const config = options?.config ?? (await loadConfig(configDir))\n\n const keyManager = new KeyManager()\n await keyManager.init()\n\n const vault = new VaultKeeper(config, keyManager, configDir)\n vault.#backend = vault.#resolveBackend()\n\n return vault\n }\n\n /** Run doctor checks without full initialization. */\n static async doctor(): Promise<PreflightResult> {\n return runDoctor()\n }\n\n /**\n * Store a secret and return a JWE token that encapsulates it.\n *\n * @param secretName - Identifier for the secret\n * @param options - Setup options\n * @returns Compact JWE string\n */\n async setup(secretName: string, options?: SetupOptions): Promise<string> {\n const backend = this.#requireBackend()\n const backendType = options?.backendType ?? backend.type\n const ttlMinutes = options?.ttlMinutes ?? this.#config.defaults.ttlMinutes\n const trustTier = options?.trustTier ?? this.#config.defaults.trustTier\n const useLimit = options?.useLimit ?? null\n const executablePath = options?.executablePath ?? 'dev'\n\n const secretValue = await backend.retrieve(secretName)\n\n let exeIdentity: string\n if (executablePath === 'dev' || this.#isDevModeExecutable(executablePath)) {\n exeIdentity = 'dev'\n } else {\n const trustResult = await verifyTrust(executablePath, {\n configDir: this.#configDir,\n })\n if (trustResult.tofuConflict) {\n throw new IdentityMismatchError(\n 'Executable hash changed — re-approval required',\n 'previously-approved',\n trustResult.identity.hash,\n )\n }\n exeIdentity = trustResult.identity.hash\n }\n\n const now = Math.floor(Date.now() / 1000)\n const claims: VaultClaims = {\n jti: crypto.randomUUID(),\n exp: now + ttlMinutes * 60,\n iat: now,\n sub: secretName,\n exe: exeIdentity,\n use: useLimit,\n tid: trustTier,\n bkd: backendType,\n val: secretValue,\n ref: secretName,\n }\n\n const currentKey = this.#keyManager.getCurrentKey()\n return createToken(currentKey.key, claims, { kid: currentKey.id })\n }\n\n /**\n * Decrypt a JWE, validate claims, verify executable identity, and return\n * an opaque CapabilityToken.\n *\n * @param jwe - Compact JWE string from setup()\n * @returns Opaque capability token for use with fetch/exec/getSecret\n */\n async authorize(jwe: string): Promise<{ token: CapabilityToken; response: VaultResponse }> {\n const kid = extractKid(jwe)\n const { claims, keyStatus } = await this.#decryptWithKeyResolution(jwe, kid)\n\n // Validate claims (expiry, blocklist, usage)\n const jti = claims.jti\n const currentCount = usageCounts.get(jti) ?? 0\n validateClaims(claims, currentCount)\n\n // Track usage and evict finished tokens to prevent unbounded map growth.\n const newCount = currentCount + 1\n if (claims.use !== null && newCount >= claims.use) {\n // Token has reached its usage limit — remove from tracking and block it\n // so future attempts hit the blocklist rather than the usageCounts map.\n usageCounts.delete(jti)\n blockToken(jti)\n } else {\n usageCounts.set(jti, newCount)\n }\n\n const token = createCapabilityToken(claims)\n\n const response: VaultResponse = { keyStatus }\n if (keyStatus === 'previous') {\n // Re-encrypt with current key\n const currentKey = this.#keyManager.getCurrentKey()\n const rotatedJwt = await createToken(currentKey.key, claims, { kid: currentKey.id })\n response.rotatedJwt = rotatedJwt\n }\n\n return { token, response }\n }\n\n /**\n * Execute a delegated HTTP fetch, injecting the secret from the token.\n *\n * The secret value is substituted for every `{{secret}}` placeholder found\n * in `request.url`, `request.headers`, and `request.body` before the fetch\n * is executed. The raw secret is never exposed in the return value.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @param request - The fetch request template. Use `{{secret}}` as a\n * placeholder wherever the secret value should be injected.\n * @returns The `Response` from the underlying `fetch()` call, together with\n * the vault metadata (`vaultResponse`).\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n async fetch(\n token: CapabilityToken,\n request: FetchRequest,\n ): Promise<{ response: Response; vaultResponse: VaultResponse }> {\n const claims = validateCapabilityToken(token)\n const response = await delegatedFetch(claims.val, request)\n return {\n response,\n vaultResponse: { keyStatus: 'current' },\n }\n }\n\n /**\n * Execute a delegated command, injecting the secret from the token.\n *\n * The secret value is substituted for every `{{secret}}` placeholder found\n * in `request.args` and `request.env` values before the process is spawned.\n * The raw secret is never exposed in the return value.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @param request - The exec request template. Use `{{secret}}` as a\n * placeholder wherever the secret value should be injected.\n * @returns The command result (`stdout`, `stderr`, `exitCode`) together with\n * the vault metadata (`vaultResponse`).\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n async exec(\n token: CapabilityToken,\n request: ExecRequest,\n ): Promise<{ result: ExecResult; vaultResponse: VaultResponse }> {\n const claims = validateCapabilityToken(token)\n const result = await delegatedExec(claims.val, request)\n return {\n result,\n vaultResponse: { keyStatus: 'current' },\n }\n }\n\n /**\n * Create a controlled-direct `SecretAccessor` from a capability token.\n *\n * The accessor wraps the secret in a single-use, auto-zeroing `Buffer`. The\n * secret is accessible only through the `read()` callback and is zeroed\n * immediately after the callback returns.\n *\n * @param token - A `CapabilityToken` obtained from `authorize()`.\n * @returns A `SecretAccessor` that can be read exactly once.\n * @throws {Error} If `token` is invalid or was not created by this vault\n * instance.\n */\n getSecret(token: CapabilityToken): SecretAccessor {\n const claims = validateCapabilityToken(token)\n return createSecretAccessor(claims.val)\n }\n\n /**\n * Rotate the current encryption key.\n *\n * The previous key remains valid for decryption during the grace period\n * configured in `keyRotation.gracePeriodDays`. JWEs presented during the\n * grace period return a `rotatedJwt` in the `VaultResponse` so callers can\n * persist the updated token.\n *\n * @throws {RotationInProgressError} If a rotation is already in progress\n * (i.e. a previous key is still within its grace period).\n */\n async rotateKey(): Promise<void> {\n const gracePeriodMs = this.#config.keyRotation.gracePeriodDays * 24 * 60 * 60 * 1000\n this.#keyManager.rotateKey(gracePeriodMs)\n await Promise.resolve()\n }\n\n /**\n * Emergency key revocation — invalidates the previous key immediately.\n *\n * After revocation, any JWE that was encrypted with the revoked key will\n * be permanently unreadable. A new encryption key is generated automatically\n * so that `setup()` can be called immediately after revocation.\n */\n async revokeKey(): Promise<void> {\n this.#keyManager.revokeKey()\n await Promise.resolve()\n }\n\n /**\n * Add or remove an executable from the development-mode whitelist.\n *\n * When an executable is in the development-mode list, identity verification\n * (TOFU hash checking) is skipped for that executable during `setup()`. This\n * is intended for local development workflows where the binary changes\n * frequently.\n *\n * @param executablePath - Absolute path to the executable to add or remove.\n * @param enabled - Pass `true` to add the executable to the list, `false`\n * to remove it.\n */\n async setDevelopmentMode(executablePath: string, enabled: boolean): Promise<void> {\n if (this.#config.developmentMode === undefined) {\n if (enabled) {\n this.#config.developmentMode = { executables: [executablePath] }\n }\n return\n }\n\n const exes = this.#config.developmentMode.executables\n const idx = exes.indexOf(executablePath)\n\n if (enabled && idx === -1) {\n exes.push(executablePath)\n } else if (!enabled && idx !== -1) {\n exes.splice(idx, 1)\n }\n\n await Promise.resolve()\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n #resolveBackend(): SecretBackend {\n const enabledBackends = this.#config.backends.filter((b) => b.enabled)\n if (enabledBackends.length === 0) {\n throw new BackendUnavailableError(\n 'No enabled backends configured',\n 'none-enabled',\n this.#config.backends.map((b) => b.type),\n )\n }\n\n const firstEnabled = enabledBackends[0]\n if (firstEnabled === undefined) {\n throw new BackendUnavailableError(\n 'No enabled backends configured',\n 'none-enabled',\n [],\n )\n }\n\n return BackendRegistry.create(firstEnabled.type)\n }\n\n #requireBackend(): SecretBackend {\n if (this.#backend === undefined) {\n throw new VaultError('VaultKeeper backend not initialized')\n }\n return this.#backend\n }\n\n #isDevModeExecutable(executablePath: string): boolean {\n if (this.#config.developmentMode === undefined) {\n return false\n }\n return this.#config.developmentMode.executables.includes(executablePath)\n }\n\n async #decryptWithKeyResolution(\n jwe: string,\n kid: string | undefined,\n ): Promise<{ claims: VaultClaims; keyStatus: 'current' | 'previous' }> {\n // Try to find key by kid\n if (kid !== undefined) {\n const key = this.#keyManager.findKeyById(kid)\n if (key !== undefined) {\n const claims = await decryptToken(key.key, jwe)\n const isCurrent = key.id === this.#keyManager.getCurrentKey().id\n return {\n claims,\n keyStatus: isCurrent ? 'current' : 'previous',\n }\n }\n // kid not found — key may have been revoked\n throw new KeyRevokedError(`Key ${kid} not found — may have been revoked`)\n }\n\n // No kid — try current key first, then previous\n try {\n const claims = await decryptToken(this.#keyManager.getCurrentKey().key, jwe)\n return { claims, keyStatus: 'current' }\n } catch {\n const previousKey = this.#keyManager.getPreviousKey()\n if (previousKey !== undefined) {\n const claims = await decryptToken(previousKey.key, jwe)\n return { claims, keyStatus: 'previous' }\n }\n throw new VaultError('Failed to decrypt JWE with any available key')\n }\n }\n}\n"]}
|