@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,92 @@
1
+ import type { CoreDatabase } from "../db/types.ts";
2
+ import { type CoreEventPublisher } from "../events/publisher.ts";
3
+ import type { Role } from "../db/schema/index.ts";
4
+ import type { WorkspaceContext } from "../workspaces/context.ts";
5
+ /**
6
+ * A permission identifier such as `"projects.create"`.
7
+ *
8
+ * Applications define their own vocabulary. Declare it with
9
+ * {@link definePermissions} to get a union type and autocompletion; the core
10
+ * itself accepts any string, because it cannot know a product's permissions.
11
+ */
12
+ export type PermissionKey = string;
13
+ export interface PermissionDefinition {
14
+ readonly key: string;
15
+ readonly description?: string;
16
+ }
17
+ export interface CreateRoleInput {
18
+ readonly key: string;
19
+ readonly name: string;
20
+ readonly description?: string;
21
+ readonly isDefault?: boolean;
22
+ readonly permissions?: readonly PermissionKey[];
23
+ }
24
+ export interface AuthorizationService {
25
+ /**
26
+ * Register the application's permission vocabulary.
27
+ *
28
+ * Idempotent, so it is safe to call on every boot or from a migration step.
29
+ * Permissions must exist before a role can be granted them.
30
+ */
31
+ registerPermissions(definitions: readonly PermissionDefinition[]): Promise<void>;
32
+ /** Every permission the user holds in this workspace: the union across their roles. */
33
+ getEffectivePermissions(context: WorkspaceContext): Promise<Set<PermissionKey>>;
34
+ /** Whether the user holds `permission` in this workspace. */
35
+ can(context: WorkspaceContext, permission: PermissionKey): Promise<boolean>;
36
+ /** True only when the user holds *every* listed permission. */
37
+ canAll(context: WorkspaceContext, required: readonly PermissionKey[]): Promise<boolean>;
38
+ /** True when the user holds *any* of the listed permissions. */
39
+ canAny(context: WorkspaceContext, required: readonly PermissionKey[]): Promise<boolean>;
40
+ /** As {@link can}, but throws {@link ForbiddenError}. */
41
+ require(context: WorkspaceContext, permission: PermissionKey): Promise<void>;
42
+ /**
43
+ * Whether the user holds a role with this key in this workspace.
44
+ *
45
+ * Prefer permissions. Role checks couple application logic to the role
46
+ * structure, so renaming or restructuring roles silently changes behaviour.
47
+ */
48
+ hasRole(context: WorkspaceContext, roleKey: string): Promise<boolean>;
49
+ /** The user's roles in this workspace. */
50
+ getRoles(context: WorkspaceContext): Promise<Role[]>;
51
+ readonly roles: {
52
+ list(context: WorkspaceContext): Promise<Role[]>;
53
+ create(context: WorkspaceContext, input: CreateRoleInput): Promise<Role>;
54
+ /** Replace a role's permission set. */
55
+ setPermissions(context: WorkspaceContext, roleId: string, keys: readonly PermissionKey[]): Promise<void>;
56
+ /** Delete a custom role. System roles are protected. */
57
+ delete(context: WorkspaceContext, roleId: string): Promise<void>;
58
+ assign(context: WorkspaceContext, input: {
59
+ userId: string;
60
+ roleId: string;
61
+ }): Promise<void>;
62
+ unassign(context: WorkspaceContext, input: {
63
+ userId: string;
64
+ roleId: string;
65
+ }): Promise<void>;
66
+ };
67
+ }
68
+ export interface AuthorizationServiceDeps {
69
+ readonly db: CoreDatabase;
70
+ /** Optional event publisher. Omit it and the service emits nothing. */
71
+ readonly events?: CoreEventPublisher;
72
+ }
73
+ export declare function createAuthorizationService(deps: AuthorizationServiceDeps): AuthorizationService;
74
+ /**
75
+ * Declare an application's permission vocabulary and get a union type for it.
76
+ *
77
+ * ```ts
78
+ * export const PERMISSIONS = definePermissions([
79
+ * "projects.read",
80
+ * "projects.create",
81
+ * ] as const);
82
+ *
83
+ * type AppPermission = (typeof PERMISSIONS)[number]; // "projects.read" | "projects.create"
84
+ * ```
85
+ *
86
+ * Purely a typing helper — it performs no I/O. Pass the same list to
87
+ * `registerPermissions()` to persist it.
88
+ */
89
+ export declare function definePermissions<const T extends readonly string[]>(keys: T): T;
90
+ /** Look up which roles in a workspace carry a given permission. */
91
+ export declare function findRolesWithPermission(db: CoreDatabase, workspaceId: string, permission: PermissionKey): Promise<Role[]>;
92
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/authorization/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,254 @@
1
+ import { and, eq, inArray } from "drizzle-orm";
2
+ import { ForbiddenError, NotFoundError } from "../errors.js";
3
+ import { isForeignKeyViolation } from "../db/errors.js";
4
+ import { permissions as permissionsTable, rolePermissions, roles, workspaceMemberRoles, } from "../db/schema/index.js";
5
+ import { EventOutbox } from "../events/publisher.js";
6
+ export function createAuthorizationService(deps) {
7
+ const outbox = () => new EventOutbox(deps.events);
8
+ /**
9
+ * Confirm a role belongs to the caller's workspace before it is used.
10
+ *
11
+ * The database rejects cross-workspace *grants* outright, but reads and
12
+ * deletes need this check so a role id from another tenant cannot be probed
13
+ * or modified.
14
+ */
15
+ async function requireOwnRole(context, roleId) {
16
+ const rows = await deps.db
17
+ .select()
18
+ .from(roles)
19
+ .where(and(eq(roles.id, roleId), eq(roles.workspaceId, context.workspaceId)))
20
+ .limit(1);
21
+ const role = rows[0];
22
+ if (role === undefined) {
23
+ throw new NotFoundError("Role not found.");
24
+ }
25
+ return role;
26
+ }
27
+ const roleAdmin = {
28
+ async list(context) {
29
+ return deps.db.select().from(roles).where(eq(roles.workspaceId, context.workspaceId));
30
+ },
31
+ async create(context, input) {
32
+ return deps.db.transaction(async (tx) => {
33
+ const [role] = await tx
34
+ .insert(roles)
35
+ .values({
36
+ workspaceId: context.workspaceId,
37
+ key: input.key,
38
+ name: input.name,
39
+ description: input.description ?? null,
40
+ isDefault: input.isDefault ?? false,
41
+ isSystem: false,
42
+ })
43
+ .returning();
44
+ if (input.permissions !== undefined && input.permissions.length > 0) {
45
+ await tx.insert(rolePermissions).values(input.permissions.map((permissionKey) => ({
46
+ roleId: role.id,
47
+ permissionKey,
48
+ })));
49
+ }
50
+ return role;
51
+ });
52
+ },
53
+ async setPermissions(context, roleId, keys) {
54
+ await requireOwnRole(context, roleId);
55
+ await deps.db.transaction(async (tx) => {
56
+ await tx.delete(rolePermissions).where(eq(rolePermissions.roleId, roleId));
57
+ if (keys.length > 0) {
58
+ await tx
59
+ .insert(rolePermissions)
60
+ .values(keys.map((permissionKey) => ({ roleId, permissionKey })));
61
+ }
62
+ });
63
+ },
64
+ async delete(context, roleId) {
65
+ const role = await requireOwnRole(context, roleId);
66
+ /**
67
+ * System roles are created with the workspace and other code assumes they
68
+ * exist — deleting `admin` would leave nobody able to administer it.
69
+ */
70
+ if (role.isSystem) {
71
+ throw new ForbiddenError("System roles cannot be deleted.");
72
+ }
73
+ await deps.db.delete(roles).where(eq(roles.id, roleId));
74
+ },
75
+ async assign(context, input) {
76
+ const events = outbox();
77
+ try {
78
+ const granted = await deps.db.transaction(async (tx) => {
79
+ const inserted = await tx
80
+ .insert(workspaceMemberRoles)
81
+ .values({
82
+ workspaceId: context.workspaceId,
83
+ userId: input.userId,
84
+ roleId: input.roleId,
85
+ })
86
+ .onConflictDoNothing()
87
+ .returning({ roleId: workspaceMemberRoles.roleId });
88
+ // Nothing inserted means the role was already held; not a change, so
89
+ // no event. Re-announcing it would make consumers act twice.
90
+ if (inserted.length === 0) {
91
+ return false;
92
+ }
93
+ await events.record({
94
+ type: "workspace.member.role.updated",
95
+ workspaceId: context.workspaceId,
96
+ actorId: context.userId,
97
+ data: { userId: input.userId, roleId: input.roleId, action: "assigned" },
98
+ }, tx);
99
+ return true;
100
+ });
101
+ if (granted) {
102
+ await events.flush();
103
+ }
104
+ }
105
+ catch (error) {
106
+ /**
107
+ * Both failures are the database enforcing tenancy: the role belongs to
108
+ * another workspace, or the user is not a member of this one. Neither
109
+ * should be reported as an unexpected error.
110
+ */
111
+ if (isForeignKeyViolation(error, "workspace_member_roles_role_fk") ||
112
+ isForeignKeyViolation(error, "workspace_member_roles_member_fk")) {
113
+ throw new NotFoundError("Role or workspace member not found.");
114
+ }
115
+ throw error;
116
+ }
117
+ },
118
+ async unassign(context, input) {
119
+ const removed = await deps.db
120
+ .delete(workspaceMemberRoles)
121
+ .where(and(eq(workspaceMemberRoles.workspaceId, context.workspaceId), eq(workspaceMemberRoles.userId, input.userId), eq(workspaceMemberRoles.roleId, input.roleId)))
122
+ .returning({ roleId: workspaceMemberRoles.roleId });
123
+ if (removed.length === 0) {
124
+ throw new NotFoundError("Role assignment not found.");
125
+ }
126
+ const events = outbox();
127
+ await events.record({
128
+ type: "workspace.member.role.updated",
129
+ workspaceId: context.workspaceId,
130
+ actorId: context.userId,
131
+ data: { userId: input.userId, roleId: input.roleId, action: "unassigned" },
132
+ }, deps.db);
133
+ await events.flush();
134
+ },
135
+ };
136
+ const service = {
137
+ async registerPermissions(definitions) {
138
+ if (definitions.length === 0) {
139
+ return;
140
+ }
141
+ await deps.db
142
+ .insert(permissionsTable)
143
+ .values(definitions.map((definition) => ({
144
+ key: definition.key,
145
+ description: definition.description ?? null,
146
+ })))
147
+ .onConflictDoUpdate({
148
+ target: permissionsTable.key,
149
+ set: { updatedAt: new Date() },
150
+ });
151
+ },
152
+ async getEffectivePermissions(context) {
153
+ /**
154
+ * A single join from the member's grants through their roles to the
155
+ * permissions those roles carry. The union is inherent: `select distinct`
156
+ * over all matching rows, so holding several roles simply widens the set.
157
+ *
158
+ * Both halves of the join to `roles` are constrained by workspace, so a
159
+ * stale grant could not contribute another tenant's permissions.
160
+ */
161
+ const rows = await deps.db
162
+ .selectDistinct({ key: rolePermissions.permissionKey })
163
+ .from(workspaceMemberRoles)
164
+ .innerJoin(roles, and(eq(roles.id, workspaceMemberRoles.roleId), eq(roles.workspaceId, workspaceMemberRoles.workspaceId)))
165
+ .innerJoin(rolePermissions, eq(rolePermissions.roleId, roles.id))
166
+ .where(and(eq(workspaceMemberRoles.workspaceId, context.workspaceId), eq(workspaceMemberRoles.userId, context.userId)));
167
+ return new Set(rows.map((row) => row.key));
168
+ },
169
+ async can(context, permission) {
170
+ const held = await service.getEffectivePermissions(context);
171
+ return held.has(permission);
172
+ },
173
+ async canAll(context, required) {
174
+ if (required.length === 0) {
175
+ return true;
176
+ }
177
+ const held = await service.getEffectivePermissions(context);
178
+ return required.every((permission) => held.has(permission));
179
+ },
180
+ async canAny(context, required) {
181
+ if (required.length === 0) {
182
+ return false;
183
+ }
184
+ const held = await service.getEffectivePermissions(context);
185
+ return required.some((permission) => held.has(permission));
186
+ },
187
+ async require(context, permission) {
188
+ if (!(await service.can(context, permission))) {
189
+ throw new ForbiddenError(`Missing permission "${permission}".`, { permission });
190
+ }
191
+ },
192
+ async hasRole(context, roleKey) {
193
+ const rows = await deps.db
194
+ .select({ id: roles.id })
195
+ .from(workspaceMemberRoles)
196
+ .innerJoin(roles, and(eq(roles.id, workspaceMemberRoles.roleId), eq(roles.workspaceId, workspaceMemberRoles.workspaceId)))
197
+ .where(and(eq(workspaceMemberRoles.workspaceId, context.workspaceId), eq(workspaceMemberRoles.userId, context.userId), eq(roles.key, roleKey)))
198
+ .limit(1);
199
+ return rows.length > 0;
200
+ },
201
+ async getRoles(context) {
202
+ return deps.db
203
+ .select({
204
+ id: roles.id,
205
+ workspaceId: roles.workspaceId,
206
+ key: roles.key,
207
+ name: roles.name,
208
+ description: roles.description,
209
+ isSystem: roles.isSystem,
210
+ isDefault: roles.isDefault,
211
+ createdAt: roles.createdAt,
212
+ updatedAt: roles.updatedAt,
213
+ })
214
+ .from(workspaceMemberRoles)
215
+ .innerJoin(roles, and(eq(roles.id, workspaceMemberRoles.roleId), eq(roles.workspaceId, workspaceMemberRoles.workspaceId)))
216
+ .where(and(eq(workspaceMemberRoles.workspaceId, context.workspaceId), eq(workspaceMemberRoles.userId, context.userId)));
217
+ },
218
+ roles: roleAdmin,
219
+ };
220
+ return service;
221
+ }
222
+ /**
223
+ * Declare an application's permission vocabulary and get a union type for it.
224
+ *
225
+ * ```ts
226
+ * export const PERMISSIONS = definePermissions([
227
+ * "projects.read",
228
+ * "projects.create",
229
+ * ] as const);
230
+ *
231
+ * type AppPermission = (typeof PERMISSIONS)[number]; // "projects.read" | "projects.create"
232
+ * ```
233
+ *
234
+ * Purely a typing helper — it performs no I/O. Pass the same list to
235
+ * `registerPermissions()` to persist it.
236
+ */
237
+ export function definePermissions(keys) {
238
+ return keys;
239
+ }
240
+ /** Look up which roles in a workspace carry a given permission. */
241
+ export async function findRolesWithPermission(db, workspaceId, permission) {
242
+ const grantedRoleIds = await db
243
+ .select({ roleId: rolePermissions.roleId })
244
+ .from(rolePermissions)
245
+ .where(eq(rolePermissions.permissionKey, permission));
246
+ if (grantedRoleIds.length === 0) {
247
+ return [];
248
+ }
249
+ return db
250
+ .select()
251
+ .from(roles)
252
+ .where(and(eq(roles.workspaceId, workspaceId), inArray(roles.id, grantedRoleIds.map((row) => row.roleId))));
253
+ }
254
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/authorization/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type BillingService } from "./service.ts";
2
+ import type { BillingProvider } from "./provider.ts";
3
+ export { assertEntitlementDefinitions, countFailedBillingEvents, createBillingService, InvalidWebhookSignatureError, type BillingService, type BillingServiceDeps, type CreateCheckoutOptions, type EntitlementDefinition, type SubscriptionWithPlan, type UpsertPlanInput, type WebhookOutcome, type WebhookRequest, } from "./service.ts";
4
+ export type { BillingProvider, CancelSubscriptionInput, CheckoutSession, CreateCheckoutInput, CreateCustomerInput, PortalInput, ProviderCustomer, ProviderSubscriptionState, ProviderWebhookEvent, WebhookVerificationInput, } from "./provider.ts";
5
+ export { createRevolutProvider, mapRevolutStatus, verifyRevolutSignature, type RevolutAdapterOptions, } from "./revolut.ts";
6
+ /** The Revolut provider, built from the `billing` configuration section. */
7
+ export declare function createConfiguredProvider(): BillingProvider;
8
+ /**
9
+ * Default service, bound to configuration and the Revolut adapter.
10
+ *
11
+ * Both dependencies are getters, so the `billing` and `database` configuration
12
+ * sections resolve on first use rather than at import — importing this module
13
+ * does not require Revolut credentials.
14
+ */
15
+ export declare const billing: BillingService;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAeA,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,oBAAoB,EACpB,4BAA4B,EAC5B,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,cAAc,CAAC;AAEtB,4EAA4E;AAC5E,wBAAgB,wBAAwB,IAAI,eAAe,CAO1D;AAID;;;;;;GAMG;AACH,eAAO,MAAM,OAAO,EAAE,cASpB,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Public billing surface: `@digimuza/saas-core/billing`. Server-only.
3
+ *
4
+ * Provider-independent by construction: everything above {@link BillingProvider}
5
+ * is generic, so adopting a second payment provider means writing an adapter.
6
+ * Application code must never inspect a plan name to decide what a customer may
7
+ * do — ask `@digimuza/saas-core/entitlements` instead.
8
+ *
9
+ * Billing state changes only from verified webhook events, never from the
10
+ * browser's return trip after checkout: that redirect is attacker-controllable
11
+ * and proves nothing about payment.
12
+ */
13
+ import { config } from "../config/index.js";
14
+ import { getDatabase } from "../db/client.js";
15
+ import { events as coreEventsService } from "../events/index.js";
16
+ import { createBillingService } from "./service.js";
17
+ import { createRevolutProvider } from "./revolut.js";
18
+ export { assertEntitlementDefinitions, countFailedBillingEvents, createBillingService, InvalidWebhookSignatureError, } from "./service.js";
19
+ export { createRevolutProvider, mapRevolutStatus, verifyRevolutSignature, } from "./revolut.js";
20
+ /** The Revolut provider, built from the `billing` configuration section. */
21
+ export function createConfiguredProvider() {
22
+ const billing = config.billing;
23
+ return createRevolutProvider({
24
+ apiKey: billing.apiKey,
25
+ webhookSecret: billing.webhookSecret,
26
+ apiUrl: billing.apiUrl,
27
+ });
28
+ }
29
+ let configuredProvider;
30
+ /**
31
+ * Default service, bound to configuration and the Revolut adapter.
32
+ *
33
+ * Both dependencies are getters, so the `billing` and `database` configuration
34
+ * sections resolve on first use rather than at import — importing this module
35
+ * does not require Revolut credentials.
36
+ */
37
+ export const billing = createBillingService({
38
+ get db() {
39
+ return getDatabase();
40
+ },
41
+ get provider() {
42
+ configuredProvider ??= createConfiguredProvider();
43
+ return configuredProvider;
44
+ },
45
+ events: coreEventsService,
46
+ });
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/billing/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAuB,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,EACxB,oBAAoB,EACpB,4BAA4B,GAS7B,MAAM,cAAc,CAAC;AAetB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,GAEvB,MAAM,cAAc,CAAC;AAEtB,4EAA4E;AAC5E,MAAM,UAAU,wBAAwB;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,OAAO,qBAAqB,CAAC;QAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;AACL,CAAC;AAED,IAAI,kBAA+C,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,OAAO,GAAmB,oBAAoB,CAAC;IAC1D,IAAI,EAAE;QACJ,OAAO,WAAW,EAAE,CAAC;IACvB,CAAC;IACD,IAAI,QAAQ;QACV,kBAAkB,KAAK,wBAAwB,EAAE,CAAC;QAClD,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IACD,MAAM,EAAE,iBAAiB;CAC1B,CAAC,CAAC"}
@@ -0,0 +1,114 @@
1
+ import type { Plan, SubscriptionStatus } from "../db/schema/index.ts";
2
+ /**
3
+ * The seam between the core and a payment provider.
4
+ *
5
+ * Everything above this interface is provider-independent, so adopting a second
6
+ * provider means writing an adapter rather than touching the schema, the
7
+ * services or any application code.
8
+ *
9
+ * Not every provider offers every capability. `cancelSubscription` and
10
+ * `getPortalUrl` are optional: Revolut has no hosted customer portal and no
11
+ * server-side subscription object to cancel, and pretending otherwise would mean
12
+ * shipping methods that silently do nothing. The billing service handles their
13
+ * absence explicitly.
14
+ */
15
+ export interface BillingProvider {
16
+ /** Stored on every row this provider produces, e.g. `"revolut"`. */
17
+ readonly name: string;
18
+ createCustomer(input: CreateCustomerInput): Promise<ProviderCustomer>;
19
+ createCheckout(input: CreateCheckoutInput): Promise<CheckoutSession>;
20
+ /** Omit when the provider has no server-side subscription to cancel. */
21
+ cancelSubscription?(input: CancelSubscriptionInput): Promise<void>;
22
+ /** Omit when the provider has no hosted billing portal. */
23
+ getPortalUrl?(input: PortalInput): Promise<string>;
24
+ /**
25
+ * Verify a webhook's authenticity.
26
+ *
27
+ * Must be given the **raw** request body. Parsing and re-serialising JSON
28
+ * changes key order and whitespace, which invalidates the signature — so a
29
+ * route handler has to read the body as text before touching it.
30
+ */
31
+ verifyWebhook(input: WebhookVerificationInput): boolean;
32
+ /** Translate a verified webhook body into a provider-independent event. */
33
+ parseWebhookEvent(rawBody: string): ProviderWebhookEvent;
34
+ }
35
+ export interface ProviderCustomer {
36
+ readonly providerCustomerId: string;
37
+ }
38
+ export interface CreateCustomerInput {
39
+ readonly workspaceId: string;
40
+ readonly workspaceName: string;
41
+ readonly email?: string;
42
+ }
43
+ export interface CreateCheckoutInput {
44
+ readonly workspaceId: string;
45
+ readonly providerCustomerId: string;
46
+ readonly plan: Plan;
47
+ readonly successUrl: string;
48
+ readonly cancelUrl: string;
49
+ readonly quantity?: number;
50
+ /** Echoed back on webhooks, where the provider supports it. */
51
+ readonly metadata?: Record<string, string>;
52
+ }
53
+ export interface CheckoutSession {
54
+ /** Where to send the customer to pay. */
55
+ readonly url: string;
56
+ readonly providerCheckoutId?: string;
57
+ }
58
+ export interface CancelSubscriptionInput {
59
+ readonly providerSubscriptionId: string;
60
+ /** Cancel at the end of the paid period rather than immediately. */
61
+ readonly atPeriodEnd: boolean;
62
+ }
63
+ export interface PortalInput {
64
+ readonly providerCustomerId: string;
65
+ readonly returnUrl: string;
66
+ }
67
+ export interface WebhookVerificationInput {
68
+ /** The request body exactly as received, before any parsing. */
69
+ readonly rawBody: string;
70
+ readonly signature: string;
71
+ /** Provider timestamp header, used for replay protection. */
72
+ readonly timestamp?: string;
73
+ }
74
+ /**
75
+ * Normalised subscription state carried by a webhook.
76
+ *
77
+ * The adapter maps the provider's status vocabulary onto
78
+ * {@link SubscriptionStatus}, so application queries never see provider strings.
79
+ *
80
+ * Date fields must be real `Date` instances. Providers send them as ISO strings,
81
+ * and converting them is the adapter's job — passing a string through would fail
82
+ * deep inside the database driver with an error that names neither the field nor
83
+ * the adapter.
84
+ */
85
+ export interface ProviderSubscriptionState {
86
+ readonly providerSubscriptionId: string;
87
+ readonly providerCustomerId: string;
88
+ /**
89
+ * Resolve the plan by `plans.provider_price_id` — for providers with a price
90
+ * catalogue (Stripe, Paddle).
91
+ */
92
+ readonly providerPriceId?: string;
93
+ /**
94
+ * Resolve the plan by `plans.key` — for providers with no catalogue, where the
95
+ * plan is carried in a reference we set when creating the payment. Consulted
96
+ * only when {@link providerPriceId} is absent.
97
+ */
98
+ readonly planKey?: string;
99
+ readonly status: SubscriptionStatus;
100
+ readonly currentPeriodStart?: Date;
101
+ readonly currentPeriodEnd?: Date;
102
+ readonly cancelAtPeriodEnd?: boolean;
103
+ readonly canceledAt?: Date;
104
+ readonly trialEndsAt?: Date;
105
+ }
106
+ export interface ProviderWebhookEvent {
107
+ /** Provider's own event id. The idempotency key for ingestion. */
108
+ readonly providerEventId: string;
109
+ readonly type: string;
110
+ readonly payload: unknown;
111
+ /** Present when the event changes subscription state. */
112
+ readonly subscription?: ProviderSubscriptionState;
113
+ }
114
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/billing/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/billing/provider.ts"],"names":[],"mappings":""}
@@ -0,0 +1,68 @@
1
+ import type { SubscriptionStatus } from "../db/schema/index.ts";
2
+ import type { BillingProvider } from "./provider.ts";
3
+ /**
4
+ * Revolut Merchant API adapter.
5
+ *
6
+ * ## Capability boundaries
7
+ *
8
+ * Revolut Merchant is an order-and-payment API, not a subscription platform. It
9
+ * has no hosted customer portal and no server-side subscription object, so
10
+ * `getPortalUrl` and `cancelSubscription` are deliberately absent from this
11
+ * adapter rather than stubbed. Recurring charges on Revolut are
12
+ * merchant-initiated: the core owns subscription state and drives the charges,
13
+ * and cancellation is therefore a local state change.
14
+ *
15
+ * ## Verification status
16
+ *
17
+ * The webhook signature scheme is fully implemented and unit-tested against the
18
+ * documented algorithm. The HTTP calls are written against the documented
19
+ * endpoints but have **not** been exercised against live Revolut credentials.
20
+ * Treat `createCustomer` and `createCheckout` as unverified until they have run
21
+ * against a sandbox account.
22
+ */
23
+ export interface RevolutAdapterOptions {
24
+ readonly apiKey: string;
25
+ readonly webhookSecret: string;
26
+ /** Base URL. Sandbox differs from production. */
27
+ readonly apiUrl: string;
28
+ /**
29
+ * Reject webhooks whose timestamp is older than this, in seconds.
30
+ *
31
+ * Replay protection: a signature stays valid forever, so without a freshness
32
+ * window a captured request could be replayed indefinitely.
33
+ */
34
+ readonly timestampToleranceSeconds?: number;
35
+ /** Injected for tests. Defaults to the global `fetch`. */
36
+ readonly fetchImpl?: typeof fetch;
37
+ /** Injected for tests, so signature freshness is deterministic. */
38
+ readonly now?: () => number;
39
+ }
40
+ /**
41
+ * Map Revolut order/payment states onto the core's vocabulary.
42
+ *
43
+ * Unknown states deliberately fall through to `incomplete` rather than `active`:
44
+ * treating an unrecognised state as paid would grant entitlements the customer
45
+ * may not have.
46
+ */
47
+ export declare function mapRevolutStatus(state: string): SubscriptionStatus;
48
+ /**
49
+ * Verify a Revolut webhook signature.
50
+ *
51
+ * Revolut signs `v1.{timestamp}.{raw body}` with HMAC-SHA256 under the webhook
52
+ * signing secret, and sends the result as `Revolut-Signature: v1=<hex>`. During
53
+ * secret rotation the header may carry several comma-separated signatures, any
54
+ * one of which may match.
55
+ *
56
+ * Exported separately from the adapter so a route handler can verify without
57
+ * constructing API credentials it does not need.
58
+ */
59
+ export declare function verifyRevolutSignature(input: {
60
+ rawBody: string;
61
+ signature: string;
62
+ timestamp: string;
63
+ secret: string;
64
+ toleranceSeconds?: number;
65
+ now?: () => number;
66
+ }): boolean;
67
+ export declare function createRevolutProvider(options: RevolutAdapterOptions): BillingProvider;
68
+ //# sourceMappingURL=revolut.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revolut.d.ts","sourceRoot":"","sources":["../../src/billing/revolut.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,iDAAiD;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAC5C,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,mEAAmE;IACnE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAID;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAmBlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB,GAAG,OAAO,CAqCV;AAYD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG,eAAe,CAiIrF"}