@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
package/docs/files.md ADDED
@@ -0,0 +1,229 @@
1
+ # Files
2
+
3
+ ```ts
4
+ import { files, createFilesService } from "@digimuza/saas-core/files";
5
+ ```
6
+
7
+ > Orientation and recipes: [`src/files/README.md`](../src/files/README.md).
8
+
9
+ The durable record of a stored object. Pairs with [storage](./storage.md), which
10
+ moves bytes and knows nothing about rows.
11
+
12
+ ---
13
+
14
+ ## Why the record is separate from the bytes
15
+
16
+ Direct browser uploads make it necessary. The server issues a presigned URL and the
17
+ client sends the bytes out-of-band, so:
18
+
19
+ 1. A row must exist **before** anything is stored — to reserve an id, derive a key,
20
+ and record intent.
21
+ 2. Something must **confirm** afterwards, because the server never sees the
22
+ transfer.
23
+
24
+ Hence `status`: `pending` → `ready`, or `failed`.
25
+
26
+ ## The core owns the record, not the association
27
+
28
+ A product table references `files.id` to say what a file is *for*:
29
+
30
+ ```ts
31
+ export const documents = pgTable("documents", {
32
+ id: uuid("id").defaultRandom().primaryKey(),
33
+ fileId: uuid("file_id").notNull().references(() => files.id, { onDelete: "cascade" }),
34
+ title: text("title").notNull(),
35
+ });
36
+ ```
37
+
38
+ A core table could not know whether a file is an avatar, an import or an
39
+ attachment, so it does not try.
40
+
41
+ ---
42
+
43
+ ## Direct browser upload
44
+
45
+ ### `files.createUpload(context, input)`
46
+
47
+ ```ts
48
+ function createUpload(context: WorkspaceContext, input: {
49
+ filename: string;
50
+ contentType?: string;
51
+ sizeBytes?: number; // advisory — see below
52
+ metadata?: Record<string, unknown>;
53
+ expiresInSeconds?: number; // default 900
54
+ maxBytes?: number;
55
+ }): Promise<{ file: FileRecord; uploadUrl: string }>
56
+ ```
57
+
58
+ Creates a `pending` row and returns a URL the browser can `PUT` to.
59
+
60
+ **The storage key is derived from the row id**, which is why the row is inserted
61
+ first. So a filename never becomes part of a path:
62
+
63
+ ```ts
64
+ const { file } = await files.createUpload(context, { filename: "../../etc/passwd" });
65
+ file.storageKey; // workspaces/<id>/files/<uuid>
66
+ file.filename; // "passwd"
67
+ ```
68
+
69
+ `sizeBytes` only avoids issuing a URL for something obviously too big — a presigned
70
+ `PUT` cannot enforce a size.
71
+
72
+ `fileStoragePath(fileId)` is the mapping — `files/<id>` — exported so a migration
73
+ or a reconciliation script can compute a key from a row without going through the
74
+ service.
75
+
76
+ ### `files.confirmUpload(context, fileId)`
77
+
78
+ ```ts
79
+ function confirmUpload(context: WorkspaceContext, fileId: string): Promise<FileRecord>
80
+ ```
81
+
82
+ **Asks the store.** A client reporting success is not evidence: without this you
83
+ could mark a file ready that was never uploaded, and every consumer downstream
84
+ would fail on a missing object.
85
+
86
+ | Outcome | Result |
87
+ | --- | --- |
88
+ | Object present, within limit | `ready`, with the store's **true** size |
89
+ | No object | row `failed`, throws `ConflictError` |
90
+ | Object over the limit | object **deleted**, row `failed`, throws `InvalidInputError` |
91
+ | Already `ready` | returned unchanged — idempotent |
92
+
93
+ Deleting an oversized object matters: leaving it would keep billing for bytes
94
+ nothing can reach.
95
+
96
+ It also backfills `contentType` from the store when the client declared none.
97
+
98
+ Uses the provider's optional `stat()`. A provider without it falls back to
99
+ `exists()`, which confirms presence but cannot verify size.
100
+
101
+ ---
102
+
103
+ ## Server-side upload
104
+
105
+ ### `files.upload(context, input)`
106
+
107
+ ```ts
108
+ function upload(context: WorkspaceContext, input: {
109
+ filename: string;
110
+ body: Uint8Array | string;
111
+ contentType?: string;
112
+ metadata?: Record<string, unknown>;
113
+ maxBytes?: number;
114
+ }): Promise<FileRecord>
115
+ ```
116
+
117
+ One step, `ready` immediately — and with a **checksum**, because the server saw the
118
+ bytes. A direct upload has no checksum for exactly that reason.
119
+
120
+ If the store rejects the write, the row is **deleted** rather than left `pending`:
121
+ a failed server-side upload leaves no object, so a reservation would be pure noise
122
+ in the sweep.
123
+
124
+ ### `files.findByChecksum(context, checksum)`
125
+
126
+ Deduplication. Scoped to the workspace, and only matches `ready` files.
127
+
128
+ ---
129
+
130
+ ## Reading, listing, deleting
131
+
132
+ ```ts
133
+ files.get(context, fileId): Promise<FileRecord>
134
+ files.list(context, options?): Promise<FileRecord[]>
135
+ files.getUrl(context, fileId, options?): Promise<string>
136
+ files.delete(context, fileId): Promise<void>
137
+ ```
138
+
139
+ `list` filters by `status` (one or several), paginates with `before`, defaults to 50
140
+ and caps at 200. Newest first, tie-broken on id so keyset pagination cannot loop.
141
+
142
+ `getUrl` defaults `downloadFilename` to the stored filename, so a download is named
143
+ sensibly and served as an **attachment** — which is what makes user uploads safe to
144
+ hand back. See [storage](./storage.md#urls). It throws `ConflictError` for a file
145
+ that is not `ready`, because there is no object behind it and the URL would 404.
146
+
147
+ `delete` removes the **object first, then the row**. The other order would orphan
148
+ the object on failure: unreachable, and still billed. There is a test asserting the
149
+ row survives when the store delete fails.
150
+
151
+ Every method takes a verified `WorkspaceContext` and scopes on it, so another
152
+ tenant's file id is simply not found.
153
+
154
+ ---
155
+
156
+ ## `files.purgeAbandoned(options?)`
157
+
158
+ ```ts
159
+ function purgeAbandoned(options?: { olderThan?: Date; limit?: number }): Promise<number>
160
+ ```
161
+
162
+ A presigned URL that is never used leaves a `pending` row forever. Run this from a
163
+ scheduled job:
164
+
165
+ ```ts
166
+ export const sweepFiles = schedules.task({
167
+ id: "sweep-files",
168
+ cron: "0 * * * *",
169
+ run: () => files.purgeAbandoned(),
170
+ });
171
+ ```
172
+
173
+ Deletes the object unconditionally first — a reservation may have a half-finished
174
+ object behind it. If the store delete fails, the **row is kept** so the next sweep
175
+ retries rather than losing the record.
176
+
177
+ Default cutoff is 24 hours, comfortably beyond any upload URL's lifetime.
178
+
179
+ > **Two clocks.** `created_at` defaults to PostgreSQL's `now()`, while the default
180
+ > cutoff uses the service's injected clock. A day of slack makes any realistic skew
181
+ > between an application server and the database irrelevant — pass `olderThan` if
182
+ > you need it exact.
183
+
184
+ ---
185
+
186
+ ## `sanitizeFilename(filename)`
187
+
188
+ The filename never becomes part of a key, so this is **not** a traversal defence.
189
+ It exists because the value is displayed and put in a `Content-Disposition` header:
190
+
191
+ - keeps only the leaf, so `C:\Users\me\report.pdf` becomes `report.pdf`
192
+ - strips control characters, which can break a header
193
+ - strips leading dots
194
+ - caps at 255 characters, so it cannot break every UI that renders it
195
+ - throws when nothing usable remains
196
+
197
+ ---
198
+
199
+ ## Lifecycle
200
+
201
+ | Deleted | Effect |
202
+ | --- | --- |
203
+ | Workspace | file rows cascade away |
204
+ | Uploading user | `uploaded_by_user_id` set null; the file survives |
205
+
206
+ The file outliving its uploader is deliberate — a departing employee's uploads
207
+ belong to the workspace, not to them.
208
+
209
+ Note that deleting a *row* directly (a cascade, or your own SQL) does **not**
210
+ remove the object. Delete through `files.delete` where you can; for a cascade,
211
+ reconcile with `purgeAbandoned`-style sweeping of your own.
212
+
213
+ ---
214
+
215
+ ## Testing
216
+
217
+ ```ts
218
+ const provider = createMemoryStorageProvider();
219
+ const files = createFilesService({
220
+ db,
221
+ storage: createStorageService({ provider }),
222
+ maxBytes: 1024,
223
+ now: () => fixedClock,
224
+ });
225
+
226
+ const { file } = await files.createUpload(context, { filename: "a.csv" });
227
+ await provider.put({ key: file.storageKey, body: "a,b,c" }); // stand in for the browser
228
+ expect((await files.confirmUpload(context, file.id)).sizeBytes).toBe(5);
229
+ ```
package/docs/jobs.md ADDED
@@ -0,0 +1,288 @@
1
+ # Background jobs
2
+
3
+ ```ts
4
+ import { jobs, task, configureJobs } from "@digimuza/saas-core/jobs";
5
+ import type { JobPayload } from "@digimuza/saas-core/jobs";
6
+ ```
7
+
8
+ > Orientation and recipes: [`src/jobs/README.md`](../src/jobs/README.md).
9
+
10
+
11
+ Trigger.dev owns durable execution — retries, scheduling, cron, waits, concurrency,
12
+ multi-step workflows and run observability. The core reimplements none of it and
13
+ **stores no run state**: a `job_runs` table would be a second, always-slightly-wrong
14
+ copy of what Trigger.dev already knows.
15
+
16
+ What the core adds is exactly two things:
17
+
18
+ 1. **Tenant attribution.** A job outlives the request that queued it, so the
19
+ workspace travels with it.
20
+ 2. **Application events.** `job.started` / `.progress` / `.completed` / `.failed`,
21
+ so the rest of the system can react.
22
+
23
+ Everything else is Trigger.dev's, and the SDK is re-exported rather than wrapped,
24
+ so advanced use is never blocked.
25
+
26
+ ---
27
+
28
+ ## Install and configure
29
+
30
+ `@trigger.dev/sdk` is an **optional peer dependency**. Install it in your
31
+ application — an app defines its tasks against the same SDK instance the core
32
+ triggers through, and two copies would not share task registries.
33
+
34
+ ```bash
35
+ npm install @trigger.dev/sdk
36
+ ```
37
+
38
+ ```ts
39
+ import { configureJobs } from "@digimuza/saas-core/jobs";
40
+
41
+ await configureJobs(); // once at startup
42
+ ```
43
+
44
+ This points the SDK at the Infisical-injected `TRIGGER_SECRET_KEY` and
45
+ `TRIGGER_API_URL`. Without it the SDK reads the environment itself, which works but
46
+ bypasses the validation every other config section gets.
47
+
48
+ ---
49
+
50
+ ## `jobs.trigger(taskId, data, options)`
51
+
52
+ ```ts
53
+ function trigger<TData>(taskId: string, data: TData, options: {
54
+ workspaceId: string;
55
+ actorId?: string | null;
56
+ idempotencyKey?: string | string[];
57
+ idempotencyKeyTTL?: string;
58
+ maxAttempts?: number;
59
+ queue?: string;
60
+ concurrencyKey?: string;
61
+ delay?: string | Date;
62
+ ttl?: string | number;
63
+ priority?: number;
64
+ tags?: string[];
65
+ metadata?: Record<string, unknown>;
66
+ }): Promise<{ runId: string; taskId: string }>
67
+ ```
68
+
69
+ ```ts
70
+ const handle = await jobs.trigger("resize-image", { assetId }, {
71
+ workspaceId: context.workspaceId,
72
+ actorId: user.id,
73
+ idempotencyKey: requestId,
74
+ concurrencyKey: context.workspaceId, // one tenant cannot starve another
75
+ });
76
+ ```
77
+
78
+ Three things happen beyond a plain `tasks.trigger`:
79
+
80
+ - The payload is wrapped in a `JobPayload` envelope, so your data stays untouched
81
+ under `data`. A payload with its own `tenant` field keeps working.
82
+ - The run is tagged `workspace:<id>` and `actor:<id>`, so runs are filterable per
83
+ tenant in the Trigger.dev dashboard. Caller tags are merged and de-duplicated,
84
+ since Trigger.dev counts them against a per-run limit.
85
+ - Tenancy is mirrored into run **metadata**, which is what makes a production
86
+ incident searchable back to a tenant.
87
+
88
+ `workspaceId` and `actorId` are stripped from what reaches Trigger.dev — they are
89
+ core concepts, not SDK options.
90
+
91
+ Throws `InvalidInputError` for a blank task id or workspace id.
92
+
93
+ ## `jobs.triggerSystem(taskId, data, options?)`
94
+
95
+ ```ts
96
+ function triggerSystem<TData>(taskId: string, data: TData, options?: JobTriggerOptions):
97
+ Promise<{ runId: string; taskId: string }>
98
+ ```
99
+
100
+ For work that belongs to no tenant — a nightly sweep, a catalogue sync. Sends
101
+ `tenant: null` and no tenant tags.
102
+
103
+ A separate method rather than accepting a null workspace, so forgetting to
104
+ attribute tenant work is a deliberate choice and not a typo.
105
+
106
+ ---
107
+
108
+ ## Writing a task
109
+
110
+ ```ts
111
+ import { task } from "@digimuza/saas-core/jobs";
112
+ import type { JobPayload } from "@digimuza/saas-core/jobs";
113
+ import { jobs } from "@digimuza/saas-core/jobs";
114
+ import { workspaces } from "@digimuza/saas-core/workspaces";
115
+
116
+ export const resizeImage = task({
117
+ id: "resize-image",
118
+ run: async (payload: JobPayload<{ assetId: string }>, { ctx }) => {
119
+ const reporter = jobs.reporter(
120
+ { runId: ctx.run.id, taskId: ctx.task.id },
121
+ payload.tenant,
122
+ );
123
+ await reporter.started();
124
+
125
+ // Re-verify. The payload is attribution, not authority.
126
+ const context = await workspaces.requireContext({
127
+ userId: payload.tenant.actorId!,
128
+ workspaceId: payload.tenant.workspaceId,
129
+ });
130
+
131
+ try {
132
+ await doWork(context, payload.data);
133
+ await reporter.completed();
134
+ } catch (error) {
135
+ await reporter.failed({ error, attempt: ctx.attempt.number });
136
+ throw error; // rethrow so Trigger.dev retries
137
+ }
138
+ },
139
+ });
140
+ ```
141
+
142
+ ### Always re-verify tenancy inside the task
143
+
144
+ `JobPayload.tenant` is **attribution, not authorisation**. Between queueing and
145
+ running, the workspace may have been deleted or the actor removed from it. Call
146
+ `workspaces.requireContext()` before touching tenant data — it is one indexed query
147
+ and it closes the gap.
148
+
149
+ For a system job (`tenant: null`) there is no membership to check; resolve whatever
150
+ scope the task needs explicitly.
151
+
152
+ ---
153
+
154
+ ## `jobs.reporter(run, tenant)`
155
+
156
+ ```ts
157
+ function reporter(run: { runId: string; taskId: string }, tenant: JobTenant | null): JobReporter
158
+
159
+ interface JobReporter {
160
+ started(): Promise<void>;
161
+ progress(progress: {
162
+ percent?: number; // 0-100
163
+ message?: string; // max 500 chars
164
+ step?: number;
165
+ totalSteps?: number;
166
+ }): Promise<void>;
167
+ completed(result?: { durationMs?: number }): Promise<void>;
168
+ failed(input: { error: unknown; attempt?: number }): Promise<void>;
169
+ }
170
+ ```
171
+
172
+ Emits `job.*` application events so the application can react and a browser can
173
+ watch progress. These are **not** a second source of truth — Trigger.dev already
174
+ tracks run state, and losing one of these events does not lose the run.
175
+
176
+ Deduplication is chosen per method, deliberately:
177
+
178
+ | Method | Key | Why |
179
+ | --- | --- | --- |
180
+ | `started` | run id | A Trigger.dev retry re-executes the task body; the run has not restarted. |
181
+ | `completed` | run id | One completion per run. |
182
+ | `failed` | run id + attempt | Each failed attempt is a distinct fact; a run failing twice should say so twice. |
183
+ | `progress` | none | Every tick is news. |
184
+
185
+ `completed()` computes `durationMs` from reporter construction if you do not supply
186
+ one.
187
+
188
+ `failed()` reduces any throwable to a bounded string via `describeJobError`, capped
189
+ at 2000 characters so the event schema accepts it. **Never put a secret in a task
190
+ error** — the message is persisted and readable.
191
+
192
+ ### Throttle progress
193
+
194
+ Each `progress()` call writes a row. A tight loop would turn the events table into
195
+ a firehose. Report on meaningful steps, or rate-limit to a few per second.
196
+
197
+ ### Without an event publisher
198
+
199
+ `createJobsService({ backend })` — no `events` — returns a reporter whose methods do
200
+ nothing, so a task can call it unconditionally without branching.
201
+
202
+ ---
203
+
204
+ ## The Trigger.dev SDK, re-exported
205
+
206
+ ```ts
207
+ import {
208
+ task, tasks, schemaTask, schedules, wait, retry, queue, queues,
209
+ batch, runs, tags, metadata, logger, timeout, usage, idempotencyKeys,
210
+ configureTriggerClient,
211
+ } from "@digimuza/saas-core/jobs";
212
+ ```
213
+
214
+ Deliberately unwrapped. Wrapping `task`, `schedules` or `wait` would mean
215
+ re-documenting and re-typing a mature API for no gain, and would lag behind it.
216
+
217
+ So scheduled jobs, cron, waits, multi-step workflows and concurrency controls are
218
+ all used exactly as Trigger.dev documents them:
219
+
220
+ ```ts
221
+ import { schedules } from "@digimuza/saas-core/jobs";
222
+
223
+ export const nightly = schedules.task({
224
+ id: "nightly-sweep",
225
+ cron: "0 3 * * *",
226
+ run: async () => { /* ... */ },
227
+ });
228
+ ```
229
+
230
+ Importing this module does not require credentials — there is a test asserting the
231
+ entry point loads with none set.
232
+
233
+ ---
234
+
235
+ ## Subscribing to job events
236
+
237
+ ```ts
238
+ import { events } from "@digimuza/saas-core/events";
239
+
240
+ events.on("job.progress", (event) => {
241
+ event.data.percent; // narrowed
242
+ });
243
+ ```
244
+
245
+ The intended architecture, end to end:
246
+
247
+ ```
248
+ Trigger.dev task → reporter → events table → realtime → RxJS → browser UI
249
+ ```
250
+
251
+ Realtime is Phase 8 and RxJS Phase 9; today the events are persisted and
252
+ in-process subscribers fire.
253
+
254
+ ---
255
+
256
+ ## Custom construction
257
+
258
+ ```ts
259
+ import { createJobsService, createTriggerDevBackend } from "@digimuza/saas-core/jobs";
260
+
261
+ const jobs = createJobsService({
262
+ backend: createTriggerDevBackend(),
263
+ events,
264
+ });
265
+ ```
266
+
267
+ `JobBackend` is a one-method interface, so tests pass a recorder instead of needing
268
+ a Trigger.dev account:
269
+
270
+ ```ts
271
+ const calls: unknown[] = [];
272
+ const jobs = createJobsService({
273
+ backend: {
274
+ trigger(taskId, payload, options) {
275
+ calls.push({ taskId, payload, options });
276
+ return Promise.resolve({ id: "run_1" });
277
+ },
278
+ },
279
+ });
280
+ ```
281
+
282
+ ---
283
+
284
+ ## What is not here
285
+
286
+ No Redis. PostgreSQL and Trigger.dev cover durable state and durable execution
287
+ between them; adding Redis for background jobs would be operational complexity with
288
+ nothing to show for it.