{"version":3,"sources":["../src/canonical.ts","../src/secure.ts","../src/index.ts"],"names":["toHex","randomBytes","toBase64url","hmac","fromBase64url","hmacVerify","enc","dec","nowSec","resolveExp"],"mappings":";;;;;AASO,SAAS,YAAA,CAAa,CAAA,EAAQ,QAAA,EAAkB,MAAA,GAAS,KAAA,EAAe;AAC7E,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,CAAA,CAAE,aAAa,OAAA,EAAS,CAAA,CACxC,MAAA,CAAO,CAAC,CAAC,CAAC,CAAA,KAAM,CAAA,KAAM,QAAQ,CAAA,CAC9B,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAO,CAAA,CAAE,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA,GAAI,EAAA,GAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,IAAI,CAAE,CAAA;AAC1D,EAAA,MAAM,IAAA,GAAO,MAAA,GACT,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAwB,CAAA,EAAG,CAAC,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,GACvC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAA,KAAwB,CAAA,EAAG,kBAAA,CAAmB,CAAC,CAAC,CAAA,CAAA,EAAI,kBAAA,CAAmB,CAAC,CAAC,CAAA,CAAA;AACnF,EAAA,OAAO,CAAA,EAAG,CAAA,CAAE,MAAM,CAAA,EAAG,CAAA,CAAE,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA;AAC/D;ACgBA,IAAM,GAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAM,GAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAM,SAAS,MAAc,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAEzD,SAAS,WAAW,CAAA,EAAsC;AACxD,EAAA,IAAI,EAAE,SAAA,KAAc,MAAA,SAAkB,IAAA,CAAK,KAAA,CAAM,EAAE,SAAS,CAAA;AAC5D,EAAA,IAAI,CAAA,CAAE,SAAA,KAAc,MAAA,EAAW,OAAA,CAAQ,CAAA,CAAE,GAAA,IAAO,MAAA,EAAO,IAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,SAAS,CAAA;AAClF,EAAA,OAAO,MAAA;AACT;AAuGA,SAAS,WAAW,IAAA,EAA4D;AAC9E,EAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,EAAA,MAAM,IAAiB,EAAC;AACxB,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW,CAAA,CAAE,IAAI,IAAA,CAAK,MAAA;AAC1C,EAAA,IAAI,IAAA,CAAK,EAAA,KAAO,MAAA,EAAW,CAAA,CAAE,IAAI,IAAA,CAAK,EAAA;AACtC,EAAA,IAAI,IAAA,CAAK,UAAA,KAAe,MAAA,EAAW,CAAA,CAAE,IAAI,IAAA,CAAK,UAAA;AAC9C,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,CAAE,SAAS,CAAA,GAAI,MAAA;AACrC;AAGA,SAAS,YAAA,CAAa,GAA4B,GAAA,EAA0C;AAC1F,EAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,EAAA,MAAM,CAAA,GAAI,OAAO,EAAC;AAClB,EAAA,IAAI,CAAA,CAAE,CAAA,KAAM,MAAA,IAAA,CAAc,CAAA,CAAE,MAAA,IAAU,EAAA,EAAI,WAAA,EAAY,KAAM,CAAA,CAAE,CAAA,CAAE,WAAA,EAAY,EAAG,OAAO,KAAA;AACtF,EAAA,IAAI,EAAE,CAAA,KAAM,MAAA,IAAa,EAAE,EAAA,KAAO,CAAA,CAAE,GAAG,OAAO,KAAA;AAC9C,EAAA,IAAI,CAAA,CAAE,CAAA,KAAM,MAAA,IAAa,CAAA,CAAE,CAAA,CAAE,IAAA,IAAQ,EAAA,EAAI,UAAA,CAAW,CAAA,CAAE,CAAC,CAAA,EAAG,OAAO,KAAA;AACjE,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,eAAe,IAAA,EAGtB;AACA,EAAA,IAAI,KAAK,IAAA,EAAM;AACb,IAAA,MAAM,EAAA,GAAK,KAAK,KAAA,IAAS,MAAA,CAAO,KAAK,IAAA,CAAK,IAAI,EAAE,CAAC,CAAA;AACjD,IAAA,IAAI,OAAO,MAAA,IAAa,IAAA,CAAK,IAAA,CAAK,EAAE,MAAM,MAAA,EAAW;AACnD,MAAA,MAAM,IAAI,MAAM,+CAA+C,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,IAAA,CAAK,KAAK,EAAE,CAAA,EAAG,OAAO,EAAA,EAAG;AAAA,EAC5C;AACA,EAAA,IAAI,KAAK,MAAA,KAAW,MAAA,SAAkB,EAAE,MAAA,EAAQ,KAAK,MAAA,EAAO;AAC5D,EAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAC/E;AAGA,SAAS,gBAAA,CAAiB,GAAuB,IAAA,EAA8D;AAC7G,EAAA,IAAI,MAAM,MAAA,IAAa,IAAA,CAAK,MAAM,OAAO,IAAA,CAAK,KAAK,CAAC,CAAA;AACpD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW,OAAO,IAAA,CAAK,MAAA;AAC3C,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,kBAAkB,KAAA,EAA6C;AACtE,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,EAAA;AAC3B,EAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,GAAQ,GAAG,OAAO,IAAA,CAAK,MAAM,KAAK,CAAA;AACnE,EAAA,OAAO,CAAA;AACT;AAoBA,eAAsB,UAAA,CAAW,MAAiB,IAAA,EAA0C;AAC1F,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,eAAe,IAAI,CAAA;AAC7C,EAAA,MAAM,GAAA,GAAM,WAAW,IAAI,CAAA;AAC3B,EAAA,MAAM,UAAA,GAAuC,EAAE,CAAA,EAAG,IAAA,EAAK;AACvD,EAAA,IAAI,GAAA,KAAQ,MAAA,EAAW,UAAA,CAAW,CAAA,GAAI,GAAA;AACtC,EAAA,IAAI,KAAA,KAAU,MAAA,EAAW,UAAA,CAAW,CAAA,GAAI,KAAA;AACxC,EAAA,MAAM,CAAA,GAAI,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA;AAC9B,EAAA,IAAI,CAAA,aAAc,CAAA,GAAI,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AACvC,EAAA,IAAI,KAAK,CAAA,EAAG,UAAA,CAAW,IAAIA,YAAA,CAAMC,kBAAA,CAAY,EAAE,CAAC,CAAA;AAChD,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,MAAA,EAAW,UAAA,CAAW,IAAI,IAAA,CAAK,MAAA;AAEnD,EAAA,MAAM,OAAA,GAAUC,mBAAY,GAAA,CAAI,MAAA,CAAO,KAAK,SAAA,CAAU,UAAU,CAAC,CAAC,CAAA;AAClE,EAAA,MAAM,GAAA,GAAMA,mBAAY,MAAMC,WAAA,CAAK,QAAQ,OAAA,EAAS,IAAA,CAAK,SAAA,IAAa,SAAS,CAAC,CAAA;AAChF,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC1B;AAgBA,eAAsB,YAAA,CACpB,OACA,IAAA,EACgC;AAChC,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC7B,EAAA,IAAI,GAAA,IAAO,CAAA,IAAK,GAAA,KAAQ,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AACrF,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAClC,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,GAAA,GAAM,CAAC,CAAA;AAE/B,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAWC,qBAAc,GAAG,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,KAAK,KAAA,CAAM,GAAA,CAAI,OAAOA,oBAAA,CAAc,OAAO,CAAC,CAAC,CAAA;AAAA,EACrD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,GAAA,CAAI,CAAA,EAAG,IAAI,CAAA;AAC3C,EAAA,IAAI,WAAW,MAAA,EAAW,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,aAAA,EAAc;AAEvE,EAAA,MAAM,KAAA,GAAQ,MAAMC,iBAAA,CAAW,MAAA,EAAQ,SAAS,QAAA,EAAU,IAAA,CAAK,aAAa,SAAS,CAAA;AACrF,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,eAAA,EAAgB;AAE3D,EAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAW;AACvB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,MAAA,EAAO;AAC/B,IAAA,IAAI,GAAA,GAAM,GAAA,CAAI,CAAA,IAAK,IAAA,CAAK,kBAAkB,CAAA,CAAA,EAAI;AAC5C,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,SAAA,EAAW,SAAA,EAAW,IAAI,CAAA,EAAE;AAAA,IAC7D;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,EAAG;AACtC,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,SAAA,EAAW,SAAA,EAAW,IAAI,CAAA,EAAE;AAAA,EAC7D;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,IAAA;AAAA,IACP,MAAM,GAAA,CAAI,CAAA;AAAA,IACV,QAAQ,GAAA,CAAI,CAAA;AAAA,IACZ,OAAO,GAAA,CAAI,CAAA;AAAA,IACX,OAAO,GAAA,CAAI,CAAA;AAAA,IACX,WAAW,GAAA,CAAI;AAAA,GACjB;AACF;AAmBA,IAAM,SAAA,GAAY,KAAA;AAClB,IAAM,WAAA,GAAc,OAAA;AACpB,IAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAM,aAAA,GAAgB,IAAA;AACtB,IAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAM,YAAA,GAAe,IAAA;AAcrB,eAAsB,aAAA,CAAc,KAAa,IAAA,EAA6C;AAC5F,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,EAAE,MAAA,EAAQ,KAAA,EAAM,GAAI,eAAe,IAAI,CAAA;AAC7C,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,EAAA,CAAA,CAAE,YAAA,CAAa,OAAO,QAAQ,CAAA;AAE9B,EAAA,MAAM,GAAA,GAAM,WAAW,IAAI,CAAA;AAC3B,EAAA,IAAI,GAAA,KAAQ,QAAW,CAAA,CAAE,YAAA,CAAa,IAAI,QAAA,EAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAC/D,EAAA,IAAI,UAAU,MAAA,EAAW,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,WAAW,KAAK,CAAA;AAC5D,EAAA,MAAM,EAAA,GAAK,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AACvC,EAAA,IAAI,EAAA,GAAK,CAAA,EAAG,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,aAAaL,YAAA,CAAMC,kBAAA,CAAY,EAAE,CAAC,CAAC,CAAA;AAClE,EAAA,IAAI,IAAA,CAAK,IAAA,EAAM,MAAA,KAAW,MAAA,EAAW,CAAA,CAAE,aAAa,GAAA,CAAI,iBAAA,EAAmB,IAAA,CAAK,IAAA,CAAK,MAAM,CAAA;AAC3F,EAAA,IAAI,IAAA,CAAK,IAAA,EAAM,EAAA,KAAO,MAAA,EAAW,CAAA,CAAE,aAAa,GAAA,CAAI,aAAA,EAAe,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA;AAC/E,EAAA,IAAI,IAAA,CAAK,IAAA,EAAM,UAAA,KAAe,MAAA,EAAW,CAAA,CAAE,aAAa,GAAA,CAAI,iBAAA,EAAmB,IAAA,CAAK,IAAA,CAAK,UAAU,CAAA;AACnG,EAAA,IAAI,IAAA,CAAK,WAAW,MAAA,EAAW;AAC7B,IAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,YAAA,EAAcC,kBAAA,CAAY,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,IAAA,CAAK,MAAM,CAAC,CAAC,CAAC,CAAA;AAAA,EACvF;AAEA,EAAA,MAAM,GAAA,GAAMA,kBAAA,CAAY,MAAMC,WAAA,CAAK,MAAA,EAAQ,YAAA,CAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,CAAK,SAAA,IAAa,SAAS,CAAC,CAAA;AAClG,EAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAA,EAAU,GAAG,CAAA;AAChC,EAAA,OAAO,EAAE,QAAA,EAAS;AACpB;AAOA,eAAsB,eAAA,CACpB,KACA,IAAA,EACoC;AACpC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAElC,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAA,GAAI,IAAI,IAAI,GAAG,CAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA;AACvC,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,WAAA,EAAY;AAErD,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAWC,qBAAc,GAAG,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,SAAS,CAAA,IAAK,MAAA;AAC/C,EAAA,MAAM,MAAA,GAAS,gBAAA,CAAiB,KAAA,EAAO,IAAI,CAAA;AAC3C,EAAA,IAAI,WAAW,MAAA,EAAW,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,aAAA,EAAc;AAEvE,EAAA,MAAM,GAAA,GAAM,KAAK,SAAA,IAAa,SAAA;AAC9B,EAAA,MAAM,KAAA,GACH,MAAMC,iBAAA,CAAW,MAAA,EAAQ,aAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,QAAA,EAAU,GAAG,CAAA,IACjE,KAAK,sBAAA,KAA2B,IAAA,IAAS,MAAMA,iBAAA,CAAW,MAAA,EAAQ,YAAA,CAAa,GAAG,QAAA,EAAU,IAAI,CAAA,EAAG,QAAA,EAAU,GAAG,CAAA;AACnH,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,eAAA,EAAgB;AAE3D,EAAA,IAAI,SAAA;AACJ,EAAA,MAAM,MAAA,GAAS,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA;AAC1C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,GAAA,GAAM,OAAO,MAAM,CAAA;AACzB,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACxB,MAAA,SAAA,GAAY,GAAA;AACZ,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAO,MAAA,EAAO;AAC/B,MAAA,IAAI,GAAA,GAAM,GAAA,IAAO,IAAA,CAAK,cAAA,IAAkB,CAAA,CAAA,EAAI,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,SAAA,EAAW,SAAA,EAAW,GAAA,EAAI;AAAA,IACvG;AAAA,EACF;AAEA,EAAA,MAAM,IAAiB,EAAC;AACxB,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,iBAAiB,CAAA;AAC/C,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,aAAa,CAAA;AAC3C,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,iBAAiB,CAAA;AAC/C,EAAA,IAAI,EAAA,KAAO,IAAA,EAAM,CAAA,CAAE,CAAA,GAAI,EAAA;AACvB,EAAA,IAAI,EAAA,KAAO,IAAA,EAAM,CAAA,CAAE,CAAA,GAAI,EAAA;AACvB,EAAA,IAAI,EAAA,KAAO,IAAA,EAAM,CAAA,CAAE,CAAA,GAAI,EAAA;AACvB,EAAA,IAAI,CAAC,YAAA,CAAa,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,MAAA,EAAW,IAAA,CAAK,OAAO,CAAA,EAAG;AACtE,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAW,SAAA,EAAU;AAAA,EACtD;AAEA,EAAA,IAAI,MAAA;AACJ,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,YAAY,CAAA;AAC1C,EAAA,IAAI,EAAA,EAAI;AACN,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,KAAK,KAAA,CAAM,GAAA,CAAI,OAAOD,oBAAA,CAAc,EAAE,CAAC,CAAC,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,aAAa,SAAA,EAAU;AAAA,IACxD;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,WAAW,CAAA,IAAK,MAAA;AACjD,EAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,MAAA,EAAQ,KAAA,EAAO,OAAO,SAAA,EAAU;AACxD;AAOO,SAAS,aAAA,CAAc,QAAQ,EAAA,EAAY;AAChD,EAAA,OAAOJ,YAAA,CAAMC,kBAAA,CAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,KAAK,CAAC,CAAC,CAAC,CAAA;AAC1D;AA4BO,SAAS,YAAA,CACd,YAAA,EACA,IAAA,GAA4B,EAAC,EACT;AACpB,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,OAAA,KAAY,MAAA,IAAa,IAAA,CAAK,OAAA,GAAU,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,OAAO,CAAA,GAAI,CAAA;AAC5F,EAAA,MAAM,KAAA,GAAQ,iBAAiB,MAAA,IAAa,YAAA,GAAe,IAAI,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA,GAAI,CAAA;AAC1F,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,IAAA,EAAM,KAAA,EAAO,WAAW,CAAA,EAAE;AAAA,EAChD;AACA,EAAA,MAAM,OAAO,KAAA,GAAQ,CAAA;AACrB,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,UAAU,IAAA,EAAK;AACrD;;;ACxbA,IAAMK,IAAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAMC,IAAAA,GAAM,IAAI,WAAA,EAAY;AAC5B,IAAMC,UAAS,MAAc,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAiBzD,SAASC,YAAW,CAAA,EAAsC;AACxD,EAAA,IAAI,EAAE,SAAA,KAAc,MAAA,SAAkB,IAAA,CAAK,KAAA,CAAM,EAAE,SAAS,CAAA;AAC5D,EAAA,IAAI,CAAA,CAAE,SAAA,KAAc,MAAA,EAAW,OAAA,CAAQ,CAAA,CAAE,GAAA,IAAOD,OAAAA,EAAO,IAAK,IAAA,CAAK,KAAA,CAAM,CAAA,CAAE,SAAS,CAAA;AAClF,EAAA,OAAO,MAAA;AACT;AAyCA,eAAsB,IAAA,CAAK,MAAiB,IAAA,EAAoC;AAC9E,EAAA,MAAM,GAAA,GAAMC,YAAW,IAAI,CAAA;AAC3B,EAAA,MAAM,UAAA,GAAiC,EAAE,CAAA,EAAG,IAAA,EAAK;AACjD,EAAA,IAAI,GAAA,KAAQ,MAAA,EAAW,UAAA,CAAW,CAAA,GAAI,GAAA;AACtC,EAAA,MAAM,OAAA,GAAUP,mBAAYI,IAAAA,CAAI,MAAA,CAAO,KAAK,SAAA,CAAU,UAAU,CAAC,CAAC,CAAA;AAClE,EAAA,MAAM,GAAA,GAAMJ,kBAAAA,CAAY,MAAMC,WAAAA,CAAK,IAAA,CAAK,QAAQ,OAAA,EAAS,IAAA,CAAK,SAAA,IAAa,SAAS,CAAC,CAAA;AACrF,EAAA,OAAO,CAAA,EAAG,OAAO,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC1B;AAUA,eAAsB,MAAA,CAAsB,OAAe,IAAA,EAA+C;AACxG,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC7B,EAAA,IAAI,GAAA,IAAO,CAAA,IAAK,GAAA,KAAQ,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AACrF,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AAClC,EAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,GAAA,GAAM,CAAC,CAAA;AAE/B,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAWC,qBAAc,GAAG,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAMC,iBAAAA,CAAW,IAAA,CAAK,QAAQ,OAAA,EAAS,QAAA,EAAU,IAAA,CAAK,SAAA,IAAa,SAAS,CAAA;AAC1F,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,eAAA,EAAgB;AAE3D,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,KAAK,KAAA,CAAME,IAAAA,CAAI,OAAOH,oBAAAA,CAAc,OAAO,CAAC,CAAC,CAAA;AAAA,EACrD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,IAAI,GAAA,CAAI,MAAM,MAAA,EAAW;AACvB,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAOI,OAAAA,EAAO;AAC/B,IAAA,IAAI,GAAA,GAAM,GAAA,CAAI,CAAA,IAAK,IAAA,CAAK,qBAAqB,CAAA,CAAA,EAAI;AAC/C,MAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,SAAA,EAAW,SAAA,EAAW,IAAI,CAAA,EAAE;AAAA,IAC7D;AAAA,EACF;AACA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,EAAG,SAAA,EAAW,IAAI,CAAA,EAAE;AACtD;AAGA,eAAsB,OAAA,CAAQ,OAAe,IAAA,EAAuC;AAClF,EAAA,OAAA,CAAQ,MAAM,MAAA,CAAO,KAAA,EAAO,IAAI,CAAA,EAAG,KAAA;AACrC;AA6BA,eAAsB,OAAA,CAAQ,KAAa,IAAA,EAAuC;AAChF,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,EAAA,CAAA,CAAE,YAAA,CAAa,OAAO,QAAQ,CAAA;AAC9B,EAAA,MAAM,GAAA,GAAMC,YAAW,IAAI,CAAA;AAC3B,EAAA,IAAI,GAAA,KAAQ,QAAW,CAAA,CAAE,YAAA,CAAa,IAAI,QAAA,EAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAC/D,EAAA,MAAM,GAAA,GAAMP,kBAAAA,CAAY,MAAMC,WAAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,YAAA,CAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,IAAA,CAAK,SAAA,IAAa,SAAS,CAAC,CAAA;AACvG,EAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAA,EAAU,GAAG,CAAA;AAChC,EAAA,OAAO,EAAE,QAAA,EAAS;AACpB;AAUA,eAAsB,SAAA,CAAU,KAAa,IAAA,EAAsD;AACjG,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAClC,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,KAAA;AAElC,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAA,GAAI,IAAI,IAAI,GAAG,CAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,GAAA,GAAM,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA;AACvC,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,WAAA,EAAY;AAErD,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAWC,qBAAc,GAAG,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AAEA,EAAA,MAAM,GAAA,GAAM,KAAK,SAAA,IAAa,SAAA;AAC9B,EAAA,MAAM,KAAA,GACH,MAAMC,iBAAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,aAAa,CAAA,EAAG,QAAQ,CAAA,EAAG,QAAA,EAAU,GAAG,CAAA,IACtE,KAAK,sBAAA,KAA2B,IAAA,IAAS,MAAMA,iBAAAA,CAAW,IAAA,CAAK,MAAA,EAAQ,YAAA,CAAa,CAAA,EAAG,QAAA,EAAU,IAAI,CAAA,EAAG,QAAA,EAAU,GAAG,CAAA;AACxH,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,eAAA,EAAgB;AAE3D,EAAA,MAAM,MAAA,GAAS,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,QAAQ,CAAA;AAC1C,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAM,GAAA,GAAM,OAAO,MAAM,CAAA;AACzB,IAAA,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG;AACxB,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,IAAOG,OAAAA,EAAO;AAC/B,MAAA,IAAI,GAAA,GAAM,GAAA,IAAO,IAAA,CAAK,iBAAA,IAAqB,CAAA,CAAA,EAAI,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,SAAA,EAAW,SAAA,EAAW,GAAA,EAAI;AACxG,MAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,GAAA,EAAI;AAAA,IACvC;AAAA,EACF;AACA,EAAA,OAAO,EAAE,OAAO,IAAA,EAAK;AACvB;AAoBA,eAAsB,SAAA,CAAU,OAAA,EAAiB,IAAA,EAAiB,IAAA,EAAyC;AACzG,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AACnC,EAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,OAAO,CAAA;AACzB,EAAA,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,KAAA,IAAS,SAAS,KAAK,CAAA;AAC/C,EAAA,OAAO,EAAE,QAAA,EAAS;AACpB;AAGA,eAAsB,aAAA,CACpB,KACA,IAAA,EAC0B;AAC1B,EAAA,IAAI,CAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAA,GAAI,IAAI,IAAI,GAAG,CAAA;AAAA,EACjB,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,WAAA,EAAY;AAAA,EAC7C;AACA,EAAA,MAAM,QAAQ,CAAA,CAAE,YAAA,CAAa,GAAA,CAAI,IAAA,CAAK,SAAS,OAAO,CAAA;AACtD,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAE,KAAA,EAAO,KAAA,EAAO,QAAQ,WAAA,EAAY;AACvD,EAAA,OAAO,MAAA,CAAU,OAAO,IAAI,CAAA;AAC9B","file":"index.cjs","sourcesContent":["/**\n * The string a signed URL's signature covers: origin + path + the query sorted\n * by key, with every key and value percent-encoded.\n *\n * Encoding is what makes it unambiguous. Before 1.2.0 the decoded values were\n * joined as-is, so `?name=x%26role%3Dadmin` (one parameter) and\n * `?name=x&role=admin` (two) produced the same string and shared a signature:\n * anyone who could get a value of their choosing signed could add parameters.\n */\nexport function canonicalize(u: URL, sigParam: string, legacy = false): string {\n  const params = [...u.searchParams.entries()]\n    .filter(([k]) => k !== sigParam)\n    .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0));\n  const pair = legacy\n    ? ([k, v]: [string, string]) => `${k}=${v}`\n    : ([k, v]: [string, string]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`;\n  return `${u.origin}${u.pathname}?${params.map(pair).join(\"&\")}`;\n}\n\n/**\n * Accept signatures made with the pre-1.2.0 canonical form, so links issued\n * before the upgrade keep working during a migration. Those signatures remain\n * forgeable as described above; turn this off once old links have expired.\n */\nexport interface LegacySignatureOption {\n  acceptLegacySignatures?: boolean;\n}\n","/**\n * @lacspace/signed-url — secure layer (additive, new in 1.1.0)\n *\n * A superset of the classic {@link sign}/{@link verify} and\n * {@link signUrl}/{@link verifyUrl} helpers that adds, all optional and fully\n * backward compatible with the same on-the-wire `\"<payload>.<signature>\"`\n * token format and the same `?exp=…&sig=…` URL scheme:\n *\n *   1. Key rotation — sign with one of several named secrets (a key id is\n *      stamped in the signature) and verify against a key *set*, so secrets can\n *      rotate without invalidating live tokens / URLs.\n *   2. Binding constraints — optionally bind a signature to an HTTP method, a\n *      client IP and/or a required path prefix; verify enforces whatever was\n *      bound (unbound behaviour is identical to the classic helpers).\n *   3. One-time / max-uses nonce — embed a random nonce in the signature and a\n *      pure {@link consumeNonce} checker so callers can enforce single-use /\n *      max-N-use against their own store (storage stays the caller's).\n *   4. Clock tolerance — an optional `clockTolerance` (leeway seconds) on expiry.\n *   5. Signed claims — attach arbitrary small, tamper-proof metadata that\n *      verify returns.\n *\n * Built on the same @lacspace/crypto primitives — no new dependencies.\n */\nimport { canonicalize, type LegacySignatureOption } from \"./canonical\";\nimport { hmac, hmacVerify, toBase64url, fromBase64url, randomBytes, toHex } from \"@lacspace/crypto\";\nimport type {\n  Secret,\n  SignAlgorithm,\n  TokenData,\n  ExpiryOptions,\n  FailReason,\n} from \"./index\";\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\nconst nowSec = (): number => Math.floor(Date.now() / 1000);\n\nfunction resolveExp(o: ExpiryOptions): number | undefined {\n  if (o.expiresAt !== undefined) return Math.floor(o.expiresAt);\n  if (o.expiresIn !== undefined) return (o.now ?? nowSec()) + Math.floor(o.expiresIn);\n  return undefined;\n}\n\n/* ------------------------------------------------------------------ *\n * Shared types\n * ------------------------------------------------------------------ */\n\n/** A named set of secrets for key rotation: `{ \"2024\": secretA, \"2025\": secretB }`. */\nexport type KeySet = Record<string, Secret>;\n\n/**\n * Optional constraints bound into the signature. Whatever is set here must be\n * satisfied by the {@link RequestContext} passed to verify, or verification\n * fails with reason `\"binding\"`. Anything left unset is not enforced.\n */\nexport interface BindConstraints {\n  /** Required HTTP method (case-insensitive), e.g. `\"POST\"`. */\n  method?: string;\n  /** Required exact client IP, e.g. `\"203.0.113.7\"`. */\n  ip?: string;\n  /** Required path prefix the request path must start with, e.g. `\"/files/\"`. */\n  pathPrefix?: string;\n}\n\n/** Runtime request context supplied to verify, checked against {@link BindConstraints}. */\nexport interface RequestContext {\n  method?: string;\n  ip?: string;\n  path?: string;\n}\n\n/** Reasons a secure verify can fail — the classic reasons plus rotation/binding. */\nexport type SecureFailReason = FailReason | \"unknown-key\" | \"binding\";\n\nexport interface SecureSignOptions extends ExpiryOptions {\n  /** Single secret (classic mode). Provide this OR `keys`. */\n  secret?: Secret;\n  /** Named secret set for rotation. When set, `keyId` picks which to sign with. */\n  keys?: KeySet;\n  /** Which id in `keys` to sign with. Defaults to the first key in `keys`. */\n  keyId?: string;\n  /** HMAC hash. Default \"SHA-256\". */\n  algorithm?: SignAlgorithm;\n  /** Bind the signature to a method / IP / path prefix that verify must match. */\n  bind?: BindConstraints;\n  /** Embed a random single-use nonce: `true` → 16 bytes, or a byte length. */\n  nonce?: boolean | number;\n  /** Arbitrary small, tamper-proof metadata returned verbatim by verify. */\n  claims?: Record<string, unknown>;\n}\n\nexport interface SecureVerifyOptions {\n  /** Single secret (classic mode). Provide this OR `keys`. */\n  secret?: Secret;\n  /** Named secret set for rotation. The stamped key id is looked up here. */\n  keys?: KeySet;\n  algorithm?: SignAlgorithm;\n  /** Override \"now\" (Unix seconds) — for deterministic tests. */\n  now?: number;\n  /** Allowed clock skew in seconds. Default 0. */\n  clockTolerance?: number;\n  /** Runtime request context enforced against any bound constraints. */\n  context?: RequestContext;\n}\n\nexport interface SecureVerifyResult<T> {\n  valid: boolean;\n  /** The original data, present when `valid`. */\n  data?: T;\n  /** The signed claims, present when `valid` and claims were attached. */\n  claims?: Record<string, unknown>;\n  /** The embedded nonce (hex), present when one was attached. */\n  nonce?: string;\n  /** The key id that signed this, present when key rotation was used. */\n  keyId?: string;\n  /** Why verification failed. */\n  reason?: SecureFailReason;\n  /** Expiry timestamp (Unix seconds), if the token/URL had one. */\n  expiresAt?: number;\n}\n\n/* ------------------------------------------------------------------ *\n * Internal helpers\n * ------------------------------------------------------------------ */\n\ninterface EncodedBind {\n  m?: string;\n  i?: string;\n  p?: string;\n}\n\ninterface SecurePayload<T> {\n  d: T;\n  e?: number;\n  /** key id */\n  k?: string;\n  /** binding */\n  b?: EncodedBind;\n  /** nonce */\n  n?: string;\n  /** claims */\n  c?: Record<string, unknown>;\n}\n\nfunction encodeBind(bind: BindConstraints | undefined): EncodedBind | undefined {\n  if (!bind) return undefined;\n  const b: EncodedBind = {};\n  if (bind.method !== undefined) b.m = bind.method;\n  if (bind.ip !== undefined) b.i = bind.ip;\n  if (bind.pathPrefix !== undefined) b.p = bind.pathPrefix;\n  return Object.keys(b).length ? b : undefined;\n}\n\n/** True iff the request context satisfies the bound constraints. */\nfunction checkBinding(b: EncodedBind | undefined, ctx: RequestContext | undefined): boolean {\n  if (!b) return true;\n  const c = ctx ?? {};\n  if (b.m !== undefined && (c.method ?? \"\").toUpperCase() !== b.m.toUpperCase()) return false;\n  if (b.i !== undefined && c.ip !== b.i) return false;\n  if (b.p !== undefined && !(c.path ?? \"\").startsWith(b.p)) return false;\n  return true;\n}\n\nfunction pickSigningKey(opts: { secret?: Secret; keys?: KeySet; keyId?: string }): {\n  secret: Secret;\n  keyId?: string;\n} {\n  if (opts.keys) {\n    const id = opts.keyId ?? Object.keys(opts.keys)[0];\n    if (id === undefined || opts.keys[id] === undefined) {\n      throw new Error(\"@lacspace/signed-url: keyId not found in keys\");\n    }\n    return { secret: opts.keys[id], keyId: id };\n  }\n  if (opts.secret !== undefined) return { secret: opts.secret };\n  throw new Error(\"@lacspace/signed-url: a `secret` or `keys` must be provided\");\n}\n\n/** Resolve the verifying secret for a (possibly stamped) key id. */\nfunction resolveVerifyKey(k: string | undefined, opts: { secret?: Secret; keys?: KeySet }): Secret | undefined {\n  if (k !== undefined && opts.keys) return opts.keys[k]; // undefined ⇒ unknown-key (wrong set)\n  if (opts.secret !== undefined) return opts.secret; // classic single-secret token\n  return undefined;\n}\n\nfunction resolveNonceBytes(nonce: boolean | number | undefined): number {\n  if (nonce === true) return 16;\n  if (typeof nonce === \"number\" && nonce > 0) return Math.floor(nonce);\n  return 0;\n}\n\n/* ------------------------------------------------------------------ *\n * Secure tokens\n * ------------------------------------------------------------------ */\n\n/**\n * Sign data into a compact, tamper-proof token like {@link sign}, with optional\n * key rotation, binding, a single-use nonce, and signed claims. The on-the-wire\n * format is identical (`\"<payload>.<signature>\"`), so a token signed with none\n * of the new options is byte-for-byte what {@link sign} would produce and\n * verifies with plain {@link verify} too.\n *\n * @example\n * const token = await signSecure({ userId: 42 }, {\n *   keys: { \"2025\": SECRET_A }, keyId: \"2025\",\n *   bind: { method: \"POST\", pathPrefix: \"/admin/\" },\n *   nonce: true, claims: { role: \"owner\" }, expiresIn: 900,\n * });\n */\nexport async function signSecure(data: TokenData, opts: SecureSignOptions): Promise<string> {\n  const { secret, keyId } = pickSigningKey(opts);\n  const exp = resolveExp(opts);\n  const payloadObj: SecurePayload<TokenData> = { d: data };\n  if (exp !== undefined) payloadObj.e = exp;\n  if (keyId !== undefined) payloadObj.k = keyId;\n  const b = encodeBind(opts.bind);\n  if (b) payloadObj.b = b;\n  const nb = resolveNonceBytes(opts.nonce);\n  if (nb > 0) payloadObj.n = toHex(randomBytes(nb));\n  if (opts.claims !== undefined) payloadObj.c = opts.claims;\n\n  const payload = toBase64url(enc.encode(JSON.stringify(payloadObj)));\n  const sig = toBase64url(await hmac(secret, payload, opts.algorithm ?? \"SHA-256\"));\n  return `${payload}.${sig}`;\n}\n\n/**\n * Verify a token from {@link signSecure} (or a plain {@link sign} token).\n * Never throws — returns `{ valid, data?, claims?, nonce?, keyId?, reason?, expiresAt? }`.\n * Enforces expiry (with optional `clockTolerance`), key rotation (looks the\n * stamped key id up in `keys`) and any bound constraints against `context`.\n *\n * @example\n * const r = await verifySecure(token, {\n *   keys: { \"2024\": OLD, \"2025\": SECRET_A },\n *   context: { method: req.method, ip: clientIp, path: url.pathname },\n *   clockTolerance: 30,\n * });\n * if (r.valid) grant(r.data, r.claims);\n */\nexport async function verifySecure<T = TokenData>(\n  token: string,\n  opts: SecureVerifyOptions,\n): Promise<SecureVerifyResult<T>> {\n  const dot = token.indexOf(\".\");\n  if (dot <= 0 || dot === token.length - 1) return { valid: false, reason: \"malformed\" };\n  const payload = token.slice(0, dot);\n  const sig = token.slice(dot + 1);\n\n  let sigBytes: Uint8Array;\n  try {\n    sigBytes = fromBase64url(sig);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  let obj: SecurePayload<T>;\n  try {\n    obj = JSON.parse(dec.decode(fromBase64url(payload))) as SecurePayload<T>;\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const secret = resolveVerifyKey(obj.k, opts);\n  if (secret === undefined) return { valid: false, reason: \"unknown-key\" };\n\n  const okSig = await hmacVerify(secret, payload, sigBytes, opts.algorithm ?? \"SHA-256\");\n  if (!okSig) return { valid: false, reason: \"bad-signature\" };\n\n  if (obj.e !== undefined) {\n    const now = opts.now ?? nowSec();\n    if (now > obj.e + (opts.clockTolerance ?? 0)) {\n      return { valid: false, reason: \"expired\", expiresAt: obj.e };\n    }\n  }\n\n  if (!checkBinding(obj.b, opts.context)) {\n    return { valid: false, reason: \"binding\", expiresAt: obj.e };\n  }\n\n  return {\n    valid: true,\n    data: obj.d,\n    claims: obj.c,\n    nonce: obj.n,\n    keyId: obj.k,\n    expiresAt: obj.e,\n  };\n}\n\n/* ------------------------------------------------------------------ *\n * Secure URLs\n * ------------------------------------------------------------------ */\n\nexport interface SecureSignUrlOptions extends SecureSignOptions {\n  /** Query param that holds the signature. Default \"sig\". */\n  sigParam?: string;\n  /** Query param that holds the expiry. Default \"exp\". */\n  expParam?: string;\n}\n\nexport interface SecureVerifyUrlOptions extends SecureVerifyOptions, LegacySignatureOption {\n  sigParam?: string;\n  expParam?: string;\n}\n\n// Param names for the secure extras (all covered by the signature canonicalisation).\nconst KID_PARAM = \"kid\";\nconst NONCE_PARAM = \"nonce\";\nconst BIND_METHOD_PARAM = \"bm\";\nconst BIND_IP_PARAM = \"bi\";\nconst BIND_PREFIX_PARAM = \"bp\";\nconst CLAIMS_PARAM = \"cl\";\n\n\n/**\n * Like {@link signUrl}, with optional key rotation, binding, a nonce and signed\n * claims stamped into the query and covered by the signature. A URL signed with\n * none of the new options is exactly what {@link signUrl} produces.\n *\n * @example\n * const link = await signSecureUrl(\"https://cdn.me/files/a.pdf?uid=42\", {\n *   keys: { \"2025\": SECRET_A }, keyId: \"2025\",\n *   bind: { pathPrefix: \"/files/\" }, claims: { uid: 42 }, expiresIn: 300,\n * });\n */\nexport async function signSecureUrl(url: string, opts: SecureSignUrlOptions): Promise<string> {\n  const sigParam = opts.sigParam ?? \"sig\";\n  const expParam = opts.expParam ?? \"exp\";\n  const { secret, keyId } = pickSigningKey(opts);\n  const u = new URL(url);\n  u.searchParams.delete(sigParam);\n\n  const exp = resolveExp(opts);\n  if (exp !== undefined) u.searchParams.set(expParam, String(exp));\n  if (keyId !== undefined) u.searchParams.set(KID_PARAM, keyId);\n  const nb = resolveNonceBytes(opts.nonce);\n  if (nb > 0) u.searchParams.set(NONCE_PARAM, toHex(randomBytes(nb)));\n  if (opts.bind?.method !== undefined) u.searchParams.set(BIND_METHOD_PARAM, opts.bind.method);\n  if (opts.bind?.ip !== undefined) u.searchParams.set(BIND_IP_PARAM, opts.bind.ip);\n  if (opts.bind?.pathPrefix !== undefined) u.searchParams.set(BIND_PREFIX_PARAM, opts.bind.pathPrefix);\n  if (opts.claims !== undefined) {\n    u.searchParams.set(CLAIMS_PARAM, toBase64url(enc.encode(JSON.stringify(opts.claims))));\n  }\n\n  const sig = toBase64url(await hmac(secret, canonicalize(u, sigParam), opts.algorithm ?? \"SHA-256\"));\n  u.searchParams.set(sigParam, sig);\n  return u.toString();\n}\n\n/**\n * Verify a URL from {@link signSecureUrl} (or a plain {@link signUrl} URL).\n * Never throws. Enforces signature, expiry (with optional `clockTolerance`),\n * key rotation and any bound constraints against `context`.\n */\nexport async function verifySecureUrl(\n  url: string,\n  opts: SecureVerifyUrlOptions,\n): Promise<SecureVerifyResult<never>> {\n  const sigParam = opts.sigParam ?? \"sig\";\n  const expParam = opts.expParam ?? \"exp\";\n\n  let u: URL;\n  try {\n    u = new URL(url);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const sig = u.searchParams.get(sigParam);\n  if (!sig) return { valid: false, reason: \"malformed\" };\n\n  let sigBytes: Uint8Array;\n  try {\n    sigBytes = fromBase64url(sig);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const keyId = u.searchParams.get(KID_PARAM) ?? undefined;\n  const secret = resolveVerifyKey(keyId, opts);\n  if (secret === undefined) return { valid: false, reason: \"unknown-key\" };\n\n  const alg = opts.algorithm ?? \"SHA-256\";\n  const okSig =\n    (await hmacVerify(secret, canonicalize(u, sigParam), sigBytes, alg)) ||\n    (opts.acceptLegacySignatures === true && (await hmacVerify(secret, canonicalize(u, sigParam, true), sigBytes, alg)));\n  if (!okSig) return { valid: false, reason: \"bad-signature\" };\n\n  let expiresAt: number | undefined;\n  const expStr = u.searchParams.get(expParam);\n  if (expStr) {\n    const exp = Number(expStr);\n    if (Number.isFinite(exp)) {\n      expiresAt = exp;\n      const now = opts.now ?? nowSec();\n      if (now > exp + (opts.clockTolerance ?? 0)) return { valid: false, reason: \"expired\", expiresAt: exp };\n    }\n  }\n\n  const b: EncodedBind = {};\n  const bm = u.searchParams.get(BIND_METHOD_PARAM);\n  const bi = u.searchParams.get(BIND_IP_PARAM);\n  const bp = u.searchParams.get(BIND_PREFIX_PARAM);\n  if (bm !== null) b.m = bm;\n  if (bi !== null) b.i = bi;\n  if (bp !== null) b.p = bp;\n  if (!checkBinding(Object.keys(b).length ? b : undefined, opts.context)) {\n    return { valid: false, reason: \"binding\", expiresAt };\n  }\n\n  let claims: Record<string, unknown> | undefined;\n  const cl = u.searchParams.get(CLAIMS_PARAM);\n  if (cl) {\n    try {\n      claims = JSON.parse(dec.decode(fromBase64url(cl))) as Record<string, unknown>;\n    } catch {\n      return { valid: false, reason: \"malformed\", expiresAt };\n    }\n  }\n\n  const nonce = u.searchParams.get(NONCE_PARAM) ?? undefined;\n  return { valid: true, claims, nonce, keyId, expiresAt };\n}\n\n/* ------------------------------------------------------------------ *\n * Nonce helpers (one-time / max-uses — storage stays the caller's)\n * ------------------------------------------------------------------ */\n\n/** Generate a random nonce (hex). Default 16 bytes. */\nexport function generateNonce(bytes = 16): string {\n  return toHex(randomBytes(Math.max(1, Math.floor(bytes))));\n}\n\nexport interface ConsumeNonceOptions {\n  /** Maximum allowed uses of the nonce. Default 1 (one-time). */\n  maxUses?: number;\n}\n\nexport interface ConsumeNonceResult {\n  /** Whether this use is allowed (i.e. the nonce was not already exhausted). */\n  ok: boolean;\n  /** The new total use count to persist back to your store. */\n  uses: number;\n  /** How many uses remain after this one. */\n  remaining: number;\n}\n\n/**\n * Pure single-use / max-N-use checker. The library owns no storage: you read the\n * current use count for a nonce from your own store, call this, and — if `ok` —\n * write the returned `uses` back. `previousUses` is the count you have stored so\n * far (undefined / 0 for a never-seen nonce).\n *\n * @example\n * const prior = await store.get(nonce);          // number | undefined\n * const c = consumeNonce(prior, { maxUses: 1 });\n * if (!c.ok) return reject(\"already used\");\n * await store.set(nonce, c.uses);                // persist\n */\nexport function consumeNonce(\n  previousUses: number | undefined,\n  opts: ConsumeNonceOptions = {},\n): ConsumeNonceResult {\n  const maxUses = opts.maxUses !== undefined && opts.maxUses > 0 ? Math.floor(opts.maxUses) : 1;\n  const prior = previousUses !== undefined && previousUses > 0 ? Math.floor(previousUses) : 0;\n  if (prior >= maxUses) {\n    return { ok: false, uses: prior, remaining: 0 };\n  }\n  const uses = prior + 1;\n  return { ok: true, uses, remaining: maxUses - uses };\n}\n","/**\n * @lacspace/signed-url\n *\n * HMAC-signed, expiring URLs & tokens over Web Crypto. Two things developers\n * re-implement badly on every project:\n *\n *   1. Signed *tokens*  — compact, tamper-proof strings for magic-login links,\n *      email unsubscribe links, one-time actions, email confirmations.\n *   2. Signed *URLs*    — protect a download / image-proxy / CDN link with an\n *      expiring `?exp=…&sig=…` signature (S3-presigned-style, self-hosted).\n *\n * Tamper-proof (any change breaks the signature), timing-safe verification,\n * optional expiry, zero config. Isomorphic: Node, edge runtimes and browsers.\n *\n * Built on @lacspace/crypto (Web Crypto) — never hand-rolled cryptography.\n */\nimport { canonicalize, type LegacySignatureOption } from \"./canonical\";\nimport { hmac, hmacVerify, toBase64url, fromBase64url } from \"@lacspace/crypto\";\n\nexport type SignAlgorithm = \"SHA-256\" | \"SHA-384\" | \"SHA-512\";\nexport type Secret = string | Uint8Array;\n\n/** JSON-serialisable token payload. */\nexport type TokenData =\n  | string\n  | number\n  | boolean\n  | null\n  | { [key: string]: unknown }\n  | unknown[];\n\nconst enc = new TextEncoder();\nconst dec = new TextDecoder();\nconst nowSec = (): number => Math.floor(Date.now() / 1000);\n\nexport interface ExpiryOptions {\n  /** Seconds until expiry (relative to now). Ignored when `expiresAt` is set. */\n  expiresIn?: number;\n  /** Absolute expiry as a Unix timestamp (seconds). */\n  expiresAt?: number;\n  /** Override \"now\" (Unix seconds) — for deterministic tests. */\n  now?: number;\n}\n\nexport interface SignOptions extends ExpiryOptions {\n  secret: Secret;\n  /** HMAC hash. Default \"SHA-256\". */\n  algorithm?: SignAlgorithm;\n}\n\nfunction resolveExp(o: ExpiryOptions): number | undefined {\n  if (o.expiresAt !== undefined) return Math.floor(o.expiresAt);\n  if (o.expiresIn !== undefined) return (o.now ?? nowSec()) + Math.floor(o.expiresIn);\n  return undefined;\n}\n\nexport type FailReason = \"malformed\" | \"bad-signature\" | \"expired\";\n\nexport interface VerifyResult<T> {\n  valid: boolean;\n  /** The original data (tokens only), present when `valid`. */\n  data?: T;\n  /** Why verification failed. */\n  reason?: FailReason;\n  /** Expiry timestamp (Unix seconds), if the token/URL had one. */\n  expiresAt?: number;\n}\n\nexport interface VerifyOptions {\n  secret: Secret;\n  algorithm?: SignAlgorithm;\n  /** Override \"now\" (Unix seconds) — for deterministic tests. */\n  now?: number;\n  /** Allowed clock skew in seconds. Default 0. */\n  clockToleranceSec?: number;\n}\n\n/* ------------------------------------------------------------------ *\n * Signed tokens\n * ------------------------------------------------------------------ */\n\ninterface Payload<T> {\n  d: T;\n  e?: number;\n}\n\n/**\n * Sign arbitrary JSON data into a compact, URL-safe, tamper-proof token:\n * `\"<payload>.<signature>\"`. Optionally expiring.\n *\n * @example\n * const token = await sign({ userId: 42, action: \"reset-password\" }, {\n *   secret: process.env.LINK_SECRET!, expiresIn: 3600,\n * });\n */\nexport async function sign(data: TokenData, opts: SignOptions): Promise<string> {\n  const exp = resolveExp(opts);\n  const payloadObj: Payload<TokenData> = { d: data };\n  if (exp !== undefined) payloadObj.e = exp;\n  const payload = toBase64url(enc.encode(JSON.stringify(payloadObj)));\n  const sig = toBase64url(await hmac(opts.secret, payload, opts.algorithm ?? \"SHA-256\"));\n  return `${payload}.${sig}`;\n}\n\n/**\n * Verify and decode a token from {@link sign}. Never throws — returns a result\n * with `valid` and, on failure, a `reason` (\"malformed\" | \"bad-signature\" | \"expired\").\n *\n * @example\n * const r = await verify<{ userId: number }>(token, { secret });\n * if (r.valid) grantAccess(r.data.userId);\n */\nexport async function verify<T = TokenData>(token: string, opts: VerifyOptions): Promise<VerifyResult<T>> {\n  const dot = token.indexOf(\".\");\n  if (dot <= 0 || dot === token.length - 1) return { valid: false, reason: \"malformed\" };\n  const payload = token.slice(0, dot);\n  const sig = token.slice(dot + 1);\n\n  let sigBytes: Uint8Array;\n  try {\n    sigBytes = fromBase64url(sig);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const okSig = await hmacVerify(opts.secret, payload, sigBytes, opts.algorithm ?? \"SHA-256\");\n  if (!okSig) return { valid: false, reason: \"bad-signature\" };\n\n  let obj: Payload<T>;\n  try {\n    obj = JSON.parse(dec.decode(fromBase64url(payload))) as Payload<T>;\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  if (obj.e !== undefined) {\n    const now = opts.now ?? nowSec();\n    if (now > obj.e + (opts.clockToleranceSec ?? 0)) {\n      return { valid: false, reason: \"expired\", expiresAt: obj.e };\n    }\n  }\n  return { valid: true, data: obj.d, expiresAt: obj.e };\n}\n\n/** Convenience: `true` iff the token is valid (signature + not expired). */\nexport async function isValid(token: string, opts: VerifyOptions): Promise<boolean> {\n  return (await verify(token, opts)).valid;\n}\n\n/* ------------------------------------------------------------------ *\n * Signed URLs\n * ------------------------------------------------------------------ */\n\nexport interface SignUrlOptions extends SignOptions {\n  /** Query param that holds the signature. Default \"sig\". */\n  sigParam?: string;\n  /** Query param that holds the expiry. Default \"exp\". */\n  expParam?: string;\n}\n\nexport interface VerifyUrlOptions extends VerifyOptions, LegacySignatureOption {\n  sigParam?: string;\n  expParam?: string;\n}\n\n\n/**\n * Append an expiring HMAC signature to a URL — self-hosted presigned URLs for\n * downloads, image proxies or any link you want to protect from tampering.\n * Query-param order is normalised, so the link verifies regardless of ordering.\n *\n * @example\n * const link = await signUrl(\"https://cdn.me/files/report.pdf?uid=42\", {\n *   secret, expiresIn: 300,\n * }); // → …?uid=42&exp=1699999999&sig=AbC…\n */\nexport async function signUrl(url: string, opts: SignUrlOptions): Promise<string> {\n  const sigParam = opts.sigParam ?? \"sig\";\n  const expParam = opts.expParam ?? \"exp\";\n  const u = new URL(url);\n  u.searchParams.delete(sigParam);\n  const exp = resolveExp(opts);\n  if (exp !== undefined) u.searchParams.set(expParam, String(exp));\n  const sig = toBase64url(await hmac(opts.secret, canonicalize(u, sigParam), opts.algorithm ?? \"SHA-256\"));\n  u.searchParams.set(sigParam, sig);\n  return u.toString();\n}\n\n/**\n * Verify a URL produced by {@link signUrl}: checks the signature (timing-safe)\n * and expiry. Never throws.\n *\n * @example\n * const r = await verifyUrl(request.url, { secret });\n * if (!r.valid) return new Response(\"Link expired or invalid\", { status: 403 });\n */\nexport async function verifyUrl(url: string, opts: VerifyUrlOptions): Promise<VerifyResult<never>> {\n  const sigParam = opts.sigParam ?? \"sig\";\n  const expParam = opts.expParam ?? \"exp\";\n\n  let u: URL;\n  try {\n    u = new URL(url);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const sig = u.searchParams.get(sigParam);\n  if (!sig) return { valid: false, reason: \"malformed\" };\n\n  let sigBytes: Uint8Array;\n  try {\n    sigBytes = fromBase64url(sig);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n\n  const alg = opts.algorithm ?? \"SHA-256\";\n  const okSig =\n    (await hmacVerify(opts.secret, canonicalize(u, sigParam), sigBytes, alg)) ||\n    (opts.acceptLegacySignatures === true && (await hmacVerify(opts.secret, canonicalize(u, sigParam, true), sigBytes, alg)));\n  if (!okSig) return { valid: false, reason: \"bad-signature\" };\n\n  const expStr = u.searchParams.get(expParam);\n  if (expStr) {\n    const exp = Number(expStr);\n    if (Number.isFinite(exp)) {\n      const now = opts.now ?? nowSec();\n      if (now > exp + (opts.clockToleranceSec ?? 0)) return { valid: false, reason: \"expired\", expiresAt: exp };\n      return { valid: true, expiresAt: exp };\n    }\n  }\n  return { valid: true };\n}\n\n/* ------------------------------------------------------------------ *\n * Magic links (token embedded in a URL)\n * ------------------------------------------------------------------ */\n\nexport interface MagicLinkOptions extends SignOptions {\n  /** Query param that carries the token. Default \"token\". */\n  param?: string;\n}\n\n/**\n * Build a magic link — a base URL with a signed token embedded as a query param.\n * Perfect for passwordless login, email verification and one-time actions.\n *\n * @example\n * const link = await magicLink(\"https://app.me/auth/callback\", { email }, {\n *   secret, expiresIn: 900,\n * });\n */\nexport async function magicLink(baseUrl: string, data: TokenData, opts: MagicLinkOptions): Promise<string> {\n  const token = await sign(data, opts);\n  const u = new URL(baseUrl);\n  u.searchParams.set(opts.param ?? \"token\", token);\n  return u.toString();\n}\n\n/** Read & verify the token embedded in a magic link by {@link magicLink}. */\nexport async function readMagicLink<T = TokenData>(\n  url: string,\n  opts: VerifyOptions & { param?: string },\n): Promise<VerifyResult<T>> {\n  let u: URL;\n  try {\n    u = new URL(url);\n  } catch {\n    return { valid: false, reason: \"malformed\" };\n  }\n  const token = u.searchParams.get(opts.param ?? \"token\");\n  if (!token) return { valid: false, reason: \"malformed\" };\n  return verify<T>(token, opts);\n}\n\n/* ------------------------------------------------------------------ *\n * Secure layer (new in 1.1.0): key rotation, binding, nonce, claims.\n * Additive superset — see ./secure. Classic exports above are unchanged.\n * ------------------------------------------------------------------ */\nexport {\n  signSecure,\n  verifySecure,\n  signSecureUrl,\n  verifySecureUrl,\n  generateNonce,\n  consumeNonce,\n} from \"./secure\";\nexport type {\n  KeySet,\n  BindConstraints,\n  RequestContext,\n  SecureFailReason,\n  SecureSignOptions,\n  SecureVerifyOptions,\n  SecureVerifyResult,\n  SecureSignUrlOptions,\n  SecureVerifyUrlOptions,\n  ConsumeNonceOptions,\n  ConsumeNonceResult,\n} from \"./secure\";\n\nexport type { LegacySignatureOption } from \"./canonical\";\n"]}