@digimuza/saas-core 0.0.2

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 (474) hide show
  1. package/CLAUDE.md +1165 -0
  2. package/LICENSE +21 -0
  3. package/README.md +234 -0
  4. package/dist/api-keys/index.d.ts +9 -0
  5. package/dist/api-keys/index.d.ts.map +1 -0
  6. package/dist/api-keys/index.js +37 -0
  7. package/dist/api-keys/index.js.map +1 -0
  8. package/dist/api-keys/keys.d.ts +55 -0
  9. package/dist/api-keys/keys.d.ts.map +1 -0
  10. package/dist/api-keys/keys.js +92 -0
  11. package/dist/api-keys/keys.js.map +1 -0
  12. package/dist/api-keys/service.d.ts +111 -0
  13. package/dist/api-keys/service.d.ts.map +1 -0
  14. package/dist/api-keys/service.js +210 -0
  15. package/dist/api-keys/service.js.map +1 -0
  16. package/dist/audit/index.d.ts +5 -0
  17. package/dist/audit/index.d.ts.map +1 -0
  18. package/dist/audit/index.js +44 -0
  19. package/dist/audit/index.js.map +1 -0
  20. package/dist/audit/service.d.ts +88 -0
  21. package/dist/audit/service.d.ts.map +1 -0
  22. package/dist/audit/service.js +128 -0
  23. package/dist/audit/service.js.map +1 -0
  24. package/dist/auth/client.d.ts +5 -0
  25. package/dist/auth/client.d.ts.map +1 -0
  26. package/dist/auth/client.js +26 -0
  27. package/dist/auth/client.js.map +1 -0
  28. package/dist/auth/cookies.d.ts +51 -0
  29. package/dist/auth/cookies.d.ts.map +1 -0
  30. package/dist/auth/cookies.js +58 -0
  31. package/dist/auth/cookies.js.map +1 -0
  32. package/dist/auth/index.d.ts +14 -0
  33. package/dist/auth/index.d.ts.map +1 -0
  34. package/dist/auth/index.js +46 -0
  35. package/dist/auth/index.js.map +1 -0
  36. package/dist/auth/service.d.ts +67 -0
  37. package/dist/auth/service.d.ts.map +1 -0
  38. package/dist/auth/service.js +275 -0
  39. package/dist/auth/service.js.map +1 -0
  40. package/dist/auth/types.d.ts +56 -0
  41. package/dist/auth/types.d.ts.map +1 -0
  42. package/dist/auth/types.js +2 -0
  43. package/dist/auth/types.js.map +1 -0
  44. package/dist/authorization/index.d.ts +4 -0
  45. package/dist/authorization/index.d.ts.map +1 -0
  46. package/dist/authorization/index.js +24 -0
  47. package/dist/authorization/index.js.map +1 -0
  48. package/dist/authorization/service.d.ts +92 -0
  49. package/dist/authorization/service.d.ts.map +1 -0
  50. package/dist/authorization/service.js +254 -0
  51. package/dist/authorization/service.js.map +1 -0
  52. package/dist/billing/index.d.ts +16 -0
  53. package/dist/billing/index.d.ts.map +1 -0
  54. package/dist/billing/index.js +47 -0
  55. package/dist/billing/index.js.map +1 -0
  56. package/dist/billing/provider.d.ts +114 -0
  57. package/dist/billing/provider.d.ts.map +1 -0
  58. package/dist/billing/provider.js +2 -0
  59. package/dist/billing/provider.js.map +1 -0
  60. package/dist/billing/revolut.d.ts +68 -0
  61. package/dist/billing/revolut.d.ts.map +1 -0
  62. package/dist/billing/revolut.js +181 -0
  63. package/dist/billing/revolut.js.map +1 -0
  64. package/dist/billing/service.d.ts +124 -0
  65. package/dist/billing/service.d.ts.map +1 -0
  66. package/dist/billing/service.js +470 -0
  67. package/dist/billing/service.js.map +1 -0
  68. package/dist/cli/commands/dev.d.ts +43 -0
  69. package/dist/cli/commands/dev.d.ts.map +1 -0
  70. package/dist/cli/commands/dev.js +212 -0
  71. package/dist/cli/commands/dev.js.map +1 -0
  72. package/dist/cli/commands/project.d.ts +12 -0
  73. package/dist/cli/commands/project.d.ts.map +1 -0
  74. package/dist/cli/commands/project.js +49 -0
  75. package/dist/cli/commands/project.js.map +1 -0
  76. package/dist/cli/docker.d.ts +50 -0
  77. package/dist/cli/docker.d.ts.map +1 -0
  78. package/dist/cli/docker.js +84 -0
  79. package/dist/cli/docker.js.map +1 -0
  80. package/dist/cli/index.d.ts +6 -0
  81. package/dist/cli/index.d.ts.map +1 -0
  82. package/dist/cli/index.js +198 -0
  83. package/dist/cli/index.js.map +1 -0
  84. package/dist/cli/output.d.ts +30 -0
  85. package/dist/cli/output.d.ts.map +1 -0
  86. package/dist/cli/output.js +66 -0
  87. package/dist/cli/output.js.map +1 -0
  88. package/dist/cli/templates.d.ts +52 -0
  89. package/dist/cli/templates.d.ts.map +1 -0
  90. package/dist/cli/templates.js +225 -0
  91. package/dist/cli/templates.js.map +1 -0
  92. package/dist/config/client.d.ts +60 -0
  93. package/dist/config/client.d.ts.map +1 -0
  94. package/dist/config/client.js +94 -0
  95. package/dist/config/client.js.map +1 -0
  96. package/dist/config/config-loader.d.ts +2 -0
  97. package/dist/config/config-loader.d.ts.map +1 -0
  98. package/dist/config/config-loader.js +2 -0
  99. package/dist/config/config-loader.js.map +1 -0
  100. package/dist/config/env.d.ts +24 -0
  101. package/dist/config/env.d.ts.map +1 -0
  102. package/dist/config/env.js +40 -0
  103. package/dist/config/env.js.map +1 -0
  104. package/dist/config/errors.d.ts +17 -0
  105. package/dist/config/errors.d.ts.map +1 -0
  106. package/dist/config/errors.js +26 -0
  107. package/dist/config/errors.js.map +1 -0
  108. package/dist/config/index.d.ts +72 -0
  109. package/dist/config/index.d.ts.map +1 -0
  110. package/dist/config/index.js +106 -0
  111. package/dist/config/index.js.map +1 -0
  112. package/dist/config/runtime.d.ts +15 -0
  113. package/dist/config/runtime.d.ts.map +1 -0
  114. package/dist/config/runtime.js +22 -0
  115. package/dist/config/runtime.js.map +1 -0
  116. package/dist/config/sections.d.ts +226 -0
  117. package/dist/config/sections.d.ts.map +1 -0
  118. package/dist/config/sections.js +141 -0
  119. package/dist/config/sections.js.map +1 -0
  120. package/dist/db/client.d.ts +43 -0
  121. package/dist/db/client.d.ts.map +1 -0
  122. package/dist/db/client.js +77 -0
  123. package/dist/db/client.js.map +1 -0
  124. package/dist/db/errors.d.ts +39 -0
  125. package/dist/db/errors.d.ts.map +1 -0
  126. package/dist/db/errors.js +67 -0
  127. package/dist/db/errors.js.map +1 -0
  128. package/dist/db/index.d.ts +10 -0
  129. package/dist/db/index.d.ts.map +1 -0
  130. package/dist/db/index.js +10 -0
  131. package/dist/db/index.js.map +1 -0
  132. package/dist/db/migrate.d.ts +21 -0
  133. package/dist/db/migrate.d.ts.map +1 -0
  134. package/dist/db/migrate.js +28 -0
  135. package/dist/db/migrate.js.map +1 -0
  136. package/dist/db/schema/_shared.d.ts +30 -0
  137. package/dist/db/schema/_shared.d.ts.map +1 -0
  138. package/dist/db/schema/_shared.js +36 -0
  139. package/dist/db/schema/_shared.js.map +1 -0
  140. package/dist/db/schema/apikeys.d.ts +263 -0
  141. package/dist/db/schema/apikeys.d.ts.map +1 -0
  142. package/dist/db/schema/apikeys.js +70 -0
  143. package/dist/db/schema/apikeys.js.map +1 -0
  144. package/dist/db/schema/authorization.d.ts +465 -0
  145. package/dist/db/schema/authorization.d.ts.map +1 -0
  146. package/dist/db/schema/authorization.js +134 -0
  147. package/dist/db/schema/authorization.js.map +1 -0
  148. package/dist/db/schema/billing.d.ts +1100 -0
  149. package/dist/db/schema/billing.d.ts.map +1 -0
  150. package/dist/db/schema/billing.js +223 -0
  151. package/dist/db/schema/billing.js.map +1 -0
  152. package/dist/db/schema/events.d.ts +161 -0
  153. package/dist/db/schema/events.d.ts.map +1 -0
  154. package/dist/db/schema/events.js +66 -0
  155. package/dist/db/schema/events.js.map +1 -0
  156. package/dist/db/schema/features.d.ts +243 -0
  157. package/dist/db/schema/features.d.ts.map +1 -0
  158. package/dist/db/schema/features.js +87 -0
  159. package/dist/db/schema/features.js.map +1 -0
  160. package/dist/db/schema/files.d.ts +253 -0
  161. package/dist/db/schema/files.d.ts.map +1 -0
  162. package/dist/db/schema/files.js +74 -0
  163. package/dist/db/schema/files.js.map +1 -0
  164. package/dist/db/schema/index.d.ts +38 -0
  165. package/dist/db/schema/index.d.ts.map +1 -0
  166. package/dist/db/schema/index.js +38 -0
  167. package/dist/db/schema/index.js.map +1 -0
  168. package/dist/db/schema/invitations.d.ts +214 -0
  169. package/dist/db/schema/invitations.d.ts.map +1 -0
  170. package/dist/db/schema/invitations.js +80 -0
  171. package/dist/db/schema/invitations.js.map +1 -0
  172. package/dist/db/schema/messaging.d.ts +442 -0
  173. package/dist/db/schema/messaging.d.ts.map +1 -0
  174. package/dist/db/schema/messaging.js +120 -0
  175. package/dist/db/schema/messaging.js.map +1 -0
  176. package/dist/db/schema/users.d.ts +246 -0
  177. package/dist/db/schema/users.d.ts.map +1 -0
  178. package/dist/db/schema/users.js +60 -0
  179. package/dist/db/schema/users.js.map +1 -0
  180. package/dist/db/schema/webhooks.d.ts +693 -0
  181. package/dist/db/schema/webhooks.d.ts.map +1 -0
  182. package/dist/db/schema/webhooks.js +147 -0
  183. package/dist/db/schema/webhooks.js.map +1 -0
  184. package/dist/db/schema/workspaces.d.ts +196 -0
  185. package/dist/db/schema/workspaces.d.ts.map +1 -0
  186. package/dist/db/schema/workspaces.js +57 -0
  187. package/dist/db/schema/workspaces.js.map +1 -0
  188. package/dist/db/types.d.ts +18 -0
  189. package/dist/db/types.d.ts.map +1 -0
  190. package/dist/db/types.js +2 -0
  191. package/dist/db/types.js.map +1 -0
  192. package/dist/email/adapters.d.ts +29 -0
  193. package/dist/email/adapters.d.ts.map +1 -0
  194. package/dist/email/adapters.js +60 -0
  195. package/dist/email/adapters.js.map +1 -0
  196. package/dist/email/index.d.ts +20 -0
  197. package/dist/email/index.d.ts.map +1 -0
  198. package/dist/email/index.js +79 -0
  199. package/dist/email/index.js.map +1 -0
  200. package/dist/email/provider.d.ts +47 -0
  201. package/dist/email/provider.d.ts.map +1 -0
  202. package/dist/email/provider.js +7 -0
  203. package/dist/email/provider.js.map +1 -0
  204. package/dist/email/resend.d.ts +22 -0
  205. package/dist/email/resend.d.ts.map +1 -0
  206. package/dist/email/resend.js +51 -0
  207. package/dist/email/resend.js.map +1 -0
  208. package/dist/email/service.d.ts +55 -0
  209. package/dist/email/service.d.ts.map +1 -0
  210. package/dist/email/service.js +87 -0
  211. package/dist/email/service.js.map +1 -0
  212. package/dist/email/templates.d.ts +81 -0
  213. package/dist/email/templates.d.ts.map +1 -0
  214. package/dist/email/templates.js +84 -0
  215. package/dist/email/templates.js.map +1 -0
  216. package/dist/entitlements/index.d.ts +10 -0
  217. package/dist/entitlements/index.d.ts.map +1 -0
  218. package/dist/entitlements/index.js +28 -0
  219. package/dist/entitlements/index.js.map +1 -0
  220. package/dist/entitlements/service.d.ts +83 -0
  221. package/dist/entitlements/service.d.ts.map +1 -0
  222. package/dist/entitlements/service.js +158 -0
  223. package/dist/entitlements/service.js.map +1 -0
  224. package/dist/errors.d.ts +85 -0
  225. package/dist/errors.d.ts.map +1 -0
  226. package/dist/errors.js +95 -0
  227. package/dist/errors.js.map +1 -0
  228. package/dist/events/core-events.d.ts +120 -0
  229. package/dist/events/core-events.d.ts.map +1 -0
  230. package/dist/events/core-events.js +109 -0
  231. package/dist/events/core-events.js.map +1 -0
  232. package/dist/events/index.d.ts +15 -0
  233. package/dist/events/index.d.ts.map +1 -0
  234. package/dist/events/index.js +58 -0
  235. package/dist/events/index.js.map +1 -0
  236. package/dist/events/publisher.d.ts +46 -0
  237. package/dist/events/publisher.d.ts.map +1 -0
  238. package/dist/events/publisher.js +54 -0
  239. package/dist/events/publisher.js.map +1 -0
  240. package/dist/events/registry.d.ts +87 -0
  241. package/dist/events/registry.d.ts.map +1 -0
  242. package/dist/events/registry.js +34 -0
  243. package/dist/events/registry.js.map +1 -0
  244. package/dist/events/service.d.ts +78 -0
  245. package/dist/events/service.d.ts.map +1 -0
  246. package/dist/events/service.js +182 -0
  247. package/dist/events/service.js.map +1 -0
  248. package/dist/features/bucket.d.ts +22 -0
  249. package/dist/features/bucket.d.ts.map +1 -0
  250. package/dist/features/bucket.js +42 -0
  251. package/dist/features/bucket.js.map +1 -0
  252. package/dist/features/index.d.ts +15 -0
  253. package/dist/features/index.d.ts.map +1 -0
  254. package/dist/features/index.js +78 -0
  255. package/dist/features/index.js.map +1 -0
  256. package/dist/features/registry.d.ts +51 -0
  257. package/dist/features/registry.d.ts.map +1 -0
  258. package/dist/features/registry.js +52 -0
  259. package/dist/features/registry.js.map +1 -0
  260. package/dist/features/service.d.ts +78 -0
  261. package/dist/features/service.d.ts.map +1 -0
  262. package/dist/features/service.js +207 -0
  263. package/dist/features/service.js.map +1 -0
  264. package/dist/files/index.d.ts +6 -0
  265. package/dist/files/index.d.ts.map +1 -0
  266. package/dist/files/index.js +64 -0
  267. package/dist/files/index.js.map +1 -0
  268. package/dist/files/service.d.ts +92 -0
  269. package/dist/files/service.d.ts.map +1 -0
  270. package/dist/files/service.js +303 -0
  271. package/dist/files/service.js.map +1 -0
  272. package/dist/index.d.ts +33 -0
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +33 -0
  275. package/dist/index.js.map +1 -0
  276. package/dist/jobs/backend.d.ts +23 -0
  277. package/dist/jobs/backend.d.ts.map +1 -0
  278. package/dist/jobs/backend.js +23 -0
  279. package/dist/jobs/backend.js.map +1 -0
  280. package/dist/jobs/index.d.ts +29 -0
  281. package/dist/jobs/index.d.ts.map +1 -0
  282. package/dist/jobs/index.js +114 -0
  283. package/dist/jobs/index.js.map +1 -0
  284. package/dist/jobs/service.d.ts +67 -0
  285. package/dist/jobs/service.d.ts.map +1 -0
  286. package/dist/jobs/service.js +139 -0
  287. package/dist/jobs/service.js.map +1 -0
  288. package/dist/jobs/types.d.ts +78 -0
  289. package/dist/jobs/types.d.ts.map +1 -0
  290. package/dist/jobs/types.js +4 -0
  291. package/dist/jobs/types.js.map +1 -0
  292. package/dist/logger/default.d.ts +7 -0
  293. package/dist/logger/default.d.ts.map +1 -0
  294. package/dist/logger/default.js +28 -0
  295. package/dist/logger/default.js.map +1 -0
  296. package/dist/logger/index.d.ts +24 -0
  297. package/dist/logger/index.d.ts.map +1 -0
  298. package/dist/logger/index.js +90 -0
  299. package/dist/logger/index.js.map +1 -0
  300. package/dist/logger/redact.d.ts +40 -0
  301. package/dist/logger/redact.d.ts.map +1 -0
  302. package/dist/logger/redact.js +178 -0
  303. package/dist/logger/redact.js.map +1 -0
  304. package/dist/logger/service.d.ts +14 -0
  305. package/dist/logger/service.d.ts.map +1 -0
  306. package/dist/logger/service.js +56 -0
  307. package/dist/logger/service.js.map +1 -0
  308. package/dist/logger/sinks.d.ts +37 -0
  309. package/dist/logger/sinks.d.ts.map +1 -0
  310. package/dist/logger/sinks.js +135 -0
  311. package/dist/logger/sinks.js.map +1 -0
  312. package/dist/logger/types.d.ts +47 -0
  313. package/dist/logger/types.d.ts.map +1 -0
  314. package/dist/logger/types.js +8 -0
  315. package/dist/logger/types.js.map +1 -0
  316. package/dist/notifications/index.d.ts +8 -0
  317. package/dist/notifications/index.d.ts.map +1 -0
  318. package/dist/notifications/index.js +72 -0
  319. package/dist/notifications/index.js.map +1 -0
  320. package/dist/notifications/service.d.ts +79 -0
  321. package/dist/notifications/service.d.ts.map +1 -0
  322. package/dist/notifications/service.js +164 -0
  323. package/dist/notifications/service.js.map +1 -0
  324. package/dist/realtime/channels.d.ts +37 -0
  325. package/dist/realtime/channels.d.ts.map +1 -0
  326. package/dist/realtime/channels.js +58 -0
  327. package/dist/realtime/channels.js.map +1 -0
  328. package/dist/realtime/index.d.ts +19 -0
  329. package/dist/realtime/index.d.ts.map +1 -0
  330. package/dist/realtime/index.js +118 -0
  331. package/dist/realtime/index.js.map +1 -0
  332. package/dist/realtime/postgres.d.ts +48 -0
  333. package/dist/realtime/postgres.d.ts.map +1 -0
  334. package/dist/realtime/postgres.js +151 -0
  335. package/dist/realtime/postgres.js.map +1 -0
  336. package/dist/realtime/service.d.ts +75 -0
  337. package/dist/realtime/service.d.ts.map +1 -0
  338. package/dist/realtime/service.js +103 -0
  339. package/dist/realtime/service.js.map +1 -0
  340. package/dist/realtime/sse.d.ts +55 -0
  341. package/dist/realtime/sse.d.ts.map +1 -0
  342. package/dist/realtime/sse.js +123 -0
  343. package/dist/realtime/sse.js.map +1 -0
  344. package/dist/realtime/transport.d.ts +52 -0
  345. package/dist/realtime/transport.d.ts.map +1 -0
  346. package/dist/realtime/transport.js +2 -0
  347. package/dist/realtime/transport.js.map +1 -0
  348. package/dist/storage/index.d.ts +18 -0
  349. package/dist/storage/index.d.ts.map +1 -0
  350. package/dist/storage/index.js +89 -0
  351. package/dist/storage/index.js.map +1 -0
  352. package/dist/storage/keys.d.ts +50 -0
  353. package/dist/storage/keys.d.ts.map +1 -0
  354. package/dist/storage/keys.js +120 -0
  355. package/dist/storage/keys.js.map +1 -0
  356. package/dist/storage/memory.d.ts +32 -0
  357. package/dist/storage/memory.d.ts.map +1 -0
  358. package/dist/storage/memory.js +84 -0
  359. package/dist/storage/memory.js.map +1 -0
  360. package/dist/storage/provider.d.ts +93 -0
  361. package/dist/storage/provider.d.ts.map +1 -0
  362. package/dist/storage/provider.js +2 -0
  363. package/dist/storage/provider.js.map +1 -0
  364. package/dist/storage/s3.d.ts +34 -0
  365. package/dist/storage/s3.d.ts.map +1 -0
  366. package/dist/storage/s3.js +175 -0
  367. package/dist/storage/s3.js.map +1 -0
  368. package/dist/storage/service.d.ts +86 -0
  369. package/dist/storage/service.d.ts.map +1 -0
  370. package/dist/storage/service.js +107 -0
  371. package/dist/storage/service.js.map +1 -0
  372. package/dist/storage/sigv4.d.ts +58 -0
  373. package/dist/storage/sigv4.d.ts.map +1 -0
  374. package/dist/storage/sigv4.js +114 -0
  375. package/dist/storage/sigv4.js.map +1 -0
  376. package/dist/streams/client.d.ts +91 -0
  377. package/dist/streams/client.d.ts.map +1 -0
  378. package/dist/streams/client.js +128 -0
  379. package/dist/streams/client.js.map +1 -0
  380. package/dist/streams/events.d.ts +68 -0
  381. package/dist/streams/events.d.ts.map +1 -0
  382. package/dist/streams/events.js +81 -0
  383. package/dist/streams/events.js.map +1 -0
  384. package/dist/streams/index.d.ts +47 -0
  385. package/dist/streams/index.d.ts.map +1 -0
  386. package/dist/streams/index.js +47 -0
  387. package/dist/streams/index.js.map +1 -0
  388. package/dist/streams/realtime.d.ts +27 -0
  389. package/dist/streams/realtime.d.ts.map +1 -0
  390. package/dist/streams/realtime.js +50 -0
  391. package/dist/streams/realtime.js.map +1 -0
  392. package/dist/streams/state.d.ts +26 -0
  393. package/dist/streams/state.d.ts.map +1 -0
  394. package/dist/streams/state.js +34 -0
  395. package/dist/streams/state.js.map +1 -0
  396. package/dist/users/index.d.ts +9 -0
  397. package/dist/users/index.d.ts.map +1 -0
  398. package/dist/users/index.js +23 -0
  399. package/dist/users/index.js.map +1 -0
  400. package/dist/users/service.d.ts +43 -0
  401. package/dist/users/service.d.ts.map +1 -0
  402. package/dist/users/service.js +113 -0
  403. package/dist/users/service.js.map +1 -0
  404. package/dist/webhooks/inbound.d.ts +70 -0
  405. package/dist/webhooks/inbound.d.ts.map +1 -0
  406. package/dist/webhooks/inbound.js +146 -0
  407. package/dist/webhooks/inbound.js.map +1 -0
  408. package/dist/webhooks/index.d.ts +12 -0
  409. package/dist/webhooks/index.d.ts.map +1 -0
  410. package/dist/webhooks/index.js +65 -0
  411. package/dist/webhooks/index.js.map +1 -0
  412. package/dist/webhooks/outgoing.d.ts +89 -0
  413. package/dist/webhooks/outgoing.d.ts.map +1 -0
  414. package/dist/webhooks/outgoing.js +375 -0
  415. package/dist/webhooks/outgoing.js.map +1 -0
  416. package/dist/webhooks/signature.d.ts +40 -0
  417. package/dist/webhooks/signature.d.ts.map +1 -0
  418. package/dist/webhooks/signature.js +77 -0
  419. package/dist/webhooks/signature.js.map +1 -0
  420. package/dist/workspaces/context.d.ts +30 -0
  421. package/dist/workspaces/context.d.ts.map +1 -0
  422. package/dist/workspaces/context.js +12 -0
  423. package/dist/workspaces/context.js.map +1 -0
  424. package/dist/workspaces/index.d.ts +5 -0
  425. package/dist/workspaces/index.d.ts.map +1 -0
  426. package/dist/workspaces/index.js +21 -0
  427. package/dist/workspaces/index.js.map +1 -0
  428. package/dist/workspaces/service.d.ts +126 -0
  429. package/dist/workspaces/service.d.ts.map +1 -0
  430. package/dist/workspaces/service.js +495 -0
  431. package/dist/workspaces/service.js.map +1 -0
  432. package/docs/README.md +71 -0
  433. package/docs/api-keys.md +184 -0
  434. package/docs/audit.md +198 -0
  435. package/docs/auth.md +196 -0
  436. package/docs/authorization.md +225 -0
  437. package/docs/billing.md +293 -0
  438. package/docs/cli.md +238 -0
  439. package/docs/config.md +163 -0
  440. package/docs/db.md +219 -0
  441. package/docs/email.md +222 -0
  442. package/docs/entitlements.md +194 -0
  443. package/docs/errors.md +158 -0
  444. package/docs/events.md +279 -0
  445. package/docs/feature-flags.md +237 -0
  446. package/docs/files.md +229 -0
  447. package/docs/jobs.md +288 -0
  448. package/docs/logger.md +269 -0
  449. package/docs/notifications.md +179 -0
  450. package/docs/publishing.md +128 -0
  451. package/docs/realtime.md +360 -0
  452. package/docs/storage.md +279 -0
  453. package/docs/streams.md +296 -0
  454. package/docs/users.md +117 -0
  455. package/docs/webhooks.md +272 -0
  456. package/docs/workspaces.md +269 -0
  457. package/drizzle/0000_init_users.sql +21 -0
  458. package/drizzle/0001_workspaces_roles_permissions.sql +86 -0
  459. package/drizzle/0002_billing_entitlements.sql +97 -0
  460. package/drizzle/0003_events.sql +17 -0
  461. package/drizzle/0004_notifications_audit.sql +64 -0
  462. package/drizzle/0005_api_keys_webhooks.sql +77 -0
  463. package/drizzle/0006_feature_flags.sql +22 -0
  464. package/drizzle/0007_files.sql +23 -0
  465. package/drizzle/meta/0000_snapshot.json +160 -0
  466. package/drizzle/meta/0001_snapshot.json +837 -0
  467. package/drizzle/meta/0002_snapshot.json +1580 -0
  468. package/drizzle/meta/0003_snapshot.json +1751 -0
  469. package/drizzle/meta/0004_snapshot.json +2109 -0
  470. package/drizzle/meta/0005_snapshot.json +2719 -0
  471. package/drizzle/meta/0006_snapshot.json +2909 -0
  472. package/drizzle/meta/0007_snapshot.json +3113 -0
  473. package/drizzle/meta/_journal.json +62 -0
  474. package/package.json +180 -0
@@ -0,0 +1,210 @@
1
+ import { and, desc, eq, isNull, or, sql } from "drizzle-orm";
2
+ import { apiKeys } from "../db/schema/index.js";
3
+ import { ForbiddenError, InvalidInputError, NotFoundError, UnauthorizedError } from "../errors.js";
4
+ import { unsafeWorkspaceContext } from "../workspaces/context.js";
5
+ import { DEFAULT_KEY_PREFIX, generateApiKey, maskApiKey, parseApiKey, secretMatchesHash, } from "./keys.js";
6
+ const DEFAULT_LAST_USED_THROTTLE_MS = 60_000;
7
+ const MAX_NAME_LENGTH = 120;
8
+ const MAX_SCOPES = 64;
9
+ function toSummary(row, prefix) {
10
+ return {
11
+ id: row.id,
12
+ name: row.name,
13
+ masked: maskApiKey(prefix, row.keyId),
14
+ scopes: row.scopes,
15
+ createdByUserId: row.createdByUserId,
16
+ createdAt: row.createdAt,
17
+ lastUsedAt: row.lastUsedAt,
18
+ expiresAt: row.expiresAt,
19
+ revokedAt: row.revokedAt,
20
+ };
21
+ }
22
+ export function createApiKeysService(deps) {
23
+ const now = deps.now ?? (() => new Date());
24
+ const throttleMs = deps.lastUsedThrottleMs ?? DEFAULT_LAST_USED_THROTTLE_MS;
25
+ /**
26
+ * A key's prefix is not stored — it is a property of the format, not the row.
27
+ * Reconstructing it for display means remembering which prefix was issued;
28
+ * the default is assumed unless a caller tracks its own.
29
+ */
30
+ const displayPrefix = DEFAULT_KEY_PREFIX;
31
+ const service = {
32
+ async create(context, input) {
33
+ if (input.name.trim().length === 0) {
34
+ throw new InvalidInputError("An API key name is required.");
35
+ }
36
+ if (input.name.length > MAX_NAME_LENGTH) {
37
+ throw new InvalidInputError(`An API key name may not exceed ${MAX_NAME_LENGTH} characters.`);
38
+ }
39
+ const scopes = [...new Set(input.scopes ?? [])];
40
+ if (scopes.length > MAX_SCOPES) {
41
+ throw new InvalidInputError(`An API key may not hold more than ${MAX_SCOPES} scopes.`);
42
+ }
43
+ if (scopes.some((scope) => scope.trim().length === 0)) {
44
+ throw new InvalidInputError("Scopes may not be blank.");
45
+ }
46
+ if (input.expiresAt != null && input.expiresAt.getTime() <= now().getTime()) {
47
+ throw new InvalidInputError("An API key cannot be created already expired.");
48
+ }
49
+ const generated = generateApiKey(input.prefix);
50
+ const [row] = await deps.db
51
+ .insert(apiKeys)
52
+ .values({
53
+ workspaceId: context.workspaceId,
54
+ name: input.name,
55
+ keyId: generated.keyId,
56
+ keyHash: generated.keyHash,
57
+ scopes,
58
+ createdByUserId: context.userId,
59
+ expiresAt: input.expiresAt ?? null,
60
+ })
61
+ .returning();
62
+ return {
63
+ key: toSummary(row, generated.prefix),
64
+ token: generated.token,
65
+ };
66
+ },
67
+ async list(context, options = {}) {
68
+ const clauses = [eq(apiKeys.workspaceId, context.workspaceId)];
69
+ if (options.includeRevoked !== true) {
70
+ clauses.push(isNull(apiKeys.revokedAt));
71
+ }
72
+ const rows = await deps.db
73
+ .select()
74
+ .from(apiKeys)
75
+ .where(and(...clauses))
76
+ .orderBy(desc(apiKeys.createdAt), desc(apiKeys.id));
77
+ return rows.map((row) => toSummary(row, displayPrefix));
78
+ },
79
+ async tryValidate(token) {
80
+ const parsed = parseApiKey(token);
81
+ if (parsed === undefined) {
82
+ return undefined;
83
+ }
84
+ const rows = await deps.db
85
+ .select()
86
+ .from(apiKeys)
87
+ .where(eq(apiKeys.keyId, parsed.keyId))
88
+ .limit(1);
89
+ const row = rows[0];
90
+ if (row === undefined) {
91
+ return undefined;
92
+ }
93
+ // Constant-time, so a near-miss cannot be distinguished by timing.
94
+ if (!secretMatchesHash(parsed.secret, row.keyHash)) {
95
+ return undefined;
96
+ }
97
+ if (row.revokedAt !== null) {
98
+ return undefined;
99
+ }
100
+ const at = now();
101
+ if (row.expiresAt !== null && row.expiresAt.getTime() <= at.getTime()) {
102
+ return undefined;
103
+ }
104
+ /**
105
+ * Recorded after the key is known good, and only when the stored value is
106
+ * stale — otherwise every request would write.
107
+ */
108
+ if (row.lastUsedAt === null || at.getTime() - row.lastUsedAt.getTime() >= throttleMs) {
109
+ await deps.db
110
+ .update(apiKeys)
111
+ .set({ lastUsedAt: at })
112
+ .where(and(eq(apiKeys.id, row.id),
113
+ /**
114
+ * Only if still stale. Two concurrent requests would otherwise both
115
+ * write, and the second one gains nothing.
116
+ */
117
+ or(isNull(apiKeys.lastUsedAt), sql `${apiKeys.lastUsedAt} <= ${new Date(at.getTime() - throttleMs)}`)));
118
+ }
119
+ return {
120
+ apiKeyId: row.id,
121
+ keyId: row.keyId,
122
+ workspaceId: row.workspaceId,
123
+ name: row.name,
124
+ scopes: row.scopes,
125
+ createdByUserId: row.createdByUserId,
126
+ };
127
+ },
128
+ async validate(token) {
129
+ const principal = await service.tryValidate(token);
130
+ if (principal === undefined) {
131
+ // One error for every failure mode, so a caller cannot probe.
132
+ throw new UnauthorizedError("Invalid API key.");
133
+ }
134
+ return principal;
135
+ },
136
+ async resolveContext(token) {
137
+ const principal = await service.validate(token);
138
+ if (deps.workspaces === undefined) {
139
+ throw new Error("resolveContext requires a workspaces service. Pass one to createApiKeysService.");
140
+ }
141
+ if (principal.createdByUserId === null) {
142
+ // The creator is gone, so there is no membership left to stand on.
143
+ throw new UnauthorizedError("Invalid API key.");
144
+ }
145
+ const context = await deps.workspaces.resolveContext({
146
+ userId: principal.createdByUserId,
147
+ workspaceId: principal.workspaceId,
148
+ });
149
+ if (context === undefined) {
150
+ /**
151
+ * The creator has left the workspace. A machine credential must not
152
+ * outlive the authority it was granted under — re-issue the key under a
153
+ * current member instead.
154
+ */
155
+ throw new UnauthorizedError("Invalid API key.");
156
+ }
157
+ return { context, principal };
158
+ },
159
+ async revoke(context, apiKeyId) {
160
+ const revoked = await deps.db
161
+ .update(apiKeys)
162
+ .set({ revokedAt: now(), updatedAt: now() })
163
+ .where(and(eq(apiKeys.id, apiKeyId),
164
+ // Scoped to the caller's workspace, so another tenant's key id
165
+ // matches nothing rather than being revocable.
166
+ eq(apiKeys.workspaceId, context.workspaceId), isNull(apiKeys.revokedAt)))
167
+ .returning({ id: apiKeys.id });
168
+ if (revoked.length === 0) {
169
+ /**
170
+ * Either it does not exist, belongs to another workspace, or was already
171
+ * revoked. Already-revoked is idempotent, so confirm it rather than
172
+ * failing.
173
+ */
174
+ const existing = await deps.db
175
+ .select({ id: apiKeys.id })
176
+ .from(apiKeys)
177
+ .where(and(eq(apiKeys.id, apiKeyId), eq(apiKeys.workspaceId, context.workspaceId)))
178
+ .limit(1);
179
+ if (existing.length === 0) {
180
+ throw new NotFoundError("API key not found.");
181
+ }
182
+ }
183
+ },
184
+ requireScope(principal, scope) {
185
+ if (!principal.scopes.includes(scope)) {
186
+ throw new ForbiddenError(`API key is missing the "${scope}" scope.`, {
187
+ permission: scope,
188
+ });
189
+ }
190
+ },
191
+ hasScopes(principal, scopes) {
192
+ return scopes.every((scope) => principal.scopes.includes(scope));
193
+ },
194
+ };
195
+ return service;
196
+ }
197
+ /**
198
+ * Build a context from a principal without re-checking membership.
199
+ *
200
+ * Internal escape hatch, exported because a machine-to-machine integration may
201
+ * legitimately have no user behind it at all — in which case there is no
202
+ * membership to verify and the key itself is the authority. Prefer
203
+ * `resolveContext`, which does verify.
204
+ *
205
+ * @internal
206
+ */
207
+ export function unsafeContextFromPrincipal(principal) {
208
+ return unsafeWorkspaceContext(principal.createdByUserId ?? principal.apiKeyId, principal.workspaceId);
209
+ }
210
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/api-keys/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type AuditService } from "./service.ts";
2
+ export { auditFromEvent, createAuditService, type AuditEntryInput, type AuditRequestContext, type AuditService, type AuditServiceDeps, type ListAuditOptions, } from "./service.ts";
3
+ /** Default service, bound to the configuration-driven database handle. */
4
+ export declare const audit: AuditService;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAErE,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC;AAEtB,0EAA0E;AAC1E,eAAO,MAAM,KAAK,EAAE,YAIlB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Public audit surface: `@digimuza/saas-core/audit`. Server-only.
3
+ *
4
+ * A durable, immutable record of consequential actions — who did what, to what,
5
+ * when. Distinct from `@digimuza/saas-core/events`, which is the application's
6
+ * reactive substrate: audit exists for a human reading it after the fact, during
7
+ * an incident or a compliance request.
8
+ *
9
+ * Two properties the spec demands, and how each is actually delivered:
10
+ *
11
+ * **Durable.** `audit.log()` writes synchronously to PostgreSQL. It never routes
12
+ * through realtime, an in-process handler, or a queue, because an entry that can
13
+ * be lost in transit is not an audit entry. Pass a transaction to make the record
14
+ * and the change it describes commit together.
15
+ *
16
+ * **Immutable.** There is no update or delete API — and a database trigger rejects
17
+ * both operations outright, so a migration or a stray `psql` session cannot
18
+ * quietly rewrite history either. Amending an entry means deliberately dropping
19
+ * the trigger, which is itself an auditable act.
20
+ *
21
+ * ```ts
22
+ * import { audit } from "@digimuza/saas-core/audit";
23
+ *
24
+ * await audit.log({
25
+ * action: "member.role.updated",
26
+ * actorId: user.id,
27
+ * workspaceId: context.workspaceId,
28
+ * targetType: "user",
29
+ * targetId: member.id,
30
+ * metadata: { from: "member", to: "admin" },
31
+ * request: { requestId, ipAddress, userAgent },
32
+ * });
33
+ * ```
34
+ */
35
+ import { getDatabase } from "../db/client.js";
36
+ import { createAuditService } from "./service.js";
37
+ export { auditFromEvent, createAuditService, } from "./service.js";
38
+ /** Default service, bound to the configuration-driven database handle. */
39
+ export const audit = createAuditService({
40
+ get db() {
41
+ return getDatabase();
42
+ },
43
+ });
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audit/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAqB,MAAM,cAAc,CAAC;AAErE,OAAO,EACL,cAAc,EACd,kBAAkB,GAMnB,MAAM,cAAc,CAAC;AAEtB,0EAA0E;AAC1E,MAAM,CAAC,MAAM,KAAK,GAAiB,kBAAkB,CAAC;IACpD,IAAI,EAAE;QACJ,OAAO,WAAW,EAAE,CAAC;IACvB,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,88 @@
1
+ import type { AuditLogEntry } from "../db/schema/index.ts";
2
+ import type { CoreDatabase } from "../db/types.ts";
3
+ import type { SaasEvent } from "../events/registry.ts";
4
+ import type { WorkspaceContext } from "../workspaces/context.ts";
5
+ /** Where the request came from, when a request is what caused the action. */
6
+ export interface AuditRequestContext {
7
+ /** Correlates the entry with a trace. */
8
+ readonly requestId?: string;
9
+ readonly ipAddress?: string;
10
+ readonly userAgent?: string;
11
+ }
12
+ export interface AuditEntryInput {
13
+ /** What happened, e.g. `"member.role.updated"`. Past tense, dot-separated. */
14
+ readonly action: string;
15
+ /** Who did it. Null or omitted for the system. Resolve from the session. */
16
+ readonly actorId?: string | null;
17
+ readonly workspaceId?: string | null;
18
+ readonly targetType?: string;
19
+ readonly targetId?: string;
20
+ readonly metadata?: Record<string, unknown>;
21
+ readonly request?: AuditRequestContext;
22
+ /** When it happened, if that differs from now. */
23
+ readonly occurredAt?: Date;
24
+ }
25
+ export interface ListAuditOptions {
26
+ readonly actions?: readonly string[];
27
+ readonly actorId?: string;
28
+ readonly targetType?: string;
29
+ readonly targetId?: string;
30
+ readonly since?: Date;
31
+ /** Keyset pagination: entries strictly older than this. */
32
+ readonly before?: Date;
33
+ readonly limit?: number;
34
+ }
35
+ export interface AuditService {
36
+ /**
37
+ * Record an action. Durable the moment it returns.
38
+ *
39
+ * Written straight to PostgreSQL — never through realtime, an in-process
40
+ * handler, or a queue. An audit entry that can be lost in transit is not an
41
+ * audit entry.
42
+ */
43
+ log(input: AuditEntryInput, tx?: CoreDatabase): Promise<AuditLogEntry>;
44
+ /** Record several actions in one statement. */
45
+ logMany(inputs: readonly AuditEntryInput[], tx?: CoreDatabase): Promise<AuditLogEntry[]>;
46
+ /** A workspace's trail, newest first. Requires verified membership. */
47
+ list(context: WorkspaceContext, options?: ListAuditOptions): Promise<AuditLogEntry[]>;
48
+ /**
49
+ * Entries with no workspace — account-level actions, and anything belonging to
50
+ * a workspace that has since been deleted.
51
+ *
52
+ * Not tenant-scoped, so it must be gated on an operator-level permission of
53
+ * your own. The core cannot know who is allowed to read it.
54
+ */
55
+ listPlatform(options?: ListAuditOptions): Promise<AuditLogEntry[]>;
56
+ }
57
+ export interface AuditServiceDeps {
58
+ readonly db: CoreDatabase;
59
+ readonly now?: () => Date;
60
+ }
61
+ export declare function createAuditService(deps: AuditServiceDeps): AuditService;
62
+ /**
63
+ * Translate an application event into an audit entry.
64
+ *
65
+ * Events and audit overlap but are not the same thing: events are the reactive
66
+ * substrate, audit is the human-readable trail. Recording every event would bury
67
+ * the consequential actions among the routine ones, so the mapping is explicit
68
+ * about what is worth keeping.
69
+ *
70
+ * ```ts
71
+ * events.onAny(async (event) => {
72
+ * const entry = auditFromEvent(event, {
73
+ * "workspace.member.removed": (e) => ({
74
+ * action: "member.removed",
75
+ * targetType: "user",
76
+ * targetId: e.data.userId,
77
+ * }),
78
+ * });
79
+ * if (entry !== undefined) await audit.log(entry);
80
+ * });
81
+ * ```
82
+ *
83
+ * Note the shape: audit is written from a *handler*, but a handler is not durable.
84
+ * For anything that must never be missed, call `audit.log` in the same transaction
85
+ * as the change — see `docs/audit.md`.
86
+ */
87
+ export declare function auditFromEvent(event: SaasEvent, mapping: Record<string, (event: never) => Omit<AuditEntryInput, "actorId" | "workspaceId">>): AuditEntryInput | undefined;
88
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEjE,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IAClC,yCAAyC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,kDAAkD;IAClD,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,GAAG,CAAC,KAAK,EAAE,eAAe,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAEvE,+CAA+C;IAC/C,OAAO,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,EAAE,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEzF,uEAAuE;IACvE,IAAI,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEtF;;;;;;OAMG;IACH,YAAY,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;CACpE;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AA6BD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CA4EvE;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC,GAC1F,eAAe,GAAG,SAAS,CAY7B"}
@@ -0,0 +1,128 @@
1
+ import { and, desc, eq, gte, inArray, lt } from "drizzle-orm";
2
+ import { auditLogs } from "../db/schema/index.js";
3
+ import { InvalidInputError } from "../errors.js";
4
+ const DEFAULT_LIMIT = 50;
5
+ const MAX_LIMIT = 500;
6
+ /** Bounded so one oversized blob cannot make a page of the trail unreadable. */
7
+ const MAX_ACTION_LENGTH = 120;
8
+ function toRow(input, now) {
9
+ if (input.action.trim().length === 0) {
10
+ throw new InvalidInputError("An audit action is required.");
11
+ }
12
+ if (input.action.length > MAX_ACTION_LENGTH) {
13
+ throw new InvalidInputError(`An audit action may not exceed ${MAX_ACTION_LENGTH} characters.`);
14
+ }
15
+ return {
16
+ action: input.action,
17
+ actorUserId: input.actorId ?? null,
18
+ workspaceId: input.workspaceId ?? null,
19
+ targetType: input.targetType ?? null,
20
+ targetId: input.targetId ?? null,
21
+ metadata: (input.metadata ?? null),
22
+ requestId: input.request?.requestId ?? null,
23
+ ipAddress: input.request?.ipAddress ?? null,
24
+ userAgent: input.request?.userAgent ?? null,
25
+ createdAt: input.occurredAt ?? now(),
26
+ };
27
+ }
28
+ export function createAuditService(deps) {
29
+ const now = deps.now ?? (() => new Date());
30
+ function filters(options) {
31
+ const clauses = [];
32
+ if (options.actions !== undefined && options.actions.length > 0) {
33
+ clauses.push(inArray(auditLogs.action, [...options.actions]));
34
+ }
35
+ if (options.actorId !== undefined) {
36
+ clauses.push(eq(auditLogs.actorUserId, options.actorId));
37
+ }
38
+ if (options.targetType !== undefined) {
39
+ clauses.push(eq(auditLogs.targetType, options.targetType));
40
+ }
41
+ if (options.targetId !== undefined) {
42
+ clauses.push(eq(auditLogs.targetId, options.targetId));
43
+ }
44
+ if (options.since !== undefined) {
45
+ clauses.push(gte(auditLogs.createdAt, options.since));
46
+ }
47
+ if (options.before !== undefined) {
48
+ clauses.push(lt(auditLogs.createdAt, options.before));
49
+ }
50
+ return clauses;
51
+ }
52
+ return {
53
+ async log(input, tx) {
54
+ const [entry] = await (tx ?? deps.db)
55
+ .insert(auditLogs)
56
+ .values(toRow(input, now))
57
+ .returning();
58
+ return entry;
59
+ },
60
+ async logMany(inputs, tx) {
61
+ if (inputs.length === 0) {
62
+ return [];
63
+ }
64
+ return (tx ?? deps.db)
65
+ .insert(auditLogs)
66
+ .values(inputs.map((input) => toRow(input, now)))
67
+ .returning();
68
+ },
69
+ async list(context, options = {}) {
70
+ return deps.db
71
+ .select()
72
+ .from(auditLogs)
73
+ .where(and(
74
+ // Always scoped to the verified workspace; a trail is tenant data.
75
+ eq(auditLogs.workspaceId, context.workspaceId), ...filters(options)))
76
+ // Tie-broken on id so keyset pagination cannot loop on equal timestamps.
77
+ .orderBy(desc(auditLogs.createdAt), desc(auditLogs.id))
78
+ .limit(Math.min(options.limit ?? DEFAULT_LIMIT, MAX_LIMIT));
79
+ },
80
+ async listPlatform(options = {}) {
81
+ const clauses = filters(options);
82
+ return deps.db
83
+ .select()
84
+ .from(auditLogs)
85
+ .where(clauses.length > 0 ? and(...clauses) : undefined)
86
+ .orderBy(desc(auditLogs.createdAt), desc(auditLogs.id))
87
+ .limit(Math.min(options.limit ?? DEFAULT_LIMIT, MAX_LIMIT));
88
+ },
89
+ };
90
+ }
91
+ /**
92
+ * Translate an application event into an audit entry.
93
+ *
94
+ * Events and audit overlap but are not the same thing: events are the reactive
95
+ * substrate, audit is the human-readable trail. Recording every event would bury
96
+ * the consequential actions among the routine ones, so the mapping is explicit
97
+ * about what is worth keeping.
98
+ *
99
+ * ```ts
100
+ * events.onAny(async (event) => {
101
+ * const entry = auditFromEvent(event, {
102
+ * "workspace.member.removed": (e) => ({
103
+ * action: "member.removed",
104
+ * targetType: "user",
105
+ * targetId: e.data.userId,
106
+ * }),
107
+ * });
108
+ * if (entry !== undefined) await audit.log(entry);
109
+ * });
110
+ * ```
111
+ *
112
+ * Note the shape: audit is written from a *handler*, but a handler is not durable.
113
+ * For anything that must never be missed, call `audit.log` in the same transaction
114
+ * as the change — see `docs/audit.md`.
115
+ */
116
+ export function auditFromEvent(event, mapping) {
117
+ const map = mapping[event.type];
118
+ if (map === undefined) {
119
+ return undefined;
120
+ }
121
+ return {
122
+ ...map(event),
123
+ actorId: event.actorId,
124
+ workspaceId: event.workspaceId,
125
+ occurredAt: event.occurredAt,
126
+ };
127
+ }
128
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/audit/service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAoEjD,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,SAAS,GAAG,GAAG,CAAC;AACtB,gFAAgF;AAChF,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B,SAAS,KAAK,CAAC,KAAsB,EAAE,GAAe;IACpD,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,iBAAiB,CAAC,8BAA8B,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QAC5C,MAAM,IAAI,iBAAiB,CAAC,kCAAkC,iBAAiB,cAAc,CAAC,CAAC;IACjG,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,IAAI;QACtC,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,IAAI;QACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI;QAChC,QAAQ,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,IAAI,CAAU;QAC3C,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,IAAI,IAAI;QAC3C,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,IAAI,IAAI;QAC3C,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,IAAI,IAAI;QAC3C,SAAS,EAAE,KAAK,CAAC,UAAU,IAAI,GAAG,EAAE;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAsB;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAE3C,SAAS,OAAO,CAAC,OAAyB;QACxC,MAAM,OAAO,GAAG,EAAE,CAAC;QAEnB,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE;YACjB,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;iBAClC,MAAM,CAAC,SAAS,CAAC;iBACjB,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;iBACzB,SAAS,EAAE,CAAC;YAEf,OAAO,KAAM,CAAC;QAChB,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE;YACtB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,OAAO,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;iBACnB,MAAM,CAAC,SAAS,CAAC;iBACjB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;iBAChD,SAAS,EAAE,CAAC;QACjB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE;YAC9B,OAAO,IAAI,CAAC,EAAE;iBACX,MAAM,EAAE;iBACR,IAAI,CAAC,SAAS,CAAC;iBACf,KAAK,CACJ,GAAG;YACD,mEAAmE;YACnE,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,EAC9C,GAAG,OAAO,CAAC,OAAO,CAAC,CACpB,CACF;gBACD,yEAAyE;iBACxE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;iBACtD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;QAChE,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,OAAO,GAAG,EAAE;YAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YAEjC,OAAO,IAAI,CAAC,EAAE;iBACX,MAAM,EAAE;iBACR,IAAI,CAAC,SAAS,CAAC;iBACf,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;iBACvD,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;iBACtD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAgB,EAChB,OAA2F;IAE3F,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,GAAG,CAAC,KAAc,CAAC;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,UAAU,EAAE,KAAK,CAAC,UAAU;KAC7B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { WorkOS } from "@workos-inc/node";
2
+ export declare function getWorkos(): WorkOS;
3
+ /** Drop the cached client. Test-only. */
4
+ export declare function resetWorkos(): void;
5
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAiB1C,wBAAgB,SAAS,IAAI,MAAM,CAYlC;AAED,yCAAyC;AACzC,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
@@ -0,0 +1,26 @@
1
+ import { WorkOS } from "@workos-inc/node";
2
+ import { config } from "../config/index.js";
3
+ /**
4
+ * Process-wide WorkOS client.
5
+ *
6
+ * Cached on `globalThis` for the same reason as the database handle: Next.js
7
+ * dev-mode hot reloading re-evaluates modules on every edit, and each new client
8
+ * would open its own JWKS cache and connection pool.
9
+ */
10
+ const CLIENT_KEY = Symbol.for("@digimuza/saas-core.workos");
11
+ export function getWorkos() {
12
+ const carrier = globalThis;
13
+ const existing = carrier[CLIENT_KEY];
14
+ if (existing !== undefined) {
15
+ return existing;
16
+ }
17
+ const { workosApiKey, workosClientId } = config.auth;
18
+ const client = new WorkOS(workosApiKey, { clientId: workosClientId });
19
+ carrier[CLIENT_KEY] = client;
20
+ return client;
21
+ }
22
+ /** Drop the cached client. Test-only. */
23
+ export function resetWorkos() {
24
+ delete globalThis[CLIENT_KEY];
25
+ }
26
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/auth/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;AAM5D,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,UAA2B,CAAC;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IACrD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAC;IAEtE,OAAO,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC;IAC7B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,WAAW;IACzB,OAAQ,UAA4B,CAAC,UAAU,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { CookieStore } from "./types.ts";
2
+ /**
3
+ * The shape of the Next.js App Router cookie jar, described structurally.
4
+ *
5
+ * The core does not import `next/headers`. Next has no `exports` map, so that
6
+ * specifier only resolves through a bundler — importing it would make this
7
+ * package unloadable in plain Node, where migration scripts, Trigger.dev tasks
8
+ * and tests run. Describing the jar structurally keeps Next an application
9
+ * concern and leaves the transport replaceable.
10
+ */
11
+ export interface RequestCookieJar {
12
+ get(name: string): {
13
+ value: string;
14
+ } | undefined;
15
+ set(name: string, value: string, options: NextCookieAttributes): unknown;
16
+ delete(name: string): unknown;
17
+ }
18
+ export interface NextCookieAttributes {
19
+ httpOnly?: boolean;
20
+ secure?: boolean;
21
+ sameSite?: "lax" | "strict" | "none";
22
+ path?: string;
23
+ maxAge?: number;
24
+ }
25
+ /**
26
+ * Adapt a Next.js-style cookie jar to a {@link CookieStore}.
27
+ *
28
+ * Pass the accessor itself, not the jar: Next resolves `cookies()` per request,
29
+ * so calling it once at module scope would bind every request to the first one.
30
+ *
31
+ * ```ts
32
+ * // lib/auth.ts
33
+ * import { cookies } from "next/headers";
34
+ * import { createConfiguredAuthService, createCookieStore } from "@digimuza/saas-core/auth";
35
+ *
36
+ * export const auth = createConfiguredAuthService(createCookieStore(cookies));
37
+ * ```
38
+ *
39
+ * Writes only succeed in Server Actions, Route Handlers and middleware. Next
40
+ * throws on cookie writes from Server Components; session refresh tolerates
41
+ * that, but sign-in and sign-out must run somewhere writable.
42
+ */
43
+ export declare function createCookieStore(getJar: () => RequestCookieJar | Promise<RequestCookieJar>): CookieStore;
44
+ /**
45
+ * An in-memory cookie store. Useful for tests and for non-HTTP runtimes that
46
+ * still need to hold a session for the duration of a call.
47
+ */
48
+ export declare function createMemoryCookieStore(initial?: Record<string, string>): CookieStore & {
49
+ readonly entries: Map<string, string>;
50
+ };
51
+ //# sourceMappingURL=cookies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/auth/cookies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAwB,MAAM,YAAY,CAAC;AAEpE;;;;;;;;GAQG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACjD,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;IACzE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,GACzD,WAAW,CAuBb;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GACnC,WAAW,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAazD"}