@zintrust/core 0.1.42 → 0.1.44

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 (381) hide show
  1. package/README.md +1 -0
  2. package/app/Controllers/AuthController.d.ts +10 -0
  3. package/app/Controllers/AuthController.d.ts.map +1 -0
  4. package/app/Controllers/AuthController.js +201 -0
  5. package/app/Controllers/UserController.d.ts +9 -0
  6. package/app/Controllers/UserController.d.ts.map +1 -0
  7. package/app/Controllers/UserController.js +8 -0
  8. package/app/Controllers/UserQueryBuilderController.d.ts +16 -0
  9. package/app/Controllers/UserQueryBuilderController.d.ts.map +1 -0
  10. package/app/Controllers/UserQueryBuilderController.js +404 -0
  11. package/app/Middleware/ProfilerMiddleware.d.ts +12 -0
  12. package/app/Middleware/ProfilerMiddleware.d.ts.map +1 -0
  13. package/app/Middleware/ProfilerMiddleware.js +47 -0
  14. package/app/Middleware/index.d.ts +59 -0
  15. package/app/Middleware/index.d.ts.map +1 -0
  16. package/app/Middleware/index.js +215 -0
  17. package/app/Models/Post.d.ts +14 -0
  18. package/app/Models/Post.d.ts.map +1 -0
  19. package/app/Models/Post.js +27 -0
  20. package/app/Models/User.d.ts +14 -0
  21. package/app/Models/User.d.ts.map +1 -0
  22. package/app/Models/User.js +44 -0
  23. package/app/Schedules/JobTracking.d.ts +3 -0
  24. package/app/Schedules/JobTracking.d.ts.map +1 -0
  25. package/app/Schedules/JobTracking.js +13 -0
  26. package/app/Schedules/index.d.ts +2 -0
  27. package/app/Schedules/index.d.ts.map +1 -0
  28. package/app/Schedules/index.js +1 -0
  29. package/app/Toolkit/Broadcast/sendBroadcast.d.ts +6 -0
  30. package/app/Toolkit/Broadcast/sendBroadcast.d.ts.map +1 -0
  31. package/app/Toolkit/Broadcast/sendBroadcast.js +5 -0
  32. package/app/Toolkit/Mail/sendWelcomeEmail.d.ts +6 -0
  33. package/app/Toolkit/Mail/sendWelcomeEmail.d.ts.map +1 -0
  34. package/app/Toolkit/Mail/sendWelcomeEmail.js +20 -0
  35. package/app/Toolkit/Notification/sendSlackNotification.d.ts +8 -0
  36. package/app/Toolkit/Notification/sendSlackNotification.d.ts.map +1 -0
  37. package/app/Toolkit/Notification/sendSlackNotification.js +5 -0
  38. package/app/Toolkit/Notification/sendSms.d.ts +6 -0
  39. package/app/Toolkit/Notification/sendSms.d.ts.map +1 -0
  40. package/app/Toolkit/Notification/sendSms.js +5 -0
  41. package/app/Types/controller.d.ts +42 -0
  42. package/app/Types/controller.d.ts.map +1 -0
  43. package/app/Types/controller.js +1 -0
  44. package/config/broadcast.d.ts +38 -0
  45. package/config/broadcast.d.ts.map +1 -0
  46. package/config/broadcast.js +37 -0
  47. package/config/cache.d.ts +40 -0
  48. package/config/cache.d.ts.map +1 -0
  49. package/config/cache.js +39 -0
  50. package/config/database.d.ts +58 -0
  51. package/config/database.d.ts.map +1 -0
  52. package/config/database.js +65 -0
  53. package/config/mail.d.ts +51 -0
  54. package/config/mail.d.ts.map +1 -0
  55. package/config/mail.js +69 -0
  56. package/config/middleware.d.ts +11 -0
  57. package/config/middleware.d.ts.map +1 -0
  58. package/config/middleware.js +30 -0
  59. package/config/notification.d.ts +33 -0
  60. package/config/notification.d.ts.map +1 -0
  61. package/config/notification.js +33 -0
  62. package/config/queue.d.ts +55 -0
  63. package/config/queue.d.ts.map +1 -0
  64. package/config/queue.js +87 -0
  65. package/config/storage.d.ts +59 -0
  66. package/config/storage.d.ts.map +1 -0
  67. package/config/storage.js +59 -0
  68. package/config/workers.d.ts +54 -0
  69. package/config/workers.d.ts.map +1 -0
  70. package/config/workers.js +83 -0
  71. package/package.json +12 -5
  72. package/packages/cloudflare-d1-proxy/src/index.d.ts +48 -0
  73. package/packages/cloudflare-d1-proxy/src/index.d.ts.map +1 -0
  74. package/packages/cloudflare-d1-proxy/src/index.js +387 -0
  75. package/packages/cloudflare-kv-proxy/src/index.d.ts +44 -0
  76. package/packages/cloudflare-kv-proxy/src/index.d.ts.map +1 -0
  77. package/packages/cloudflare-kv-proxy/src/index.js +325 -0
  78. package/packages/queue-monitor/src/QueueMonitoringService.d.ts +35 -0
  79. package/packages/queue-monitor/src/QueueMonitoringService.d.ts.map +1 -0
  80. package/packages/queue-monitor/src/QueueMonitoringService.js +194 -0
  81. package/packages/queue-monitor/src/connection.d.ts +3 -0
  82. package/packages/queue-monitor/src/connection.d.ts.map +1 -0
  83. package/packages/queue-monitor/src/connection.js +1 -0
  84. package/packages/queue-monitor/src/dashboard-ui.d.ts +7 -0
  85. package/packages/queue-monitor/src/dashboard-ui.d.ts.map +1 -0
  86. package/packages/queue-monitor/src/dashboard-ui.js +997 -0
  87. package/packages/queue-monitor/src/driver.d.ts +15 -0
  88. package/packages/queue-monitor/src/driver.d.ts.map +1 -0
  89. package/packages/queue-monitor/src/driver.js +115 -0
  90. package/packages/queue-monitor/src/index.d.ts +71 -0
  91. package/packages/queue-monitor/src/index.d.ts.map +1 -0
  92. package/packages/queue-monitor/src/index.js +296 -0
  93. package/packages/queue-monitor/src/metrics.d.ts +27 -0
  94. package/packages/queue-monitor/src/metrics.d.ts.map +1 -0
  95. package/packages/queue-monitor/src/metrics.js +92 -0
  96. package/packages/queue-monitor/src/worker.d.ts +8 -0
  97. package/packages/queue-monitor/src/worker.d.ts.map +1 -0
  98. package/packages/queue-monitor/src/worker.js +35 -0
  99. package/packages/queue-redis/src/BullMQRedisQueue.d.ts +26 -0
  100. package/packages/queue-redis/src/BullMQRedisQueue.d.ts.map +1 -0
  101. package/packages/queue-redis/src/BullMQRedisQueue.js +463 -0
  102. package/packages/queue-redis/src/HttpQueueDriver.d.ts +18 -0
  103. package/packages/queue-redis/src/HttpQueueDriver.d.ts.map +1 -0
  104. package/packages/queue-redis/src/HttpQueueDriver.js +249 -0
  105. package/packages/queue-redis/src/QueueHttpGateway.d.ts +16 -0
  106. package/packages/queue-redis/src/QueueHttpGateway.d.ts.map +1 -0
  107. package/packages/queue-redis/src/QueueHttpGateway.js +217 -0
  108. package/packages/queue-redis/src/RedisPublishClient.d.ts +14 -0
  109. package/packages/queue-redis/src/RedisPublishClient.d.ts.map +1 -0
  110. package/packages/queue-redis/src/RedisPublishClient.js +251 -0
  111. package/packages/queue-redis/src/index.d.ts +12 -0
  112. package/packages/queue-redis/src/index.d.ts.map +1 -0
  113. package/packages/queue-redis/src/index.js +10 -0
  114. package/packages/queue-redis/src/register.d.ts +6 -0
  115. package/packages/queue-redis/src/register.d.ts.map +1 -0
  116. package/packages/queue-redis/src/register.js +21 -0
  117. package/packages/workers/migrations/20260119100000_create_zintrust_workers_table.d.ts +11 -0
  118. package/packages/workers/migrations/20260119100000_create_zintrust_workers_table.d.ts.map +1 -0
  119. package/packages/workers/migrations/20260119100000_create_zintrust_workers_table.js +32 -0
  120. package/packages/workers/migrations/20260123180000_create_queue_jobs_table.d.ts +11 -0
  121. package/packages/workers/migrations/20260123180000_create_queue_jobs_table.d.ts.map +1 -0
  122. package/packages/workers/migrations/20260123180000_create_queue_jobs_table.js +46 -0
  123. package/packages/workers/migrations/20260213142000_create_zintrust_job_tracking_tables.d.ts +7 -0
  124. package/packages/workers/migrations/20260213142000_create_zintrust_job_tracking_tables.d.ts.map +1 -0
  125. package/packages/workers/migrations/20260213142000_create_zintrust_job_tracking_tables.js +44 -0
  126. package/packages/workers/migrations/20260213183000_expand_zintrust_job_tracking_reliability_tables.d.ts +7 -0
  127. package/packages/workers/migrations/20260213183000_expand_zintrust_job_tracking_reliability_tables.d.ts.map +1 -0
  128. package/packages/workers/migrations/20260213183000_expand_zintrust_job_tracking_reliability_tables.js +104 -0
  129. package/packages/workers/src/AnomalyDetection.d.ts +107 -0
  130. package/packages/workers/src/AnomalyDetection.d.ts.map +1 -0
  131. package/packages/workers/src/AnomalyDetection.js +329 -0
  132. package/packages/workers/src/AutoScaler.d.ts +128 -0
  133. package/packages/workers/src/AutoScaler.d.ts.map +1 -0
  134. package/packages/workers/src/AutoScaler.js +425 -0
  135. package/packages/workers/src/BroadcastWorker.d.ts +24 -0
  136. package/packages/workers/src/BroadcastWorker.d.ts.map +1 -0
  137. package/packages/workers/src/BroadcastWorker.js +24 -0
  138. package/packages/workers/src/CanaryController.d.ts +104 -0
  139. package/packages/workers/src/CanaryController.d.ts.map +1 -0
  140. package/packages/workers/src/CanaryController.js +424 -0
  141. package/packages/workers/src/ChaosEngineering.d.ts +80 -0
  142. package/packages/workers/src/ChaosEngineering.d.ts.map +1 -0
  143. package/packages/workers/src/ChaosEngineering.js +229 -0
  144. package/packages/workers/src/CircuitBreaker.d.ts +107 -0
  145. package/packages/workers/src/CircuitBreaker.d.ts.map +1 -0
  146. package/packages/workers/src/CircuitBreaker.js +374 -0
  147. package/packages/workers/src/ClusterLock.d.ts +91 -0
  148. package/packages/workers/src/ClusterLock.d.ts.map +1 -0
  149. package/packages/workers/src/ClusterLock.js +397 -0
  150. package/packages/workers/src/ComplianceManager.d.ts +178 -0
  151. package/packages/workers/src/ComplianceManager.d.ts.map +1 -0
  152. package/packages/workers/src/ComplianceManager.js +556 -0
  153. package/packages/workers/src/DatacenterOrchestrator.d.ts +134 -0
  154. package/packages/workers/src/DatacenterOrchestrator.d.ts.map +1 -0
  155. package/packages/workers/src/DatacenterOrchestrator.js +404 -0
  156. package/packages/workers/src/DeadLetterQueue.d.ts +123 -0
  157. package/packages/workers/src/DeadLetterQueue.d.ts.map +1 -0
  158. package/packages/workers/src/DeadLetterQueue.js +544 -0
  159. package/packages/workers/src/HealthMonitor.d.ts +43 -0
  160. package/packages/workers/src/HealthMonitor.d.ts.map +1 -0
  161. package/packages/workers/src/HealthMonitor.js +312 -0
  162. package/packages/workers/src/MultiQueueWorker.d.ts +90 -0
  163. package/packages/workers/src/MultiQueueWorker.d.ts.map +1 -0
  164. package/packages/workers/src/MultiQueueWorker.js +282 -0
  165. package/packages/workers/src/NotificationWorker.d.ts +24 -0
  166. package/packages/workers/src/NotificationWorker.d.ts.map +1 -0
  167. package/packages/workers/src/NotificationWorker.js +23 -0
  168. package/packages/workers/src/Observability.d.ts +154 -0
  169. package/packages/workers/src/Observability.d.ts.map +1 -0
  170. package/packages/workers/src/Observability.js +538 -0
  171. package/packages/workers/src/PluginManager.d.ts +124 -0
  172. package/packages/workers/src/PluginManager.d.ts.map +1 -0
  173. package/packages/workers/src/PluginManager.js +392 -0
  174. package/packages/workers/src/PriorityQueue.d.ts +118 -0
  175. package/packages/workers/src/PriorityQueue.d.ts.map +1 -0
  176. package/packages/workers/src/PriorityQueue.js +276 -0
  177. package/packages/workers/src/ResourceMonitor.d.ts +165 -0
  178. package/packages/workers/src/ResourceMonitor.d.ts.map +1 -0
  179. package/packages/workers/src/ResourceMonitor.js +632 -0
  180. package/packages/workers/src/SLAMonitor.d.ts +111 -0
  181. package/packages/workers/src/SLAMonitor.d.ts.map +1 -0
  182. package/packages/workers/src/SLAMonitor.js +274 -0
  183. package/packages/workers/src/WorkerFactory.d.ts +218 -0
  184. package/packages/workers/src/WorkerFactory.d.ts.map +1 -0
  185. package/packages/workers/src/WorkerFactory.js +2253 -0
  186. package/packages/workers/src/WorkerInit.d.ts +86 -0
  187. package/packages/workers/src/WorkerInit.d.ts.map +1 -0
  188. package/packages/workers/src/WorkerInit.js +307 -0
  189. package/packages/workers/src/WorkerMetrics.d.ts +116 -0
  190. package/packages/workers/src/WorkerMetrics.d.ts.map +1 -0
  191. package/packages/workers/src/WorkerMetrics.js +570 -0
  192. package/packages/workers/src/WorkerRegistry.d.ts +152 -0
  193. package/packages/workers/src/WorkerRegistry.d.ts.map +1 -0
  194. package/packages/workers/src/WorkerRegistry.js +396 -0
  195. package/packages/workers/src/WorkerShutdown.d.ts +70 -0
  196. package/packages/workers/src/WorkerShutdown.d.ts.map +1 -0
  197. package/packages/workers/src/WorkerShutdown.js +185 -0
  198. package/packages/workers/src/WorkerVersioning.d.ts +108 -0
  199. package/packages/workers/src/WorkerVersioning.d.ts.map +1 -0
  200. package/packages/workers/src/WorkerVersioning.js +300 -0
  201. package/packages/workers/src/config/workerConfig.d.ts +5 -0
  202. package/packages/workers/src/config/workerConfig.d.ts.map +1 -0
  203. package/packages/workers/src/config/workerConfig.js +25 -0
  204. package/packages/workers/src/createQueueWorker.d.ts +26 -0
  205. package/packages/workers/src/createQueueWorker.d.ts.map +1 -0
  206. package/packages/workers/src/createQueueWorker.js +367 -0
  207. package/packages/workers/src/dashboard/index.d.ts +2 -0
  208. package/packages/workers/src/dashboard/index.d.ts.map +1 -0
  209. package/packages/workers/src/dashboard/index.js +1 -0
  210. package/packages/workers/src/dashboard/types.d.ts +123 -0
  211. package/packages/workers/src/dashboard/types.d.ts.map +1 -0
  212. package/packages/workers/src/dashboard/types.js +1 -0
  213. package/packages/workers/src/dashboard/workers-api.d.ts +5 -0
  214. package/packages/workers/src/dashboard/workers-api.d.ts.map +1 -0
  215. package/packages/workers/src/dashboard/workers-api.js +738 -0
  216. package/packages/workers/src/helper/index.d.ts +6 -0
  217. package/packages/workers/src/helper/index.d.ts.map +1 -0
  218. package/packages/workers/src/helper/index.js +10 -0
  219. package/packages/workers/src/http/WorkerApiController.d.ts +39 -0
  220. package/packages/workers/src/http/WorkerApiController.d.ts.map +1 -0
  221. package/packages/workers/src/http/WorkerApiController.js +313 -0
  222. package/packages/workers/src/http/WorkerController.d.ts +375 -0
  223. package/packages/workers/src/http/WorkerController.d.ts.map +1 -0
  224. package/packages/workers/src/http/WorkerController.js +1454 -0
  225. package/packages/workers/src/http/WorkerMonitoringService.d.ts +12 -0
  226. package/packages/workers/src/http/WorkerMonitoringService.d.ts.map +1 -0
  227. package/packages/workers/src/http/WorkerMonitoringService.js +89 -0
  228. package/packages/workers/src/http/middleware/CustomValidation.d.ts +93 -0
  229. package/packages/workers/src/http/middleware/CustomValidation.d.ts.map +1 -0
  230. package/packages/workers/src/http/middleware/CustomValidation.js +270 -0
  231. package/packages/workers/src/http/middleware/DatacenterValidator.d.ts +4 -0
  232. package/packages/workers/src/http/middleware/DatacenterValidator.d.ts.map +1 -0
  233. package/packages/workers/src/http/middleware/DatacenterValidator.js +94 -0
  234. package/packages/workers/src/http/middleware/EditWorkerValidation.d.ts +8 -0
  235. package/packages/workers/src/http/middleware/EditWorkerValidation.d.ts.map +1 -0
  236. package/packages/workers/src/http/middleware/EditWorkerValidation.js +56 -0
  237. package/packages/workers/src/http/middleware/FeaturesValidator.d.ts +4 -0
  238. package/packages/workers/src/http/middleware/FeaturesValidator.d.ts.map +1 -0
  239. package/packages/workers/src/http/middleware/FeaturesValidator.js +60 -0
  240. package/packages/workers/src/http/middleware/InfrastructureValidator.d.ts +32 -0
  241. package/packages/workers/src/http/middleware/InfrastructureValidator.d.ts.map +1 -0
  242. package/packages/workers/src/http/middleware/InfrastructureValidator.js +226 -0
  243. package/packages/workers/src/http/middleware/OptionsValidator.d.ts +4 -0
  244. package/packages/workers/src/http/middleware/OptionsValidator.d.ts.map +1 -0
  245. package/packages/workers/src/http/middleware/OptionsValidator.js +112 -0
  246. package/packages/workers/src/http/middleware/PayloadSanitizer.d.ts +8 -0
  247. package/packages/workers/src/http/middleware/PayloadSanitizer.d.ts.map +1 -0
  248. package/packages/workers/src/http/middleware/PayloadSanitizer.js +42 -0
  249. package/packages/workers/src/http/middleware/ProcessorPathSanitizer.d.ts +4 -0
  250. package/packages/workers/src/http/middleware/ProcessorPathSanitizer.d.ts.map +1 -0
  251. package/packages/workers/src/http/middleware/ProcessorPathSanitizer.js +140 -0
  252. package/packages/workers/src/http/middleware/QueueNameSanitizer.d.ts +4 -0
  253. package/packages/workers/src/http/middleware/QueueNameSanitizer.d.ts.map +1 -0
  254. package/packages/workers/src/http/middleware/QueueNameSanitizer.js +45 -0
  255. package/packages/workers/src/http/middleware/ValidateDriver.d.ts +8 -0
  256. package/packages/workers/src/http/middleware/ValidateDriver.d.ts.map +1 -0
  257. package/packages/workers/src/http/middleware/ValidateDriver.js +20 -0
  258. package/packages/workers/src/http/middleware/VersionSanitizer.d.ts +4 -0
  259. package/packages/workers/src/http/middleware/VersionSanitizer.d.ts.map +1 -0
  260. package/packages/workers/src/http/middleware/VersionSanitizer.js +25 -0
  261. package/packages/workers/src/http/middleware/WorkerNameSanitizer.d.ts +4 -0
  262. package/packages/workers/src/http/middleware/WorkerNameSanitizer.d.ts.map +1 -0
  263. package/packages/workers/src/http/middleware/WorkerNameSanitizer.js +46 -0
  264. package/packages/workers/src/http/middleware/WorkerValidationChain.d.ts +28 -0
  265. package/packages/workers/src/http/middleware/WorkerValidationChain.d.ts.map +1 -0
  266. package/packages/workers/src/http/middleware/WorkerValidationChain.js +186 -0
  267. package/packages/workers/src/index.d.ts +47 -0
  268. package/packages/workers/src/index.d.ts.map +1 -0
  269. package/packages/workers/src/index.js +48 -0
  270. package/packages/workers/src/routes/workers.d.ts +13 -0
  271. package/packages/workers/src/routes/workers.d.ts.map +1 -0
  272. package/packages/workers/src/routes/workers.js +126 -0
  273. package/packages/workers/src/storage/WorkerStore.d.ts +52 -0
  274. package/packages/workers/src/storage/WorkerStore.d.ts.map +1 -0
  275. package/packages/workers/src/storage/WorkerStore.js +259 -0
  276. package/packages/workers/src/telemetry/api/TelemetryAPI.d.ts +47 -0
  277. package/packages/workers/src/telemetry/api/TelemetryAPI.d.ts.map +1 -0
  278. package/packages/workers/src/telemetry/api/TelemetryAPI.js +219 -0
  279. package/packages/workers/src/telemetry/api/TelemetryMonitoringService.d.ts +18 -0
  280. package/packages/workers/src/telemetry/api/TelemetryMonitoringService.d.ts.map +1 -0
  281. package/packages/workers/src/telemetry/api/TelemetryMonitoringService.js +140 -0
  282. package/packages/workers/src/telemetry/components/AlertPanel.d.ts +2 -0
  283. package/packages/workers/src/telemetry/components/AlertPanel.d.ts.map +1 -0
  284. package/packages/workers/src/telemetry/components/AlertPanel.js +13 -0
  285. package/packages/workers/src/telemetry/components/CostTracking.d.ts +2 -0
  286. package/packages/workers/src/telemetry/components/CostTracking.d.ts.map +1 -0
  287. package/packages/workers/src/telemetry/components/CostTracking.js +14 -0
  288. package/packages/workers/src/telemetry/components/ResourceUsageChart.d.ts +2 -0
  289. package/packages/workers/src/telemetry/components/ResourceUsageChart.d.ts.map +1 -0
  290. package/packages/workers/src/telemetry/components/ResourceUsageChart.js +11 -0
  291. package/packages/workers/src/telemetry/components/WorkerHealthChart.d.ts +2 -0
  292. package/packages/workers/src/telemetry/components/WorkerHealthChart.d.ts.map +1 -0
  293. package/packages/workers/src/telemetry/components/WorkerHealthChart.js +11 -0
  294. package/packages/workers/src/telemetry/index.d.ts +16 -0
  295. package/packages/workers/src/telemetry/index.d.ts.map +1 -0
  296. package/packages/workers/src/telemetry/index.js +60 -0
  297. package/packages/workers/src/telemetry/routes/dashboard.d.ts +7 -0
  298. package/packages/workers/src/telemetry/routes/dashboard.d.ts.map +1 -0
  299. package/packages/workers/src/telemetry/routes/dashboard.js +608 -0
  300. package/packages/workers/src/type.d.ts +77 -0
  301. package/packages/workers/src/type.d.ts.map +1 -0
  302. package/packages/workers/src/type.js +1 -0
  303. package/packages/workers/src/ui/router/EmbeddedAssets.d.ts +5 -0
  304. package/packages/workers/src/ui/router/EmbeddedAssets.d.ts.map +1 -0
  305. package/packages/workers/src/ui/router/EmbeddedAssets.js +13 -0
  306. package/packages/workers/src/ui/router/ui.d.ts +4 -0
  307. package/packages/workers/src/ui/router/ui.d.ts.map +1 -0
  308. package/packages/workers/src/ui/router/ui.js +208 -0
  309. package/packages/workers/src/ui/types/worker-ui.d.ts +230 -0
  310. package/packages/workers/src/ui/types/worker-ui.d.ts.map +1 -0
  311. package/packages/workers/src/ui/types/worker-ui.js +5 -0
  312. package/routes/api.d.ts +7 -0
  313. package/routes/api.d.ts.map +1 -0
  314. package/routes/api.js +129 -0
  315. package/routes/broadcast.d.ts +9 -0
  316. package/routes/broadcast.d.ts.map +1 -0
  317. package/routes/broadcast.js +27 -0
  318. package/routes/storage.d.ts +4 -0
  319. package/routes/storage.d.ts.map +1 -0
  320. package/routes/storage.js +35 -0
  321. package/src/cache/Cache.d.ts.map +1 -1
  322. package/src/cache/Cache.js +40 -8
  323. package/src/cache/drivers/KVRemoteDriver.d.ts +1 -1
  324. package/src/cache/drivers/KVRemoteDriver.d.ts.map +1 -1
  325. package/src/cache/drivers/KVRemoteDriver.js +259 -44
  326. package/src/cache/drivers/MemoryDriver.d.ts.map +1 -1
  327. package/src/cache/drivers/MemoryDriver.js +10 -2
  328. package/src/cache/drivers/RedisDriver.d.ts.map +1 -1
  329. package/src/cache/drivers/RedisDriver.js +256 -33
  330. package/src/cli/CLI.d.ts.map +1 -1
  331. package/src/cli/CLI.js +6 -0
  332. package/src/cli/commands/DeployCommand.d.ts.map +1 -1
  333. package/src/cli/commands/DeployCommand.js +12 -1
  334. package/src/cli/commands/DeployContainersProxyCommand.d.ts +5 -0
  335. package/src/cli/commands/DeployContainersProxyCommand.d.ts.map +1 -0
  336. package/src/cli/commands/DeployContainersProxyCommand.js +45 -0
  337. package/src/cli/commands/DockerCommand.d.ts +5 -0
  338. package/src/cli/commands/DockerCommand.d.ts.map +1 -0
  339. package/src/cli/commands/DockerCommand.js +74 -0
  340. package/src/cli/commands/InitContainerCommand.js +10 -10
  341. package/src/cli/commands/InitContainersProxyCommand.d.ts +5 -0
  342. package/src/cli/commands/InitContainersProxyCommand.d.ts.map +1 -0
  343. package/src/cli/commands/InitContainersProxyCommand.js +159 -0
  344. package/src/cli/commands/NewCommand.d.ts.map +1 -1
  345. package/src/cli/commands/NewCommand.js +33 -0
  346. package/src/cli/commands/PutCommand.d.ts.map +1 -1
  347. package/src/cli/commands/PutCommand.js +15 -5
  348. package/src/cli/commands/StartCommand.d.ts.map +1 -1
  349. package/src/cli/commands/StartCommand.js +43 -4
  350. package/src/cli/scaffolding/ProjectScaffolder.d.ts.map +1 -1
  351. package/src/cli/scaffolding/ProjectScaffolder.js +65 -73
  352. package/src/cli/utils/DistPackager.d.ts.map +1 -1
  353. package/src/cli/utils/DistPackager.js +25 -0
  354. package/src/cli/utils/EnvFileLoader.d.ts +1 -0
  355. package/src/cli/utils/EnvFileLoader.d.ts.map +1 -1
  356. package/src/cli/utils/EnvFileLoader.js +14 -0
  357. package/src/common/RemoteSignedJson.d.ts.map +1 -1
  358. package/src/common/RemoteSignedJson.js +9 -2
  359. package/src/config/cache.js +1 -1
  360. package/src/config/env.d.ts +7 -0
  361. package/src/config/env.d.ts.map +1 -1
  362. package/src/config/env.js +8 -0
  363. package/src/config/queue.js +1 -1
  364. package/src/functions/cloudflare.d.ts.map +1 -1
  365. package/src/functions/cloudflare.js +4 -2
  366. package/src/index.js +3 -3
  367. package/src/middleware/JwtAuthMiddleware.d.ts.map +1 -1
  368. package/src/middleware/JwtAuthMiddleware.js +11 -5
  369. package/src/runtime/RuntimeAdapter.d.ts.map +1 -1
  370. package/src/runtime/RuntimeAdapter.js +30 -12
  371. package/src/runtime/adapters/CloudflareAdapter.d.ts.map +1 -1
  372. package/src/runtime/adapters/CloudflareAdapter.js +15 -4
  373. package/src/scheduler/Schedule.js +1 -1
  374. package/src/scheduler/leader/SchedulerLeader.js +1 -1
  375. package/src/schedules/job-tracking-cleanup.js +1 -1
  376. package/src/security/TokenRevocation.d.ts +19 -2
  377. package/src/security/TokenRevocation.d.ts.map +1 -1
  378. package/src/security/TokenRevocation.js +558 -30
  379. package/src/templates/project/basic/app/Controllers/AuthController.ts.tpl +11 -3
  380. package/src/templates/project/basic/config/middleware.ts.tpl +23 -22
  381. package/src/templates/project/basic/wrangler.jsonc.tpl +28 -0
@@ -1,57 +1,585 @@
1
+ import { RemoteSignedJson } from '../common/RemoteSignedJson.js';
2
+ import { Cloudflare } from '../config/cloudflare.js';
3
+ import { Env } from '../config/env.js';
4
+ import { Logger } from '../config/logger.js';
1
5
  import { securityConfig } from '../config/security.js';
6
+ import { createRedisConnection } from '../config/workers.js';
7
+ import { ErrorFactory } from '../exceptions/ZintrustError.js';
8
+ import { useDatabase } from '../orm/Database.js';
2
9
  import { JwtManager } from './JwtManager.js';
3
- const revokedTokens = new Map();
10
+ const DEFAULTS = {
11
+ driver: 'database',
12
+ dbConnection: 'default',
13
+ dbTable: 'zintrust_jwt_revocations',
14
+ redisPrefix: 'zt:jwt:revoked:',
15
+ kvBinding: 'CACHE',
16
+ kvRemoteNamespace: '',
17
+ };
4
18
  const defaultTtlMs = Math.max(securityConfig.jwt.expiresIn * 1000, 60_000);
19
+ const normalizeDriverName = (raw) => {
20
+ const value = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
21
+ if (value === 'db' || value === 'database')
22
+ return 'database';
23
+ if (value === 'redis')
24
+ return 'redis';
25
+ if (value === 'kv')
26
+ return 'kv';
27
+ if (value === 'kv-remote' || value === 'kvremote')
28
+ return 'kv-remote';
29
+ if (value === 'memory' || value === 'mem')
30
+ return 'memory';
31
+ return DEFAULTS.driver;
32
+ };
33
+ const resolveSigningPrefix = (baseUrl) => {
34
+ try {
35
+ const parsed = new URL(baseUrl);
36
+ const path = parsed.pathname.endsWith('/') ? parsed.pathname.slice(0, -1) : parsed.pathname;
37
+ if (path === '' || path === '/')
38
+ return undefined;
39
+ return path;
40
+ }
41
+ catch {
42
+ return undefined;
43
+ }
44
+ };
5
45
  const getBearerToken = (header) => {
6
46
  const value = Array.isArray(header) ? header[0] : header;
7
47
  if (typeof value !== 'string')
8
48
  return null;
9
- const [scheme, token] = value.trim().split(' ');
10
- if (scheme.toLowerCase() !== 'bearer')
49
+ const trimmed = value.trim();
50
+ if (trimmed === '')
11
51
  return null;
12
- if (typeof token !== 'string' || token.trim() === '')
52
+ const [scheme, ...rest] = trimmed.split(/\s+/);
53
+ if (typeof scheme !== 'string' || scheme.toLowerCase() !== 'bearer')
13
54
  return null;
14
- return token;
15
- };
16
- const cleanupExpired = () => {
17
- const now = Date.now();
18
- for (const [token, expiresAt] of revokedTokens.entries()) {
19
- if (expiresAt <= now) {
20
- revokedTokens.delete(token);
21
- }
22
- }
55
+ const token = rest.join(' ').trim();
56
+ return token === '' ? null : token;
23
57
  };
24
58
  const resolveExpiryMs = (token) => {
25
59
  try {
26
60
  const payload = JwtManager.create().decode(token);
27
- if (typeof payload.exp === 'number' && Number.isFinite(payload.exp)) {
28
- return payload.exp * 1000;
61
+ const expiresAtMs = typeof payload.exp === 'number' && Number.isFinite(payload.exp)
62
+ ? payload.exp * 1000
63
+ : Date.now() + defaultTtlMs;
64
+ const sub = typeof payload.sub === 'string' && payload.sub.trim() !== '' ? payload.sub : undefined;
65
+ const jti = typeof payload.jti === 'string' && payload.jti.trim() !== '' ? payload.jti : undefined;
66
+ return { expiresAtMs, sub, jti };
67
+ }
68
+ catch {
69
+ return { expiresAtMs: Date.now() + defaultTtlMs };
70
+ }
71
+ };
72
+ const resolveKey = (token) => {
73
+ const { expiresAtMs, sub, jti } = resolveExpiryMs(token);
74
+ return {
75
+ id: jti ?? token,
76
+ expiresAtMs,
77
+ sub,
78
+ };
79
+ };
80
+ const logWarnBestEffort = (message, meta) => {
81
+ const anyLogger = Logger;
82
+ if (typeof anyLogger.warn === 'function') {
83
+ anyLogger.warn(message, meta);
84
+ return;
85
+ }
86
+ if (typeof anyLogger.debug === 'function') {
87
+ anyLogger.debug(message, meta);
88
+ return;
89
+ }
90
+ if (typeof anyLogger.info === 'function') {
91
+ anyLogger.info(message, meta);
92
+ }
93
+ };
94
+ const createMemoryStore = () => {
95
+ const revoked = new Map();
96
+ const cleanupExpired = () => {
97
+ const now = Date.now();
98
+ for (const [id, expiresAtMs] of revoked.entries()) {
99
+ if (expiresAtMs <= now)
100
+ revoked.delete(id);
101
+ }
102
+ };
103
+ return {
104
+ async revoke(key) {
105
+ cleanupExpired();
106
+ revoked.set(key.id, key.expiresAtMs);
107
+ await Promise.resolve();
108
+ },
109
+ async isRevoked(id) {
110
+ cleanupExpired();
111
+ const expiresAtMs = revoked.get(id);
112
+ if (expiresAtMs === undefined)
113
+ return false;
114
+ if (expiresAtMs <= Date.now()) {
115
+ revoked.delete(id);
116
+ return false;
117
+ }
118
+ await Promise.resolve();
119
+ return true;
120
+ },
121
+ };
122
+ };
123
+ const createDatabaseStore = (params) => {
124
+ let checkCount = 0;
125
+ const maybeCleanup = async () => {
126
+ checkCount += 1;
127
+ if (checkCount % 250 !== 0)
128
+ return;
129
+ try {
130
+ const db = useDatabase(undefined, params.connection);
131
+ await db.table(params.table).where('expires_at_ms', '<=', Date.now()).delete();
29
132
  }
133
+ catch (error) {
134
+ Logger.debug('TokenRevocation database cleanup failed', {
135
+ error: error instanceof Error ? error.message : String(error),
136
+ });
137
+ }
138
+ };
139
+ return {
140
+ async revoke(key) {
141
+ const ttlMs = Math.max(0, key.expiresAtMs - Date.now());
142
+ if (ttlMs === 0)
143
+ return;
144
+ try {
145
+ const db = useDatabase(undefined, params.connection);
146
+ const existing = await db
147
+ .table(params.table)
148
+ .where('jti', '=', key.id)
149
+ .first();
150
+ const payload = {
151
+ jti: key.id,
152
+ sub: key.sub ?? null,
153
+ expires_at_ms: key.expiresAtMs,
154
+ };
155
+ if (existing) {
156
+ await db.table(params.table).where('jti', '=', key.id).update(payload);
157
+ }
158
+ else {
159
+ await db.table(params.table).insert(payload);
160
+ }
161
+ }
162
+ catch (error) {
163
+ logWarnBestEffort('TokenRevocation database revoke failed (token will not be revoked)', {
164
+ error: error instanceof Error ? error.message : String(error),
165
+ table: params.table,
166
+ });
167
+ }
168
+ },
169
+ async isRevoked(id) {
170
+ await maybeCleanup();
171
+ try {
172
+ const db = useDatabase(undefined, params.connection);
173
+ const row = await db
174
+ .table(params.table)
175
+ .where('jti', '=', id)
176
+ .first();
177
+ if (!row)
178
+ return false;
179
+ const expiresAt = row['expires_at_ms'];
180
+ const expiresAtMs = typeof expiresAt === 'number' ? expiresAt : Number(expiresAt);
181
+ if (!Number.isFinite(expiresAtMs))
182
+ return true;
183
+ if (expiresAtMs <= Date.now()) {
184
+ await db.table(params.table).where('jti', '=', id).delete();
185
+ return false;
186
+ }
187
+ return true;
188
+ }
189
+ catch (error) {
190
+ logWarnBestEffort('TokenRevocation database check failed (treating as not revoked)', {
191
+ error: error instanceof Error ? error.message : String(error),
192
+ table: params.table,
193
+ });
194
+ return false;
195
+ }
196
+ },
197
+ };
198
+ };
199
+ const createRedisStore = (params) => {
200
+ const client = createRedisConnection({
201
+ host: Env.REDIS_HOST,
202
+ port: Env.REDIS_PORT,
203
+ password: Env.REDIS_PASSWORD,
204
+ db: Env.getInt('JWT_REVOCATION_REDIS_DB', Env.REDIS_DB),
205
+ });
206
+ return {
207
+ async revoke(key) {
208
+ const ttlMs = Math.max(0, key.expiresAtMs - Date.now());
209
+ if (ttlMs === 0)
210
+ return;
211
+ await client.set(`${params.keyPrefix}${key.id}`, '1', 'PX', ttlMs);
212
+ },
213
+ async isRevoked(id) {
214
+ const value = await client.get(`${params.keyPrefix}${id}`);
215
+ return value !== null;
216
+ },
217
+ };
218
+ };
219
+ const createKvStore = (params) => {
220
+ const getKvOrThrow = () => {
221
+ const kv = Cloudflare.getKVBinding(params.bindingName);
222
+ if (kv === null) {
223
+ throw ErrorFactory.createConfigError(`KV binding '${params.bindingName}' not found`, {
224
+ bindingName: params.bindingName,
225
+ });
226
+ }
227
+ return kv;
228
+ };
229
+ return {
230
+ async revoke(key) {
231
+ const ttlMs = Math.max(0, key.expiresAtMs - Date.now());
232
+ if (ttlMs === 0)
233
+ return;
234
+ const ttlSeconds = Math.max(60, Math.ceil(ttlMs / 1000));
235
+ const kv = getKvOrThrow();
236
+ await kv.put(`${params.keyPrefix}${key.id}`, '1', { expirationTtl: ttlSeconds });
237
+ },
238
+ async isRevoked(id) {
239
+ const kv = getKvOrThrow();
240
+ const value = await kv.get(`${params.keyPrefix}${id}`);
241
+ return value !== null;
242
+ },
243
+ };
244
+ };
245
+ const kvRemoteGetProxySettings = () => ({
246
+ baseUrl: Env.get('KV_REMOTE_URL'),
247
+ keyId: Env.get('KV_REMOTE_KEY_ID'),
248
+ secret: Env.get('KV_REMOTE_SECRET', Env.APP_KEY),
249
+ timeoutMs: Env.getInt('ZT_PROXY_TIMEOUT_MS', Env.REQUEST_TIMEOUT),
250
+ });
251
+ const kvRemoteGetCloudflareCreds = () => ({
252
+ accountId: Env.get('KV_ACCOUNT_ID', Env.get('CLOUDFLARE_ACCOUNT_ID', '')).trim(),
253
+ apiToken: Env.get('KV_API_TOKEN', Env.get('CLOUDFLARE_API_TOKEN', '')).trim(),
254
+ namespaceId: Env.get('KV_NAMESPACE_ID', Env.get('CLOUDFLARE_KV_NAMESPACE_ID', '')).trim(),
255
+ namespaceTitle: Env.get('KV_NAMESPACE', '').trim(),
256
+ });
257
+ const kvRemoteHasCloudflareApiCreds = (getCreds) => {
258
+ const creds = getCreds();
259
+ return creds.accountId !== '' && creds.apiToken !== '';
260
+ };
261
+ const kvRemoteHasProxySigningCreds = (proxy) => proxy.keyId.trim() !== '' && proxy.secret.trim() !== '';
262
+ const kvRemoteBuildCloudflareValueUrl = (creds, key, ttlSeconds) => {
263
+ const base = `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(creds.accountId)}/storage/kv/namespaces/${encodeURIComponent(creds.namespaceId)}/values/${encodeURIComponent(key)}`;
264
+ if (ttlSeconds === undefined)
265
+ return base;
266
+ const ttl = Math.max(60, Math.floor(ttlSeconds));
267
+ return ttl > 0 ? `${base}?expiration_ttl=${ttl}` : base;
268
+ };
269
+ const kvRemoteCfFetch = async (apiToken, url, init) => {
270
+ const headers = new Headers(init.headers);
271
+ headers.set('Authorization', `Bearer ${apiToken}`);
272
+ return fetch(url, {
273
+ ...init,
274
+ headers,
275
+ });
276
+ };
277
+ const kvRemoteFetchCloudflareNamespacesPage = async (args) => {
278
+ const url = `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(args.accountId)}/storage/kv/namespaces?page=${args.page}&per_page=${args.perPage}`;
279
+ const res = await args.cfFetch(args.apiToken, url, { method: 'GET' });
280
+ const text = await res.text();
281
+ if (!res.ok) {
282
+ throw ErrorFactory.createConnectionError(`Cloudflare KV namespaces list failed (${res.status})`, {
283
+ status: res.status,
284
+ body: text,
285
+ });
286
+ }
287
+ try {
288
+ return JSON.parse(text);
30
289
  }
31
290
  catch {
32
- // ignore decode errors; fallback to default TTL
291
+ throw ErrorFactory.createConnectionError('Cloudflare KV namespaces list returned invalid JSON', {
292
+ body: text,
293
+ });
33
294
  }
34
- return Date.now() + defaultTtlMs;
295
+ };
296
+ const kvRemoteResolveNamespaceIdFromPage = (parsed, title) => {
297
+ const found = (parsed.result ?? []).find((ns) => ns.title === title);
298
+ return typeof found?.id === 'string' ? found.id.trim() : '';
299
+ };
300
+ const kvRemoteResolveTotalPagesFromPage = (parsed) => {
301
+ const raw = Number(parsed.result_info?.total_pages ?? 1);
302
+ return Number.isFinite(raw) ? Math.max(1, Math.floor(raw)) : 1;
303
+ };
304
+ const kvRemoteFindNamespaceIdByTitle = async (args) => {
305
+ const perPage = 100;
306
+ const first = await kvRemoteFetchCloudflareNamespacesPage({
307
+ apiToken: args.apiToken,
308
+ accountId: args.accountId,
309
+ page: 1,
310
+ perPage,
311
+ cfFetch: args.cfFetch,
312
+ });
313
+ const firstId = kvRemoteResolveNamespaceIdFromPage(first, args.namespaceTitle);
314
+ if (firstId !== '')
315
+ return firstId;
316
+ const maxPages = Math.min(10, kvRemoteResolveTotalPagesFromPage(first));
317
+ if (maxPages <= 1)
318
+ return null;
319
+ const remainingPages = Array.from({ length: maxPages - 1 }, (_, i) => i + 2);
320
+ const out = await Promise.all(remainingPages.map(async (page) => kvRemoteFetchCloudflareNamespacesPage({
321
+ apiToken: args.apiToken,
322
+ accountId: args.accountId,
323
+ page,
324
+ perPage,
325
+ cfFetch: args.cfFetch,
326
+ })));
327
+ for (const page of out) {
328
+ const id = kvRemoteResolveNamespaceIdFromPage(page, args.namespaceTitle);
329
+ if (id !== '')
330
+ return id;
331
+ }
332
+ return null;
333
+ };
334
+ const createKvRemoteCloudflareNamespaceIdResolver = (args) => {
335
+ let cachedNamespaceId = null;
336
+ let cachedNamespaceTitle = null;
337
+ let cachedAccountId = null;
338
+ return async () => {
339
+ const creds = args.getCloudflareCreds();
340
+ if (creds.namespaceId !== '')
341
+ return creds.namespaceId;
342
+ if (cachedNamespaceId !== null &&
343
+ cachedNamespaceTitle === creds.namespaceTitle &&
344
+ cachedAccountId === creds.accountId) {
345
+ return cachedNamespaceId;
346
+ }
347
+ if (creds.namespaceTitle === '') {
348
+ throw ErrorFactory.createConfigError('Cloudflare KV namespace id is missing (KV_NAMESPACE_ID) and no namespace title is provided (KV_NAMESPACE)');
349
+ }
350
+ const resolved = await kvRemoteFindNamespaceIdByTitle({
351
+ apiToken: creds.apiToken,
352
+ accountId: creds.accountId,
353
+ namespaceTitle: creds.namespaceTitle,
354
+ cfFetch: args.cfFetch,
355
+ });
356
+ if (resolved === null) {
357
+ throw ErrorFactory.createConfigError('Cloudflare KV namespace not found', {
358
+ namespaceTitle: creds.namespaceTitle,
359
+ });
360
+ }
361
+ cachedNamespaceId = resolved;
362
+ cachedNamespaceTitle = creds.namespaceTitle;
363
+ cachedAccountId = creds.accountId;
364
+ return resolved;
365
+ };
366
+ };
367
+ const kvRemoteCreateRemoteSettings = (proxy) => ({
368
+ baseUrl: proxy.baseUrl,
369
+ keyId: proxy.keyId,
370
+ secret: proxy.secret,
371
+ timeoutMs: proxy.timeoutMs,
372
+ signaturePathPrefixToStrip: resolveSigningPrefix(proxy.baseUrl),
373
+ missingUrlMessage: 'KV remote proxy URL is missing (KV_REMOTE_URL)',
374
+ missingCredentialsMessage: 'KV remote signing credentials are missing (KV_REMOTE_KEY_ID / KV_REMOTE_SECRET)',
375
+ messages: {
376
+ unauthorized: 'KV remote proxy unauthorized',
377
+ forbidden: 'KV remote proxy forbidden',
378
+ rateLimited: 'KV remote proxy rate limited',
379
+ rejected: 'KV remote proxy rejected request',
380
+ error: 'KV remote proxy error',
381
+ timedOut: 'KV remote proxy request timed out',
382
+ },
383
+ });
384
+ const kvRemoteNormalizeNamespace = (value) => {
385
+ const trimmed = value.trim();
386
+ return trimmed === '' ? undefined : trimmed;
387
+ };
388
+ const kvRemoteIsRevokedViaCloudflareApi = async (ctx, id, meta) => {
389
+ const creds = ctx.getCloudflareCreds();
390
+ const namespaceId = await ctx.resolveCloudflareNamespaceId();
391
+ const url = ctx.buildCloudflareValueUrl({ accountId: creds.accountId, namespaceId }, `${ctx.keyPrefix}${id}`);
392
+ const res = await ctx.cfFetch(creds.apiToken, url, { method: 'GET' });
393
+ if (res.status === 404)
394
+ return false;
395
+ if (!res.ok) {
396
+ const text = await res.text();
397
+ const warnMeta = {
398
+ status: res.status,
399
+ body: text,
400
+ };
401
+ if (meta)
402
+ Object.assign(warnMeta, meta);
403
+ logWarnBestEffort('TokenRevocation kv-remote (Cloudflare API) check failed', warnMeta);
404
+ return false;
405
+ }
406
+ const value = await res.text();
407
+ return value.trim() !== '';
408
+ };
409
+ const kvRemoteIsRevokedViaProxy = async (ctx, proxy, id) => {
410
+ const remote = ctx.createRemoteSettings(proxy);
411
+ const out = await RemoteSignedJson.request(remote, '/zin/kv/get', {
412
+ namespace: ctx.normalizeNamespace(ctx.namespace),
413
+ key: `${ctx.keyPrefix}${id}`,
414
+ type: 'text',
415
+ });
416
+ return out.value !== null && out.value !== undefined && String(out.value).trim() !== '';
417
+ };
418
+ const kvRemoteRevokeViaCloudflareApi = async (ctx, key, ttlSeconds, meta) => {
419
+ const creds = ctx.getCloudflareCreds();
420
+ const namespaceId = await ctx.resolveCloudflareNamespaceId();
421
+ const url = ctx.buildCloudflareValueUrl({ accountId: creds.accountId, namespaceId }, `${ctx.keyPrefix}${key.id}`, ttlSeconds);
422
+ const res = await ctx.cfFetch(creds.apiToken, url, {
423
+ method: 'PUT',
424
+ headers: { 'content-type': 'text/plain' },
425
+ body: '1',
426
+ });
427
+ if (res.ok)
428
+ return;
429
+ const text = await res.text();
430
+ const warnMeta = {
431
+ status: res.status,
432
+ body: text,
433
+ };
434
+ if (meta)
435
+ Object.assign(warnMeta, meta);
436
+ logWarnBestEffort('TokenRevocation kv-remote (Cloudflare API) revoke failed', warnMeta);
437
+ };
438
+ const createKvRemoteRevoke = (ctx) => async (key) => {
439
+ const ttlMs = Math.max(0, key.expiresAtMs - Date.now());
440
+ if (ttlMs === 0)
441
+ return;
442
+ const ttlSeconds = Math.max(60, Math.ceil(ttlMs / 1000));
443
+ const proxy = ctx.getProxySettings();
444
+ const shouldUseCloudflareApiFirst = !ctx.hasProxySigningCreds(proxy) && ctx.hasCloudflareApiCreds();
445
+ if (shouldUseCloudflareApiFirst) {
446
+ await kvRemoteRevokeViaCloudflareApi(ctx, key, ttlSeconds);
447
+ return;
448
+ }
449
+ try {
450
+ const remote = ctx.createRemoteSettings(proxy);
451
+ await RemoteSignedJson.request(remote, '/zin/kv/put', {
452
+ namespace: ctx.normalizeNamespace(ctx.namespace),
453
+ key: `${ctx.keyPrefix}${key.id}`,
454
+ value: '1',
455
+ ttlSeconds,
456
+ });
457
+ }
458
+ catch (error) {
459
+ if (ctx.hasCloudflareApiCreds()) {
460
+ await kvRemoteRevokeViaCloudflareApi(ctx, key, ttlSeconds, {
461
+ proxyError: error instanceof Error ? error.message : String(error),
462
+ });
463
+ return;
464
+ }
465
+ throw error;
466
+ }
467
+ };
468
+ const createKvRemoteIsRevoked = (ctx) => async (id) => {
469
+ const proxy = ctx.getProxySettings();
470
+ const shouldUseCloudflareApiFirst = !ctx.hasProxySigningCreds(proxy) && ctx.hasCloudflareApiCreds();
471
+ if (shouldUseCloudflareApiFirst)
472
+ return kvRemoteIsRevokedViaCloudflareApi(ctx, id);
473
+ try {
474
+ return await kvRemoteIsRevokedViaProxy(ctx, proxy, id);
475
+ }
476
+ catch (error) {
477
+ if (ctx.hasCloudflareApiCreds()) {
478
+ return kvRemoteIsRevokedViaCloudflareApi(ctx, id, {
479
+ proxyError: error instanceof Error ? error.message : String(error),
480
+ });
481
+ }
482
+ throw error;
483
+ }
484
+ };
485
+ const createKvRemoteStore = (params) => {
486
+ const getCloudflareCreds = kvRemoteGetCloudflareCreds;
487
+ const cfFetch = kvRemoteCfFetch;
488
+ const resolveCloudflareNamespaceId = createKvRemoteCloudflareNamespaceIdResolver({
489
+ getCloudflareCreds,
490
+ cfFetch,
491
+ });
492
+ const ctx = {
493
+ keyPrefix: params.keyPrefix,
494
+ namespace: params.namespace,
495
+ getProxySettings: kvRemoteGetProxySettings,
496
+ getCloudflareCreds,
497
+ hasCloudflareApiCreds: () => kvRemoteHasCloudflareApiCreds(getCloudflareCreds),
498
+ hasProxySigningCreds: kvRemoteHasProxySigningCreds,
499
+ buildCloudflareValueUrl: kvRemoteBuildCloudflareValueUrl,
500
+ cfFetch,
501
+ resolveCloudflareNamespaceId,
502
+ createRemoteSettings: kvRemoteCreateRemoteSettings,
503
+ normalizeNamespace: kvRemoteNormalizeNamespace,
504
+ };
505
+ return {
506
+ revoke: createKvRemoteRevoke(ctx),
507
+ isRevoked: createKvRemoteIsRevoked(ctx),
508
+ };
509
+ };
510
+ let cachedStore = null;
511
+ let cachedDriver = null;
512
+ const resolveStore = () => {
513
+ const driver = normalizeDriverName(Env.get('JWT_REVOCATION_DRIVER', DEFAULTS.driver));
514
+ if (cachedStore !== null && cachedDriver === driver) {
515
+ return { driver, store: cachedStore };
516
+ }
517
+ if (driver === 'memory') {
518
+ cachedStore = createMemoryStore();
519
+ cachedDriver = driver;
520
+ return { driver, store: cachedStore };
521
+ }
522
+ if (driver === 'database') {
523
+ const connection = Env.get('JWT_REVOCATION_DB_CONNECTION', DEFAULTS.dbConnection);
524
+ const table = Env.get('JWT_REVOCATION_DB_TABLE', DEFAULTS.dbTable);
525
+ cachedStore = createDatabaseStore({ connection, table });
526
+ cachedDriver = driver;
527
+ return { driver, store: cachedStore };
528
+ }
529
+ if (driver === 'redis') {
530
+ const keyPrefix = Env.get('JWT_REVOCATION_REDIS_PREFIX', DEFAULTS.redisPrefix);
531
+ cachedStore = createRedisStore({ keyPrefix });
532
+ cachedDriver = driver;
533
+ return { driver, store: cachedStore };
534
+ }
535
+ if (driver === 'kv-remote') {
536
+ const keyPrefix = Env.get('JWT_REVOCATION_KV_PREFIX', DEFAULTS.redisPrefix);
537
+ const namespace = Env.get('KV_REMOTE_NAMESPACE', DEFAULTS.kvRemoteNamespace);
538
+ cachedStore = createKvRemoteStore({ keyPrefix, namespace });
539
+ cachedDriver = driver;
540
+ return { driver, store: cachedStore };
541
+ }
542
+ const bindingName = Env.get('JWT_REVOCATION_KV_BINDING', DEFAULTS.kvBinding);
543
+ const keyPrefix = Env.get('JWT_REVOCATION_KV_PREFIX', DEFAULTS.redisPrefix);
544
+ cachedStore = createKvStore({ bindingName, keyPrefix });
545
+ cachedDriver = driver;
546
+ return { driver, store: cachedStore };
35
547
  };
36
548
  export const TokenRevocation = Object.freeze({
37
- revoke(header) {
549
+ /**
550
+ * Mark a token as revoked.
551
+ *
552
+ * Storage is keyed by JWT `jti` when present; otherwise falls back to the raw token string.
553
+ */
554
+ async revoke(header) {
38
555
  const token = getBearerToken(header);
39
556
  if (token === null)
40
557
  return null;
41
- cleanupExpired();
42
- revokedTokens.set(token, resolveExpiryMs(token));
558
+ const { store } = resolveStore();
559
+ const key = resolveKey(token);
560
+ await store.revoke(key);
43
561
  return token;
44
562
  },
45
- isRevoked(token) {
46
- cleanupExpired();
47
- const expiresAt = revokedTokens.get(token);
48
- if (expiresAt === undefined)
49
- return false;
50
- if (expiresAt <= Date.now()) {
51
- revokedTokens.delete(token);
52
- return false;
53
- }
54
- return true;
563
+ /**
564
+ * Check if a token is revoked.
565
+ */
566
+ async isRevoked(token) {
567
+ const { store } = resolveStore();
568
+ const key = resolveKey(token);
569
+ return store.isRevoked(key.id);
570
+ },
571
+ /**
572
+ * For observability.
573
+ */
574
+ getDriver() {
575
+ return resolveStore().driver;
576
+ },
577
+ /**
578
+ * Test/boot helper: reset cached driver.
579
+ */
580
+ _resetForTests() {
581
+ cachedStore = null;
582
+ cachedDriver = null;
55
583
  },
56
584
  });
57
585
  export default TokenRevocation;
@@ -148,9 +148,17 @@ async function register(req: IRequest, res: IResponse): Promise<void> {
148
148
  password: passwordHash,
149
149
  });
150
150
 
151
- if (result.id !== null && result.id !== undefined) {
151
+ let insertedUserId: unknown = result.id;
152
+ if (insertedUserId === null || insertedUserId === undefined) {
153
+ const inserted = await User.where('email', '=', email).limit(1).first<UserRow>();
154
+ if (inserted?.id !== null && inserted?.id !== undefined) {
155
+ insertedUserId = inserted.id;
156
+ }
157
+ }
158
+
159
+ if (insertedUserId !== null && insertedUserId !== undefined) {
152
160
  Logger.info('AuthController.register: successful registration', {
153
- user_id: result.id,
161
+ user_id: insertedUserId,
154
162
  email,
155
163
  ip: ipAddress,
156
164
  timestamp: new Date().toISOString(),
@@ -179,7 +187,7 @@ async function register(req: IRequest, res: IResponse): Promise<void> {
179
187
  async function logout(req: IRequest, res: IResponse): Promise<void> {
180
188
  const authHeader =
181
189
  typeof req.getHeader === 'function' ? req.getHeader('authorization') : undefined;
182
- TokenRevocation.revoke(authHeader);
190
+ await TokenRevocation.revoke(authHeader);
183
191
  res.json({ message: 'Logged out' });
184
192
  }
185
193