@shipfox/api-auth 5.0.0 → 6.0.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.
Files changed (154) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +52 -0
  3. package/README.md +71 -37
  4. package/dist/config.d.ts +0 -12
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +0 -62
  7. package/dist/config.js.map +1 -1
  8. package/dist/core/auth.d.ts +21 -2
  9. package/dist/core/auth.d.ts.map +1 -1
  10. package/dist/core/auth.js +109 -77
  11. package/dist/core/auth.js.map +1 -1
  12. package/dist/core/email-owner.d.ts +12 -0
  13. package/dist/core/email-owner.d.ts.map +1 -0
  14. package/dist/core/email-owner.js +20 -0
  15. package/dist/core/email-owner.js.map +1 -0
  16. package/dist/core/job-lease-token.d.ts.map +1 -1
  17. package/dist/core/job-lease-token.js +3 -2
  18. package/dist/core/job-lease-token.js.map +1 -1
  19. package/dist/core/jwt.d.ts +2 -2
  20. package/dist/core/jwt.d.ts.map +1 -1
  21. package/dist/core/jwt.js.map +1 -1
  22. package/dist/core/rate-limit.d.ts.map +1 -1
  23. package/dist/core/rate-limit.js +2 -7
  24. package/dist/core/rate-limit.js.map +1 -1
  25. package/dist/core/runner-session-token.d.ts.map +1 -1
  26. package/dist/core/runner-session-token.js +3 -2
  27. package/dist/core/runner-session-token.js.map +1 -1
  28. package/dist/db/db.d.ts +0 -218
  29. package/dist/db/db.d.ts.map +1 -1
  30. package/dist/db/db.js +0 -2
  31. package/dist/db/db.js.map +1 -1
  32. package/dist/db/users.d.ts +3 -0
  33. package/dist/db/users.d.ts.map +1 -1
  34. package/dist/db/users.js +28 -10
  35. package/dist/db/users.js.map +1 -1
  36. package/dist/index.d.ts +5 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +40 -34
  39. package/dist/index.js.map +1 -1
  40. package/dist/presentation/auth/jwt-auth.d.ts.map +1 -1
  41. package/dist/presentation/auth/jwt-auth.js +2 -2
  42. package/dist/presentation/auth/jwt-auth.js.map +1 -1
  43. package/dist/presentation/e2eRoutes/create-session.d.ts +2 -1
  44. package/dist/presentation/e2eRoutes/create-session.d.ts.map +1 -1
  45. package/dist/presentation/e2eRoutes/create-session.js +42 -39
  46. package/dist/presentation/e2eRoutes/create-session.js.map +1 -1
  47. package/dist/presentation/e2eRoutes/index.d.ts +2 -1
  48. package/dist/presentation/e2eRoutes/index.d.ts.map +1 -1
  49. package/dist/presentation/e2eRoutes/index.js +12 -10
  50. package/dist/presentation/e2eRoutes/index.js.map +1 -1
  51. package/dist/presentation/inter-module.d.ts +4 -0
  52. package/dist/presentation/inter-module.d.ts.map +1 -0
  53. package/dist/presentation/inter-module.js +16 -0
  54. package/dist/presentation/inter-module.js.map +1 -0
  55. package/dist/presentation/routes/email-verification/verify-email-confirm.d.ts +2 -1
  56. package/dist/presentation/routes/email-verification/verify-email-confirm.d.ts.map +1 -1
  57. package/dist/presentation/routes/email-verification/verify-email-confirm.js +36 -25
  58. package/dist/presentation/routes/email-verification/verify-email-confirm.js.map +1 -1
  59. package/dist/presentation/routes/email-verification/verify-email-resend.d.ts.map +1 -1
  60. package/dist/presentation/routes/email-verification/verify-email-resend.js +20 -4
  61. package/dist/presentation/routes/email-verification/verify-email-resend.js.map +1 -1
  62. package/dist/presentation/routes/index.d.ts +2 -2
  63. package/dist/presentation/routes/index.d.ts.map +1 -1
  64. package/dist/presentation/routes/index.js +11 -13
  65. package/dist/presentation/routes/index.js.map +1 -1
  66. package/dist/presentation/routes/password/password-reset-confirm.d.ts +2 -1
  67. package/dist/presentation/routes/password/password-reset-confirm.d.ts.map +1 -1
  68. package/dist/presentation/routes/password/password-reset-confirm.js +29 -26
  69. package/dist/presentation/routes/password/password-reset-confirm.js.map +1 -1
  70. package/dist/presentation/routes/registration/signup.d.ts +2 -1
  71. package/dist/presentation/routes/registration/signup.d.ts.map +1 -1
  72. package/dist/presentation/routes/registration/signup.js +86 -68
  73. package/dist/presentation/routes/registration/signup.js.map +1 -1
  74. package/dist/presentation/routes/session/login.d.ts +2 -1
  75. package/dist/presentation/routes/session/login.d.ts.map +1 -1
  76. package/dist/presentation/routes/session/login.js +40 -37
  77. package/dist/presentation/routes/session/login.js.map +1 -1
  78. package/dist/presentation/routes/session/refresh.d.ts +2 -1
  79. package/dist/presentation/routes/session/refresh.d.ts.map +1 -1
  80. package/dist/presentation/routes/session/refresh.js +42 -39
  81. package/dist/presentation/routes/session/refresh.js.map +1 -1
  82. package/dist/presentation/subscribers/index.d.ts +0 -1
  83. package/dist/presentation/subscribers/index.d.ts.map +1 -1
  84. package/dist/presentation/subscribers/index.js +0 -1
  85. package/dist/presentation/subscribers/index.js.map +1 -1
  86. package/dist/presentation/subscribers/on-password-reset-send-requested.js +1 -1
  87. package/dist/presentation/subscribers/on-password-reset-send-requested.js.map +1 -1
  88. package/dist/tsconfig.test.tsbuildinfo +1 -1
  89. package/drizzle/0000_initial.sql +1 -13
  90. package/drizzle/meta/0000_snapshot.json +0 -92
  91. package/package.json +17 -13
  92. package/src/config.ts +0 -56
  93. package/src/core/auth.test.ts +106 -187
  94. package/src/core/auth.ts +131 -87
  95. package/src/core/email-owner.test.ts +86 -0
  96. package/src/core/email-owner.ts +23 -0
  97. package/src/core/job-lease-token.test.ts +2 -1
  98. package/src/core/job-lease-token.ts +3 -2
  99. package/src/core/jwt.ts +2 -2
  100. package/src/core/rate-limit.test.ts +11 -28
  101. package/src/core/rate-limit.ts +3 -11
  102. package/src/core/runner-session-token.test.ts +2 -1
  103. package/src/core/runner-session-token.ts +3 -2
  104. package/src/db/db.ts +0 -2
  105. package/src/db/users.ts +32 -14
  106. package/src/index.test.ts +15 -11
  107. package/src/index.ts +23 -20
  108. package/src/presentation/auth/jwt-auth.test.ts +2 -1
  109. package/src/presentation/auth/jwt-auth.ts +2 -2
  110. package/src/presentation/e2eRoutes/create-session.ts +34 -30
  111. package/src/presentation/e2eRoutes/index.test.ts +9 -6
  112. package/src/presentation/e2eRoutes/index.ts +8 -5
  113. package/src/presentation/inter-module.ts +13 -0
  114. package/src/presentation/routes/email-verification/verify-email-confirm.ts +42 -24
  115. package/src/presentation/routes/email-verification/verify-email-resend.ts +18 -4
  116. package/src/presentation/routes/index.test.ts +10 -3
  117. package/src/presentation/routes/index.ts +22 -12
  118. package/src/presentation/routes/password/password-reset-confirm.ts +25 -22
  119. package/src/presentation/routes/password/password-reset-request.test.ts +1 -0
  120. package/src/presentation/routes/rate-limit.test.ts +2 -2
  121. package/src/presentation/routes/registration/signup.test.ts +39 -74
  122. package/src/presentation/routes/registration/signup.ts +89 -70
  123. package/src/presentation/routes/session/login.ts +38 -35
  124. package/src/presentation/routes/session/refresh.ts +43 -40
  125. package/src/presentation/subscribers/email-send-requested.test.ts +2 -30
  126. package/src/presentation/subscribers/index.ts +0 -1
  127. package/src/presentation/subscribers/on-password-reset-send-requested.ts +1 -1
  128. package/test/env.ts +1 -3
  129. package/test/globalSetup.ts +10 -1
  130. package/test/routes.ts +51 -84
  131. package/tsconfig.build.tsbuildinfo +1 -1
  132. package/dist/core/entities/email-verification.d.ts +0 -9
  133. package/dist/core/entities/email-verification.d.ts.map +0 -1
  134. package/dist/core/entities/email-verification.js +0 -3
  135. package/dist/core/entities/email-verification.js.map +0 -1
  136. package/dist/db/email-verifications.d.ts +0 -39
  137. package/dist/db/email-verifications.d.ts.map +0 -1
  138. package/dist/db/email-verifications.js +0 -95
  139. package/dist/db/email-verifications.js.map +0 -1
  140. package/dist/db/schema/email-verifications.d.ts +0 -114
  141. package/dist/db/schema/email-verifications.d.ts.map +0 -1
  142. package/dist/db/schema/email-verifications.js +0 -35
  143. package/dist/db/schema/email-verifications.js.map +0 -1
  144. package/dist/presentation/subscribers/on-email-verification-send-requested.d.ts +0 -3
  145. package/dist/presentation/subscribers/on-email-verification-send-requested.d.ts.map +0 -1
  146. package/dist/presentation/subscribers/on-email-verification-send-requested.js +0 -13
  147. package/dist/presentation/subscribers/on-email-verification-send-requested.js.map +0 -1
  148. package/src/core/entities/email-verification.ts +0 -8
  149. package/src/db/email-verifications.test.ts +0 -61
  150. package/src/db/email-verifications.ts +0 -160
  151. package/src/db/schema/email-verifications.ts +0 -37
  152. package/src/presentation/routes/email-verification/verify-email-confirm.test.ts +0 -66
  153. package/src/presentation/routes/email-verification/verify-email-resend.test.ts +0 -100
  154. package/src/presentation/subscribers/on-email-verification-send-requested.ts +0 -10
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/jwt.ts"],"sourcesContent":["import {workspaceRoleSchema} from '@shipfox/api-workspaces-dto';\nimport {signHs256, verifyHs256} from '@shipfox/node-jwt';\nimport {z} from 'zod';\nimport {recordTokenIssued, recordTokenVerified} from '#metrics/index.js';\n\nexport const tokenMembershipSchema = z.object({\n workspaceId: z.string().uuid(),\n role: workspaceRoleSchema,\n});\n\nexport type TokenMembership = z.infer<typeof tokenMembershipSchema>;\n\nexport const userTokenClaimsSchema = z.object({\n sub: z.string().uuid(),\n email: z.string().email(),\n name: z.string().nullable().optional(),\n memberships: z.array(tokenMembershipSchema),\n iat: z.number().int(),\n exp: z.number().int(),\n});\n\nexport type UserTokenClaims = z.infer<typeof userTokenClaimsSchema>;\n\nexport interface SignUserTokenParams {\n userId: string;\n email: string;\n name?: string | null | undefined;\n memberships: TokenMembership[];\n secret: string;\n expiresIn: string;\n}\n\nexport interface VerifyUserTokenParams {\n token: string;\n secret: string;\n}\n\nexport async function signUserToken(params: SignUserTokenParams): Promise<string> {\n const token = await signHs256({\n payload: {\n email: params.email,\n name: params.name ?? null,\n memberships: params.memberships,\n },\n secret: params.secret,\n expiresIn: params.expiresIn,\n subject: params.userId,\n });\n recordTokenIssued('session');\n return token;\n}\n\nexport async function verifyUserToken(params: VerifyUserTokenParams): Promise<UserTokenClaims> {\n try {\n const claims = await verifyHs256({\n token: params.token,\n secret: params.secret,\n schema: userTokenClaimsSchema,\n });\n recordTokenVerified('session', 'ok');\n return claims;\n } catch (error) {\n recordTokenVerified('session', 'rejected');\n throw error;\n }\n}\n"],"names":["workspaceRoleSchema","signHs256","verifyHs256","z","recordTokenIssued","recordTokenVerified","tokenMembershipSchema","object","workspaceId","string","uuid","role","userTokenClaimsSchema","sub","email","name","nullable","optional","memberships","array","iat","number","int","exp","signUserToken","params","token","payload","secret","expiresIn","subject","userId","verifyUserToken","claims","schema","error"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,8BAA8B;AAChE,SAAQC,SAAS,EAAEC,WAAW,QAAO,oBAAoB;AACzD,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,iBAAiB,EAAEC,mBAAmB,QAAO,oBAAoB;AAEzE,OAAO,MAAMC,wBAAwBH,EAAEI,MAAM,CAAC;IAC5CC,aAAaL,EAAEM,MAAM,GAAGC,IAAI;IAC5BC,MAAMX;AACR,GAAG;AAIH,OAAO,MAAMY,wBAAwBT,EAAEI,MAAM,CAAC;IAC5CM,KAAKV,EAAEM,MAAM,GAAGC,IAAI;IACpBI,OAAOX,EAAEM,MAAM,GAAGK,KAAK;IACvBC,MAAMZ,EAAEM,MAAM,GAAGO,QAAQ,GAAGC,QAAQ;IACpCC,aAAaf,EAAEgB,KAAK,CAACb;IACrBc,KAAKjB,EAAEkB,MAAM,GAAGC,GAAG;IACnBC,KAAKpB,EAAEkB,MAAM,GAAGC,GAAG;AACrB,GAAG;AAkBH,OAAO,eAAeE,cAAcC,MAA2B;IAC7D,MAAMC,QAAQ,MAAMzB,UAAU;QAC5B0B,SAAS;YACPb,OAAOW,OAAOX,KAAK;YACnBC,MAAMU,OAAOV,IAAI,IAAI;YACrBG,aAAaO,OAAOP,WAAW;QACjC;QACAU,QAAQH,OAAOG,MAAM;QACrBC,WAAWJ,OAAOI,SAAS;QAC3BC,SAASL,OAAOM,MAAM;IACxB;IACA3B,kBAAkB;IAClB,OAAOsB;AACT;AAEA,OAAO,eAAeM,gBAAgBP,MAA6B;IACjE,IAAI;QACF,MAAMQ,SAAS,MAAM/B,YAAY;YAC/BwB,OAAOD,OAAOC,KAAK;YACnBE,QAAQH,OAAOG,MAAM;YACrBM,QAAQtB;QACV;QACAP,oBAAoB,WAAW;QAC/B,OAAO4B;IACT,EAAE,OAAOE,OAAO;QACd9B,oBAAoB,WAAW;QAC/B,MAAM8B;IACR;AACF"}
1
+ {"version":3,"sources":["../../src/core/jwt.ts"],"sourcesContent":["import {workspaceRoleSchema} from '@shipfox/api-workspaces-dto';\nimport {signHs256, verifyHs256} from '@shipfox/node-jwt';\nimport {z} from 'zod';\nimport {recordTokenIssued, recordTokenVerified} from '#metrics/index.js';\n\nexport const tokenMembershipSchema = z.object({\n workspaceId: z.string().uuid(),\n role: workspaceRoleSchema,\n});\n\nexport type TokenMembership = z.infer<typeof tokenMembershipSchema>;\n\nexport const userTokenClaimsSchema = z.object({\n sub: z.string().uuid(),\n email: z.string().email(),\n name: z.string().nullable().optional(),\n memberships: z.array(tokenMembershipSchema),\n iat: z.number().int(),\n exp: z.number().int(),\n});\n\nexport type UserTokenClaims = z.infer<typeof userTokenClaimsSchema>;\n\nexport interface SignUserTokenParams {\n userId: string;\n email: string;\n name?: string | null | undefined;\n memberships: TokenMembership[];\n secret: string | Uint8Array;\n expiresIn: string;\n}\n\nexport interface VerifyUserTokenParams {\n token: string;\n secret: string | Uint8Array;\n}\n\nexport async function signUserToken(params: SignUserTokenParams): Promise<string> {\n const token = await signHs256({\n payload: {\n email: params.email,\n name: params.name ?? null,\n memberships: params.memberships,\n },\n secret: params.secret,\n expiresIn: params.expiresIn,\n subject: params.userId,\n });\n recordTokenIssued('session');\n return token;\n}\n\nexport async function verifyUserToken(params: VerifyUserTokenParams): Promise<UserTokenClaims> {\n try {\n const claims = await verifyHs256({\n token: params.token,\n secret: params.secret,\n schema: userTokenClaimsSchema,\n });\n recordTokenVerified('session', 'ok');\n return claims;\n } catch (error) {\n recordTokenVerified('session', 'rejected');\n throw error;\n }\n}\n"],"names":["workspaceRoleSchema","signHs256","verifyHs256","z","recordTokenIssued","recordTokenVerified","tokenMembershipSchema","object","workspaceId","string","uuid","role","userTokenClaimsSchema","sub","email","name","nullable","optional","memberships","array","iat","number","int","exp","signUserToken","params","token","payload","secret","expiresIn","subject","userId","verifyUserToken","claims","schema","error"],"mappings":"AAAA,SAAQA,mBAAmB,QAAO,8BAA8B;AAChE,SAAQC,SAAS,EAAEC,WAAW,QAAO,oBAAoB;AACzD,SAAQC,CAAC,QAAO,MAAM;AACtB,SAAQC,iBAAiB,EAAEC,mBAAmB,QAAO,oBAAoB;AAEzE,OAAO,MAAMC,wBAAwBH,EAAEI,MAAM,CAAC;IAC5CC,aAAaL,EAAEM,MAAM,GAAGC,IAAI;IAC5BC,MAAMX;AACR,GAAG;AAIH,OAAO,MAAMY,wBAAwBT,EAAEI,MAAM,CAAC;IAC5CM,KAAKV,EAAEM,MAAM,GAAGC,IAAI;IACpBI,OAAOX,EAAEM,MAAM,GAAGK,KAAK;IACvBC,MAAMZ,EAAEM,MAAM,GAAGO,QAAQ,GAAGC,QAAQ;IACpCC,aAAaf,EAAEgB,KAAK,CAACb;IACrBc,KAAKjB,EAAEkB,MAAM,GAAGC,GAAG;IACnBC,KAAKpB,EAAEkB,MAAM,GAAGC,GAAG;AACrB,GAAG;AAkBH,OAAO,eAAeE,cAAcC,MAA2B;IAC7D,MAAMC,QAAQ,MAAMzB,UAAU;QAC5B0B,SAAS;YACPb,OAAOW,OAAOX,KAAK;YACnBC,MAAMU,OAAOV,IAAI,IAAI;YACrBG,aAAaO,OAAOP,WAAW;QACjC;QACAU,QAAQH,OAAOG,MAAM;QACrBC,WAAWJ,OAAOI,SAAS;QAC3BC,SAASL,OAAOM,MAAM;IACxB;IACA3B,kBAAkB;IAClB,OAAOsB;AACT;AAEA,OAAO,eAAeM,gBAAgBP,MAA6B;IACjE,IAAI;QACF,MAAMQ,SAAS,MAAM/B,YAAY;YAC/BwB,OAAOD,OAAOC,KAAK;YACnBE,QAAQH,OAAOG,MAAM;YACrBM,QAAQtB;QACV;QACAP,oBAAoB,WAAW;QAC/B,OAAO4B;IACT,EAAE,OAAOE,OAAO;QACd9B,oBAAoB,WAAW;QAC/B,MAAM8B;IACR;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/core/rate-limit.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAGxB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAElD,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,qBAAa,0BAA2B,SAAQ,sBAAsB,CACpE,mBAAmB,EACnB,kBAAkB,CACnB;gBACa,MAAM,EAAE;QAClB,MAAM,EAAE,mBAAmB,CAAC;QAC5B,KAAK,EAAE,kBAAkB,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;KAC9B;CAKF;AAED,qBAAa,6BAA8B,SAAQ,yBAAyB,CAC1E,mBAAmB,EACnB,kBAAkB,CACnB;gBACa,MAAM,EAAE;QAClB,MAAM,EAAE,mBAAmB,CAAC;QAC5B,KAAK,EAAE,kBAAkB,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,KAAK,EAAE,OAAO,CAAC;KAChB;CAKF;AAgBD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAQT;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCxF"}
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/core/rate-limit.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,sBAAsB,EACtB,KAAK,eAAe,EACpB,yBAAyB,EAC1B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAGxB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,mBAAmB,GAAG,eAAe,CAAC;AAElD,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,qBAAa,0BAA2B,SAAQ,sBAAsB,CACpE,mBAAmB,EACnB,kBAAkB,CACnB;gBACa,MAAM,EAAE;QAClB,MAAM,EAAE,mBAAmB,CAAC;QAC5B,KAAK,EAAE,kBAAkB,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;KAC9B;CAKF;AAED,qBAAa,6BAA8B,SAAQ,yBAAyB,CAC1E,mBAAmB,EACnB,kBAAkB,CACnB;gBACa,MAAM,EAAE;QAClB,MAAM,EAAE,mBAAmB,CAAC;QAC5B,KAAK,EAAE,kBAAkB,CAAC;QAC1B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,KAAK,EAAE,OAAO,CAAC;KAChB;CAKF;AASD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,EAAE,kBAAkB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,CAQT;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCxF"}
@@ -1,6 +1,5 @@
1
- import { createHmac } from 'node:crypto';
1
+ import { rateLimitIdentifierKey } from '@shipfox/node-auth-root-key';
2
2
  import { checkRateLimit, hashRateLimitIdentifier, RateLimitExceededError, RateLimitUnavailableError } from '@shipfox/node-rate-limit';
3
- import { config } from '#config.js';
4
3
  import { consumeAuthRateLimit, pruneExpiredAuthRateLimits } from '#db/rate-limits.js';
5
4
  import { recordAuthRateLimitCheck, recordAuthRateLimitPruneFailure } from '#metrics/index.js';
6
5
  export class AuthRateLimitExceededError extends RateLimitExceededError {
@@ -18,13 +17,9 @@ export class AuthRateLimitUnavailableError extends RateLimitUnavailableError {
18
17
  }
19
18
  }
20
19
  const DEFAULT_TIMEOUT_MS = 250;
21
- const IDENTIFIER_SECRET_DERIVATION_DOMAIN = 'shipfox.auth.rate-limit.identifier-secret.v1';
22
20
  const IDENTIFIER_HASH_DOMAIN = 'shipfox.auth.rate-limit.identifier.v1';
23
21
  function effectiveIdentifierSecret() {
24
- if (config.RATE_LIMIT_IDENTIFIER_SECRET) {
25
- return config.RATE_LIMIT_IDENTIFIER_SECRET;
26
- }
27
- return createHmac('sha256', config.AUTH_JWT_SECRET).update(IDENTIFIER_SECRET_DERIVATION_DOMAIN).digest();
22
+ return rateLimitIdentifierKey();
28
23
  }
29
24
  export function hashAuthRateLimitIdentifier(params) {
30
25
  return hashRateLimitIdentifier({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/rate-limit.ts"],"sourcesContent":["import {createHmac} from 'node:crypto';\nimport {\n checkRateLimit,\n hashRateLimitIdentifier,\n RateLimitExceededError,\n type RateLimitPolicy,\n RateLimitUnavailableError,\n} from '@shipfox/node-rate-limit';\nimport {config} from '#config.js';\nimport {consumeAuthRateLimit, pruneExpiredAuthRateLimits} from '#db/rate-limits.js';\nimport {\n type AuthRateLimitAction,\n type AuthRateLimitScope,\n recordAuthRateLimitCheck,\n recordAuthRateLimitPruneFailure,\n} from '#metrics/index.js';\n\nexport type {\n AuthRateLimitAction,\n AuthRateLimitOutcome,\n AuthRateLimitScope,\n} from '#metrics/index.js';\n\nexport type AuthRateLimitPolicy = RateLimitPolicy;\n\nexport interface CheckAuthRateLimitParams extends AuthRateLimitPolicy {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifier: string;\n now?: Date | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport class AuthRateLimitExceededError extends RateLimitExceededError<\n AuthRateLimitAction,\n AuthRateLimitScope\n> {\n constructor(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n retryAfterSeconds: number;\n identifierHmacPrefix: string;\n }) {\n super(params);\n this.name = 'AuthRateLimitExceededError';\n this.message = 'Authentication rate limit exceeded';\n }\n}\n\nexport class AuthRateLimitUnavailableError extends RateLimitUnavailableError<\n AuthRateLimitAction,\n AuthRateLimitScope\n> {\n constructor(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifierHmacPrefix: string;\n cause: unknown;\n }) {\n super(params);\n this.name = 'AuthRateLimitUnavailableError';\n this.message = 'Authentication rate limiter unavailable';\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 250;\nconst IDENTIFIER_SECRET_DERIVATION_DOMAIN = 'shipfox.auth.rate-limit.identifier-secret.v1';\nconst IDENTIFIER_HASH_DOMAIN = 'shipfox.auth.rate-limit.identifier.v1';\n\nfunction effectiveIdentifierSecret(): Buffer | string {\n if (config.RATE_LIMIT_IDENTIFIER_SECRET) {\n return config.RATE_LIMIT_IDENTIFIER_SECRET;\n }\n\n return createHmac('sha256', config.AUTH_JWT_SECRET)\n .update(IDENTIFIER_SECRET_DERIVATION_DOMAIN)\n .digest();\n}\n\nexport function hashAuthRateLimitIdentifier(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifier: string;\n}): string {\n return hashRateLimitIdentifier({\n action: params.action,\n scope: params.scope,\n identifier: params.identifier,\n secret: effectiveIdentifierSecret(),\n domain: IDENTIFIER_HASH_DOMAIN,\n });\n}\n\nexport async function checkAuthRateLimit(params: CheckAuthRateLimitParams): Promise<void> {\n try {\n await checkRateLimit({\n action: params.action,\n scope: params.scope,\n identifier: params.identifier,\n limit: params.limit,\n windowSeconds: params.windowSeconds,\n identifierSecret: effectiveIdentifierSecret(),\n identifierHashDomain: IDENTIFIER_HASH_DOMAIN,\n consume: consumeAuthRateLimit,\n prune: pruneExpiredAuthRateLimits,\n onCheck: recordAuthRateLimitCheck,\n onPruneFailure: recordAuthRateLimitPruneFailure,\n now: params.now,\n timeoutMs: params.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n });\n } catch (error) {\n if (error instanceof RateLimitExceededError) {\n throw new AuthRateLimitExceededError({\n action: error.action,\n scope: error.scope,\n retryAfterSeconds: error.retryAfterSeconds,\n identifierHmacPrefix: error.identifierHmacPrefix,\n });\n }\n if (error instanceof RateLimitUnavailableError) {\n throw new AuthRateLimitUnavailableError({\n action: error.action,\n scope: error.scope,\n identifierHmacPrefix: error.identifierHmacPrefix,\n cause: error.cause,\n });\n }\n throw error;\n }\n}\n"],"names":["createHmac","checkRateLimit","hashRateLimitIdentifier","RateLimitExceededError","RateLimitUnavailableError","config","consumeAuthRateLimit","pruneExpiredAuthRateLimits","recordAuthRateLimitCheck","recordAuthRateLimitPruneFailure","AuthRateLimitExceededError","params","name","message","AuthRateLimitUnavailableError","DEFAULT_TIMEOUT_MS","IDENTIFIER_SECRET_DERIVATION_DOMAIN","IDENTIFIER_HASH_DOMAIN","effectiveIdentifierSecret","RATE_LIMIT_IDENTIFIER_SECRET","AUTH_JWT_SECRET","update","digest","hashAuthRateLimitIdentifier","action","scope","identifier","secret","domain","checkAuthRateLimit","limit","windowSeconds","identifierSecret","identifierHashDomain","consume","prune","onCheck","onPruneFailure","now","timeoutMs","error","retryAfterSeconds","identifierHmacPrefix","cause"],"mappings":"AAAA,SAAQA,UAAU,QAAO,cAAc;AACvC,SACEC,cAAc,EACdC,uBAAuB,EACvBC,sBAAsB,EAEtBC,yBAAyB,QACpB,2BAA2B;AAClC,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,oBAAoB,EAAEC,0BAA0B,QAAO,qBAAqB;AACpF,SAGEC,wBAAwB,EACxBC,+BAA+B,QAC1B,oBAAoB;AAkB3B,OAAO,MAAMC,mCAAmCP;IAI9C,YAAYQ,MAKX,CAAE;QACD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACC,OAAO,GAAG;IACjB;AACF;AAEA,OAAO,MAAMC,sCAAsCV;IAIjD,YAAYO,MAKX,CAAE;QACD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACC,OAAO,GAAG;IACjB;AACF;AAEA,MAAME,qBAAqB;AAC3B,MAAMC,sCAAsC;AAC5C,MAAMC,yBAAyB;AAE/B,SAASC;IACP,IAAIb,OAAOc,4BAA4B,EAAE;QACvC,OAAOd,OAAOc,4BAA4B;IAC5C;IAEA,OAAOnB,WAAW,UAAUK,OAAOe,eAAe,EAC/CC,MAAM,CAACL,qCACPM,MAAM;AACX;AAEA,OAAO,SAASC,4BAA4BZ,MAI3C;IACC,OAAOT,wBAAwB;QAC7BsB,QAAQb,OAAOa,MAAM;QACrBC,OAAOd,OAAOc,KAAK;QACnBC,YAAYf,OAAOe,UAAU;QAC7BC,QAAQT;QACRU,QAAQX;IACV;AACF;AAEA,OAAO,eAAeY,mBAAmBlB,MAAgC;IACvE,IAAI;QACF,MAAMV,eAAe;YACnBuB,QAAQb,OAAOa,MAAM;YACrBC,OAAOd,OAAOc,KAAK;YACnBC,YAAYf,OAAOe,UAAU;YAC7BI,OAAOnB,OAAOmB,KAAK;YACnBC,eAAepB,OAAOoB,aAAa;YACnCC,kBAAkBd;YAClBe,sBAAsBhB;YACtBiB,SAAS5B;YACT6B,OAAO5B;YACP6B,SAAS5B;YACT6B,gBAAgB5B;YAChB6B,KAAK3B,OAAO2B,GAAG;YACfC,WAAW5B,OAAO4B,SAAS,IAAIxB;QACjC;IACF,EAAE,OAAOyB,OAAO;QACd,IAAIA,iBAAiBrC,wBAAwB;YAC3C,MAAM,IAAIO,2BAA2B;gBACnCc,QAAQgB,MAAMhB,MAAM;gBACpBC,OAAOe,MAAMf,KAAK;gBAClBgB,mBAAmBD,MAAMC,iBAAiB;gBAC1CC,sBAAsBF,MAAME,oBAAoB;YAClD;QACF;QACA,IAAIF,iBAAiBpC,2BAA2B;YAC9C,MAAM,IAAIU,8BAA8B;gBACtCU,QAAQgB,MAAMhB,MAAM;gBACpBC,OAAOe,MAAMf,KAAK;gBAClBiB,sBAAsBF,MAAME,oBAAoB;gBAChDC,OAAOH,MAAMG,KAAK;YACpB;QACF;QACA,MAAMH;IACR;AACF"}
1
+ {"version":3,"sources":["../../src/core/rate-limit.ts"],"sourcesContent":["import {rateLimitIdentifierKey} from '@shipfox/node-auth-root-key';\nimport {\n checkRateLimit,\n hashRateLimitIdentifier,\n RateLimitExceededError,\n type RateLimitPolicy,\n RateLimitUnavailableError,\n} from '@shipfox/node-rate-limit';\nimport {consumeAuthRateLimit, pruneExpiredAuthRateLimits} from '#db/rate-limits.js';\nimport {\n type AuthRateLimitAction,\n type AuthRateLimitScope,\n recordAuthRateLimitCheck,\n recordAuthRateLimitPruneFailure,\n} from '#metrics/index.js';\n\nexport type {\n AuthRateLimitAction,\n AuthRateLimitOutcome,\n AuthRateLimitScope,\n} from '#metrics/index.js';\n\nexport type AuthRateLimitPolicy = RateLimitPolicy;\n\nexport interface CheckAuthRateLimitParams extends AuthRateLimitPolicy {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifier: string;\n now?: Date | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport class AuthRateLimitExceededError extends RateLimitExceededError<\n AuthRateLimitAction,\n AuthRateLimitScope\n> {\n constructor(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n retryAfterSeconds: number;\n identifierHmacPrefix: string;\n }) {\n super(params);\n this.name = 'AuthRateLimitExceededError';\n this.message = 'Authentication rate limit exceeded';\n }\n}\n\nexport class AuthRateLimitUnavailableError extends RateLimitUnavailableError<\n AuthRateLimitAction,\n AuthRateLimitScope\n> {\n constructor(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifierHmacPrefix: string;\n cause: unknown;\n }) {\n super(params);\n this.name = 'AuthRateLimitUnavailableError';\n this.message = 'Authentication rate limiter unavailable';\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 250;\nconst IDENTIFIER_HASH_DOMAIN = 'shipfox.auth.rate-limit.identifier.v1';\n\nfunction effectiveIdentifierSecret(): Uint8Array {\n return rateLimitIdentifierKey();\n}\n\nexport function hashAuthRateLimitIdentifier(params: {\n action: AuthRateLimitAction;\n scope: AuthRateLimitScope;\n identifier: string;\n}): string {\n return hashRateLimitIdentifier({\n action: params.action,\n scope: params.scope,\n identifier: params.identifier,\n secret: effectiveIdentifierSecret(),\n domain: IDENTIFIER_HASH_DOMAIN,\n });\n}\n\nexport async function checkAuthRateLimit(params: CheckAuthRateLimitParams): Promise<void> {\n try {\n await checkRateLimit({\n action: params.action,\n scope: params.scope,\n identifier: params.identifier,\n limit: params.limit,\n windowSeconds: params.windowSeconds,\n identifierSecret: effectiveIdentifierSecret(),\n identifierHashDomain: IDENTIFIER_HASH_DOMAIN,\n consume: consumeAuthRateLimit,\n prune: pruneExpiredAuthRateLimits,\n onCheck: recordAuthRateLimitCheck,\n onPruneFailure: recordAuthRateLimitPruneFailure,\n now: params.now,\n timeoutMs: params.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n });\n } catch (error) {\n if (error instanceof RateLimitExceededError) {\n throw new AuthRateLimitExceededError({\n action: error.action,\n scope: error.scope,\n retryAfterSeconds: error.retryAfterSeconds,\n identifierHmacPrefix: error.identifierHmacPrefix,\n });\n }\n if (error instanceof RateLimitUnavailableError) {\n throw new AuthRateLimitUnavailableError({\n action: error.action,\n scope: error.scope,\n identifierHmacPrefix: error.identifierHmacPrefix,\n cause: error.cause,\n });\n }\n throw error;\n }\n}\n"],"names":["rateLimitIdentifierKey","checkRateLimit","hashRateLimitIdentifier","RateLimitExceededError","RateLimitUnavailableError","consumeAuthRateLimit","pruneExpiredAuthRateLimits","recordAuthRateLimitCheck","recordAuthRateLimitPruneFailure","AuthRateLimitExceededError","params","name","message","AuthRateLimitUnavailableError","DEFAULT_TIMEOUT_MS","IDENTIFIER_HASH_DOMAIN","effectiveIdentifierSecret","hashAuthRateLimitIdentifier","action","scope","identifier","secret","domain","checkAuthRateLimit","limit","windowSeconds","identifierSecret","identifierHashDomain","consume","prune","onCheck","onPruneFailure","now","timeoutMs","error","retryAfterSeconds","identifierHmacPrefix","cause"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,8BAA8B;AACnE,SACEC,cAAc,EACdC,uBAAuB,EACvBC,sBAAsB,EAEtBC,yBAAyB,QACpB,2BAA2B;AAClC,SAAQC,oBAAoB,EAAEC,0BAA0B,QAAO,qBAAqB;AACpF,SAGEC,wBAAwB,EACxBC,+BAA+B,QAC1B,oBAAoB;AAkB3B,OAAO,MAAMC,mCAAmCN;IAI9C,YAAYO,MAKX,CAAE;QACD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACC,OAAO,GAAG;IACjB;AACF;AAEA,OAAO,MAAMC,sCAAsCT;IAIjD,YAAYM,MAKX,CAAE;QACD,KAAK,CAACA;QACN,IAAI,CAACC,IAAI,GAAG;QACZ,IAAI,CAACC,OAAO,GAAG;IACjB;AACF;AAEA,MAAME,qBAAqB;AAC3B,MAAMC,yBAAyB;AAE/B,SAASC;IACP,OAAOhB;AACT;AAEA,OAAO,SAASiB,4BAA4BP,MAI3C;IACC,OAAOR,wBAAwB;QAC7BgB,QAAQR,OAAOQ,MAAM;QACrBC,OAAOT,OAAOS,KAAK;QACnBC,YAAYV,OAAOU,UAAU;QAC7BC,QAAQL;QACRM,QAAQP;IACV;AACF;AAEA,OAAO,eAAeQ,mBAAmBb,MAAgC;IACvE,IAAI;QACF,MAAMT,eAAe;YACnBiB,QAAQR,OAAOQ,MAAM;YACrBC,OAAOT,OAAOS,KAAK;YACnBC,YAAYV,OAAOU,UAAU;YAC7BI,OAAOd,OAAOc,KAAK;YACnBC,eAAef,OAAOe,aAAa;YACnCC,kBAAkBV;YAClBW,sBAAsBZ;YACtBa,SAASvB;YACTwB,OAAOvB;YACPwB,SAASvB;YACTwB,gBAAgBvB;YAChBwB,KAAKtB,OAAOsB,GAAG;YACfC,WAAWvB,OAAOuB,SAAS,IAAInB;QACjC;IACF,EAAE,OAAOoB,OAAO;QACd,IAAIA,iBAAiB/B,wBAAwB;YAC3C,MAAM,IAAIM,2BAA2B;gBACnCS,QAAQgB,MAAMhB,MAAM;gBACpBC,OAAOe,MAAMf,KAAK;gBAClBgB,mBAAmBD,MAAMC,iBAAiB;gBAC1CC,sBAAsBF,MAAME,oBAAoB;YAClD;QACF;QACA,IAAIF,iBAAiB9B,2BAA2B;YAC9C,MAAM,IAAIS,8BAA8B;gBACtCK,QAAQgB,MAAMhB,MAAM;gBACpBC,OAAOe,MAAMf,KAAK;gBAClBiB,sBAAsBF,MAAME,oBAAoB;gBAChDC,OAAOH,MAAMG,KAAK;YACpB;QACF;QACA,MAAMH;IACR;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner-session-token.d.ts","sourceRoot":"","sources":["../../src/core/runner-session-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,uBAAuB,CAAC;AAM/B,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;AAElG,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,qFAAqF;AACrF,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAc1C"}
1
+ {"version":3,"file":"runner-session-token.d.ts","sourceRoot":"","sources":["../../src/core/runner-session-token.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,uBAAuB,CAAC;AAO/B,MAAM,MAAM,6BAA6B,GAAG,IAAI,CAAC,wBAAwB,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;AAElG,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED,qFAAqF;AACrF,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAc1C"}
@@ -1,4 +1,5 @@
1
1
  import { RUNNER_SESSION_TOKEN_AUDIENCE, runnerSessionTokenClaimsSchema } from '@shipfox/api-auth-dto';
2
+ import { runnerSessionTokenKey } from '@shipfox/node-auth-root-key';
2
3
  import { signHs256, verifyHs256 } from '@shipfox/node-jwt';
3
4
  import { config } from '#config.js';
4
5
  import { recordTokenIssued, recordTokenVerified } from '#metrics/index.js';
@@ -11,7 +12,7 @@ export async function issueRunnerSessionToken(claims) {
11
12
  labels: claims.labels,
12
13
  maxClaims: claims.maxClaims
13
14
  },
14
- secret: config.AUTH_RUNNER_SESSION_TOKEN_SECRET,
15
+ secret: runnerSessionTokenKey(),
15
16
  expiresIn: config.AUTH_RUNNER_SESSION_TOKEN_EXPIRES_IN,
16
17
  audience: RUNNER_SESSION_TOKEN_AUDIENCE
17
18
  });
@@ -22,7 +23,7 @@ export async function issueRunnerSessionToken(claims) {
22
23
  try {
23
24
  const claims = await verifyHs256({
24
25
  token,
25
- secret: config.AUTH_RUNNER_SESSION_TOKEN_SECRET,
26
+ secret: runnerSessionTokenKey(),
26
27
  schema: runnerSessionTokenClaimsSchema,
27
28
  audience: RUNNER_SESSION_TOKEN_AUDIENCE
28
29
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/runner-session-token.ts"],"sourcesContent":["import {\n RUNNER_SESSION_TOKEN_AUDIENCE,\n type RunnerSessionTokenClaims,\n runnerSessionTokenClaimsSchema,\n} from '@shipfox/api-auth-dto';\nimport {signHs256, verifyHs256} from '@shipfox/node-jwt';\nimport {config} from '#config.js';\nimport {recordTokenIssued, recordTokenVerified} from '#metrics/index.js';\n\n// `aud`, `iat` and `exp` are set by the codec (jose); callers supply the business ids only.\nexport type IssueRunnerSessionTokenParams = Omit<RunnerSessionTokenClaims, 'aud' | 'iat' | 'exp'>;\n\nexport async function issueRunnerSessionToken(\n claims: IssueRunnerSessionTokenParams,\n): Promise<string> {\n const token = await signHs256({\n payload: {\n runnerSessionId: claims.runnerSessionId,\n workspaceId: claims.workspaceId,\n scope: claims.scope,\n labels: claims.labels,\n maxClaims: claims.maxClaims,\n },\n secret: config.AUTH_RUNNER_SESSION_TOKEN_SECRET,\n expiresIn: config.AUTH_RUNNER_SESSION_TOKEN_EXPIRES_IN,\n audience: RUNNER_SESSION_TOKEN_AUDIENCE,\n });\n recordTokenIssued('runner_session');\n return token;\n}\n\n/** Returns the claims on success, or `null` for any invalid input — never throws. */\nexport async function verifyRunnerSessionToken(\n token: string,\n): Promise<RunnerSessionTokenClaims | null> {\n try {\n const claims = await verifyHs256({\n token,\n secret: config.AUTH_RUNNER_SESSION_TOKEN_SECRET,\n schema: runnerSessionTokenClaimsSchema,\n audience: RUNNER_SESSION_TOKEN_AUDIENCE,\n });\n recordTokenVerified('runner_session', 'ok');\n return claims;\n } catch {\n recordTokenVerified('runner_session', 'rejected');\n return null;\n }\n}\n"],"names":["RUNNER_SESSION_TOKEN_AUDIENCE","runnerSessionTokenClaimsSchema","signHs256","verifyHs256","config","recordTokenIssued","recordTokenVerified","issueRunnerSessionToken","claims","token","payload","runnerSessionId","workspaceId","scope","labels","maxClaims","secret","AUTH_RUNNER_SESSION_TOKEN_SECRET","expiresIn","AUTH_RUNNER_SESSION_TOKEN_EXPIRES_IN","audience","verifyRunnerSessionToken","schema"],"mappings":"AAAA,SACEA,6BAA6B,EAE7BC,8BAA8B,QACzB,wBAAwB;AAC/B,SAAQC,SAAS,EAAEC,WAAW,QAAO,oBAAoB;AACzD,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,iBAAiB,EAAEC,mBAAmB,QAAO,oBAAoB;AAKzE,OAAO,eAAeC,wBACpBC,MAAqC;IAErC,MAAMC,QAAQ,MAAMP,UAAU;QAC5BQ,SAAS;YACPC,iBAAiBH,OAAOG,eAAe;YACvCC,aAAaJ,OAAOI,WAAW;YAC/BC,OAAOL,OAAOK,KAAK;YACnBC,QAAQN,OAAOM,MAAM;YACrBC,WAAWP,OAAOO,SAAS;QAC7B;QACAC,QAAQZ,OAAOa,gCAAgC;QAC/CC,WAAWd,OAAOe,oCAAoC;QACtDC,UAAUpB;IACZ;IACAK,kBAAkB;IAClB,OAAOI;AACT;AAEA,mFAAmF,GACnF,OAAO,eAAeY,yBACpBZ,KAAa;IAEb,IAAI;QACF,MAAMD,SAAS,MAAML,YAAY;YAC/BM;YACAO,QAAQZ,OAAOa,gCAAgC;YAC/CK,QAAQrB;YACRmB,UAAUpB;QACZ;QACAM,oBAAoB,kBAAkB;QACtC,OAAOE;IACT,EAAE,OAAM;QACNF,oBAAoB,kBAAkB;QACtC,OAAO;IACT;AACF"}
1
+ {"version":3,"sources":["../../src/core/runner-session-token.ts"],"sourcesContent":["import {\n RUNNER_SESSION_TOKEN_AUDIENCE,\n type RunnerSessionTokenClaims,\n runnerSessionTokenClaimsSchema,\n} from '@shipfox/api-auth-dto';\nimport {runnerSessionTokenKey} from '@shipfox/node-auth-root-key';\nimport {signHs256, verifyHs256} from '@shipfox/node-jwt';\nimport {config} from '#config.js';\nimport {recordTokenIssued, recordTokenVerified} from '#metrics/index.js';\n\n// `aud`, `iat` and `exp` are set by the codec (jose); callers supply the business ids only.\nexport type IssueRunnerSessionTokenParams = Omit<RunnerSessionTokenClaims, 'aud' | 'iat' | 'exp'>;\n\nexport async function issueRunnerSessionToken(\n claims: IssueRunnerSessionTokenParams,\n): Promise<string> {\n const token = await signHs256({\n payload: {\n runnerSessionId: claims.runnerSessionId,\n workspaceId: claims.workspaceId,\n scope: claims.scope,\n labels: claims.labels,\n maxClaims: claims.maxClaims,\n },\n secret: runnerSessionTokenKey(),\n expiresIn: config.AUTH_RUNNER_SESSION_TOKEN_EXPIRES_IN,\n audience: RUNNER_SESSION_TOKEN_AUDIENCE,\n });\n recordTokenIssued('runner_session');\n return token;\n}\n\n/** Returns the claims on success, or `null` for any invalid input — never throws. */\nexport async function verifyRunnerSessionToken(\n token: string,\n): Promise<RunnerSessionTokenClaims | null> {\n try {\n const claims = await verifyHs256({\n token,\n secret: runnerSessionTokenKey(),\n schema: runnerSessionTokenClaimsSchema,\n audience: RUNNER_SESSION_TOKEN_AUDIENCE,\n });\n recordTokenVerified('runner_session', 'ok');\n return claims;\n } catch {\n recordTokenVerified('runner_session', 'rejected');\n return null;\n }\n}\n"],"names":["RUNNER_SESSION_TOKEN_AUDIENCE","runnerSessionTokenClaimsSchema","runnerSessionTokenKey","signHs256","verifyHs256","config","recordTokenIssued","recordTokenVerified","issueRunnerSessionToken","claims","token","payload","runnerSessionId","workspaceId","scope","labels","maxClaims","secret","expiresIn","AUTH_RUNNER_SESSION_TOKEN_EXPIRES_IN","audience","verifyRunnerSessionToken","schema"],"mappings":"AAAA,SACEA,6BAA6B,EAE7BC,8BAA8B,QACzB,wBAAwB;AAC/B,SAAQC,qBAAqB,QAAO,8BAA8B;AAClE,SAAQC,SAAS,EAAEC,WAAW,QAAO,oBAAoB;AACzD,SAAQC,MAAM,QAAO,aAAa;AAClC,SAAQC,iBAAiB,EAAEC,mBAAmB,QAAO,oBAAoB;AAKzE,OAAO,eAAeC,wBACpBC,MAAqC;IAErC,MAAMC,QAAQ,MAAMP,UAAU;QAC5BQ,SAAS;YACPC,iBAAiBH,OAAOG,eAAe;YACvCC,aAAaJ,OAAOI,WAAW;YAC/BC,OAAOL,OAAOK,KAAK;YACnBC,QAAQN,OAAOM,MAAM;YACrBC,WAAWP,OAAOO,SAAS;QAC7B;QACAC,QAAQf;QACRgB,WAAWb,OAAOc,oCAAoC;QACtDC,UAAUpB;IACZ;IACAM,kBAAkB;IAClB,OAAOI;AACT;AAEA,mFAAmF,GACnF,OAAO,eAAeW,yBACpBX,KAAa;IAEb,IAAI;QACF,MAAMD,SAAS,MAAML,YAAY;YAC/BM;YACAO,QAAQf;YACRoB,QAAQrB;YACRmB,UAAUpB;QACZ;QACAO,oBAAoB,kBAAkB;QACtC,OAAOE;IACT,EAAE,OAAM;QACNF,oBAAoB,kBAAkB;QACtC,OAAO;IACT;AACF"}
package/dist/db/db.d.ts CHANGED
@@ -412,115 +412,6 @@ export declare const schema: {
412
412
  };
413
413
  dialect: "pg";
414
414
  }>;
415
- emailVerifications: import("drizzle-orm/pg-core").PgTableWithColumns<{
416
- name: "email_verifications";
417
- schema: undefined;
418
- columns: {
419
- id: import("drizzle-orm/pg-core").PgColumn<{
420
- name: "id";
421
- tableName: "email_verifications";
422
- dataType: "string";
423
- columnType: "PgUUID";
424
- data: string;
425
- driverParam: string;
426
- notNull: true;
427
- hasDefault: true;
428
- isPrimaryKey: true;
429
- isAutoincrement: false;
430
- hasRuntimeDefault: false;
431
- enumValues: undefined;
432
- baseColumn: never;
433
- identity: undefined;
434
- generated: undefined;
435
- }, {}, {}>;
436
- userId: import("drizzle-orm/pg-core").PgColumn<{
437
- name: "user_id";
438
- tableName: "email_verifications";
439
- dataType: "string";
440
- columnType: "PgUUID";
441
- data: string;
442
- driverParam: string;
443
- notNull: true;
444
- hasDefault: false;
445
- isPrimaryKey: false;
446
- isAutoincrement: false;
447
- hasRuntimeDefault: false;
448
- enumValues: undefined;
449
- baseColumn: never;
450
- identity: undefined;
451
- generated: undefined;
452
- }, {}, {}>;
453
- hashedToken: import("drizzle-orm/pg-core").PgColumn<{
454
- name: "hashed_token";
455
- tableName: "email_verifications";
456
- dataType: "string";
457
- columnType: "PgText";
458
- data: string;
459
- driverParam: string;
460
- notNull: true;
461
- hasDefault: false;
462
- isPrimaryKey: false;
463
- isAutoincrement: false;
464
- hasRuntimeDefault: false;
465
- enumValues: [string, ...string[]];
466
- baseColumn: never;
467
- identity: undefined;
468
- generated: undefined;
469
- }, {}, {}>;
470
- expiresAt: import("drizzle-orm/pg-core").PgColumn<{
471
- name: "expires_at";
472
- tableName: "email_verifications";
473
- dataType: "date";
474
- columnType: "PgTimestamp";
475
- data: Date;
476
- driverParam: string;
477
- notNull: true;
478
- hasDefault: false;
479
- isPrimaryKey: false;
480
- isAutoincrement: false;
481
- hasRuntimeDefault: false;
482
- enumValues: undefined;
483
- baseColumn: never;
484
- identity: undefined;
485
- generated: undefined;
486
- }, {}, {}>;
487
- usedAt: import("drizzle-orm/pg-core").PgColumn<{
488
- name: "used_at";
489
- tableName: "email_verifications";
490
- dataType: "date";
491
- columnType: "PgTimestamp";
492
- data: Date;
493
- driverParam: string;
494
- notNull: false;
495
- hasDefault: false;
496
- isPrimaryKey: false;
497
- isAutoincrement: false;
498
- hasRuntimeDefault: false;
499
- enumValues: undefined;
500
- baseColumn: never;
501
- identity: undefined;
502
- generated: undefined;
503
- }, {}, {}>;
504
- createdAt: import("drizzle-orm/pg-core").PgColumn<{
505
- name: "created_at";
506
- tableName: "email_verifications";
507
- dataType: "date";
508
- columnType: "PgTimestamp";
509
- data: Date;
510
- driverParam: string;
511
- notNull: true;
512
- hasDefault: true;
513
- isPrimaryKey: false;
514
- isAutoincrement: false;
515
- hasRuntimeDefault: false;
516
- enumValues: undefined;
517
- baseColumn: never;
518
- identity: undefined;
519
- generated: undefined;
520
- }, {}, {}>;
521
- };
522
- dialect: "pg";
523
- }>;
524
415
  authOutbox: import("drizzle-orm/pg-core").PgTableWithColumns<{
525
416
  name: "outbox";
526
417
  schema: undefined;
@@ -1272,115 +1163,6 @@ export declare function db(): NodePgDatabase<{
1272
1163
  };
1273
1164
  dialect: "pg";
1274
1165
  }>;
1275
- emailVerifications: import("drizzle-orm/pg-core").PgTableWithColumns<{
1276
- name: "email_verifications";
1277
- schema: undefined;
1278
- columns: {
1279
- id: import("drizzle-orm/pg-core").PgColumn<{
1280
- name: "id";
1281
- tableName: "email_verifications";
1282
- dataType: "string";
1283
- columnType: "PgUUID";
1284
- data: string;
1285
- driverParam: string;
1286
- notNull: true;
1287
- hasDefault: true;
1288
- isPrimaryKey: true;
1289
- isAutoincrement: false;
1290
- hasRuntimeDefault: false;
1291
- enumValues: undefined;
1292
- baseColumn: never;
1293
- identity: undefined;
1294
- generated: undefined;
1295
- }, {}, {}>;
1296
- userId: import("drizzle-orm/pg-core").PgColumn<{
1297
- name: "user_id";
1298
- tableName: "email_verifications";
1299
- dataType: "string";
1300
- columnType: "PgUUID";
1301
- data: string;
1302
- driverParam: string;
1303
- notNull: true;
1304
- hasDefault: false;
1305
- isPrimaryKey: false;
1306
- isAutoincrement: false;
1307
- hasRuntimeDefault: false;
1308
- enumValues: undefined;
1309
- baseColumn: never;
1310
- identity: undefined;
1311
- generated: undefined;
1312
- }, {}, {}>;
1313
- hashedToken: import("drizzle-orm/pg-core").PgColumn<{
1314
- name: "hashed_token";
1315
- tableName: "email_verifications";
1316
- dataType: "string";
1317
- columnType: "PgText";
1318
- data: string;
1319
- driverParam: string;
1320
- notNull: true;
1321
- hasDefault: false;
1322
- isPrimaryKey: false;
1323
- isAutoincrement: false;
1324
- hasRuntimeDefault: false;
1325
- enumValues: [string, ...string[]];
1326
- baseColumn: never;
1327
- identity: undefined;
1328
- generated: undefined;
1329
- }, {}, {}>;
1330
- expiresAt: import("drizzle-orm/pg-core").PgColumn<{
1331
- name: "expires_at";
1332
- tableName: "email_verifications";
1333
- dataType: "date";
1334
- columnType: "PgTimestamp";
1335
- data: Date;
1336
- driverParam: string;
1337
- notNull: true;
1338
- hasDefault: false;
1339
- isPrimaryKey: false;
1340
- isAutoincrement: false;
1341
- hasRuntimeDefault: false;
1342
- enumValues: undefined;
1343
- baseColumn: never;
1344
- identity: undefined;
1345
- generated: undefined;
1346
- }, {}, {}>;
1347
- usedAt: import("drizzle-orm/pg-core").PgColumn<{
1348
- name: "used_at";
1349
- tableName: "email_verifications";
1350
- dataType: "date";
1351
- columnType: "PgTimestamp";
1352
- data: Date;
1353
- driverParam: string;
1354
- notNull: false;
1355
- hasDefault: false;
1356
- isPrimaryKey: false;
1357
- isAutoincrement: false;
1358
- hasRuntimeDefault: false;
1359
- enumValues: undefined;
1360
- baseColumn: never;
1361
- identity: undefined;
1362
- generated: undefined;
1363
- }, {}, {}>;
1364
- createdAt: import("drizzle-orm/pg-core").PgColumn<{
1365
- name: "created_at";
1366
- tableName: "email_verifications";
1367
- dataType: "date";
1368
- columnType: "PgTimestamp";
1369
- data: Date;
1370
- driverParam: string;
1371
- notNull: true;
1372
- hasDefault: true;
1373
- isPrimaryKey: false;
1374
- isAutoincrement: false;
1375
- hasRuntimeDefault: false;
1376
- enumValues: undefined;
1377
- baseColumn: never;
1378
- identity: undefined;
1379
- generated: undefined;
1380
- }, {}, {}>;
1381
- };
1382
- dialect: "pg";
1383
- }>;
1384
1166
  authOutbox: import("drizzle-orm/pg-core").PgTableWithColumns<{
1385
1167
  name: "outbox";
1386
1168
  schema: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AASnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAQnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAMlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B"}
package/dist/db/db.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { drizzle } from '@shipfox/node-drizzle';
2
2
  import { pgClient } from '@shipfox/node-postgres';
3
- import { emailVerifications } from './schema/email-verifications.js';
4
3
  import { authOutbox } from './schema/outbox.js';
5
4
  import { passwordResets } from './schema/password-resets.js';
6
5
  import { authRateLimits } from './schema/rate-limits.js';
@@ -10,7 +9,6 @@ export const schema = {
10
9
  users,
11
10
  passwordResets,
12
11
  refreshTokens,
13
- emailVerifications,
14
12
  authOutbox,
15
13
  authRateLimits
16
14
  };
package/dist/db/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/db.ts"],"sourcesContent":["import {drizzle, type NodePgDatabase} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {emailVerifications} from './schema/email-verifications.js';\nimport {authOutbox} from './schema/outbox.js';\nimport {passwordResets} from './schema/password-resets.js';\nimport {authRateLimits} from './schema/rate-limits.js';\nimport {refreshTokens} from './schema/refresh-tokens.js';\nimport {users} from './schema/users.js';\n\nexport const schema = {\n users,\n passwordResets,\n refreshTokens,\n emailVerifications,\n authOutbox,\n authRateLimits,\n};\n\nlet _db: NodePgDatabase<typeof schema> | undefined;\n\nexport function db() {\n if (!_db) _db = drizzle(pgClient(), {schema});\n return _db;\n}\n\nexport function closeDb(): void {\n _db = undefined;\n}\n"],"names":["drizzle","pgClient","emailVerifications","authOutbox","passwordResets","authRateLimits","refreshTokens","users","schema","_db","db","closeDb","undefined"],"mappings":"AAAA,SAAQA,OAAO,QAA4B,wBAAwB;AACnE,SAAQC,QAAQ,QAAO,yBAAyB;AAChD,SAAQC,kBAAkB,QAAO,kCAAkC;AACnE,SAAQC,UAAU,QAAO,qBAAqB;AAC9C,SAAQC,cAAc,QAAO,8BAA8B;AAC3D,SAAQC,cAAc,QAAO,0BAA0B;AACvD,SAAQC,aAAa,QAAO,6BAA6B;AACzD,SAAQC,KAAK,QAAO,oBAAoB;AAExC,OAAO,MAAMC,SAAS;IACpBD;IACAH;IACAE;IACAJ;IACAC;IACAE;AACF,EAAE;AAEF,IAAII;AAEJ,OAAO,SAASC;IACd,IAAI,CAACD,KAAKA,MAAMT,QAAQC,YAAY;QAACO;IAAM;IAC3C,OAAOC;AACT;AAEA,OAAO,SAASE;IACdF,MAAMG;AACR"}
1
+ {"version":3,"sources":["../../src/db/db.ts"],"sourcesContent":["import {drizzle, type NodePgDatabase} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {authOutbox} from './schema/outbox.js';\nimport {passwordResets} from './schema/password-resets.js';\nimport {authRateLimits} from './schema/rate-limits.js';\nimport {refreshTokens} from './schema/refresh-tokens.js';\nimport {users} from './schema/users.js';\n\nexport const schema = {\n users,\n passwordResets,\n refreshTokens,\n authOutbox,\n authRateLimits,\n};\n\nlet _db: NodePgDatabase<typeof schema> | undefined;\n\nexport function db() {\n if (!_db) _db = drizzle(pgClient(), {schema});\n return _db;\n}\n\nexport function closeDb(): void {\n _db = undefined;\n}\n"],"names":["drizzle","pgClient","authOutbox","passwordResets","authRateLimits","refreshTokens","users","schema","_db","db","closeDb","undefined"],"mappings":"AAAA,SAAQA,OAAO,QAA4B,wBAAwB;AACnE,SAAQC,QAAQ,QAAO,yBAAyB;AAChD,SAAQC,UAAU,QAAO,qBAAqB;AAC9C,SAAQC,cAAc,QAAO,8BAA8B;AAC3D,SAAQC,cAAc,QAAO,0BAA0B;AACvD,SAAQC,aAAa,QAAO,6BAA6B;AACzD,SAAQC,KAAK,QAAO,oBAAoB;AAExC,OAAO,MAAMC,SAAS;IACpBD;IACAH;IACAE;IACAH;IACAE;AACF,EAAE;AAEF,IAAII;AAEJ,OAAO,SAASC;IACd,IAAI,CAACD,KAAKA,MAAMR,QAAQC,YAAY;QAACM;IAAM;IAC3C,OAAOC;AACT;AAEA,OAAO,SAASE;IACdF,MAAMG;AACR"}
@@ -4,6 +4,9 @@ export interface CreateUserParams {
4
4
  hashedPassword: string | null;
5
5
  name?: string | null;
6
6
  emailVerifiedAt?: Date | null;
7
+ signedUp?: {
8
+ viaInvitation: boolean;
9
+ };
7
10
  }
8
11
  export interface ProvisionUserParams {
9
12
  email: string;
@@ -1 +1 @@
1
- {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/db/users.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAKjD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAcD,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBxE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB9E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAKxF;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAKlF;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAa3B;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAU3F"}
1
+ {"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../src/db/users.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,wBAAwB,CAAC;AAMjD,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE;QAAC,aAAa,EAAE,OAAO,CAAA;KAAC,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAcD,wBAAsB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoCxE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB9E;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAKxF;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAKlF;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAa3B;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,CAU3F"}
package/dist/db/users.js CHANGED
@@ -1,6 +1,9 @@
1
+ import { AUTH_USER_SIGNED_UP } from '@shipfox/api-auth-dto';
2
+ import { writeOutboxEvent } from '@shipfox/node-outbox';
1
3
  import { eq } from 'drizzle-orm';
2
4
  import { EmailTakenError } from '#core/errors.js';
3
5
  import { db } from './db.js';
6
+ import { authOutbox } from './schema/outbox.js';
4
7
  import { toUser, users } from './schema/users.js';
5
8
  // Drizzle wraps the underlying Postgres error; walk `.cause` to reach it.
6
9
  function isAuthUsersEmailUniqueViolation(error) {
@@ -14,23 +17,38 @@ function isAuthUsersEmailUniqueViolation(error) {
14
17
  return false;
15
18
  }
16
19
  export async function createUser(params) {
17
- let rows;
18
20
  try {
19
- rows = await db().insert(users).values({
20
- email: params.email,
21
- hashedPassword: params.hashedPassword,
22
- name: params.name ?? null,
23
- emailVerifiedAt: params.emailVerifiedAt ?? null
24
- }).returning();
21
+ return await db().transaction(async (tx)=>{
22
+ const rows = await tx.insert(users).values({
23
+ email: params.email,
24
+ hashedPassword: params.hashedPassword,
25
+ name: params.name ?? null,
26
+ emailVerifiedAt: params.emailVerifiedAt ?? null
27
+ }).returning();
28
+ const row = rows[0];
29
+ if (!row) throw new Error('Insert returned no rows');
30
+ const user = toUser(row);
31
+ if (params.signedUp) {
32
+ await writeOutboxEvent(tx, authOutbox, {
33
+ type: AUTH_USER_SIGNED_UP,
34
+ payload: {
35
+ userId: user.id,
36
+ email: user.email,
37
+ ...user.name ? {
38
+ name: user.name
39
+ } : {},
40
+ viaInvitation: params.signedUp.viaInvitation
41
+ }
42
+ });
43
+ }
44
+ return user;
45
+ });
25
46
  } catch (error) {
26
47
  if (isAuthUsersEmailUniqueViolation(error)) {
27
48
  throw new EmailTakenError(params.email);
28
49
  }
29
50
  throw error;
30
51
  }
31
- const row = rows[0];
32
- if (!row) throw new Error('Insert returned no rows');
33
- return toUser(row);
34
52
  }
35
53
  export async function provisionUser(params) {
36
54
  const rows = await db().insert(users).values({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/users.ts"],"sourcesContent":["import {eq} from 'drizzle-orm';\nimport type {User} from '#core/entities/user.js';\nimport {EmailTakenError} from '#core/errors.js';\nimport {db} from './db.js';\nimport {toUser, type UserDb, users} from './schema/users.js';\n\nexport interface CreateUserParams {\n email: string;\n hashedPassword: string | null;\n name?: string | null;\n emailVerifiedAt?: Date | null;\n}\n\nexport interface ProvisionUserParams {\n email: string;\n name?: string | null;\n}\n\n// Drizzle wraps the underlying Postgres error; walk `.cause` to reach it.\nfunction isAuthUsersEmailUniqueViolation(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth += 1) {\n if (typeof current !== 'object') return false;\n const {code, constraint} = current as {code?: unknown; constraint?: unknown};\n if (code === '23505' && constraint === 'auth_users_email_unique') return true;\n current = (current as {cause?: unknown}).cause;\n }\n return false;\n}\n\nexport async function createUser(params: CreateUserParams): Promise<User> {\n let rows: UserDb[];\n try {\n rows = await db()\n .insert(users)\n .values({\n email: params.email,\n hashedPassword: params.hashedPassword,\n name: params.name ?? null,\n emailVerifiedAt: params.emailVerifiedAt ?? null,\n })\n .returning();\n } catch (error) {\n if (isAuthUsersEmailUniqueViolation(error)) {\n throw new EmailTakenError(params.email);\n }\n throw error;\n }\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n return toUser(row);\n}\n\nexport async function provisionUser(params: ProvisionUserParams): Promise<User> {\n const rows = await db()\n .insert(users)\n .values({\n email: params.email,\n hashedPassword: null,\n name: params.name ?? null,\n emailVerifiedAt: new Date(),\n })\n .onConflictDoNothing({target: users.email})\n .returning();\n\n const row = rows[0];\n if (row) return toUser(row);\n\n const existing = await findUserByEmail({email: params.email});\n if (existing) return existing;\n throw new Error('Provisioning user conflict returned no user');\n}\n\nexport async function findUserByEmail(params: {email: string}): Promise<User | undefined> {\n const rows = await db().select().from(users).where(eq(users.email, params.email)).limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport async function findUserById(params: {id: string}): Promise<User | undefined> {\n const rows = await db().select().from(users).where(eq(users.id, params.id)).limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport interface UpdateUserPasswordParams {\n userId: string;\n hashedPassword: string;\n}\n\nexport async function updateUserPassword(\n params: UpdateUserPasswordParams,\n): Promise<User | undefined> {\n const rows = await db()\n .update(users)\n .set({\n hashedPassword: params.hashedPassword,\n updatedAt: new Date(),\n })\n .where(eq(users.id, params.userId))\n .returning();\n\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport async function markEmailVerified(params: {userId: string}): Promise<User | undefined> {\n const rows = await db()\n .update(users)\n .set({emailVerifiedAt: new Date(), updatedAt: new Date()})\n .where(eq(users.id, params.userId))\n .returning();\n\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n"],"names":["eq","EmailTakenError","db","toUser","users","isAuthUsersEmailUniqueViolation","error","current","depth","code","constraint","cause","createUser","params","rows","insert","values","email","hashedPassword","name","emailVerifiedAt","returning","row","Error","provisionUser","Date","onConflictDoNothing","target","existing","findUserByEmail","select","from","where","limit","undefined","findUserById","id","updateUserPassword","update","set","updatedAt","userId","markEmailVerified"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/db/users.ts"],"sourcesContent":["import {AUTH_USER_SIGNED_UP, type AuthEventMap} from '@shipfox/api-auth-dto';\nimport {writeOutboxEvent} from '@shipfox/node-outbox';\nimport {eq} from 'drizzle-orm';\nimport type {User} from '#core/entities/user.js';\nimport {EmailTakenError} from '#core/errors.js';\nimport {db} from './db.js';\nimport {authOutbox} from './schema/outbox.js';\nimport {toUser, type UserDb, users} from './schema/users.js';\n\nexport interface CreateUserParams {\n email: string;\n hashedPassword: string | null;\n name?: string | null;\n emailVerifiedAt?: Date | null;\n signedUp?: {viaInvitation: boolean};\n}\n\nexport interface ProvisionUserParams {\n email: string;\n name?: string | null;\n}\n\n// Drizzle wraps the underlying Postgres error; walk `.cause` to reach it.\nfunction isAuthUsersEmailUniqueViolation(error: unknown): boolean {\n let current: unknown = error;\n for (let depth = 0; depth < 5 && current != null; depth += 1) {\n if (typeof current !== 'object') return false;\n const {code, constraint} = current as {code?: unknown; constraint?: unknown};\n if (code === '23505' && constraint === 'auth_users_email_unique') return true;\n current = (current as {cause?: unknown}).cause;\n }\n return false;\n}\n\nexport async function createUser(params: CreateUserParams): Promise<User> {\n try {\n return await db().transaction(async (tx) => {\n const rows: UserDb[] = await tx\n .insert(users)\n .values({\n email: params.email,\n hashedPassword: params.hashedPassword,\n name: params.name ?? null,\n emailVerifiedAt: params.emailVerifiedAt ?? null,\n })\n .returning();\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n\n const user = toUser(row);\n if (params.signedUp) {\n await writeOutboxEvent<AuthEventMap>(tx, authOutbox, {\n type: AUTH_USER_SIGNED_UP,\n payload: {\n userId: user.id,\n email: user.email,\n ...(user.name ? {name: user.name} : {}),\n viaInvitation: params.signedUp.viaInvitation,\n },\n });\n }\n return user;\n });\n } catch (error) {\n if (isAuthUsersEmailUniqueViolation(error)) {\n throw new EmailTakenError(params.email);\n }\n throw error;\n }\n}\n\nexport async function provisionUser(params: ProvisionUserParams): Promise<User> {\n const rows = await db()\n .insert(users)\n .values({\n email: params.email,\n hashedPassword: null,\n name: params.name ?? null,\n emailVerifiedAt: new Date(),\n })\n .onConflictDoNothing({target: users.email})\n .returning();\n\n const row = rows[0];\n if (row) return toUser(row);\n\n const existing = await findUserByEmail({email: params.email});\n if (existing) return existing;\n throw new Error('Provisioning user conflict returned no user');\n}\n\nexport async function findUserByEmail(params: {email: string}): Promise<User | undefined> {\n const rows = await db().select().from(users).where(eq(users.email, params.email)).limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport async function findUserById(params: {id: string}): Promise<User | undefined> {\n const rows = await db().select().from(users).where(eq(users.id, params.id)).limit(1);\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport interface UpdateUserPasswordParams {\n userId: string;\n hashedPassword: string;\n}\n\nexport async function updateUserPassword(\n params: UpdateUserPasswordParams,\n): Promise<User | undefined> {\n const rows = await db()\n .update(users)\n .set({\n hashedPassword: params.hashedPassword,\n updatedAt: new Date(),\n })\n .where(eq(users.id, params.userId))\n .returning();\n\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n\nexport async function markEmailVerified(params: {userId: string}): Promise<User | undefined> {\n const rows = await db()\n .update(users)\n .set({emailVerifiedAt: new Date(), updatedAt: new Date()})\n .where(eq(users.id, params.userId))\n .returning();\n\n const row = rows[0];\n if (!row) return undefined;\n return toUser(row);\n}\n"],"names":["AUTH_USER_SIGNED_UP","writeOutboxEvent","eq","EmailTakenError","db","authOutbox","toUser","users","isAuthUsersEmailUniqueViolation","error","current","depth","code","constraint","cause","createUser","params","transaction","tx","rows","insert","values","email","hashedPassword","name","emailVerifiedAt","returning","row","Error","user","signedUp","type","payload","userId","id","viaInvitation","provisionUser","Date","onConflictDoNothing","target","existing","findUserByEmail","select","from","where","limit","undefined","findUserById","updateUserPassword","update","set","updatedAt","markEmailVerified"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ import type { ShipfoxModule } from '@shipfox/node-module';
2
2
  export type { JobLeaseTokenClaims, RunnerSessionTokenClaims } from '@shipfox/api-auth-dto';
3
3
  export type { CreateSessionForUserError, CreateSessionForUserParams, CreateSessionForUserResult, ProvisionUserParams, } from '#core/auth.js';
4
4
  export { createSessionForUser, provisionUser } from '#core/auth.js';
5
+ export type { EmailOwner, FindUserByEmailParams } from '#core/email-owner.js';
6
+ export { findUserByEmail } from '#core/email-owner.js';
5
7
  export type { User, UserStatus } from '#core/entities/user.js';
6
8
  export { AuthDependencyUnavailableError, EmailNotVerifiedError, InvalidCredentialsError, UserNotFoundError, } from '#core/errors.js';
7
9
  export { issueJobLeaseToken, jobLeaseParamsFrom, verifyJobLeaseToken, } from '#core/job-lease-token.js';
@@ -10,5 +12,7 @@ export { createJwtAuthMethod } from '#presentation/auth/jwt-auth.js';
10
12
  export { createLeaseTokenAuthMethod } from '#presentation/auth/lease-token-auth.js';
11
13
  export { authCookiePlugin, clearRefreshTokenCookie, getRefreshTokenCookie, setRefreshTokenCookie, } from '#presentation/auth/refresh-cookie.js';
12
14
  export { createRunnerSessionAuthMethod } from '#presentation/auth/runner-session-auth.js';
13
- export declare const authModule: ShipfoxModule;
15
+ export declare function createAuthModule({ workspaces, }: {
16
+ workspaces: import('@shipfox/api-workspaces-dto/inter-module').WorkspacesInterModuleClient;
17
+ }): ShipfoxModule;
14
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAiBxD,YAAY,EAAC,mBAAmB,EAAE,wBAAwB,EAAC,MAAM,uBAAuB,CAAC;AACzF,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,oBAAoB,EAAE,aAAa,EAAC,MAAM,eAAe,CAAC;AAClE,YAAY,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAC,0BAA0B,EAAC,MAAM,wCAAwC,CAAC;AAClF,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAC,6BAA6B,EAAC,MAAM,2CAA2C,CAAC;AAIxF,eAAO,MAAM,UAAU,EAAE,aAYxB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAexD,YAAY,EAAC,mBAAmB,EAAE,wBAAwB,EAAC,MAAM,uBAAuB,CAAC;AACzF,YAAY,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,0BAA0B,EAC1B,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAC,oBAAoB,EAAE,aAAa,EAAC,MAAM,eAAe,CAAC;AAClE,YAAY,EAAC,UAAU,EAAE,qBAAqB,EAAC,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAC,IAAI,EAAE,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAC,mBAAmB,EAAC,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAC,0BAA0B,EAAC,MAAM,wCAAwC,CAAC;AAClF,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAC,6BAA6B,EAAC,MAAM,2CAA2C,CAAC;AAIxF,wBAAgB,gBAAgB,CAAC,EAC/B,UAAU,GACX,EAAE;IACD,UAAU,EAAE,OAAO,0CAA0C,EAAE,2BAA2B,CAAC;CAC5F,GAAG,aAAa,CAYhB"}