@sixthsummit/ship-api 0.0.0-stage → 4.1.1

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 (556) hide show
  1. package/CHANGELOG.md +605 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +4 -0
  4. package/README.md +58 -2
  5. package/cli/commands/add.js +537 -0
  6. package/cli/commands/contract.js +2 -0
  7. package/cli/commands/create.js +250 -0
  8. package/cli/commands/dev.js +227 -0
  9. package/cli/commands/doctor.js +286 -0
  10. package/cli/commands/generate.js +937 -0
  11. package/cli/commands/graph.js +2 -0
  12. package/cli/commands/migrate-orm.js +1171 -0
  13. package/cli/commands/update.js +37 -0
  14. package/cli/ship-api.js +285 -0
  15. package/lib/app/auth/AuthProvider.d.ts +91 -0
  16. package/lib/app/auth/AuthProvider.d.ts.map +1 -0
  17. package/lib/app/auth/AuthProvider.js +13 -0
  18. package/lib/app/auth/AuthProvider.js.map +1 -0
  19. package/lib/app/auth/adapters/firebase.d.ts +79 -0
  20. package/lib/app/auth/adapters/firebase.d.ts.map +1 -0
  21. package/lib/app/auth/adapters/firebase.js +122 -0
  22. package/lib/app/auth/adapters/firebase.js.map +1 -0
  23. package/lib/app/auth/adapters/jwtCookie.d.ts +55 -0
  24. package/lib/app/auth/adapters/jwtCookie.d.ts.map +1 -0
  25. package/lib/app/auth/adapters/jwtCookie.js +120 -0
  26. package/lib/app/auth/adapters/jwtCookie.js.map +1 -0
  27. package/lib/app/auth/index.d.ts +8 -0
  28. package/lib/app/auth/index.d.ts.map +1 -0
  29. package/lib/app/auth/index.js +7 -0
  30. package/lib/app/auth/index.js.map +1 -0
  31. package/lib/app/auth/jwt/AuthFlow.d.ts +94 -0
  32. package/lib/app/auth/jwt/AuthFlow.d.ts.map +1 -0
  33. package/lib/app/auth/jwt/AuthFlow.js +127 -0
  34. package/lib/app/auth/jwt/AuthFlow.js.map +1 -0
  35. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts +80 -0
  36. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.d.ts.map +1 -0
  37. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js +134 -0
  38. package/lib/app/auth/jwt/DrizzleRefreshTokenStore.js.map +1 -0
  39. package/lib/app/auth/jwt/JwtSigner.d.ts +123 -0
  40. package/lib/app/auth/jwt/JwtSigner.d.ts.map +1 -0
  41. package/lib/app/auth/jwt/JwtSigner.js +118 -0
  42. package/lib/app/auth/jwt/JwtSigner.js.map +1 -0
  43. package/lib/app/auth/jwt/RefreshTokenStore.d.ts +97 -0
  44. package/lib/app/auth/jwt/RefreshTokenStore.d.ts.map +1 -0
  45. package/lib/app/auth/jwt/RefreshTokenStore.js +122 -0
  46. package/lib/app/auth/jwt/RefreshTokenStore.js.map +1 -0
  47. package/lib/app/auth/permissionDefinition.d.ts +20 -0
  48. package/lib/app/auth/permissionDefinition.d.ts.map +1 -0
  49. package/lib/app/auth/permissionDefinition.js +2 -0
  50. package/lib/app/auth/permissionDefinition.js.map +1 -0
  51. package/lib/app/context/RequestContext.d.ts +59 -0
  52. package/lib/app/context/RequestContext.d.ts.map +1 -0
  53. package/lib/app/context/RequestContext.js +25 -0
  54. package/lib/app/context/RequestContext.js.map +1 -0
  55. package/lib/app/db/QueryOptions.d.ts +82 -0
  56. package/lib/app/db/QueryOptions.d.ts.map +1 -0
  57. package/lib/app/db/QueryOptions.js +37 -0
  58. package/lib/app/db/QueryOptions.js.map +1 -0
  59. package/lib/app/db/baseFields.d.ts +60 -0
  60. package/lib/app/db/baseFields.d.ts.map +1 -0
  61. package/lib/app/db/baseFields.js +54 -0
  62. package/lib/app/db/baseFields.js.map +1 -0
  63. package/lib/app/db/buildWhere.d.ts +22 -0
  64. package/lib/app/db/buildWhere.d.ts.map +1 -0
  65. package/lib/app/db/buildWhere.js +75 -0
  66. package/lib/app/db/buildWhere.js.map +1 -0
  67. package/lib/app/db/client.d.ts +111 -0
  68. package/lib/app/db/client.d.ts.map +1 -0
  69. package/lib/app/db/client.js +99 -0
  70. package/lib/app/db/client.js.map +1 -0
  71. package/lib/app/db/tenantScoped.d.ts +59 -0
  72. package/lib/app/db/tenantScoped.d.ts.map +1 -0
  73. package/lib/app/db/tenantScoped.js +54 -0
  74. package/lib/app/db/tenantScoped.js.map +1 -0
  75. package/lib/app/db/transaction.d.ts +58 -0
  76. package/lib/app/db/transaction.d.ts.map +1 -0
  77. package/lib/app/db/transaction.js +106 -0
  78. package/lib/app/db/transaction.js.map +1 -0
  79. package/lib/app/health/HealthCheck.d.ts +121 -0
  80. package/lib/app/health/HealthCheck.d.ts.map +1 -0
  81. package/lib/app/health/HealthCheck.js +151 -0
  82. package/lib/app/health/HealthCheck.js.map +1 -0
  83. package/lib/app/health/redisHealthCheck.d.ts +14 -0
  84. package/lib/app/health/redisHealthCheck.d.ts.map +1 -0
  85. package/lib/app/health/redisHealthCheck.js +21 -0
  86. package/lib/app/health/redisHealthCheck.js.map +1 -0
  87. package/lib/app/lifecycle/Bootstrapper.d.ts +92 -0
  88. package/lib/app/lifecycle/Bootstrapper.d.ts.map +1 -0
  89. package/lib/app/lifecycle/Bootstrapper.js +99 -0
  90. package/lib/app/lifecycle/Bootstrapper.js.map +1 -0
  91. package/lib/app/registry/routes.d.ts +89 -0
  92. package/lib/app/registry/routes.d.ts.map +1 -0
  93. package/lib/app/registry/routes.js +72 -0
  94. package/lib/app/registry/routes.js.map +1 -0
  95. package/lib/app/services/DrizzleEntityService.d.ts +123 -0
  96. package/lib/app/services/DrizzleEntityService.d.ts.map +1 -0
  97. package/lib/app/services/DrizzleEntityService.js +342 -0
  98. package/lib/app/services/DrizzleEntityService.js.map +1 -0
  99. package/lib/app/services/RedisProvider.d.ts +52 -0
  100. package/lib/app/services/RedisProvider.d.ts.map +1 -0
  101. package/lib/app/services/RedisProvider.js +75 -0
  102. package/lib/app/services/RedisProvider.js.map +1 -0
  103. package/lib/app/services/cache/Cache.d.ts +70 -0
  104. package/lib/app/services/cache/Cache.d.ts.map +1 -0
  105. package/lib/app/services/cache/Cache.js +18 -0
  106. package/lib/app/services/cache/Cache.js.map +1 -0
  107. package/lib/app/services/cache/InMemoryCache.d.ts +35 -0
  108. package/lib/app/services/cache/InMemoryCache.d.ts.map +1 -0
  109. package/lib/app/services/cache/InMemoryCache.js +76 -0
  110. package/lib/app/services/cache/InMemoryCache.js.map +1 -0
  111. package/lib/app/services/cache/RedisCache.d.ts +99 -0
  112. package/lib/app/services/cache/RedisCache.d.ts.map +1 -0
  113. package/lib/app/services/cache/RedisCache.js +150 -0
  114. package/lib/app/services/cache/RedisCache.js.map +1 -0
  115. package/lib/app/services/cache/cached.d.ts +30 -0
  116. package/lib/app/services/cache/cached.d.ts.map +1 -0
  117. package/lib/app/services/cache/cached.js +38 -0
  118. package/lib/app/services/cache/cached.js.map +1 -0
  119. package/lib/app/services/cache/index.d.ts +5 -0
  120. package/lib/app/services/cache/index.d.ts.map +1 -0
  121. package/lib/app/services/cache/index.js +4 -0
  122. package/lib/app/services/cache/index.js.map +1 -0
  123. package/lib/app/services/cron/defineCron.d.ts +57 -0
  124. package/lib/app/services/cron/defineCron.d.ts.map +1 -0
  125. package/lib/app/services/cron/defineCron.js +15 -0
  126. package/lib/app/services/cron/defineCron.js.map +1 -0
  127. package/lib/app/services/cron/index.d.ts +2 -0
  128. package/lib/app/services/cron/index.d.ts.map +1 -0
  129. package/lib/app/services/cron/index.js +2 -0
  130. package/lib/app/services/cron/index.js.map +1 -0
  131. package/lib/app/services/hooks/LifecycleHooks.d.ts +61 -0
  132. package/lib/app/services/hooks/LifecycleHooks.d.ts.map +1 -0
  133. package/lib/app/services/hooks/LifecycleHooks.js +85 -0
  134. package/lib/app/services/hooks/LifecycleHooks.js.map +1 -0
  135. package/lib/app/services/jobs/JobsManager.d.ts +67 -0
  136. package/lib/app/services/jobs/JobsManager.d.ts.map +1 -0
  137. package/lib/app/services/jobs/JobsManager.js +121 -0
  138. package/lib/app/services/jobs/JobsManager.js.map +1 -0
  139. package/lib/app/services/jobs/bullBoard.d.ts +72 -0
  140. package/lib/app/services/jobs/bullBoard.d.ts.map +1 -0
  141. package/lib/app/services/jobs/bullBoard.js +96 -0
  142. package/lib/app/services/jobs/bullBoard.js.map +1 -0
  143. package/lib/app/services/jobs/defineJob.d.ts +81 -0
  144. package/lib/app/services/jobs/defineJob.d.ts.map +1 -0
  145. package/lib/app/services/jobs/defineJob.js +49 -0
  146. package/lib/app/services/jobs/defineJob.js.map +1 -0
  147. package/lib/app/services/jobs/index.d.ts +4 -0
  148. package/lib/app/services/jobs/index.d.ts.map +1 -0
  149. package/lib/app/services/jobs/index.js +4 -0
  150. package/lib/app/services/jobs/index.js.map +1 -0
  151. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts +23 -0
  152. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.d.ts.map +1 -0
  153. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js +51 -0
  154. package/lib/app/services/rateLimit/InMemorySlidingWindowBackend.js.map +1 -0
  155. package/lib/app/services/rateLimit/RateLimitBackend.d.ts +41 -0
  156. package/lib/app/services/rateLimit/RateLimitBackend.d.ts.map +1 -0
  157. package/lib/app/services/rateLimit/RateLimitBackend.js +19 -0
  158. package/lib/app/services/rateLimit/RateLimitBackend.js.map +1 -0
  159. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts +16 -0
  160. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.d.ts.map +1 -0
  161. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js +80 -0
  162. package/lib/app/services/rateLimit/RedisSlidingWindowBackend.js.map +1 -0
  163. package/lib/app/services/rateLimit/index.d.ts +4 -0
  164. package/lib/app/services/rateLimit/index.d.ts.map +1 -0
  165. package/lib/app/services/rateLimit/index.js +3 -0
  166. package/lib/app/services/rateLimit/index.js.map +1 -0
  167. package/lib/app/services/storage/DiskStorageAdapter.d.ts +62 -0
  168. package/lib/app/services/storage/DiskStorageAdapter.d.ts.map +1 -0
  169. package/lib/app/services/storage/DiskStorageAdapter.js +295 -0
  170. package/lib/app/services/storage/DiskStorageAdapter.js.map +1 -0
  171. package/lib/app/services/storage/GCSStorageAdapter.d.ts +44 -0
  172. package/lib/app/services/storage/GCSStorageAdapter.d.ts.map +1 -0
  173. package/lib/app/services/storage/GCSStorageAdapter.js +133 -0
  174. package/lib/app/services/storage/GCSStorageAdapter.js.map +1 -0
  175. package/lib/app/services/storage/S3StorageAdapter.d.ts +57 -0
  176. package/lib/app/services/storage/S3StorageAdapter.d.ts.map +1 -0
  177. package/lib/app/services/storage/S3StorageAdapter.js +162 -0
  178. package/lib/app/services/storage/S3StorageAdapter.js.map +1 -0
  179. package/lib/app/services/storage/StorageService.d.ts +88 -0
  180. package/lib/app/services/storage/StorageService.d.ts.map +1 -0
  181. package/lib/app/services/storage/StorageService.js +18 -0
  182. package/lib/app/services/storage/StorageService.js.map +1 -0
  183. package/lib/app/services/storage/index.d.ts +5 -0
  184. package/lib/app/services/storage/index.d.ts.map +1 -0
  185. package/lib/app/services/storage/index.js +4 -0
  186. package/lib/app/services/storage/index.js.map +1 -0
  187. package/lib/app/utils/ContextValidators.d.ts +46 -0
  188. package/lib/app/utils/ContextValidators.d.ts.map +1 -0
  189. package/lib/app/utils/ContextValidators.js +81 -0
  190. package/lib/app/utils/ContextValidators.js.map +1 -0
  191. package/lib/app/utils/defineEnv.d.ts +80 -0
  192. package/lib/app/utils/defineEnv.d.ts.map +1 -0
  193. package/lib/app/utils/defineEnv.js +95 -0
  194. package/lib/app/utils/defineEnv.js.map +1 -0
  195. package/lib/client.d.ts +139 -0
  196. package/lib/client.d.ts.map +1 -0
  197. package/lib/client.js +98 -0
  198. package/lib/client.js.map +1 -0
  199. package/lib/contract/application.d.ts +3 -0
  200. package/lib/contract/application.d.ts.map +1 -0
  201. package/lib/contract/application.js +2 -0
  202. package/lib/contract/application.js.map +1 -0
  203. package/lib/contract/client.d.ts +3 -0
  204. package/lib/contract/client.d.ts.map +1 -0
  205. package/lib/contract/client.js +3 -0
  206. package/lib/contract/client.js.map +1 -0
  207. package/lib/contract/index.d.ts +3 -0
  208. package/lib/contract/index.d.ts.map +1 -0
  209. package/lib/contract/index.js +3 -0
  210. package/lib/contract/index.js.map +1 -0
  211. package/lib/contract/manifest.d.ts +3 -0
  212. package/lib/contract/manifest.d.ts.map +1 -0
  213. package/lib/contract/manifest.js +2 -0
  214. package/lib/contract/manifest.js.map +1 -0
  215. package/lib/contract/openapi.d.ts +3 -0
  216. package/lib/contract/openapi.d.ts.map +1 -0
  217. package/lib/contract/openapi.js +3 -0
  218. package/lib/contract/openapi.js.map +1 -0
  219. package/lib/contract/project.d.ts +3 -0
  220. package/lib/contract/project.d.ts.map +1 -0
  221. package/lib/contract/project.js +3 -0
  222. package/lib/contract/project.js.map +1 -0
  223. package/lib/contract/schema.d.ts +3 -0
  224. package/lib/contract/schema.d.ts.map +1 -0
  225. package/lib/contract/schema.js +3 -0
  226. package/lib/contract/schema.js.map +1 -0
  227. package/lib/drizzle/index.d.ts +3 -0
  228. package/lib/drizzle/index.d.ts.map +1 -0
  229. package/lib/drizzle/index.js +3 -0
  230. package/lib/drizzle/index.js.map +1 -0
  231. package/lib/hono/auth.d.ts +6 -0
  232. package/lib/hono/auth.d.ts.map +1 -0
  233. package/lib/hono/auth.js +54 -0
  234. package/lib/hono/auth.js.map +1 -0
  235. package/lib/hono/index.d.ts +4 -0
  236. package/lib/hono/index.d.ts.map +1 -0
  237. package/lib/hono/index.js +4 -0
  238. package/lib/hono/index.js.map +1 -0
  239. package/lib/http/app/createApp.d.ts +132 -0
  240. package/lib/http/app/createApp.d.ts.map +1 -0
  241. package/lib/http/app/createApp.js +215 -0
  242. package/lib/http/app/createApp.js.map +1 -0
  243. package/lib/http/app/devRoutes.d.ts +31 -0
  244. package/lib/http/app/devRoutes.d.ts.map +1 -0
  245. package/lib/http/app/devRoutes.js +145 -0
  246. package/lib/http/app/devRoutes.js.map +1 -0
  247. package/lib/http/app/errors.d.ts +45 -0
  248. package/lib/http/app/errors.d.ts.map +1 -0
  249. package/lib/http/app/errors.js +93 -0
  250. package/lib/http/app/errors.js.map +1 -0
  251. package/lib/http/app/health.d.ts +66 -0
  252. package/lib/http/app/health.d.ts.map +1 -0
  253. package/lib/http/app/health.js +104 -0
  254. package/lib/http/app/health.js.map +1 -0
  255. package/lib/http/errors/AppError.d.ts +10 -0
  256. package/lib/http/errors/AppError.d.ts.map +1 -0
  257. package/lib/http/errors/AppError.js +19 -0
  258. package/lib/http/errors/AppError.js.map +1 -0
  259. package/lib/http/errors/AuthenticationError.d.ts +8 -0
  260. package/lib/http/errors/AuthenticationError.d.ts.map +1 -0
  261. package/lib/http/errors/AuthenticationError.js +10 -0
  262. package/lib/http/errors/AuthenticationError.js.map +1 -0
  263. package/lib/http/errors/AuthorizationError.d.ts +8 -0
  264. package/lib/http/errors/AuthorizationError.d.ts.map +1 -0
  265. package/lib/http/errors/AuthorizationError.js +10 -0
  266. package/lib/http/errors/AuthorizationError.js.map +1 -0
  267. package/lib/http/errors/BadRequestError.d.ts +8 -0
  268. package/lib/http/errors/BadRequestError.d.ts.map +1 -0
  269. package/lib/http/errors/BadRequestError.js +10 -0
  270. package/lib/http/errors/BadRequestError.js.map +1 -0
  271. package/lib/http/errors/ConflictError.d.ts +8 -0
  272. package/lib/http/errors/ConflictError.d.ts.map +1 -0
  273. package/lib/http/errors/ConflictError.js +10 -0
  274. package/lib/http/errors/ConflictError.js.map +1 -0
  275. package/lib/http/errors/InternalServerError.d.ts +8 -0
  276. package/lib/http/errors/InternalServerError.d.ts.map +1 -0
  277. package/lib/http/errors/InternalServerError.js +10 -0
  278. package/lib/http/errors/InternalServerError.js.map +1 -0
  279. package/lib/http/errors/NotFoundError.d.ts +8 -0
  280. package/lib/http/errors/NotFoundError.d.ts.map +1 -0
  281. package/lib/http/errors/NotFoundError.js +10 -0
  282. package/lib/http/errors/NotFoundError.js.map +1 -0
  283. package/lib/http/errors/RateLimitError.d.ts +13 -0
  284. package/lib/http/errors/RateLimitError.d.ts.map +1 -0
  285. package/lib/http/errors/RateLimitError.js +16 -0
  286. package/lib/http/errors/RateLimitError.js.map +1 -0
  287. package/lib/http/errors/ServiceUnavailableError.d.ts +8 -0
  288. package/lib/http/errors/ServiceUnavailableError.d.ts.map +1 -0
  289. package/lib/http/errors/ServiceUnavailableError.js +10 -0
  290. package/lib/http/errors/ServiceUnavailableError.js.map +1 -0
  291. package/lib/http/errors/ValidationError.d.ts +9 -0
  292. package/lib/http/errors/ValidationError.d.ts.map +1 -0
  293. package/lib/http/errors/ValidationError.js +12 -0
  294. package/lib/http/errors/ValidationError.js.map +1 -0
  295. package/lib/http/errors/index.d.ts +11 -0
  296. package/lib/http/errors/index.d.ts.map +1 -0
  297. package/lib/http/errors/index.js +12 -0
  298. package/lib/http/errors/index.js.map +1 -0
  299. package/lib/http/middleware/apiKey.d.ts +9 -0
  300. package/lib/http/middleware/apiKey.d.ts.map +1 -0
  301. package/lib/http/middleware/apiKey.js +71 -0
  302. package/lib/http/middleware/apiKey.js.map +1 -0
  303. package/lib/http/middleware/csrf.d.ts +63 -0
  304. package/lib/http/middleware/csrf.d.ts.map +1 -0
  305. package/lib/http/middleware/csrf.js +169 -0
  306. package/lib/http/middleware/csrf.js.map +1 -0
  307. package/lib/http/middleware/httpLogger.d.ts +39 -0
  308. package/lib/http/middleware/httpLogger.d.ts.map +1 -0
  309. package/lib/http/middleware/httpLogger.js +118 -0
  310. package/lib/http/middleware/httpLogger.js.map +1 -0
  311. package/lib/http/middleware/idempotency.d.ts +48 -0
  312. package/lib/http/middleware/idempotency.d.ts.map +1 -0
  313. package/lib/http/middleware/idempotency.js +180 -0
  314. package/lib/http/middleware/idempotency.js.map +1 -0
  315. package/lib/http/middleware/rateLimit.d.ts +105 -0
  316. package/lib/http/middleware/rateLimit.d.ts.map +1 -0
  317. package/lib/http/middleware/rateLimit.js +84 -0
  318. package/lib/http/middleware/rateLimit.js.map +1 -0
  319. package/lib/http/middleware/requireAuth.d.ts +58 -0
  320. package/lib/http/middleware/requireAuth.d.ts.map +1 -0
  321. package/lib/http/middleware/requireAuth.js +63 -0
  322. package/lib/http/middleware/requireAuth.js.map +1 -0
  323. package/lib/http/middleware/requirePermission.d.ts +23 -0
  324. package/lib/http/middleware/requirePermission.d.ts.map +1 -0
  325. package/lib/http/middleware/requirePermission.js +50 -0
  326. package/lib/http/middleware/requirePermission.js.map +1 -0
  327. package/lib/http/middleware/resolveTenant.d.ts +41 -0
  328. package/lib/http/middleware/resolveTenant.d.ts.map +1 -0
  329. package/lib/http/middleware/resolveTenant.js +17 -0
  330. package/lib/http/middleware/resolveTenant.js.map +1 -0
  331. package/lib/http/streaming/sse.d.ts +31 -0
  332. package/lib/http/streaming/sse.d.ts.map +1 -0
  333. package/lib/http/streaming/sse.js +11 -0
  334. package/lib/http/streaming/sse.js.map +1 -0
  335. package/lib/http/streaming/streamLLM.d.ts +94 -0
  336. package/lib/http/streaming/streamLLM.d.ts.map +1 -0
  337. package/lib/http/streaming/streamLLM.js +94 -0
  338. package/lib/http/streaming/streamLLM.js.map +1 -0
  339. package/lib/http/utils/authCookies.d.ts +74 -0
  340. package/lib/http/utils/authCookies.d.ts.map +1 -0
  341. package/lib/http/utils/authCookies.js +102 -0
  342. package/lib/http/utils/authCookies.js.map +1 -0
  343. package/lib/http/utils/clientIp.d.ts +85 -0
  344. package/lib/http/utils/clientIp.d.ts.map +1 -0
  345. package/lib/http/utils/clientIp.js +249 -0
  346. package/lib/http/utils/clientIp.js.map +1 -0
  347. package/lib/http/utils/index.d.ts +4 -0
  348. package/lib/http/utils/index.d.ts.map +1 -0
  349. package/lib/http/utils/index.js +5 -0
  350. package/lib/http/utils/index.js.map +1 -0
  351. package/lib/http/utils/metaTags.d.ts +49 -0
  352. package/lib/http/utils/metaTags.d.ts.map +1 -0
  353. package/lib/http/utils/metaTags.js +32 -0
  354. package/lib/http/utils/metaTags.js.map +1 -0
  355. package/lib/http/utils/publicSuffix.d.ts +34 -0
  356. package/lib/http/utils/publicSuffix.d.ts.map +1 -0
  357. package/lib/http/utils/publicSuffix.js +276 -0
  358. package/lib/http/utils/publicSuffix.js.map +1 -0
  359. package/lib/http/utils/uploads.d.ts +92 -0
  360. package/lib/http/utils/uploads.d.ts.map +1 -0
  361. package/lib/http/utils/uploads.js +126 -0
  362. package/lib/http/utils/uploads.js.map +1 -0
  363. package/lib/http/utils/validate.d.ts +41 -0
  364. package/lib/http/utils/validate.d.ts.map +1 -0
  365. package/lib/http/utils/validate.js +55 -0
  366. package/lib/http/utils/validate.js.map +1 -0
  367. package/lib/http/utils/webhooks.d.ts +63 -0
  368. package/lib/http/utils/webhooks.d.ts.map +1 -0
  369. package/lib/http/utils/webhooks.js +133 -0
  370. package/lib/http/utils/webhooks.js.map +1 -0
  371. package/lib/http/ws/auth.d.ts +46 -0
  372. package/lib/http/ws/auth.d.ts.map +1 -0
  373. package/lib/http/ws/auth.js +123 -0
  374. package/lib/http/ws/auth.js.map +1 -0
  375. package/lib/index.d.ts +80 -0
  376. package/lib/index.d.ts.map +1 -0
  377. package/lib/index.js +61 -0
  378. package/lib/index.js.map +1 -0
  379. package/lib/kernel/index.d.ts +3 -0
  380. package/lib/kernel/index.d.ts.map +1 -0
  381. package/lib/kernel/index.js +3 -0
  382. package/lib/kernel/index.js.map +1 -0
  383. package/lib/libraries/.gitkeep +0 -0
  384. package/lib/libraries/ai/CHANGELOG.md +17 -0
  385. package/lib/libraries/ai/README.md +164 -0
  386. package/lib/libraries/ai/adapters/AnthropicAdapter.ts +382 -0
  387. package/lib/libraries/ai/adapters/LLMProvider.ts +76 -0
  388. package/lib/libraries/ai/adapters/OpenAIAdapter.ts +466 -0
  389. package/lib/libraries/ai/experimental/index.ts +20 -0
  390. package/lib/libraries/ai/index.ts +128 -0
  391. package/lib/libraries/ai/library.json +19 -0
  392. package/lib/libraries/ai/loop/agentLoop.ts +377 -0
  393. package/lib/libraries/ai/prompts/definePrompt.ts +0 -0
  394. package/lib/libraries/ai/rag/retrieveAndAnswer.ts +177 -0
  395. package/lib/libraries/ai/streaming/streamLLM.ts +94 -0
  396. package/lib/libraries/ai/structured/completeStructured.ts +143 -0
  397. package/lib/libraries/ai/tokens/Tokenizer.ts +216 -0
  398. package/lib/libraries/ai/tools/defineTool.ts +208 -0
  399. package/lib/libraries/ai/types.ts +260 -0
  400. package/lib/libraries/chunking/ChunkingService.ts +103 -0
  401. package/lib/libraries/chunking/README.md +104 -0
  402. package/lib/libraries/chunking/docs/api-reference.md +549 -0
  403. package/lib/libraries/chunking/docs/best-practices.md +321 -0
  404. package/lib/libraries/chunking/docs/code-organization.md +538 -0
  405. package/lib/libraries/chunking/docs/configuration.md +418 -0
  406. package/lib/libraries/chunking/docs/index.md +236 -0
  407. package/lib/libraries/chunking/docs/quick-start.md +298 -0
  408. package/lib/libraries/chunking/docs/strategies.md +407 -0
  409. package/lib/libraries/chunking/docs/summary.md +258 -0
  410. package/lib/libraries/chunking/docs/troubleshooting.md +527 -0
  411. package/lib/libraries/chunking/index.ts +17 -0
  412. package/lib/libraries/chunking/library.json +16 -0
  413. package/lib/libraries/chunking/strategies/ChunkingStrategy.ts +13 -0
  414. package/lib/libraries/chunking/strategies/FixedLengthChunkingStrategy.ts +88 -0
  415. package/lib/libraries/chunking/strategies/SemanticChunkingStrategy.ts +389 -0
  416. package/lib/libraries/chunking/strategies/SlidingWindowChunkingStrategy.ts +258 -0
  417. package/lib/libraries/chunking/types/index.ts +63 -0
  418. package/lib/libraries/email/EmailService.ts +591 -0
  419. package/lib/libraries/email/README.md +777 -0
  420. package/lib/libraries/email/TemplateRegistry.ts +148 -0
  421. package/lib/libraries/email/TemplateRenderer.ts +273 -0
  422. package/lib/libraries/email/index.ts +4 -0
  423. package/lib/libraries/email/initializeEmailService.ts +60 -0
  424. package/lib/libraries/email/library.json +12 -0
  425. package/lib/libraries/email/types/EmailAddress.ts +4 -0
  426. package/lib/libraries/email/types/EmailAttachment.ts +11 -0
  427. package/lib/libraries/email/types/EmailTag.ts +9 -0
  428. package/lib/libraries/email/types/EmailTemplate.ts +124 -0
  429. package/lib/libraries/email/types/SendBatchEmailsOptions.ts +9 -0
  430. package/lib/libraries/email/types/SendBatchEmailsResult.ts +9 -0
  431. package/lib/libraries/email/types/SendEmailOptions.ts +33 -0
  432. package/lib/libraries/email/types/SendEmailResult.ts +9 -0
  433. package/lib/libraries/email/types/index.ts +8 -0
  434. package/lib/libraries/weaviate/QueryBuilder.ts +292 -0
  435. package/lib/libraries/weaviate/README.md +284 -0
  436. package/lib/libraries/weaviate/Weaviate.ts +1419 -0
  437. package/lib/libraries/weaviate/WeaviateConfig.ts +268 -0
  438. package/lib/libraries/weaviate/docs/.gitkeep +1 -0
  439. package/lib/libraries/weaviate/docs/API_REFERENCE.md +1067 -0
  440. package/lib/libraries/weaviate/docs/CONFIGURATION.md +320 -0
  441. package/lib/libraries/weaviate/docs/ERROR_HANDLING.md +271 -0
  442. package/lib/libraries/weaviate/docs/MULTI_TENANCY.md +348 -0
  443. package/lib/libraries/weaviate/docs/PERFORMANCE.md +602 -0
  444. package/lib/libraries/weaviate/docs/PLUGIN_DEVELOPMENT.md +547 -0
  445. package/lib/libraries/weaviate/docs/QUICK_START.md +443 -0
  446. package/lib/libraries/weaviate/docs/README.md +269 -0
  447. package/lib/libraries/weaviate/docs/SCHEMA_GUIDE.md +630 -0
  448. package/lib/libraries/weaviate/docs/WEAVIATE_README.md +520 -0
  449. package/lib/libraries/weaviate/errors/WeaviateError.ts +92 -0
  450. package/lib/libraries/weaviate/errors/index.ts +1 -0
  451. package/lib/libraries/weaviate/index.ts +35 -0
  452. package/lib/libraries/weaviate/library.json +26 -0
  453. package/lib/libraries/weaviate/plugins/index.ts +2 -0
  454. package/lib/libraries/weaviate/schemas/SchemaRegistry.ts +284 -0
  455. package/lib/libraries/weaviate/schemas/index.ts +2 -0
  456. package/lib/libraries/weaviate/types/BM25SearchOptions.ts +9 -0
  457. package/lib/libraries/weaviate/types/ExtendedWeaviateClient.ts +7 -0
  458. package/lib/libraries/weaviate/types/HybridSearchOptions.ts +11 -0
  459. package/lib/libraries/weaviate/types/MultiTenancy.ts +81 -0
  460. package/lib/libraries/weaviate/types/Plugin.ts +17 -0
  461. package/lib/libraries/weaviate/types/SchemaConfig.ts +25 -0
  462. package/lib/libraries/weaviate/types/SearchMethod.ts +8 -0
  463. package/lib/libraries/weaviate/types/SearchOptions.ts +16 -0
  464. package/lib/libraries/weaviate/types/SearchRequest.ts +19 -0
  465. package/lib/libraries/weaviate/types/SearchResult.ts +16 -0
  466. package/lib/libraries/weaviate/types/SearchableField.ts +87 -0
  467. package/lib/libraries/weaviate/types/VectorIndexConfig.ts +19 -0
  468. package/lib/libraries/weaviate/types/VectorSearchOptions.ts +18 -0
  469. package/lib/libraries/weaviate/types/VectorizerConfig.ts +8 -0
  470. package/lib/libraries/weaviate/types/index.ts +29 -0
  471. package/lib/libraries/weaviate/utils/TenantContextManager.ts +94 -0
  472. package/lib/modules/accounts/index.ts +47 -0
  473. package/lib/modules/accounts/module.json +15 -0
  474. package/lib/modules/accounts/permissions.ts +33 -0
  475. package/lib/modules/accounts/routes.ts +200 -0
  476. package/lib/modules/accounts/schema.ts +219 -0
  477. package/lib/modules/accounts/services/AccountService.ts +44 -0
  478. package/lib/modules/accounts/validation/schemas.ts +70 -0
  479. package/lib/modules/oauth/adapters/GmailOAuthAdapter.ts +35 -0
  480. package/lib/modules/oauth/adapters/GoogleOAuthAdapter.ts +278 -0
  481. package/lib/modules/oauth/adapters/MicrosoftOAuthAdapter.ts +269 -0
  482. package/lib/modules/oauth/adapters/MockOAuthAdapter.ts +138 -0
  483. package/lib/modules/oauth/adapters/OAuthAdapter.ts +211 -0
  484. package/lib/modules/oauth/adapters/OAuthAdapterRegistry.ts +77 -0
  485. package/lib/modules/oauth/adapters/OutlookOAuthAdapter.ts +38 -0
  486. package/lib/modules/oauth/index.ts +79 -0
  487. package/lib/modules/oauth/module.json +23 -0
  488. package/lib/modules/oauth/permissions.ts +39 -0
  489. package/lib/modules/oauth/routes.ts +497 -0
  490. package/lib/modules/oauth/schema.ts +127 -0
  491. package/lib/modules/oauth/services/OAuthConnectionService.ts +147 -0
  492. package/lib/modules/oauth/state.ts +234 -0
  493. package/lib/modules/oauth/stateJtiCache.ts +85 -0
  494. package/lib/modules/oauth/verifyIdToken.ts +178 -0
  495. package/lib/modules/outbox/EventEmitter.ts +106 -0
  496. package/lib/modules/outbox/OutboxDrainer.ts +163 -0
  497. package/lib/modules/outbox/handlers/EventHandler.ts +115 -0
  498. package/lib/modules/outbox/index.ts +43 -0
  499. package/lib/modules/outbox/module.json +15 -0
  500. package/lib/modules/outbox/permissions.ts +36 -0
  501. package/lib/modules/outbox/routes.ts +219 -0
  502. package/lib/modules/outbox/schema.ts +207 -0
  503. package/lib/modules/outbox/services/OutboxEventService.ts +223 -0
  504. package/lib/observability/logger.d.ts +30 -0
  505. package/lib/observability/logger.d.ts.map +1 -0
  506. package/lib/observability/logger.js +110 -0
  507. package/lib/observability/logger.js.map +1 -0
  508. package/lib/observability/metrics.d.ts +3 -0
  509. package/lib/observability/metrics.d.ts.map +1 -0
  510. package/lib/observability/metrics.js +3 -0
  511. package/lib/observability/metrics.js.map +1 -0
  512. package/lib/observability/otel.d.ts +3 -0
  513. package/lib/observability/otel.d.ts.map +1 -0
  514. package/lib/observability/otel.js +3 -0
  515. package/lib/observability/otel.js.map +1 -0
  516. package/lib/observability/safeErrorFields.d.ts +14 -0
  517. package/lib/observability/safeErrorFields.d.ts.map +1 -0
  518. package/lib/observability/safeErrorFields.js +14 -0
  519. package/lib/observability/safeErrorFields.js.map +1 -0
  520. package/lib/observability/tracing.d.ts +3 -0
  521. package/lib/observability/tracing.d.ts.map +1 -0
  522. package/lib/observability/tracing.js +3 -0
  523. package/lib/observability/tracing.js.map +1 -0
  524. package/lib/package.json +4 -0
  525. package/lib/testing.d.ts +3 -0
  526. package/lib/testing.d.ts.map +1 -0
  527. package/lib/testing.js +3 -0
  528. package/lib/testing.js.map +1 -0
  529. package/package.json +193 -3
  530. package/templates/default/.claude/agents/qa-brief.md +106 -0
  531. package/templates/default/.claude/commands/sherpa-brief.md +23 -0
  532. package/templates/default/.cursor/rules/api.mdc +80 -0
  533. package/templates/default/.cursor/rules/commits.mdc +88 -0
  534. package/templates/default/.cursor/rules/security.mdc +92 -0
  535. package/templates/default/.cursor/rules/testing.mdc +123 -0
  536. package/templates/default/.cursor/rules/typescript.mdc +86 -0
  537. package/templates/default/.env.example +79 -0
  538. package/templates/default/.github/workflows/sherpa-brief.yml +180 -0
  539. package/templates/default/AGENTS.md +166 -0
  540. package/templates/default/CLAUDE.md +17 -0
  541. package/templates/default/README.md +97 -0
  542. package/templates/default/_gitignore +27 -0
  543. package/templates/default/docker-compose.yml +83 -0
  544. package/templates/default/drizzle.config.ts +34 -0
  545. package/templates/default/eslint.config.mjs +106 -0
  546. package/templates/default/package.json +57 -0
  547. package/templates/default/ship-api.config.ts +21 -0
  548. package/templates/default/src/client.ts +34 -0
  549. package/templates/default/src/config/modules.ts +23 -0
  550. package/templates/default/src/db/schema.ts +26 -0
  551. package/templates/default/src/environment.ts +81 -0
  552. package/templates/default/src/index.test.ts +53 -0
  553. package/templates/default/src/index.ts +11 -0
  554. package/templates/default/src/instrumentation.ts +13 -0
  555. package/templates/default/src/server.ts +90 -0
  556. package/templates/default/tsconfig.json +24 -0
@@ -0,0 +1,134 @@
1
+ import { and, eq, isNull, or, sql } from "drizzle-orm";
2
+ import { withTransaction } from "../../db/transaction.js";
3
+ export class DrizzleRefreshTokenStore {
4
+ db;
5
+ table;
6
+ constructor(opts) {
7
+ this.db = opts.db;
8
+ this.table = opts.table;
9
+ }
10
+ async issue(input) {
11
+ const [row] = await this.db
12
+ .insert(this.table)
13
+ .values({
14
+ accountId: input.accountId,
15
+ tokenHash: input.tokenHash,
16
+ expiresAt: input.expiresAt,
17
+ userAgent: input.userAgent ?? null,
18
+ issuedFromIp: input.issuedFromIp ?? null,
19
+ })
20
+ .returning();
21
+ return rowToRecord(row);
22
+ }
23
+ async findByHash(tokenHash) {
24
+ const rows = await this.db
25
+ .select()
26
+ .from(this.table)
27
+ .where(eq(this.table.tokenHash, tokenHash))
28
+ .limit(1);
29
+ if (!rows.length)
30
+ return null;
31
+ return rowToRecord(rows[0]);
32
+ }
33
+ async rotate(oldId, newToken) {
34
+ return withTransaction(this.db, async (tx) => {
35
+ const [inserted] = await tx
36
+ .insert(this.table)
37
+ .values({
38
+ accountId: newToken.accountId,
39
+ tokenHash: newToken.tokenHash,
40
+ expiresAt: newToken.expiresAt,
41
+ userAgent: newToken.userAgent ?? null,
42
+ issuedFromIp: newToken.issuedFromIp ?? null,
43
+ })
44
+ .returning();
45
+ const row = inserted;
46
+ await tx
47
+ .update(this.table)
48
+ .set({ replacedById: row.id })
49
+ .where(eq(this.table.id, oldId));
50
+ return rowToRecord(row);
51
+ });
52
+ }
53
+ async revoke(id) {
54
+ await this.db
55
+ .update(this.table)
56
+ .set({ revokedAt: new Date() })
57
+ .where(and(eq(this.table.id, id), isNull(this.table.revokedAt)));
58
+ }
59
+ async revokeChain(id) {
60
+ // Single-shot: a recursive CTE collects every ancestor + descendant
61
+ // reachable from `id`, then a single UPDATE flips them all to revoked.
62
+ // Stable across Postgres ≥12.
63
+ const tableName = sql.identifier(getTableName(this.table));
64
+ const result = await this.db.execute(sql `
65
+ WITH RECURSIVE forward AS (
66
+ SELECT id, replaced_by_id FROM ${tableName} WHERE id = ${id}
67
+ UNION ALL
68
+ SELECT t.id, t.replaced_by_id
69
+ FROM ${tableName} t
70
+ JOIN forward f ON t.id = f.replaced_by_id
71
+ ),
72
+ backward AS (
73
+ SELECT id, replaced_by_id FROM ${tableName} WHERE id = ${id}
74
+ UNION ALL
75
+ SELECT t.id, t.replaced_by_id
76
+ FROM ${tableName} t
77
+ JOIN backward b ON t.replaced_by_id = b.id
78
+ ),
79
+ chain AS (
80
+ SELECT id FROM forward UNION SELECT id FROM backward
81
+ )
82
+ UPDATE ${tableName} SET revoked_at = NOW()
83
+ WHERE id IN (SELECT id FROM chain) AND revoked_at IS NULL
84
+ RETURNING id
85
+ `);
86
+ return readRowCount(result);
87
+ }
88
+ async revokeAllForAccount(accountId) {
89
+ const result = await this.db
90
+ .update(this.table)
91
+ .set({ revokedAt: new Date() })
92
+ .where(and(eq(this.table.accountId, accountId), or(isNull(this.table.revokedAt),
93
+ // No-op clause keeps the predicate non-empty if `or` collapses.
94
+ sql `false`)))
95
+ .returning({ id: this.table.id });
96
+ return result.length;
97
+ }
98
+ }
99
+ function rowToRecord(row) {
100
+ return {
101
+ id: row.id,
102
+ accountId: row.accountId,
103
+ tokenHash: row.tokenHash,
104
+ expiresAt: row.expiresAt,
105
+ revokedAt: row.revokedAt,
106
+ replacedById: row.replacedById,
107
+ userAgent: row.userAgent,
108
+ issuedFromIp: row.issuedFromIp,
109
+ };
110
+ }
111
+ function getTableName(table) {
112
+ // Drizzle exposes table metadata via the `Symbol.for('drizzle:Name')` slot.
113
+ // Falls back to the inline name for forward-compat with future Drizzle
114
+ // versions that may shift the symbol.
115
+ const sym = Object.getOwnPropertySymbols(table).find((s) => s.description?.includes("drizzle") || s.description?.includes("Name"));
116
+ if (sym) {
117
+ const value = table[sym];
118
+ if (typeof value === "string")
119
+ return value;
120
+ }
121
+ // Last resort — every PgTable carries a stringifiable identifier.
122
+ return String(table._?.name ?? "refresh_tokens");
123
+ }
124
+ function readRowCount(result) {
125
+ // node-postgres returns `{ rows, rowCount, ... }`; Drizzle's `execute`
126
+ // forwards that shape. Guard for shape drift across drivers.
127
+ const r = result;
128
+ if (typeof r.rowCount === "number")
129
+ return r.rowCount;
130
+ if (Array.isArray(r.rows))
131
+ return r.rows.length;
132
+ return 0;
133
+ }
134
+ //# sourceMappingURL=DrizzleRefreshTokenStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DrizzleRefreshTokenStore.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/DrizzleRefreshTokenStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import { type CryptoKey, type JWTPayload } from "jose";
2
+ /**
3
+ * `JwtSigner` — ES256 JWT signing/verification with `kid`-based key rotation.
4
+ *
5
+ * Wraps `jose@^6` for the framework's stateless cookie-auth flow. Owned by
6
+ * `AuthFlow` (which combines this with `RefreshTokenStore` to handle issue /
7
+ * rotate / revoke). Lives at this level because:
8
+ *
9
+ * 1. **Key rotation is a load-bearing security primitive.** A signer that
10
+ * can verify with multiple public keys lets operators add a new key,
11
+ * cut signing over to it, wait for max-token-lifetime, then retire the
12
+ * old key — without forcing every active session to re-authenticate.
13
+ * The rotation procedure is documented in `.cursor/rules/security.mdc`.
14
+ *
15
+ * 2. **Edge-runtime parity.** `CryptoKey` (Web Crypto) is portable between
16
+ * Node, Cloudflare Workers, and Bun, so v4.x edge adapters reuse this
17
+ * class without a runtime fork.
18
+ *
19
+ * 3. **Pluggable adapter boundary.** `AuthFlow` owns persistence (refresh
20
+ * token store) and HTTP (cookies); `JwtSigner` owns *only* the JWS step.
21
+ * Easier to test, easier to swap (e.g., HSM-backed signer in v4.x).
22
+ *
23
+ * The single signing key (`signingKey.kid`) is the active key; tokens carry
24
+ * the `kid` in their protected header. Verification looks the `kid` up in the
25
+ * `verificationKeys` map, which always includes the active signing key plus
26
+ * any retiring keys still inside their max-lifetime grace window.
27
+ */
28
+ export interface JwtSigningKey {
29
+ /** Key identifier — propagated into the token's `kid` header. */
30
+ kid: string;
31
+ /** Web Crypto private key for ES256. Use jose's `importPKCS8(pem, 'ES256')`. */
32
+ privateKey: CryptoKey;
33
+ }
34
+ export interface JwtVerificationKey {
35
+ kid: string;
36
+ /** Web Crypto public key for ES256. Use jose's `importSPKI(pem, 'ES256')`. */
37
+ publicKey: CryptoKey;
38
+ }
39
+ export interface JwtSignerOptions {
40
+ /** Active signing key. Tokens are issued with `protectedHeader.kid = signingKey.kid`. */
41
+ signingKey: JwtSigningKey;
42
+ /**
43
+ * All public keys currently accepted at verification time. MUST include
44
+ * `signingKey`'s public counterpart and any retiring keys within their
45
+ * grace window. Empty arrays are rejected at construction.
46
+ */
47
+ verificationKeys: JwtVerificationKey[];
48
+ /** Default `iss` claim on signed tokens; verified at decode time. */
49
+ issuer?: string;
50
+ /** Default `aud` claim on signed tokens; verified at decode time. */
51
+ audience?: string;
52
+ /**
53
+ * Clock-skew tolerance for `exp`/`nbf`/`iat` validation in seconds.
54
+ *
55
+ * **Default 30** — the industry-standard tolerance per NIST SP
56
+ * 800-63B §5.1.1.2. Tight enough to defend against meaningful
57
+ * replay (the access-token TTL is the dominant window) and broad
58
+ * enough to survive the ~1–5 s NTP drift typical between hosts
59
+ * with healthy clock-sync. A 0 default produced flaky 401s in
60
+ * mixed environments and pushed adopters toward minutes-long
61
+ * tolerances that weakened the contract further than necessary.
62
+ *
63
+ * Explicit `clockToleranceSec: 0` reproduces the prior strict
64
+ * behavior for callers who genuinely want zero slack.
65
+ */
66
+ clockToleranceSec?: number;
67
+ }
68
+ export interface SignTokenOptions {
69
+ /** Subject (`sub`) — typically the Account ID. */
70
+ subject: string;
71
+ /** TTL in seconds. Required to force callers to make an explicit decision. */
72
+ ttlSec: number;
73
+ /** Optional explicit `jti`. Auto-generated as a UUIDv4 when omitted. */
74
+ jti?: string;
75
+ /** Optional override of the construction-time `iss`. */
76
+ issuer?: string;
77
+ /** Optional override of the construction-time `aud`. */
78
+ audience?: string;
79
+ /** Custom claims merged into the JWT payload. Avoid colliding with reserved names. */
80
+ claims?: Record<string, unknown>;
81
+ }
82
+ export interface SignedToken {
83
+ /** Compact JWS string (`xxxx.yyyy.zzzz`). */
84
+ token: string;
85
+ /** UUID issued for this token; persisted by `AuthFlow` for refresh-token revocation. */
86
+ jti: string;
87
+ /** Epoch seconds at issue time. */
88
+ issuedAt: number;
89
+ /** Epoch seconds at expiry. */
90
+ expiresAt: number;
91
+ /** Key id used to sign — useful for log correlation during rotation. */
92
+ kid: string;
93
+ }
94
+ export interface VerifiedToken<TClaims extends JWTPayload = JWTPayload> {
95
+ payload: TClaims;
96
+ kid: string;
97
+ }
98
+ export declare class JwtSigner {
99
+ private readonly signingKey;
100
+ private readonly verificationKeysByKid;
101
+ private readonly issuer?;
102
+ private readonly audience?;
103
+ private readonly clockToleranceSec;
104
+ constructor(opts: JwtSignerOptions);
105
+ /**
106
+ * Sign a token. The caller is responsible for choosing `ttlSec` (e.g., 15m
107
+ * for access tokens, 30d for refresh tokens). Returns the compact JWS plus
108
+ * metadata `AuthFlow` needs to persist a `refresh_tokens` row.
109
+ */
110
+ sign(opts: SignTokenOptions): Promise<SignedToken>;
111
+ /**
112
+ * Verify a token. Throws `AuthenticationError` on any failure — caller
113
+ * surfaces this through the framework's standard error path. Signature,
114
+ * expiry, and (when configured) issuer/audience are all enforced.
115
+ */
116
+ verify<TClaims extends JWTPayload = JWTPayload>(token: string): Promise<VerifiedToken<TClaims>>;
117
+ /** Expose the active signing kid for log/metric correlation. */
118
+ getSigningKid(): string;
119
+ /** Expose the kids currently accepted at verification — useful for `/dev/routes`-style introspection. */
120
+ getVerificationKids(): string[];
121
+ private resolveKey;
122
+ }
123
+ //# sourceMappingURL=JwtSigner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtSigner.d.ts","sourceRoot":"","sources":["../../../../src/app/auth/jwt/JwtSigner.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAA4C,MAAM,MAAM,CAAC;AAGjG;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,GAAG,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,UAAU,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,8EAA8E;IAC9E,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,yFAAyF;IACzF,UAAU,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,WAAW;IAC1B,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,GAAG,EAAE,MAAM,CAAC;IACZ,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,aAAa,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU;IACpE,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAID,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAyB;IAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;gBAE/B,IAAI,EAAE,gBAAgB;IAsBlC;;;;OAIG;IACG,IAAI,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;IAsBxD;;;;OAIG;IACG,MAAM,CAAC,OAAO,SAAS,UAAU,GAAG,UAAU,EAClD,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAelC,gEAAgE;IAChE,aAAa,IAAI,MAAM;IAIvB,yGAAyG;IACzG,mBAAmB,IAAI,MAAM,EAAE;IAI/B,OAAO,CAAC,UAAU;CAYnB"}
@@ -0,0 +1,118 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { errors as joseErrors, jwtVerify, SignJWT } from "jose";
3
+ import { AuthenticationError } from "../../../http/errors/AuthenticationError.js";
4
+ const ALG = "ES256";
5
+ export class JwtSigner {
6
+ signingKey;
7
+ verificationKeysByKid;
8
+ issuer;
9
+ audience;
10
+ clockToleranceSec;
11
+ constructor(opts) {
12
+ if (!opts.verificationKeys.length) {
13
+ throw new Error("JwtSigner: verificationKeys must contain at least one key");
14
+ }
15
+ this.signingKey = opts.signingKey;
16
+ this.verificationKeysByKid = new Map();
17
+ for (const key of opts.verificationKeys) {
18
+ if (this.verificationKeysByKid.has(key.kid)) {
19
+ throw new Error(`JwtSigner: duplicate verification key kid "${key.kid}"`);
20
+ }
21
+ this.verificationKeysByKid.set(key.kid, key.publicKey);
22
+ }
23
+ if (!this.verificationKeysByKid.has(opts.signingKey.kid)) {
24
+ throw new Error(`JwtSigner: signing key kid "${opts.signingKey.kid}" missing from verificationKeys`);
25
+ }
26
+ this.issuer = opts.issuer;
27
+ this.audience = opts.audience;
28
+ this.clockToleranceSec = opts.clockToleranceSec ?? 30;
29
+ }
30
+ /**
31
+ * Sign a token. The caller is responsible for choosing `ttlSec` (e.g., 15m
32
+ * for access tokens, 30d for refresh tokens). Returns the compact JWS plus
33
+ * metadata `AuthFlow` needs to persist a `refresh_tokens` row.
34
+ */
35
+ async sign(opts) {
36
+ const jti = opts.jti ?? randomUUID();
37
+ const issuedAt = Math.floor(Date.now() / 1000);
38
+ const expiresAt = issuedAt + opts.ttlSec;
39
+ const builder = new SignJWT({ ...(opts.claims ?? {}) })
40
+ .setProtectedHeader({ alg: ALG, kid: this.signingKey.kid })
41
+ .setSubject(opts.subject)
42
+ .setJti(jti)
43
+ .setIssuedAt(issuedAt)
44
+ .setExpirationTime(expiresAt);
45
+ const issuer = opts.issuer ?? this.issuer;
46
+ if (issuer)
47
+ builder.setIssuer(issuer);
48
+ const audience = opts.audience ?? this.audience;
49
+ if (audience)
50
+ builder.setAudience(audience);
51
+ const token = await builder.sign(this.signingKey.privateKey);
52
+ return { token, jti, issuedAt, expiresAt, kid: this.signingKey.kid };
53
+ }
54
+ /**
55
+ * Verify a token. Throws `AuthenticationError` on any failure — caller
56
+ * surfaces this through the framework's standard error path. Signature,
57
+ * expiry, and (when configured) issuer/audience are all enforced.
58
+ */
59
+ async verify(token) {
60
+ try {
61
+ const result = await jwtVerify(token, (header) => this.resolveKey(header.kid), {
62
+ algorithms: [ALG],
63
+ issuer: this.issuer,
64
+ audience: this.audience,
65
+ clockTolerance: this.clockToleranceSec,
66
+ });
67
+ const kid = result.protectedHeader.kid ?? this.signingKey.kid;
68
+ return { payload: result.payload, kid };
69
+ }
70
+ catch (err) {
71
+ throw classifyVerificationError(err);
72
+ }
73
+ }
74
+ /** Expose the active signing kid for log/metric correlation. */
75
+ getSigningKid() {
76
+ return this.signingKey.kid;
77
+ }
78
+ /** Expose the kids currently accepted at verification — useful for `/dev/routes`-style introspection. */
79
+ getVerificationKids() {
80
+ return [...this.verificationKeysByKid.keys()];
81
+ }
82
+ resolveKey(kid) {
83
+ if (!kid) {
84
+ // We always sign with a `kid` header, so an unsigned token is a forgery
85
+ // attempt against this verifier.
86
+ throw new joseErrors.JWSInvalid("Token missing kid header");
87
+ }
88
+ const key = this.verificationKeysByKid.get(kid);
89
+ if (!key) {
90
+ throw new joseErrors.JWKSNoMatchingKey();
91
+ }
92
+ return key;
93
+ }
94
+ }
95
+ function classifyVerificationError(err) {
96
+ if (err instanceof joseErrors.JWTExpired) {
97
+ return new AuthenticationError("Token expired");
98
+ }
99
+ if (err instanceof joseErrors.JWTClaimValidationFailed) {
100
+ return new AuthenticationError(`Token claim invalid: ${err.claim}`);
101
+ }
102
+ if (err instanceof joseErrors.JWKSNoMatchingKey) {
103
+ return new AuthenticationError("Token signing key not recognized");
104
+ }
105
+ if (err instanceof joseErrors.JWSInvalid) {
106
+ // Forwards messages like "Token missing kid header" set in `resolveKey`.
107
+ return new AuthenticationError(err.message || "Token signature invalid");
108
+ }
109
+ if (err instanceof joseErrors.JOSEError) {
110
+ return new AuthenticationError("Token verification failed");
111
+ }
112
+ // Unknown/unexpected — surface as generic auth failure but preserve cause
113
+ // so OTel/pino can capture the stack.
114
+ const auth = new AuthenticationError("Token verification failed");
115
+ auth.cause = err;
116
+ return auth;
117
+ }
118
+ //# sourceMappingURL=JwtSigner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtSigner.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/JwtSigner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAmC,MAAM,IAAI,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACjG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAyGlF,MAAM,GAAG,GAAG,OAAgB,CAAC;AAE7B,MAAM,OAAO,SAAS;IACH,UAAU,CAAgB;IAC1B,qBAAqB,CAAyB;IAC9C,MAAM,CAAU;IAChB,QAAQ,CAAU;IAClB,iBAAiB,CAAS;IAE3C,YAAY,IAAsB;QAChC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,qBAAqB,GAAG,IAAI,GAAG,EAAE,CAAC;QACvC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACxC,IAAI,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,KAAK,CAAC,8CAA8C,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;YAC5E,CAAC;YACD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CACb,+BAA+B,IAAI,CAAC,UAAU,CAAC,GAAG,iCAAiC,CACpF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CAAC,IAAsB;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC;QAEzC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;aACpD,kBAAkB,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;aAC1D,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC;aACxB,MAAM,CAAC,GAAG,CAAC;aACX,WAAW,CAAC,QAAQ,CAAC;aACrB,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;QAC1C,IAAI,MAAM;YAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC;QAChD,IAAI,QAAQ;YAAE,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAE7D,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC;IACvE,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CACV,KAAa;QAEb,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAU,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBACtF,UAAU,EAAE,CAAC,GAAG,CAAC;gBACjB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,cAAc,EAAE,IAAI,CAAC,iBAAiB;aACvC,CAAC,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,yBAAyB,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;IAC7B,CAAC;IAED,yGAAyG;IACzG,mBAAmB;QACjB,OAAO,CAAC,GAAG,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAEO,UAAU,CAAC,GAAuB;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,wEAAwE;YACxE,iCAAiC;YACjC,MAAM,IAAI,UAAU,CAAC,UAAU,CAAC,0BAA0B,CAAC,CAAC;QAC9D,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,CAAC;QAC3C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED,SAAS,yBAAyB,CAAC,GAAY;IAC7C,IAAI,GAAG,YAAY,UAAU,CAAC,UAAU,EAAE,CAAC;QACzC,OAAO,IAAI,mBAAmB,CAAC,eAAe,CAAC,CAAC;IAClD,CAAC;IACD,IAAI,GAAG,YAAY,UAAU,CAAC,wBAAwB,EAAE,CAAC;QACvD,OAAO,IAAI,mBAAmB,CAAC,wBAAwB,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,GAAG,YAAY,UAAU,CAAC,iBAAiB,EAAE,CAAC;QAChD,OAAO,IAAI,mBAAmB,CAAC,kCAAkC,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,GAAG,YAAY,UAAU,CAAC,UAAU,EAAE,CAAC;QACzC,yEAAyE;QACzE,OAAO,IAAI,mBAAmB,CAAC,GAAG,CAAC,OAAO,IAAI,yBAAyB,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,GAAG,YAAY,UAAU,CAAC,SAAS,EAAE,CAAC;QACxC,OAAO,IAAI,mBAAmB,CAAC,2BAA2B,CAAC,CAAC;IAC9D,CAAC;IACD,0EAA0E;IAC1E,sCAAsC;IACtC,MAAM,IAAI,GAAG,IAAI,mBAAmB,CAAC,2BAA2B,CAAC,CAAC;IACjE,IAAoC,CAAC,KAAK,GAAG,GAAG,CAAC;IAClD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * `RefreshTokenStore` — abstract persistence for refresh-token rotation.
3
+ *
4
+ * The auth flow stores a SHA-256 *hash* of every issued refresh token. The
5
+ * raw token leaves the server only once (in the response cookie); subsequent
6
+ * requests recompute the hash and look up the row. This means even a full
7
+ * database compromise does not let an attacker mint or replay refresh tokens
8
+ * — they would still need the raw cookie value.
9
+ *
10
+ * Reuse detection is the load-bearing security property: when a refresh
11
+ * token is consumed (`consume()`), the row's `replacedById` is set to the
12
+ * successor's ID. If a token is presented whose row already has
13
+ * `replacedById` set, it has been used before — a strong signal of theft.
14
+ * The auth flow's response is to revoke the entire chain (`revokeChain()`)
15
+ * so neither the legitimate user nor the attacker can keep refreshing.
16
+ */
17
+ /**
18
+ * Stored representation of a refresh token. Implementations may add fields,
19
+ * but the framework only depends on these.
20
+ */
21
+ export interface RefreshTokenRecord {
22
+ id: string;
23
+ accountId: string;
24
+ /** SHA-256 hex digest of the raw token. Never stores the raw token itself. */
25
+ tokenHash: string;
26
+ expiresAt: Date;
27
+ revokedAt: Date | null;
28
+ /** Successor's ID when this token has been rotated; null otherwise. */
29
+ replacedById: string | null;
30
+ userAgent?: string | null;
31
+ issuedFromIp?: string | null;
32
+ }
33
+ export interface IssueRefreshTokenInput {
34
+ accountId: string;
35
+ /** Pre-computed SHA-256 hex digest. Computed by the auth flow. */
36
+ tokenHash: string;
37
+ expiresAt: Date;
38
+ userAgent?: string;
39
+ issuedFromIp?: string;
40
+ }
41
+ export interface RefreshTokenStore {
42
+ /** Persist a newly minted refresh token. Returns the stored record's ID. */
43
+ issue(input: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
44
+ /** Look up a token by its hash. Returns `null` if absent. */
45
+ findByHash(tokenHash: string): Promise<RefreshTokenRecord | null>;
46
+ /**
47
+ * Atomically rotate: mark the old row's `replacedById` and persist the
48
+ * new row. Implementations MUST do this in a single transaction so a
49
+ * crash between the two writes can't lose the link.
50
+ */
51
+ rotate(oldId: string, newToken: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
52
+ /** Mark a single token revoked (e.g., on logout). */
53
+ revoke(id: string): Promise<void>;
54
+ /**
55
+ * Revoke an entire rotation chain — every ancestor and every descendant.
56
+ * Triggered on reuse detection (a strong signal of stolen tokens).
57
+ */
58
+ revokeChain(id: string): Promise<number>;
59
+ /**
60
+ * Revoke every active token for an account — e.g., on password reset or
61
+ * "sign out everywhere". Returns the number of rows revoked.
62
+ */
63
+ revokeAllForAccount(accountId: string): Promise<number>;
64
+ }
65
+ /**
66
+ * Compute the SHA-256 digest of a raw refresh token. Hex-encoded so it fits
67
+ * the `varchar(128)` column on `refresh_tokens.token_hash` exactly.
68
+ */
69
+ export declare function hashRefreshToken(rawToken: string): string;
70
+ /**
71
+ * Generate a cryptographically random refresh-token string. 32 random bytes
72
+ * (256 bits) base64url-encoded — opaque to clients, indistinguishable from
73
+ * a UUID. Not a JWT: refresh tokens have no payload of their own; the row
74
+ * in `refresh_tokens` carries all the metadata.
75
+ */
76
+ export declare function generateRefreshTokenValue(): string;
77
+ /**
78
+ * In-memory implementation for tests and dev. Implementations MUST keep the
79
+ * full chain reachable so `revokeChain` can walk both directions.
80
+ */
81
+ export declare class InMemoryRefreshTokenStore implements RefreshTokenStore {
82
+ private byId;
83
+ private byHash;
84
+ private idCounter;
85
+ issue(input: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
86
+ findByHash(tokenHash: string): Promise<RefreshTokenRecord | null>;
87
+ rotate(oldId: string, newToken: IssueRefreshTokenInput): Promise<RefreshTokenRecord>;
88
+ revoke(id: string): Promise<void>;
89
+ revokeChain(id: string): Promise<number>;
90
+ revokeAllForAccount(accountId: string): Promise<number>;
91
+ /** Test helper. */
92
+ size(): number;
93
+ /** Test helper. */
94
+ clear(): void;
95
+ private nextId;
96
+ }
97
+ //# sourceMappingURL=RefreshTokenStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefreshTokenStore.d.ts","sourceRoot":"","sources":["../../../../src/app/auth/jwt/RefreshTokenStore.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,uEAAuE;IACvE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAElE,6DAA6D;IAC7D,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAElE;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAErF,qDAAqD;IACrD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC;;;OAGG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACzD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,IAAI,CAAyC;IACrD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,SAAS,CAAK;IAEhB,KAAK,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAiBjE,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAMjE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAQpF,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqCxC,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,mBAAmB;IACnB,IAAI,IAAI,MAAM;IAId,mBAAmB;IACnB,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,MAAM;CAIf"}
@@ -0,0 +1,122 @@
1
+ import { createHash, randomBytes } from "node:crypto";
2
+ /**
3
+ * Compute the SHA-256 digest of a raw refresh token. Hex-encoded so it fits
4
+ * the `varchar(128)` column on `refresh_tokens.token_hash` exactly.
5
+ */
6
+ export function hashRefreshToken(rawToken) {
7
+ return createHash("sha256").update(rawToken).digest("hex");
8
+ }
9
+ /**
10
+ * Generate a cryptographically random refresh-token string. 32 random bytes
11
+ * (256 bits) base64url-encoded — opaque to clients, indistinguishable from
12
+ * a UUID. Not a JWT: refresh tokens have no payload of their own; the row
13
+ * in `refresh_tokens` carries all the metadata.
14
+ */
15
+ export function generateRefreshTokenValue() {
16
+ return randomBytes(32).toString("base64url");
17
+ }
18
+ /**
19
+ * In-memory implementation for tests and dev. Implementations MUST keep the
20
+ * full chain reachable so `revokeChain` can walk both directions.
21
+ */
22
+ export class InMemoryRefreshTokenStore {
23
+ byId = new Map();
24
+ byHash = new Map();
25
+ idCounter = 0;
26
+ async issue(input) {
27
+ const id = this.nextId();
28
+ const record = {
29
+ id,
30
+ accountId: input.accountId,
31
+ tokenHash: input.tokenHash,
32
+ expiresAt: input.expiresAt,
33
+ revokedAt: null,
34
+ replacedById: null,
35
+ userAgent: input.userAgent ?? null,
36
+ issuedFromIp: input.issuedFromIp ?? null,
37
+ };
38
+ this.byId.set(id, record);
39
+ this.byHash.set(input.tokenHash, id);
40
+ return record;
41
+ }
42
+ async findByHash(tokenHash) {
43
+ const id = this.byHash.get(tokenHash);
44
+ if (!id)
45
+ return null;
46
+ return this.byId.get(id) ?? null;
47
+ }
48
+ async rotate(oldId, newToken) {
49
+ const old = this.byId.get(oldId);
50
+ if (!old)
51
+ throw new Error(`RefreshTokenStore: cannot rotate unknown id ${oldId}`);
52
+ const newRecord = await this.issue(newToken);
53
+ old.replacedById = newRecord.id;
54
+ return newRecord;
55
+ }
56
+ async revoke(id) {
57
+ const row = this.byId.get(id);
58
+ if (!row)
59
+ return;
60
+ if (!row.revokedAt)
61
+ row.revokedAt = new Date();
62
+ }
63
+ async revokeChain(id) {
64
+ const visited = new Set();
65
+ let count = 0;
66
+ // Walk forward via replacedById.
67
+ let cursor = id;
68
+ while (cursor && !visited.has(cursor)) {
69
+ visited.add(cursor);
70
+ const row = this.byId.get(cursor);
71
+ if (!row)
72
+ break;
73
+ if (!row.revokedAt) {
74
+ row.revokedAt = new Date();
75
+ count += 1;
76
+ }
77
+ cursor = row.replacedById;
78
+ }
79
+ // Walk backward by scanning for predecessors. Cheap on small in-memory
80
+ // sets; the Drizzle implementation does it with a recursive CTE.
81
+ let changed = true;
82
+ while (changed) {
83
+ changed = false;
84
+ for (const row of this.byId.values()) {
85
+ if (row.replacedById && visited.has(row.replacedById) && !visited.has(row.id)) {
86
+ visited.add(row.id);
87
+ if (!row.revokedAt) {
88
+ row.revokedAt = new Date();
89
+ count += 1;
90
+ }
91
+ changed = true;
92
+ }
93
+ }
94
+ }
95
+ return count;
96
+ }
97
+ async revokeAllForAccount(accountId) {
98
+ let count = 0;
99
+ for (const row of this.byId.values()) {
100
+ if (row.accountId === accountId && !row.revokedAt) {
101
+ row.revokedAt = new Date();
102
+ count += 1;
103
+ }
104
+ }
105
+ return count;
106
+ }
107
+ /** Test helper. */
108
+ size() {
109
+ return this.byId.size;
110
+ }
111
+ /** Test helper. */
112
+ clear() {
113
+ this.byId.clear();
114
+ this.byHash.clear();
115
+ this.idCounter = 0;
116
+ }
117
+ nextId() {
118
+ this.idCounter += 1;
119
+ return `mem-${this.idCounter}`;
120
+ }
121
+ }
122
+ //# sourceMappingURL=RefreshTokenStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefreshTokenStore.js","sourceRoot":"","sources":["../../../../src/app/auth/jwt/RefreshTokenStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Canonical shape of a permission definition.
3
+ *
4
+ * Each module exports a `<MODULE>_PERMISSION_DEFINITIONS: readonly
5
+ * PermissionDefinition[]` array that the consuming app's bootstrapper / seed
6
+ * upserts into the Permission table. `slug` is the forward-compatible
7
+ * identifier (`module[:resource]:action` — lowercase, colon-separated;
8
+ * hyphenate multi-word actions, e.g. `oauth:connections:read-self`); `label`
9
+ * is the human-facing string shown in admin UIs.
10
+ *
11
+ * Contract: once an app deploys against a slug it is frozen — changing or
12
+ * removing a slug is a breaking change. `label` may change freely.
13
+ */
14
+ export interface PermissionDefinition {
15
+ /** Stable `module[:resource]:action` identifier checked by `requirePermission`. */
16
+ slug: string;
17
+ /** Human-facing name surfaced in admin UIs when assigning permissions to roles. */
18
+ label: string;
19
+ }
20
+ //# sourceMappingURL=permissionDefinition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissionDefinition.d.ts","sourceRoot":"","sources":["../../../src/app/auth/permissionDefinition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=permissionDefinition.js.map