@antelopejs/dms-saas 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (687) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +658 -0
  3. package/dist/auth/index.d.ts +3 -0
  4. package/dist/auth/index.js +20 -0
  5. package/dist/auth/index.js.map +1 -0
  6. package/dist/auth/oauth-entry.d.ts +5 -0
  7. package/dist/auth/oauth-entry.js +10 -0
  8. package/dist/auth/oauth-entry.js.map +1 -0
  9. package/dist/auth/plan-permissions-resolver.d.ts +1 -0
  10. package/dist/auth/plan-permissions-resolver.js +44 -0
  11. package/dist/auth/plan-permissions-resolver.js.map +1 -0
  12. package/dist/auth/subscription-access-gate.d.ts +8 -0
  13. package/dist/auth/subscription-access-gate.js +38 -0
  14. package/dist/auth/subscription-access-gate.js.map +1 -0
  15. package/dist/automation/index.d.ts +44 -0
  16. package/dist/automation/index.js +209 -0
  17. package/dist/automation/index.js.map +1 -0
  18. package/dist/billing-state/index.d.ts +5 -0
  19. package/dist/billing-state/index.js +58 -0
  20. package/dist/billing-state/index.js.map +1 -0
  21. package/dist/billing-state/recovery.d.ts +22 -0
  22. package/dist/billing-state/recovery.js +81 -0
  23. package/dist/billing-state/recovery.js.map +1 -0
  24. package/dist/config/dev-mode.d.ts +3 -0
  25. package/dist/config/dev-mode.js +27 -0
  26. package/dist/config/dev-mode.js.map +1 -0
  27. package/dist/config/index.d.ts +2 -0
  28. package/dist/config/index.js +19 -0
  29. package/dist/config/index.js.map +1 -0
  30. package/dist/config/runtime.d.ts +6 -0
  31. package/dist/config/runtime.js +54 -0
  32. package/dist/config/runtime.js.map +1 -0
  33. package/dist/crons/auto-suspend-past-due.d.ts +2 -0
  34. package/dist/crons/auto-suspend-past-due.js +43 -0
  35. package/dist/crons/auto-suspend-past-due.js.map +1 -0
  36. package/dist/crons/cleanup-stripe-webhook-events.d.ts +2 -0
  37. package/dist/crons/cleanup-stripe-webhook-events.js +27 -0
  38. package/dist/crons/cleanup-stripe-webhook-events.js.map +1 -0
  39. package/dist/crons/expire-free-workspaces.d.ts +2 -0
  40. package/dist/crons/expire-free-workspaces.js +36 -0
  41. package/dist/crons/expire-free-workspaces.js.map +1 -0
  42. package/dist/crons/hard-delete-cancelled.d.ts +2 -0
  43. package/dist/crons/hard-delete-cancelled.js +55 -0
  44. package/dist/crons/hard-delete-cancelled.js.map +1 -0
  45. package/dist/crons/index.d.ts +8 -0
  46. package/dist/crons/index.js +25 -0
  47. package/dist/crons/index.js.map +1 -0
  48. package/dist/crons/notify-free-workspaces-ending-soon.d.ts +2 -0
  49. package/dist/crons/notify-free-workspaces-ending-soon.js +69 -0
  50. package/dist/crons/notify-free-workspaces-ending-soon.js.map +1 -0
  51. package/dist/crons/recompute-billing-state.d.ts +2 -0
  52. package/dist/crons/recompute-billing-state.js +19 -0
  53. package/dist/crons/recompute-billing-state.js.map +1 -0
  54. package/dist/crons/recompute-segments.d.ts +2 -0
  55. package/dist/crons/recompute-segments.js +19 -0
  56. package/dist/crons/recompute-segments.js.map +1 -0
  57. package/dist/crons/reconcile-workspace-lifecycle.d.ts +2 -0
  58. package/dist/crons/reconcile-workspace-lifecycle.js +19 -0
  59. package/dist/crons/reconcile-workspace-lifecycle.js.map +1 -0
  60. package/dist/crons/register.d.ts +2 -0
  61. package/dist/crons/register.js +24 -0
  62. package/dist/crons/register.js.map +1 -0
  63. package/dist/crons/subscription-notifications.d.ts +2 -0
  64. package/dist/crons/subscription-notifications.js +55 -0
  65. package/dist/crons/subscription-notifications.js.map +1 -0
  66. package/dist/data-api/index.d.ts +2 -0
  67. package/dist/data-api/index.js +19 -0
  68. package/dist/data-api/index.js.map +1 -0
  69. package/dist/data-api/platformOwner/admin-user-invoices.d.ts +27 -0
  70. package/dist/data-api/platformOwner/admin-user-invoices.js +158 -0
  71. package/dist/data-api/platformOwner/admin-user-invoices.js.map +1 -0
  72. package/dist/data-api/platformOwner/admin-user-workspaces.d.ts +22 -0
  73. package/dist/data-api/platformOwner/admin-user-workspaces.js +97 -0
  74. package/dist/data-api/platformOwner/admin-user-workspaces.js.map +1 -0
  75. package/dist/data-api/platformOwner/credit-notes.d.ts +24 -0
  76. package/dist/data-api/platformOwner/credit-notes.js +133 -0
  77. package/dist/data-api/platformOwner/credit-notes.js.map +1 -0
  78. package/dist/data-api/platformOwner/features.d.ts +30 -0
  79. package/dist/data-api/platformOwner/features.js +141 -0
  80. package/dist/data-api/platformOwner/features.js.map +1 -0
  81. package/dist/data-api/platformOwner/hidden-filter.d.ts +1 -0
  82. package/dist/data-api/platformOwner/hidden-filter.js +18 -0
  83. package/dist/data-api/platformOwner/hidden-filter.js.map +1 -0
  84. package/dist/data-api/platformOwner/index.d.ts +12 -0
  85. package/dist/data-api/platformOwner/index.js +29 -0
  86. package/dist/data-api/platformOwner/index.js.map +1 -0
  87. package/dist/data-api/platformOwner/invoice-options.d.ts +7 -0
  88. package/dist/data-api/platformOwner/invoice-options.js +14 -0
  89. package/dist/data-api/platformOwner/invoice-options.js.map +1 -0
  90. package/dist/data-api/platformOwner/invoices.d.ts +26 -0
  91. package/dist/data-api/platformOwner/invoices.js +147 -0
  92. package/dist/data-api/platformOwner/invoices.js.map +1 -0
  93. package/dist/data-api/platformOwner/members.d.ts +24 -0
  94. package/dist/data-api/platformOwner/members.js +125 -0
  95. package/dist/data-api/platformOwner/members.js.map +1 -0
  96. package/dist/data-api/platformOwner/plan-migrations.d.ts +24 -0
  97. package/dist/data-api/platformOwner/plan-migrations.js +138 -0
  98. package/dist/data-api/platformOwner/plan-migrations.js.map +1 -0
  99. package/dist/data-api/platformOwner/plans.d.ts +30 -0
  100. package/dist/data-api/platformOwner/plans.js +228 -0
  101. package/dist/data-api/platformOwner/plans.js.map +1 -0
  102. package/dist/data-api/platformOwner/segments.d.ts +29 -0
  103. package/dist/data-api/platformOwner/segments.js +223 -0
  104. package/dist/data-api/platformOwner/segments.js.map +1 -0
  105. package/dist/data-api/platformOwner/support.d.ts +58 -0
  106. package/dist/data-api/platformOwner/support.js +111 -0
  107. package/dist/data-api/platformOwner/support.js.map +1 -0
  108. package/dist/data-api/platformOwner/users.d.ts +22 -0
  109. package/dist/data-api/platformOwner/users.js +128 -0
  110. package/dist/data-api/platformOwner/users.js.map +1 -0
  111. package/dist/data-api/platformOwner/workspaces.d.ts +22 -0
  112. package/dist/data-api/platformOwner/workspaces.js +153 -0
  113. package/dist/data-api/platformOwner/workspaces.js.map +1 -0
  114. package/dist/data-api/support-fields.d.ts +49 -0
  115. package/dist/data-api/support-fields.js +166 -0
  116. package/dist/data-api/support-fields.js.map +1 -0
  117. package/dist/data-api/support-routes.d.ts +10 -0
  118. package/dist/data-api/support-routes.js +71 -0
  119. package/dist/data-api/support-routes.js.map +1 -0
  120. package/dist/data-api/tenant/index.d.ts +2 -0
  121. package/dist/data-api/tenant/index.js +19 -0
  122. package/dist/data-api/tenant/index.js.map +1 -0
  123. package/dist/data-api/tenant/support.d.ts +39 -0
  124. package/dist/data-api/tenant/support.js +53 -0
  125. package/dist/data-api/tenant/support.js.map +1 -0
  126. package/dist/data-api/tenant/tenant-invoices.d.ts +37 -0
  127. package/dist/data-api/tenant/tenant-invoices.js +242 -0
  128. package/dist/data-api/tenant/tenant-invoices.js.map +1 -0
  129. package/dist/db/index.d.ts +1 -0
  130. package/dist/db/index.js +18 -0
  131. package/dist/db/index.js.map +1 -0
  132. package/dist/hooks/index.d.ts +3 -0
  133. package/dist/hooks/index.js +20 -0
  134. package/dist/hooks/index.js.map +1 -0
  135. package/dist/hooks/register.d.ts +1 -0
  136. package/dist/hooks/register.js +57 -0
  137. package/dist/hooks/register.js.map +1 -0
  138. package/dist/hooks/tenant-export.d.ts +2 -0
  139. package/dist/hooks/tenant-export.js +64 -0
  140. package/dist/hooks/tenant-export.js.map +1 -0
  141. package/dist/hooks/tenant-provisioning.d.ts +3 -0
  142. package/dist/hooks/tenant-provisioning.js +12 -0
  143. package/dist/hooks/tenant-provisioning.js.map +1 -0
  144. package/dist/implementations/dms-saas/billing.d.ts +2 -0
  145. package/dist/implementations/dms-saas/billing.js +49 -0
  146. package/dist/implementations/dms-saas/billing.js.map +1 -0
  147. package/dist/implementations/dms-saas/invoice-line-items.d.ts +11 -0
  148. package/dist/implementations/dms-saas/invoice-line-items.js +24 -0
  149. package/dist/implementations/dms-saas/invoice-line-items.js.map +1 -0
  150. package/dist/implementations/dms-saas/pages.d.ts +3 -0
  151. package/dist/implementations/dms-saas/pages.js +12 -0
  152. package/dist/implementations/dms-saas/pages.js.map +1 -0
  153. package/dist/implementations/dms-saas/workspace-lifecycle.d.ts +2 -0
  154. package/dist/implementations/dms-saas/workspace-lifecycle.js +23 -0
  155. package/dist/implementations/dms-saas/workspace-lifecycle.js.map +1 -0
  156. package/dist/index.d.ts +8 -0
  157. package/dist/index.js +107 -0
  158. package/dist/index.js.map +1 -0
  159. package/dist/invoice-line-items/billing-window.d.ts +3 -0
  160. package/dist/invoice-line-items/billing-window.js +19 -0
  161. package/dist/invoice-line-items/billing-window.js.map +1 -0
  162. package/dist/invoice-line-items/index.d.ts +1 -0
  163. package/dist/invoice-line-items/index.js +18 -0
  164. package/dist/invoice-line-items/index.js.map +1 -0
  165. package/dist/invoice-line-items/injection.d.ts +2 -0
  166. package/dist/invoice-line-items/injection.js +171 -0
  167. package/dist/invoice-line-items/injection.js.map +1 -0
  168. package/dist/notifications/index.d.ts +2 -0
  169. package/dist/notifications/index.js +19 -0
  170. package/dist/notifications/index.js.map +1 -0
  171. package/dist/notifications/recipients.d.ts +14 -0
  172. package/dist/notifications/recipients.js +87 -0
  173. package/dist/notifications/recipients.js.map +1 -0
  174. package/dist/notifications/subjects.d.ts +21 -0
  175. package/dist/notifications/subjects.js +121 -0
  176. package/dist/notifications/subjects.js.map +1 -0
  177. package/dist/operator-actions/commands.d.ts +41 -0
  178. package/dist/operator-actions/commands.js +233 -0
  179. package/dist/operator-actions/commands.js.map +1 -0
  180. package/dist/operator-actions/db/index.d.ts +4 -0
  181. package/dist/operator-actions/db/index.js +21 -0
  182. package/dist/operator-actions/db/index.js.map +1 -0
  183. package/dist/operator-actions/db/lifecycle-delivery.model.d.ts +29 -0
  184. package/dist/operator-actions/db/lifecycle-delivery.model.js +85 -0
  185. package/dist/operator-actions/db/lifecycle-delivery.model.js.map +1 -0
  186. package/dist/operator-actions/db/lifecycle-delivery.table.d.ts +26 -0
  187. package/dist/operator-actions/db/lifecycle-delivery.table.js +107 -0
  188. package/dist/operator-actions/db/lifecycle-delivery.table.js.map +1 -0
  189. package/dist/operator-actions/db/operator-action.model.d.ts +33 -0
  190. package/dist/operator-actions/db/operator-action.model.js +63 -0
  191. package/dist/operator-actions/db/operator-action.model.js.map +1 -0
  192. package/dist/operator-actions/db/operator-action.table.d.ts +21 -0
  193. package/dist/operator-actions/db/operator-action.table.js +95 -0
  194. package/dist/operator-actions/db/operator-action.table.js.map +1 -0
  195. package/dist/operator-actions/index.d.ts +3 -0
  196. package/dist/operator-actions/index.js +20 -0
  197. package/dist/operator-actions/index.js.map +1 -0
  198. package/dist/operator-actions/journal.d.ts +22 -0
  199. package/dist/operator-actions/journal.js +183 -0
  200. package/dist/operator-actions/journal.js.map +1 -0
  201. package/dist/operator-actions/lifecycle-consumers.d.ts +12 -0
  202. package/dist/operator-actions/lifecycle-consumers.js +28 -0
  203. package/dist/operator-actions/lifecycle-consumers.js.map +1 -0
  204. package/dist/operator-actions/lifecycle-outbox.d.ts +19 -0
  205. package/dist/operator-actions/lifecycle-outbox.js +229 -0
  206. package/dist/operator-actions/lifecycle-outbox.js.map +1 -0
  207. package/dist/operator-actions/types.d.ts +11 -0
  208. package/dist/operator-actions/types.js +3 -0
  209. package/dist/operator-actions/types.js.map +1 -0
  210. package/dist/pages/definitions.d.ts +1 -0
  211. package/dist/pages/definitions.js +18 -0
  212. package/dist/pages/definitions.js.map +1 -0
  213. package/dist/pages/index.d.ts +4 -0
  214. package/dist/pages/index.js +21 -0
  215. package/dist/pages/index.js.map +1 -0
  216. package/dist/pages/module.d.ts +5 -0
  217. package/dist/pages/module.js +15 -0
  218. package/dist/pages/module.js.map +1 -0
  219. package/dist/pages/platform/categories.d.ts +6 -0
  220. package/dist/pages/platform/categories.js +48 -0
  221. package/dist/pages/platform/categories.js.map +1 -0
  222. package/dist/pages/platform/credit-notes.d.ts +9 -0
  223. package/dist/pages/platform/credit-notes.js +40 -0
  224. package/dist/pages/platform/credit-notes.js.map +1 -0
  225. package/dist/pages/platform/dashboard.d.ts +10 -0
  226. package/dist/pages/platform/dashboard.js +95 -0
  227. package/dist/pages/platform/dashboard.js.map +1 -0
  228. package/dist/pages/platform/features.d.ts +9 -0
  229. package/dist/pages/platform/features.js +42 -0
  230. package/dist/pages/platform/features.js.map +1 -0
  231. package/dist/pages/platform/index.d.ts +15 -0
  232. package/dist/pages/platform/index.js +32 -0
  233. package/dist/pages/platform/index.js.map +1 -0
  234. package/dist/pages/platform/invoices.d.ts +9 -0
  235. package/dist/pages/platform/invoices.js +63 -0
  236. package/dist/pages/platform/invoices.js.map +1 -0
  237. package/dist/pages/platform/plans/edit.d.ts +17 -0
  238. package/dist/pages/platform/plans/edit.js +213 -0
  239. package/dist/pages/platform/plans/edit.js.map +1 -0
  240. package/dist/pages/platform/plans/index.d.ts +9 -0
  241. package/dist/pages/platform/plans/index.js +99 -0
  242. package/dist/pages/platform/plans/index.js.map +1 -0
  243. package/dist/pages/platform/plans/migrations.d.ts +9 -0
  244. package/dist/pages/platform/plans/migrations.js +38 -0
  245. package/dist/pages/platform/plans/migrations.js.map +1 -0
  246. package/dist/pages/platform/segments/index.d.ts +9 -0
  247. package/dist/pages/platform/segments/index.js +59 -0
  248. package/dist/pages/platform/segments/index.js.map +1 -0
  249. package/dist/pages/platform/settings.d.ts +9 -0
  250. package/dist/pages/platform/settings.js +147 -0
  251. package/dist/pages/platform/settings.js.map +1 -0
  252. package/dist/pages/platform/support.d.ts +9 -0
  253. package/dist/pages/platform/support.js +29 -0
  254. package/dist/pages/platform/support.js.map +1 -0
  255. package/dist/pages/platform/users/detail.d.ts +9 -0
  256. package/dist/pages/platform/users/detail.js +78 -0
  257. package/dist/pages/platform/users/detail.js.map +1 -0
  258. package/dist/pages/platform/users/index.d.ts +9 -0
  259. package/dist/pages/platform/users/index.js +77 -0
  260. package/dist/pages/platform/users/index.js.map +1 -0
  261. package/dist/pages/platform/workspaces/detail.d.ts +9 -0
  262. package/dist/pages/platform/workspaces/detail.js +120 -0
  263. package/dist/pages/platform/workspaces/detail.js.map +1 -0
  264. package/dist/pages/platform/workspaces/index.d.ts +35 -0
  265. package/dist/pages/platform/workspaces/index.js +300 -0
  266. package/dist/pages/platform/workspaces/index.js.map +1 -0
  267. package/dist/pages/public/auth/index.d.ts +1 -0
  268. package/dist/pages/public/auth/index.js +18 -0
  269. package/dist/pages/public/auth/index.js.map +1 -0
  270. package/dist/pages/public/auth/no-workspace.d.ts +9 -0
  271. package/dist/pages/public/auth/no-workspace.js +26 -0
  272. package/dist/pages/public/auth/no-workspace.js.map +1 -0
  273. package/dist/pages/public/index.d.ts +3 -0
  274. package/dist/pages/public/index.js +20 -0
  275. package/dist/pages/public/index.js.map +1 -0
  276. package/dist/pages/public/legal/index.d.ts +3 -0
  277. package/dist/pages/public/legal/index.js +20 -0
  278. package/dist/pages/public/legal/index.js.map +1 -0
  279. package/dist/pages/public/legal/privacy-policy.d.ts +9 -0
  280. package/dist/pages/public/legal/privacy-policy.js +29 -0
  281. package/dist/pages/public/legal/privacy-policy.js.map +1 -0
  282. package/dist/pages/public/legal/terms-and-conditions.d.ts +9 -0
  283. package/dist/pages/public/legal/terms-and-conditions.js +29 -0
  284. package/dist/pages/public/legal/terms-and-conditions.js.map +1 -0
  285. package/dist/pages/public/legal/terms-of-use.d.ts +9 -0
  286. package/dist/pages/public/legal/terms-of-use.js +29 -0
  287. package/dist/pages/public/legal/terms-of-use.js.map +1 -0
  288. package/dist/pages/public/register.d.ts +9 -0
  289. package/dist/pages/public/register.js +29 -0
  290. package/dist/pages/public/register.js.map +1 -0
  291. package/dist/pages/public/screens.d.ts +3 -0
  292. package/dist/pages/public/screens.js +50 -0
  293. package/dist/pages/public/screens.js.map +1 -0
  294. package/dist/pages/tenant/billing.d.ts +15 -0
  295. package/dist/pages/tenant/billing.js +87 -0
  296. package/dist/pages/tenant/billing.js.map +1 -0
  297. package/dist/pages/tenant/data-export.d.ts +10 -0
  298. package/dist/pages/tenant/data-export.js +32 -0
  299. package/dist/pages/tenant/data-export.js.map +1 -0
  300. package/dist/pages/tenant/general.d.ts +10 -0
  301. package/dist/pages/tenant/general.js +33 -0
  302. package/dist/pages/tenant/general.js.map +1 -0
  303. package/dist/pages/tenant/index.d.ts +6 -0
  304. package/dist/pages/tenant/index.js +23 -0
  305. package/dist/pages/tenant/index.js.map +1 -0
  306. package/dist/pages/tenant/members-seat-quota.d.ts +3 -0
  307. package/dist/pages/tenant/members-seat-quota.js +25 -0
  308. package/dist/pages/tenant/members-seat-quota.js.map +1 -0
  309. package/dist/pages/tenant/support.d.ts +9 -0
  310. package/dist/pages/tenant/support.js +27 -0
  311. package/dist/pages/tenant/support.js.map +1 -0
  312. package/dist/pages/tenant/workspace-suspended.d.ts +9 -0
  313. package/dist/pages/tenant/workspace-suspended.js +26 -0
  314. package/dist/pages/tenant/workspace-suspended.js.map +1 -0
  315. package/dist/plan-changes/deferred.d.ts +18 -0
  316. package/dist/plan-changes/deferred.js +225 -0
  317. package/dist/plan-changes/deferred.js.map +1 -0
  318. package/dist/plan-changes/index.d.ts +1 -0
  319. package/dist/plan-changes/index.js +18 -0
  320. package/dist/plan-changes/index.js.map +1 -0
  321. package/dist/plans/index.d.ts +4 -0
  322. package/dist/plans/index.js +21 -0
  323. package/dist/plans/index.js.map +1 -0
  324. package/dist/plans/seat-capacity.d.ts +9 -0
  325. package/dist/plans/seat-capacity.js +38 -0
  326. package/dist/plans/seat-capacity.js.map +1 -0
  327. package/dist/plans/seat-hooks.d.ts +1 -0
  328. package/dist/plans/seat-hooks.js +80 -0
  329. package/dist/plans/seat-hooks.js.map +1 -0
  330. package/dist/plans/seat-sync.d.ts +10 -0
  331. package/dist/plans/seat-sync.js +23 -0
  332. package/dist/plans/seat-sync.js.map +1 -0
  333. package/dist/routes/index.d.ts +3 -0
  334. package/dist/routes/index.js +20 -0
  335. package/dist/routes/index.js.map +1 -0
  336. package/dist/routes/platformOwner/billing-settings.d.ts +20 -0
  337. package/dist/routes/platformOwner/billing-settings.js +98 -0
  338. package/dist/routes/platformOwner/billing-settings.js.map +1 -0
  339. package/dist/routes/platformOwner/credit-notes-issue.d.ts +16 -0
  340. package/dist/routes/platformOwner/credit-notes-issue.js +56 -0
  341. package/dist/routes/platformOwner/credit-notes-issue.js.map +1 -0
  342. package/dist/routes/platformOwner/dashboard.d.ts +62 -0
  343. package/dist/routes/platformOwner/dashboard.js +310 -0
  344. package/dist/routes/platformOwner/dashboard.js.map +1 -0
  345. package/dist/routes/platformOwner/index.d.ts +12 -0
  346. package/dist/routes/platformOwner/index.js +29 -0
  347. package/dist/routes/platformOwner/index.js.map +1 -0
  348. package/dist/routes/platformOwner/plan-deletion.d.ts +30 -0
  349. package/dist/routes/platformOwner/plan-deletion.js +156 -0
  350. package/dist/routes/platformOwner/plan-deletion.js.map +1 -0
  351. package/dist/routes/platformOwner/plans.d.ts +99 -0
  352. package/dist/routes/platformOwner/plans.js +376 -0
  353. package/dist/routes/platformOwner/plans.js.map +1 -0
  354. package/dist/routes/platformOwner/platform-notes.d.ts +36 -0
  355. package/dist/routes/platformOwner/platform-notes.js +149 -0
  356. package/dist/routes/platformOwner/platform-notes.js.map +1 -0
  357. package/dist/routes/platformOwner/platform-owners.d.ts +12 -0
  358. package/dist/routes/platformOwner/platform-owners.js +77 -0
  359. package/dist/routes/platformOwner/platform-owners.js.map +1 -0
  360. package/dist/routes/platformOwner/segments.d.ts +24 -0
  361. package/dist/routes/platformOwner/segments.js +174 -0
  362. package/dist/routes/platformOwner/segments.js.map +1 -0
  363. package/dist/routes/platformOwner/support.d.ts +21 -0
  364. package/dist/routes/platformOwner/support.js +180 -0
  365. package/dist/routes/platformOwner/support.js.map +1 -0
  366. package/dist/routes/platformOwner/users-detail.d.ts +26 -0
  367. package/dist/routes/platformOwner/users-detail.js +82 -0
  368. package/dist/routes/platformOwner/users-detail.js.map +1 -0
  369. package/dist/routes/platformOwner/workspace-operator-actions.d.ts +34 -0
  370. package/dist/routes/platformOwner/workspace-operator-actions.js +183 -0
  371. package/dist/routes/platformOwner/workspace-operator-actions.js.map +1 -0
  372. package/dist/routes/platformOwner/workspaces-admin.d.ts +27 -0
  373. package/dist/routes/platformOwner/workspaces-admin.js +140 -0
  374. package/dist/routes/platformOwner/workspaces-admin.js.map +1 -0
  375. package/dist/routes/public/index.d.ts +3 -0
  376. package/dist/routes/public/index.js +20 -0
  377. package/dist/routes/public/index.js.map +1 -0
  378. package/dist/routes/public/legal-documents.d.ts +15 -0
  379. package/dist/routes/public/legal-documents.js +72 -0
  380. package/dist/routes/public/legal-documents.js.map +1 -0
  381. package/dist/routes/public/register.d.ts +48 -0
  382. package/dist/routes/public/register.js +193 -0
  383. package/dist/routes/public/register.js.map +1 -0
  384. package/dist/routes/public/webhooks/index.d.ts +1 -0
  385. package/dist/routes/public/webhooks/index.js +18 -0
  386. package/dist/routes/public/webhooks/index.js.map +1 -0
  387. package/dist/routes/public/webhooks/stripe.d.ts +7 -0
  388. package/dist/routes/public/webhooks/stripe.js +41 -0
  389. package/dist/routes/public/webhooks/stripe.js.map +1 -0
  390. package/dist/routes/tenant/billing-portal.d.ts +31 -0
  391. package/dist/routes/tenant/billing-portal.js +117 -0
  392. package/dist/routes/tenant/billing-portal.js.map +1 -0
  393. package/dist/routes/tenant/billing-self-refund.d.ts +18 -0
  394. package/dist/routes/tenant/billing-self-refund.js +199 -0
  395. package/dist/routes/tenant/billing-self-refund.js.map +1 -0
  396. package/dist/routes/tenant/data-export.d.ts +16 -0
  397. package/dist/routes/tenant/data-export.js +102 -0
  398. package/dist/routes/tenant/data-export.js.map +1 -0
  399. package/dist/routes/tenant/index.d.ts +9 -0
  400. package/dist/routes/tenant/index.js +26 -0
  401. package/dist/routes/tenant/index.js.map +1 -0
  402. package/dist/routes/tenant/support.d.ts +27 -0
  403. package/dist/routes/tenant/support.js +185 -0
  404. package/dist/routes/tenant/support.js.map +1 -0
  405. package/dist/routes/tenant/tenant-billing.d.ts +26 -0
  406. package/dist/routes/tenant/tenant-billing.js +148 -0
  407. package/dist/routes/tenant/tenant-billing.js.map +1 -0
  408. package/dist/routes/tenant/tenant-plan-ops.d.ts +57 -0
  409. package/dist/routes/tenant/tenant-plan-ops.js +244 -0
  410. package/dist/routes/tenant/tenant-plan-ops.js.map +1 -0
  411. package/dist/routes/tenant/tenant-plan.d.ts +19 -0
  412. package/dist/routes/tenant/tenant-plan.js +172 -0
  413. package/dist/routes/tenant/tenant-plan.js.map +1 -0
  414. package/dist/routes/tenant/tenant-seats.d.ts +17 -0
  415. package/dist/routes/tenant/tenant-seats.js +58 -0
  416. package/dist/routes/tenant/tenant-seats.js.map +1 -0
  417. package/dist/routes/tenant/workspaces.d.ts +78 -0
  418. package/dist/routes/tenant/workspaces.js +301 -0
  419. package/dist/routes/tenant/workspaces.js.map +1 -0
  420. package/dist/stripe/client.d.ts +6 -0
  421. package/dist/stripe/client.js +44 -0
  422. package/dist/stripe/client.js.map +1 -0
  423. package/dist/stripe/customer-balance.d.ts +12 -0
  424. package/dist/stripe/customer-balance.js +16 -0
  425. package/dist/stripe/customer-balance.js.map +1 -0
  426. package/dist/stripe/customer-billing.d.ts +33 -0
  427. package/dist/stripe/customer-billing.js +140 -0
  428. package/dist/stripe/customer-billing.js.map +1 -0
  429. package/dist/stripe/index.d.ts +11 -0
  430. package/dist/stripe/index.js +28 -0
  431. package/dist/stripe/index.js.map +1 -0
  432. package/dist/stripe/plan-schedule.d.ts +9 -0
  433. package/dist/stripe/plan-schedule.js +83 -0
  434. package/dist/stripe/plan-schedule.js.map +1 -0
  435. package/dist/stripe/proration.d.ts +2 -0
  436. package/dist/stripe/proration.js +19 -0
  437. package/dist/stripe/proration.js.map +1 -0
  438. package/dist/stripe/sync-plan.d.ts +2 -0
  439. package/dist/stripe/sync-plan.js +66 -0
  440. package/dist/stripe/sync-plan.js.map +1 -0
  441. package/dist/stripe/webhook-checkout.d.ts +3 -0
  442. package/dist/stripe/webhook-checkout.js +157 -0
  443. package/dist/stripe/webhook-checkout.js.map +1 -0
  444. package/dist/stripe/webhook-credit-notes.d.ts +3 -0
  445. package/dist/stripe/webhook-credit-notes.js +192 -0
  446. package/dist/stripe/webhook-credit-notes.js.map +1 -0
  447. package/dist/stripe/webhook-dispatch.d.ts +2 -0
  448. package/dist/stripe/webhook-dispatch.js +45 -0
  449. package/dist/stripe/webhook-dispatch.js.map +1 -0
  450. package/dist/stripe/webhook-handlers.d.ts +11 -0
  451. package/dist/stripe/webhook-handlers.js +318 -0
  452. package/dist/stripe/webhook-handlers.js.map +1 -0
  453. package/dist/stripe/webhook-shared.d.ts +28 -0
  454. package/dist/stripe/webhook-shared.js +126 -0
  455. package/dist/stripe/webhook-shared.js.map +1 -0
  456. package/dist/stripe/workspace-checkout.d.ts +29 -0
  457. package/dist/stripe/workspace-checkout.js +106 -0
  458. package/dist/stripe/workspace-checkout.js.map +1 -0
  459. package/dist/support/admissions.d.ts +36 -0
  460. package/dist/support/admissions.js +136 -0
  461. package/dist/support/admissions.js.map +1 -0
  462. package/dist/support/attachments.d.ts +12 -0
  463. package/dist/support/attachments.js +56 -0
  464. package/dist/support/attachments.js.map +1 -0
  465. package/dist/support/config.d.ts +19 -0
  466. package/dist/support/config.js +75 -0
  467. package/dist/support/config.js.map +1 -0
  468. package/dist/support/index.d.ts +6 -0
  469. package/dist/support/index.js +23 -0
  470. package/dist/support/index.js.map +1 -0
  471. package/dist/support/operations.d.ts +51 -0
  472. package/dist/support/operations.js +109 -0
  473. package/dist/support/operations.js.map +1 -0
  474. package/dist/support/plans.d.ts +6 -0
  475. package/dist/support/plans.js +130 -0
  476. package/dist/support/plans.js.map +1 -0
  477. package/dist/support/publications.d.ts +8 -0
  478. package/dist/support/publications.js +106 -0
  479. package/dist/support/publications.js.map +1 -0
  480. package/dist/support/recovery.d.ts +7 -0
  481. package/dist/support/recovery.js +43 -0
  482. package/dist/support/recovery.js.map +1 -0
  483. package/dist/support/service.d.ts +51 -0
  484. package/dist/support/service.js +143 -0
  485. package/dist/support/service.js.map +1 -0
  486. package/dist/support/transitions.d.ts +4 -0
  487. package/dist/support/transitions.js +29 -0
  488. package/dist/support/transitions.js.map +1 -0
  489. package/dist/support/uploads.d.ts +39 -0
  490. package/dist/support/uploads.js +115 -0
  491. package/dist/support/uploads.js.map +1 -0
  492. package/dist/support/validation.d.ts +15 -0
  493. package/dist/support/validation.js +54 -0
  494. package/dist/support/validation.js.map +1 -0
  495. package/dist/types/config.d.ts +16 -0
  496. package/dist/types/config.js +3 -0
  497. package/dist/types/config.js.map +1 -0
  498. package/dist/types/index.d.ts +1 -0
  499. package/dist/types/index.js +18 -0
  500. package/dist/types/index.js.map +1 -0
  501. package/dist/utils/billing-document-type.d.ts +3 -0
  502. package/dist/utils/billing-document-type.js +18 -0
  503. package/dist/utils/billing-document-type.js.map +1 -0
  504. package/dist/utils/billing-period-type.d.ts +3 -0
  505. package/dist/utils/billing-period-type.js +18 -0
  506. package/dist/utils/billing-period-type.js.map +1 -0
  507. package/dist/utils/email-hash.d.ts +1 -0
  508. package/dist/utils/email-hash.js +8 -0
  509. package/dist/utils/email-hash.js.map +1 -0
  510. package/dist/utils/export-dataset-stream.d.ts +19 -0
  511. package/dist/utils/export-dataset-stream.js +40 -0
  512. package/dist/utils/export-dataset-stream.js.map +1 -0
  513. package/dist/utils/index.d.ts +15 -0
  514. package/dist/utils/index.js +32 -0
  515. package/dist/utils/index.js.map +1 -0
  516. package/dist/utils/invoice-lines-type.d.ts +27 -0
  517. package/dist/utils/invoice-lines-type.js +34 -0
  518. package/dist/utils/invoice-lines-type.js.map +1 -0
  519. package/dist/utils/money-cents-type.d.ts +3 -0
  520. package/dist/utils/money-cents-type.js +18 -0
  521. package/dist/utils/money-cents-type.js.map +1 -0
  522. package/dist/utils/pagination.d.ts +22 -0
  523. package/dist/utils/pagination.js +35 -0
  524. package/dist/utils/pagination.js.map +1 -0
  525. package/dist/utils/parse-future-date.d.ts +1 -0
  526. package/dist/utils/parse-future-date.js +15 -0
  527. package/dist/utils/parse-future-date.js.map +1 -0
  528. package/dist/utils/row-instance.d.ts +1 -0
  529. package/dist/utils/row-instance.js +8 -0
  530. package/dist/utils/row-instance.js.map +1 -0
  531. package/dist/utils/segment-conditions-type.d.ts +33 -0
  532. package/dist/utils/segment-conditions-type.js +86 -0
  533. package/dist/utils/segment-conditions-type.js.map +1 -0
  534. package/dist/utils/segment-evaluator.d.ts +3 -0
  535. package/dist/utils/segment-evaluator.js +117 -0
  536. package/dist/utils/segment-evaluator.js.map +1 -0
  537. package/dist/utils/segment-fields.d.ts +19 -0
  538. package/dist/utils/segment-fields.js +212 -0
  539. package/dist/utils/segment-fields.js.map +1 -0
  540. package/dist/utils/segment-matching.d.ts +56 -0
  541. package/dist/utils/segment-matching.js +200 -0
  542. package/dist/utils/segment-matching.js.map +1 -0
  543. package/dist/utils/segment-name-cache.d.ts +2 -0
  544. package/dist/utils/segment-name-cache.js +22 -0
  545. package/dist/utils/segment-name-cache.js.map +1 -0
  546. package/dist/utils/time.d.ts +3 -0
  547. package/dist/utils/time.js +10 -0
  548. package/dist/utils/time.js.map +1 -0
  549. package/dist/workers/index.d.ts +1 -0
  550. package/dist/workers/index.js +18 -0
  551. package/dist/workers/index.js.map +1 -0
  552. package/dist/workers/plan-migration.d.ts +4 -0
  553. package/dist/workers/plan-migration.js +206 -0
  554. package/dist/workers/plan-migration.js.map +1 -0
  555. package/dist/workspaces/billing-profile.d.ts +3 -0
  556. package/dist/workspaces/billing-profile.js +55 -0
  557. package/dist/workspaces/billing-profile.js.map +1 -0
  558. package/dist/workspaces/complimentary.d.ts +7 -0
  559. package/dist/workspaces/complimentary.js +47 -0
  560. package/dist/workspaces/complimentary.js.map +1 -0
  561. package/dist/workspaces/db/card-capacity.model.d.ts +30 -0
  562. package/dist/workspaces/db/card-capacity.model.js +98 -0
  563. package/dist/workspaces/db/card-capacity.model.js.map +1 -0
  564. package/dist/workspaces/db/card-capacity.table.d.ts +11 -0
  565. package/dist/workspaces/db/card-capacity.table.js +34 -0
  566. package/dist/workspaces/db/card-capacity.table.js.map +1 -0
  567. package/dist/workspaces/db/provisioning-attempt.model.d.ts +24 -0
  568. package/dist/workspaces/db/provisioning-attempt.model.js +33 -0
  569. package/dist/workspaces/db/provisioning-attempt.model.js.map +1 -0
  570. package/dist/workspaces/db/provisioning-attempt.table.d.ts +18 -0
  571. package/dist/workspaces/db/provisioning-attempt.table.js +77 -0
  572. package/dist/workspaces/db/provisioning-attempt.table.js.map +1 -0
  573. package/dist/workspaces/db/trial-identity.model.d.ts +25 -0
  574. package/dist/workspaces/db/trial-identity.model.js +62 -0
  575. package/dist/workspaces/db/trial-identity.model.js.map +1 -0
  576. package/dist/workspaces/db/trial-identity.table.d.ts +7 -0
  577. package/dist/workspaces/db/trial-identity.table.js +34 -0
  578. package/dist/workspaces/db/trial-identity.table.js.map +1 -0
  579. package/dist/workspaces/deletion.d.ts +8 -0
  580. package/dist/workspaces/deletion.js +75 -0
  581. package/dist/workspaces/deletion.js.map +1 -0
  582. package/dist/workspaces/free-workspace-guard.d.ts +11 -0
  583. package/dist/workspaces/free-workspace-guard.js +96 -0
  584. package/dist/workspaces/free-workspace-guard.js.map +1 -0
  585. package/dist/workspaces/index.d.ts +6 -0
  586. package/dist/workspaces/index.js +23 -0
  587. package/dist/workspaces/index.js.map +1 -0
  588. package/dist/workspaces/provisioning-rollback.d.ts +2 -0
  589. package/dist/workspaces/provisioning-rollback.js +78 -0
  590. package/dist/workspaces/provisioning-rollback.js.map +1 -0
  591. package/dist/workspaces/provisioning-state.d.ts +6 -0
  592. package/dist/workspaces/provisioning-state.js +91 -0
  593. package/dist/workspaces/provisioning-state.js.map +1 -0
  594. package/dist/workspaces/provisioning.d.ts +49 -0
  595. package/dist/workspaces/provisioning.js +263 -0
  596. package/dist/workspaces/provisioning.js.map +1 -0
  597. package/dist/workspaces/registration-extras.d.ts +1 -0
  598. package/dist/workspaces/registration-extras.js +50 -0
  599. package/dist/workspaces/registration-extras.js.map +1 -0
  600. package/dist/workspaces/suspension.d.ts +13 -0
  601. package/dist/workspaces/suspension.js +124 -0
  602. package/dist/workspaces/suspension.js.map +1 -0
  603. package/frontend-vue/.editorconfig +12 -0
  604. package/frontend-vue/.prettierrc +11 -0
  605. package/frontend-vue/app/build/.gitkeep +0 -0
  606. package/frontend-vue/app/components/CardGrid.vue +77 -0
  607. package/frontend-vue/app/components/CustomerPortalButton.vue +45 -0
  608. package/frontend-vue/app/components/DataExport.vue +300 -0
  609. package/frontend-vue/app/components/DeletePlanModal.vue +223 -0
  610. package/frontend-vue/app/components/FreeAccessBanner.vue +70 -0
  611. package/frontend-vue/app/components/InvoiceLines.vue +57 -0
  612. package/frontend-vue/app/components/IssueCreditNoteModal.vue +128 -0
  613. package/frontend-vue/app/components/LegalLayout.vue +63 -0
  614. package/frontend-vue/app/components/LoadFailure.vue +25 -0
  615. package/frontend-vue/app/components/PastDueAlert.vue +96 -0
  616. package/frontend-vue/app/components/PaymentMethodCard.vue +86 -0
  617. package/frontend-vue/app/components/PlanCard.vue +294 -0
  618. package/frontend-vue/app/components/PlanCardPublic.vue +59 -0
  619. package/frontend-vue/app/components/PlanCardsDisplay.vue +127 -0
  620. package/frontend-vue/app/components/PlanComparisonModal.vue +213 -0
  621. package/frontend-vue/app/components/PlanInheritancePicker.vue +329 -0
  622. package/frontend-vue/app/components/PlatformNotes.vue +281 -0
  623. package/frontend-vue/app/components/PlatformSupport.vue +461 -0
  624. package/frontend-vue/app/components/RecentActivity.vue +72 -0
  625. package/frontend-vue/app/components/RefundButton.vue +126 -0
  626. package/frontend-vue/app/components/Register.vue +174 -0
  627. package/frontend-vue/app/components/RegistrationClosed.vue +15 -0
  628. package/frontend-vue/app/components/SeatQuotaBanner.vue +78 -0
  629. package/frontend-vue/app/components/SegmentConditionsBuilder.vue +176 -0
  630. package/frontend-vue/app/components/SegmentConditionsGroup.vue +494 -0
  631. package/frontend-vue/app/components/SupportAttachmentUpload.vue +140 -0
  632. package/frontend-vue/app/components/SupportThreadHistory.vue +139 -0
  633. package/frontend-vue/app/components/TenantBillingForm.vue +208 -0
  634. package/frontend-vue/app/components/TenantPlanCard.vue +223 -0
  635. package/frontend-vue/app/components/TenantSupport.vue +415 -0
  636. package/frontend-vue/app/components/UserSummaryCard.vue +166 -0
  637. package/frontend-vue/app/components/WorkspaceBillingInfo.vue +68 -0
  638. package/frontend-vue/app/components/WorkspaceCompAccessButton.vue +198 -0
  639. package/frontend-vue/app/components/WorkspaceCreateModal.vue +256 -0
  640. package/frontend-vue/app/components/WorkspaceDangerZone.vue +146 -0
  641. package/frontend-vue/app/components/WorkspaceDetailHeader.vue +24 -0
  642. package/frontend-vue/app/components/WorkspaceIdentity.vue +99 -0
  643. package/frontend-vue/app/components/WorkspaceJoinButton.vue +50 -0
  644. package/frontend-vue/app/components/WorkspaceOperatorActions.vue +340 -0
  645. package/frontend-vue/app/components/WorkspaceSummaryCard.vue +161 -0
  646. package/frontend-vue/app/components/WorkspaceSuspendButton.vue +167 -0
  647. package/frontend-vue/app/components/WorkspaceSuspended.vue +164 -0
  648. package/frontend-vue/app/components/WorkspaceSwitcherWidget.vue +247 -0
  649. package/frontend-vue/app/composables/useApiErrorMessage.ts +35 -0
  650. package/frontend-vue/app/composables/useBillingCountries.ts +54 -0
  651. package/frontend-vue/app/composables/useBillingDocumentType.ts +7 -0
  652. package/frontend-vue/app/composables/useBillingStatus.ts +39 -0
  653. package/frontend-vue/app/composables/useCurrentWorkspace.ts +43 -0
  654. package/frontend-vue/app/composables/useDetailRefresh.ts +17 -0
  655. package/frontend-vue/app/composables/useExportHistory.ts +143 -0
  656. package/frontend-vue/app/composables/useInvoiceLines.ts +22 -0
  657. package/frontend-vue/app/composables/useMoneyFormat.ts +49 -0
  658. package/frontend-vue/app/composables/useMyWorkspaces.ts +47 -0
  659. package/frontend-vue/app/composables/usePlanFeatureFormat.ts +60 -0
  660. package/frontend-vue/app/composables/usePlanIntervalLabel.ts +30 -0
  661. package/frontend-vue/app/composables/useSaasRegistration.ts +522 -0
  662. package/frontend-vue/app/composables/useSeatQuota.ts +18 -0
  663. package/frontend-vue/app/composables/useSharedRequest.ts +54 -0
  664. package/frontend-vue/app/composables/useStripePaymentElement.ts +74 -0
  665. package/frontend-vue/app/composables/useSubscriptionAccess.ts +12 -0
  666. package/frontend-vue/app/composables/useSupportRequest.ts +74 -0
  667. package/frontend-vue/app/composables/useTenantPlan.ts +95 -0
  668. package/frontend-vue/app/composables/useTenantSwitch.ts +22 -0
  669. package/frontend-vue/app/composables/useWorkspaceAccessCache.ts +25 -0
  670. package/frontend-vue/app/custom-pages/auth/no-workspace.vue +495 -0
  671. package/frontend-vue/app/middleware/workspace-suspended.global.ts +56 -0
  672. package/frontend-vue/app/plugins/auth-links.ts +24 -0
  673. package/frontend-vue/app/plugins/billing-data-types.ts +62 -0
  674. package/frontend-vue/app/plugins/footer-links.ts +36 -0
  675. package/frontend-vue/app/plugins/plan-cards-display.client.ts +16 -0
  676. package/frontend-vue/app/plugins/segment-conditions-data-type.client.ts +122 -0
  677. package/frontend-vue/app/plugins/sidebar-widgets.ts +13 -0
  678. package/frontend-vue/app/types/support.ts +123 -0
  679. package/frontend-vue/dms.frontend.ts +68 -0
  680. package/frontend-vue/eslint.config.mjs +13 -0
  681. package/frontend-vue/i18n/locales/saas-en-GB.json +1285 -0
  682. package/frontend-vue/i18n/locales/saas-fr-FR.json +1285 -0
  683. package/frontend-vue/package.json +27 -0
  684. package/frontend-vue/pnpm-lock.yaml +4948 -0
  685. package/frontend-vue/pnpm-workspace.yaml +2 -0
  686. package/frontend-vue/server/routes/auth/finalize-workspace.post.ts +61 -0
  687. package/package.json +91 -0
package/README.md ADDED
@@ -0,0 +1,658 @@
1
+ # @antelopejs/dms-saas
2
+
3
+ <div align="center">
4
+ <a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-blue?style=for-the-badge&labelColor=000000"></a>
5
+ <a href="https://discord.gg/sjK28QHrA7"><img src="https://img.shields.io/badge/Discord-18181B?logo=discord&style=for-the-badge&color=000000" alt="Discord"></a>
6
+ <a href="https://antelopejs.com"><img src="https://img.shields.io/badge/Docs-18181B?style=for-the-badge&color=000000" alt="Documentation"></a>
7
+ </div>
8
+
9
+ SaaS extension module for the AntelopeJS DMS.
10
+
11
+ Adds multi-tenant billing, plans, workspace switching, self-service workspace creation, refund policies, segments, reminders, and Stripe integration on top of the core DMS multi-tenant primitives.
12
+
13
+ See the design documents in `dms/saas/` (sibling repo) for the full architectural reference.
14
+
15
+ ## Vue frontend development
16
+
17
+ The module registers `frontend-vue/dms.frontend.ts` with the Vue 3 Inertia
18
+ adapter. It preserves the `DmsSaas*` component names, the `auth/no-workspace`
19
+ page override, client-only displays, global guards, and English/French catalogs.
20
+ Public module configuration moves from `public.cmsSaas` to `public.dmsSaas` —
21
+ a breaking change for any frontend reading the old key. Stripe secrets are
22
+ never exposed to the frontend.
23
+
24
+ The backend integration requires `@antelopejs/dms`. Frontend source
25
+ verification runs through `@antelopejs/dms-frontend` and the DMS frontend
26
+ source shipped in that published DMS package; no sibling checkout or local
27
+ package link is required.
28
+
29
+ This package lives in `packages/dms-saas` of the `AntelopeJS/dms-saas`
30
+ workspace. From that directory run `pnpm install`,
31
+ `pnpm --dir frontend-vue install`, `pnpm build`, `pnpm typecheck`, and
32
+ `pnpm test:frontend`. The frontend check generates a temporary workspace, then
33
+ builds client, SSR, and email bundles and runs Vue typechecking.
34
+
35
+ ## Tenant owner permissions
36
+
37
+ The `dms-saas.plan-intersection` permissions resolver runs at order 100. For a
38
+ member whose `isTenantOwner` is true in the requested tenant, it grants all
39
+ explicit permissions from that tenant's resolved plan, including inherited
40
+ permissions, regardless of assigned roles. Permissions outside the plan are
41
+ removed even when a role grants them. Other members retain only the intersection
42
+ of their incoming permissions and the resolved plan.
43
+
44
+ Tenant ownership never grants `*`, even if a plan contains it. An incoming `*`
45
+ (including the DMS platform owner's wildcard) retains the existing behavior:
46
+ the wildcard survives, and other incoming permissions are intersected with the
47
+ plan. Without a subscription, a `planId`, or an existing plan, the resolver
48
+ preserves incoming permissions and grants nothing new. This compatibility
49
+ fallback is not a denial of access for tenants with missing billing data.
50
+
51
+ Applications define their business permissions and can project the capabilities
52
+ that survive the plan into resource-specific actions in later resolvers. They
53
+ do not need a separate tenant-owner grant list. Subscription access gates remain
54
+ independent and unchanged. This resolver alone does not constrain
55
+ `defaultGranted` permissions or guards that do not consult effective permissions.
56
+
57
+ ## Native support tickets
58
+
59
+ The Support page stores tickets, messages, and ticket events in the active
60
+ tenant schema. Platform ticket listing uses `CROSS_INSTANCE`; MongoDB's
61
+ `_instance` identifies each ticket's tenant. Detail reads and writes use that
62
+ tenant's scoped models.
63
+
64
+ Support listings use the Data API endpoints:
65
+
66
+ - `/api/saas/tenant/tables/support-tickets/list`
67
+ - `/api/saas/tables/support-tickets/list`
68
+ - `/api/saas/tables/support-owners/list`
69
+ - Existing tenant and platform detail URLs, with `/messages/list` and
70
+ `/events/list` children (and `/count` variants)
71
+
72
+ List queries accept `offset`, `limit`, `sortKey`, `sortDirection`, and
73
+ `filter_<field>`. Responses contain `{ results, total, offset, limit }`. Owner
74
+ rows contain `_id`, `name`, and `email`. Global ticket rows include the joined
75
+ `tenantName`.
76
+
77
+ Pages default to 20 rows and are capped at 100. String filters use the DMS
78
+ comparison modes, for example `filter_status=is:open`. Recent-first reads keep
79
+ timestamp/ID compound ordering. Message and event pagination loads only the
80
+ requested collection; ticket scope is enforced by the server.
81
+
82
+ Status and assignment changes record the actor, previous/new values, and time
83
+ in `support_ticket_events`. This includes automatic reply transitions: support
84
+ replies wait for the customer, and customer replies resume tickets waiting for
85
+ them. Existing tickets start with no historical events; old history is not
86
+ invented. Existing central mirror data is unused and is not automatically deleted.
87
+
88
+ Support level comes from the inherited plan feature whose id is
89
+ `support-sla`. Supported string values are `community`, `email`, `priority`,
90
+ and `dedicated`. An absent or invalid value falls back to community support.
91
+ Those levels respectively expose normal; low/normal; low/normal/high; and all
92
+ priorities. Displayed first-response targets are no guarantee, 48 business
93
+ hours, 8 business hours, and 2 elapsed hours.
94
+
95
+ Attachments use the DMS upload token and staging flow below the tenant-bound
96
+ `support-attachments/{tenantId}` path. A message accepts up to five image, PDF,
97
+ or text files of 10 MiB each. Only staged keys from that tenant path are
98
+ accepted, each is promoted before the tenant message is persisted, and failed
99
+ writes move promoted files back to staging. Ticket-specific metadata routes
100
+ verify that a key belongs to the requested thread before issuing its read URL.
101
+
102
+ ## Extension points
103
+
104
+ ### Consuming this module
105
+
106
+ A module that extends dms-saas depends on the separately published interface
107
+ package (`"@antelopejs/interface-dms-saas"` in its `dependencies`) and
108
+ imports the extension points from it. The dms-saas runtime package remains a
109
+ separate dependency for modules that need the implementation; its package root
110
+ boots the registration graph:
111
+
112
+ | Subpath | Surface |
113
+ | --- | --- |
114
+ | `@antelopejs/interface-dms-saas` | every extension point except `db`: billing, data API, pages, plans, provisioning and registration flat, plus the `invoiceLineItems` and `workspaceLifecycle` namespaces |
115
+ | `@antelopejs/interface-dms-saas/billing` | customer balance and complimentary subscription state |
116
+ | `@antelopejs/interface-dms-saas/data-api` | hidden-value data API filters |
117
+ | `@antelopejs/interface-dms-saas/db` | canonical SaaS tables and data models |
118
+ | `@antelopejs/interface-dms-saas/hidden-filter` | the `HiddenStringFilter` decorator on its own |
119
+ | `@antelopejs/interface-dms-saas/invoice-line-items` | provider registration, line item types, line key helpers |
120
+ | `@antelopejs/interface-dms-saas/page-definitions` | page and module ids, slugs and descriptors |
121
+ | `@antelopejs/interface-dms-saas/pages` | workspace settings category and tenant billing page extensions |
122
+ | `@antelopejs/interface-dms-saas/plans` | plan projections, catalog builder, and price normalization |
123
+ | `@antelopejs/interface-dms-saas/provisioning` | provisioning hook payload |
124
+ | `@antelopejs/interface-dms-saas/registration` | public registration capture limits |
125
+ | `@antelopejs/interface-dms-saas/workspace-lifecycle` | workspace lifecycle events and operator actions |
126
+
127
+ `invoiceLineItems` and `workspaceLifecycle` come off the root entry as
128
+ namespaces because each carries an `internal` proxy namespace of its own; `db`
129
+ is reachable only through its subpath, since importing it registers the SaaS
130
+ tables.
131
+
132
+ This module declares the interface package name in `antelopeJs.implements`, so as
133
+ long as both modules run in the same AntelopeJS project, those imports are
134
+ detoured to the running dms-saas instance instead of a second copy pulled from
135
+ `node_modules`. Registration goes through an interface proxy on top of that: a
136
+ provider registered before dms-saas is constructed is held and replayed on
137
+ attach, replayed again when dms-saas is reloaded, and dropped when the
138
+ registering module is unloaded.
139
+
140
+ The interface package must be released before dms-saas. During workspace
141
+ development dms-saas uses `workspace:*`; publishing replaces that range with
142
+ the released interface version. Release the interface package first, then
143
+ release dms-saas, and update consumers to the published interface version.
144
+
145
+ ### Public screens
146
+
147
+ dms-saas ships a working registration screen so a fresh project can sell from
148
+ day one. It is a reference implementation, not a design: the module owns the
149
+ money and the compliance of the flow, the consuming SaaS owns the conversion.
150
+
151
+ Replacing it takes two steps. Turn the bundled page off in the module config —
152
+ page registration is keyed by slug, so declaring a second page on `register`
153
+ races the bundled one instead of overriding it:
154
+
155
+ ```json
156
+ {
157
+ "modules": {
158
+ "dms-saas": {
159
+ "config": {
160
+ "publicScreens": { "register": false }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ ```
166
+
167
+ Then register your own page on the `register` slug and build it on the
168
+ `useSaasRegistration()` composable the Vue adapter auto-imports. It holds the
169
+ whole flow — plan loading and filtering by customer type, the Stripe setup
170
+ intent and card confirmation, the order the requirements are validated in, the
171
+ provisioning call and the landing route — and renders nothing:
172
+
173
+ ```vue
174
+ <script setup lang="ts">
175
+ const { form, plans, errorMessage, isSubmitting, formatPlanPrice, submit } =
176
+ useSaasRegistration({ redirectTo: "/welcome" });
177
+ </script>
178
+ ```
179
+
180
+ Nothing it returns throws: a failure surfaces as a translated `errorMessage`,
181
+ and `submit()` resolves to the new tenant id or `null`. Every screen stays
182
+ enabled by default, so an existing project needs no configuration change.
183
+
184
+ ### Registration extras and the provisioning hook
185
+
186
+ A SaaS that captures its own fields at signup — referral source, team size,
187
+ anything — sends them as `extras` on the registration payload and writes them
188
+ from a `TENANT_BEING_PROVISIONED` listener. dms-saas forwards the object
189
+ verbatim: it never reads it, never stores it, never returns it. The data stays
190
+ the consumer's, and so does the schema.
191
+
192
+ ```ts
193
+ import type { TenantBeingProvisionedPayload } from "@antelopejs/interface-dms-saas/provisioning";
194
+ import {
195
+ Hook,
196
+ RegisterHook,
197
+ } from "@antelopejs/interface-dms/hooks";
198
+
199
+ RegisterHook(
200
+ Hook.TENANT_BEING_PROVISIONED,
201
+ async ({ tenantId, userId, extras }: TenantBeingProvisionedPayload) => {
202
+ await storeOnboardingAnswers(tenantId, userId, extras);
203
+ return undefined;
204
+ },
205
+ );
206
+ ```
207
+
208
+ `storeOnboardingAnswers` is your module's persistence function. Keep the explicit `undefined` return: this hook's handler contract is `Promise<undefined>`, not `Promise<void>`.
209
+
210
+ **Contract**
211
+
212
+ - The hook is emitted inside the provisioning transaction, once the workspace
213
+ is complete and before it is handed back. Listeners run in series and are
214
+ awaited; **a listener that throws cancels the registration** — tenant,
215
+ subscription, Stripe customer and, on the password path, the account itself
216
+ are rolled back. That is the point: a workspace that is paid for but missing
217
+ the data its owner filled in is worse than no workspace.
218
+ - It runs while the per-card provisioning lock is held, so a slow listener
219
+ slows every concurrent signup on that card. Write, do not call out.
220
+ - `extras` reaches both entry points — password registration and the
221
+ OAuth-entry completion — and is absent when the consumer captured nothing.
222
+ - Registration is public and unauthenticated, so `extras` is bounded before it
223
+ is forwarded: **4 KB serialised, 64 keys, 4 levels deep**, and no
224
+ `__proto__` / `constructor` / `prototype` key. Anything above answers 400
225
+ with `saas.errors.registration.extras_*`. `REGISTRATION_EXTRAS_LIMITS` is
226
+ available from `dms-saas/registration` so a consumer can bound
227
+ its own capture first.
228
+ - Nothing else in dms-saas depends on a listener existing: with no listener
229
+ registered, registration behaves exactly as before.
230
+
231
+ On the browser side, `useSaasRegistration()` takes the capture as an option
232
+ and sends it with the rest of the form:
233
+
234
+ ```vue
235
+ <script setup lang="ts">
236
+ const answers = reactive({ referral: "", teamSize: "" });
237
+ const { form, submit } = useSaasRegistration({ extras: () => answers });
238
+ </script>
239
+ ```
240
+
241
+ ### Invoice line items
242
+
243
+ `RegisterInvoiceLineItemsProvider` lets a module bill its own metered usage on
244
+ the workspace's subscription invoice. When Stripe opens the renewal invoice of
245
+ a billing cycle, dms-saas asks every registered provider for the lines it wants
246
+ and pushes them as Stripe invoice items while the invoice is still a draft, so
247
+ they are charged on finalization.
248
+
249
+ dms-saas stays agnostic: it never interprets a line. What a metric is, how it
250
+ is measured and how it is priced belong to the provider.
251
+
252
+ ```ts
253
+ import {
254
+ RegisterInvoiceLineItemsProvider,
255
+ UnregisterInvoiceLineItemsProvider,
256
+ } from "@antelopejs/interface-dms-saas/invoice-line-items";
257
+
258
+ const PROVIDER_ID = "cloud";
259
+
260
+ export async function construct(): Promise<void> {
261
+ RegisterInvoiceLineItemsProvider({
262
+ id: PROVIDER_ID,
263
+ resolve: async ({ tenantId, periodStart, periodEnd, currency }) => {
264
+ const usage = await aggregateUsage(tenantId, periodStart, periodEnd);
265
+ return [
266
+ {
267
+ key: "vcpu-minutes",
268
+ description: "vCPU minutes",
269
+ amountCents: usage.vcpuCents,
270
+ quantity: usage.vcpuMinutes,
271
+ unit: "minute",
272
+ },
273
+ {
274
+ key: "included-credit",
275
+ description: "Included usage credit",
276
+ amountCents: -usage.includedCreditCents,
277
+ },
278
+ ];
279
+ },
280
+ });
281
+ }
282
+
283
+ export async function stop(): Promise<void> {
284
+ UnregisterInvoiceLineItemsProvider(PROVIDER_ID);
285
+ }
286
+ ```
287
+
288
+ **Contract**
289
+
290
+ - Providers run on `subscription_cycle` invoices only — never on a
291
+ subscription's first invoice nor on one-off invoices, which have no closed
292
+ usage period behind them.
293
+ - `periodStart` / `periodEnd` are the boundaries of the **cycle that just
294
+ closed**, not of the upcoming cycle the plan line covers.
295
+ - `amountCents` is an integer total in the invoice currency and may be
296
+ negative: that is how a plan's included credit is deducted. Zero-amount lines
297
+ are dropped. A structurally invalid line (non-integer amount, empty key or
298
+ description, oversized or `:`-carrying key) fails the webhook event once
299
+ every provider has run: it is usage that would otherwise never be billed.
300
+ - `key` is the unit of idempotency, namespaced by the provider `id`. The same
301
+ key is injected at most once per invoice, whatever the number of webhook
302
+ redeliveries or concurrent workers — so keep it stable across cycles and
303
+ never derive it from a timestamp. Neither `id` nor `key` may contain `:`,
304
+ which joins them, and together they must stay under 150 characters — they
305
+ compose the Stripe idempotency key. `quantity` and `unit` are recorded as
306
+ Stripe metadata for auditability; the amount charged is always
307
+ `amountCents`.
308
+ - A resolver that throws is logged and skipped: the other providers still run
309
+ and the invoice is still mirrored. Once every provider has been attempted,
310
+ a partial injection fails the webhook so it surfaces instead of silently
311
+ underbilling the cycle — replays cannot double-charge, every line being
312
+ idempotent.
313
+ - Resolvers run inside the Stripe webhook request. Read pre-aggregated
314
+ rollups; a resolver that computes usage on the fly delays the webhook
315
+ response for every provider.
316
+ - Register in `construct()`, unregister in `stop()`. An `id` must be unique
317
+ across modules: registering one that is already taken replaces the previous
318
+ provider, whose usage lines then stop being invoiced. Registration is keyed
319
+ by `id` all the way down to the interface proxy — which is both why a clash
320
+ cannot be refused without stranding whichever module registered first, and
321
+ why it is only reported at error level once dms-saas is attached. Two modules
322
+ registering the same `id` before that collapse into one silently, so pick an
323
+ `id` no other module could plausibly choose.
324
+
325
+ ### Workspace settings pages
326
+
327
+ A module adding a page to a workspace's settings takes the side-effect-free
328
+ `workspaceSettingsCategory` descriptor from the interface rather than
329
+ rebuilding its hierarchy and metadata. The descriptor supports synchronous
330
+ `PageController` declarations but is intentionally not reference-equal to the
331
+ registered runtime object. Runtime code that requires canonical identity can
332
+ await `GetWorkspaceSettingsCategory()` after the SaaS runtime implements the
333
+ interface.
334
+
335
+ ```ts
336
+ import { PageController, RegisterPage } from "@antelopejs/interface-dms/page";
337
+ import { workspaceSettingsCategory } from "@antelopejs/interface-dms-saas/pages";
338
+
339
+ @RegisterPage()
340
+ export class WorkspaceRegistriesController extends PageController("registries", {
341
+ displayName: "$cloud.workspace.registries.title",
342
+ category: workspaceSettingsCategory,
343
+ icon: "i-ph-package",
344
+ order: 10,
345
+ }) {}
346
+ ```
347
+
348
+ Extensions of the existing tenant billing page register components through
349
+ stable page and anchor identifiers. They do not import the page controller,
350
+ which would load the module's page registration graph.
351
+
352
+ ```ts
353
+ import { CustomComponent } from "@antelopejs/interface-dms/base/custom";
354
+ import {
355
+ RegisterTenantBillingPageExtension,
356
+ tenantBillingPage,
357
+ type TenantBillingPageExtensionRegistration,
358
+ } from "@antelopejs/interface-dms-saas/pages";
359
+
360
+ let billingBlocks: TenantBillingPageExtensionRegistration | undefined;
361
+
362
+ export function construct(): void {
363
+ billingBlocks = RegisterTenantBillingPageExtension({
364
+ name: "CloudBillingBlocks",
365
+ components: [
366
+ {
367
+ key: "inProgressInvoice",
368
+ component: CustomComponent("CloudInProgressInvoice"),
369
+ side: "after",
370
+ anchorKey: tenantBillingPage.components.planCard,
371
+ },
372
+ ],
373
+ });
374
+ }
375
+
376
+ export function stop(): void {
377
+ billingBlocks?.unregister();
378
+ billingBlocks = undefined;
379
+ }
380
+ ```
381
+
382
+ Platform modules can extend the SaaS platform-owner workspace detail without
383
+ importing its controller or the private `saasModule` instance. Use
384
+ `platformSaasModule`, `platformWorkspaceDetailPage`, and
385
+ `RegisterPlatformWorkspaceDetailPageExtension` from the same public `pages`
386
+ entry point. `platformSaasModule` is also a synchronous descriptor; runtime
387
+ code that requires the registered module root can await
388
+ `GetPlatformSaasModule()`. Platform data controllers that must hide a tenant
389
+ routing field can import `HiddenStringFilter` from
390
+ `@antelopejs/interface-dms-saas/data-api`; the underlying
391
+ SaaS data controllers and database models remain private.
392
+
393
+ ### Platform-owner operations and workspace lifecycle
394
+
395
+ The platform-owner workspace page provides suspension, reactivation, immediate
396
+ Stripe-backed upgrades, and Stripe customer-balance credits. Every request
397
+ uses a caller-supplied operation ID and creates a private durable command intent
398
+ before any Stripe or lifecycle effect. The command state retains the actor,
399
+ tenant, action, redacted-safe values, attempts, outcome, and effective time.
400
+ Retrying the same ID and values resumes an eligible failed operation; reusing
401
+ it with different values is rejected.
402
+
403
+ Operator attempts do not use leases or timed takeover. A definitive failure
404
+ whose execution has finished may retry with the same operation and provider
405
+ payload for 23 hours from intent creation. This preserves a one-hour margin
406
+ inside Stripe's minimum 24-hour idempotency retention. An unknown outcome,
407
+ including lost journal acknowledgement, requires reconciliation instead.
408
+
409
+ Suspension, reactivation, and immediate plan changes persist a subscription
410
+ transition before effects. Its revision fences competing local transitions and
411
+ deletion; the operator journal must succeed before its intent is cleared.
412
+ An ordinary subscription write rejects pending transitions and deletion markers.
413
+ This does not provide distributed transactions or fence an external request
414
+ that has already left the process.
415
+
416
+ Inspect an operation through the platform-owner-only endpoint
417
+ `GET /api/saas/workspaces/:tenantId/operations/:operationId`. A running or
418
+ reconciliation-required operation may have an old executor still active.
419
+ Before resolving it, establish **both** that the previous executor is stopped
420
+ or quiescent and what happened externally, using the persisted operation,
421
+ provider request details, and provider records. A matching Stripe read alone
422
+ does not establish quiescence. There is deliberately no force-success endpoint
423
+ that clears the intent without those proofs. This trades automatic crash
424
+ recovery and availability for protection against conflicting external effects.
425
+
426
+ Bulk plan migrations capture an immutable workspace list and resolved target
427
+ configuration before admitting an execution. Each workspace gets a persisted
428
+ outcome and a subscription transition before provider effects. A crash after
429
+ changing `planId` does not remove that workspace from the snapshot. Running
430
+ jobs never use timed takeover; startup marks interrupted jobs as
431
+ `reconciliation_required`, retaining their per-workspace evidence and pending
432
+ subscription intents instead of blindly replaying effects.
433
+
434
+ The historical `migrate-and-delete` endpoint now requests migration only.
435
+ Inspect `GET /api/saas/plans-deletion/migrations/:migrationId` for the snapshot,
436
+ outcomes, and reconciliation requirements. **Snapshot completion does not retire
437
+ the source plan.** The source remains available even at zero observed references;
438
+ workspaces arriving after capture are outside this job. Any later retirement
439
+ requires a separate procedure that establishes writer quiescence. A current
440
+ reference count cannot exclude a suspended writer that already validated the plan.
441
+
442
+ Migration reconciliation requires stopping or proving quiescence of the prior
443
+ executor and establishing the provider, subscription, permission-cleanup, and
444
+ notification outcomes. A target `planId` or matching Stripe response alone is
445
+ not sufficient. Failed core lifecycle admissions may also remain closed to
446
+ destruction until their evidence is resolved. There is no automatic force-success
447
+ or effect-replay endpoint; arbitrary hooks are not made idempotent by a job ID.
448
+
449
+ Self-service cancellation, deferred plan changes, and administrative free grants
450
+ also admit subscription intent before Stripe effects. An ambiguous schedule
451
+ replacement retains the previous mirror and pending intent; it does not attempt
452
+ to restore or erase provider state blindly. Owners can inspect these intents and
453
+ the irreversible deletion marker through the workspace `admin-state` endpoint.
454
+
455
+ Checkout holds a `checkout` intent until the exact recorded session completes
456
+ or expires. Completion admits one callback executor and writes a terminal session
457
+ receipt only after its awaited provider effects finish. Unknown callback outcomes
458
+ retain intent rather than enabling timed replay. A session whose ID was never
459
+ acknowledged locally requires manual reconciliation, including executor quiescence.
460
+ Trial reservations are permanent across checkout expiration; uncertain attempts
461
+ do not receive another trial. Checkout automation remains best-effort, outside
462
+ the terminal receipt, and does not promise exactly-once delivery or external order.
463
+
464
+ Stripe webhook dispatch admits an event once and fences completion with its
465
+ admitted revision. An old `pending` record never permits timed takeover. Handler
466
+ failures become `reconciliation_required`; legacy `failed` records also block
467
+ replay because they may contain partial effects. Redelivery receives an error
468
+ while unresolved, rather than a successful acknowledgement or another execution.
469
+
470
+ Inspect `stripe_webhook_events` by Stripe event ID for its result, revision, and
471
+ error message. Recovery requires establishing the prior executor's quiescence
472
+ and the handler's database and external outcomes; do not delete the admission
473
+ or resend blindly. There is no automatic recovery endpoint. Unresolved records
474
+ remain indefinitely. The existing retention policy still removes old terminal
475
+ `success`/`skipped` receipts, so deduplication is not guaranteed after that window.
476
+
477
+ Revision mutations require the published database interface `0.1.6` or later
478
+ and an adapter implementing that contract. The MongoDB test adapter uses `1.3.0`,
479
+ and any DMS release carrying this module satisfies the requirement. New records
480
+ initialize revisions; legacy PostgreSQL rows with a declared revision column
481
+ require an explicit revision backfill
482
+ before these mutations can proceed. An absent revision is not equivalent to
483
+ `null`, and unsupported bootstrap fails closed. Do not run this backfill against
484
+ shared data without a separately approved migration and quiescent writers.
485
+
486
+ Lifecycle-dependent modules register a required consumer through the public
487
+ interface:
488
+
489
+ ```ts
490
+ import {
491
+ RegisterWorkspaceLifecycleConsumer,
492
+ type WorkspaceLifecycleConsumerRegistration,
493
+ } from "@antelopejs/interface-dms-saas/workspace-lifecycle";
494
+
495
+ let lifecycleRegistration: WorkspaceLifecycleConsumerRegistration | undefined;
496
+
497
+ export function construct(): void {
498
+ lifecycleRegistration = RegisterWorkspaceLifecycleConsumer({
499
+ name: "cloud.workspaces",
500
+ transitions: ["suspended", "reactivation_requested"],
501
+ async consume(message) {
502
+ const receipt = await applyWorkspaceLifecycle(message);
503
+ return {
504
+ receiptId: receipt.id,
505
+ effectiveAt: receipt.effectiveAt,
506
+ };
507
+ },
508
+ });
509
+ }
510
+
511
+ export function stop(): void {
512
+ lifecycleRegistration?.unregister();
513
+ lifecycleRegistration = undefined;
514
+ }
515
+ ```
516
+
517
+ Registration may happen before dms-saas construction: dms-saas replays buffered
518
+ consumers when it attaches its module-owned registry. Registrations are removed
519
+ automatically when their owning module unloads; the explicit handle remains
520
+ available for module stop compatibility. Register required consumers during
521
+ module construction, before module startup reconciliation. Messages carry
522
+ stable `tenantId` and `operationId` values. Deliveries and receipts are
523
+ persisted; a persisted success is skipped on later retries. Concurrent
524
+ reconcilers may invoke the same consumer more than once before its receipt is
525
+ persisted. Consumers must deduplicate concurrent calls by operation identity;
526
+ the outbox does not provide exactly-once execution or ordering of external
527
+ effects. Failed deliveries remain available to startup reconciliation and a
528
+ five-minute retry worker. Suspension
529
+ closes SaaS access before consumer delivery. Reactivation keeps SaaS access
530
+ closed until every required consumer returns a durable receipt; the consumer
531
+ therefore owns any product-specific sleep or wake work.
532
+
533
+ #### Successful workspace creation
534
+
535
+ Provisioning reserves free-workspace capacity per card and trial eligibility
536
+ per email/card identity before issuing provider effects. Reservations do not
537
+ expire. An unknown provider or persistence outcome keeps the reservation and
538
+ the account for reconciliation; the service never replays opaque provisioning
539
+ hooks or stores their `extras`. Known provider handles and the attempt ID are
540
+ persisted separately from billing profiles. Stripe customer metadata also
541
+ contains the attempt ID for investigating a lost creation response.
542
+
543
+ Platform owners inspect the first 100 unresolved records through
544
+ `GET /api/saas/workspaces/provisioning-attempts` and an individual record through
545
+ `GET /api/saas/workspaces/:tenantId/provisioning-attempt`. Preparing records can
546
+ represent an executor that disappeared before recording its error. Establish
547
+ executor quiescence, provider cancellation or successful creation, and tenant
548
+ closure before repairing a record or releasing an allocation. This release
549
+ does not provide an automated repair command. Never release uncertain
550
+ reservations by age or re-run non-idempotent hooks with guessed input.
551
+
552
+ Every consumer declares the transitions it handles, for example
553
+ `transitions: ["created"]` for creation only or all three when it also handles
554
+ suspension and reactivation. A consumer must return a durable receipt and
555
+ deduplicate effects by `operationId`:
556
+ `workspace-created:<tenantId>` remains stable across delivery retries.
557
+
558
+ Self-service provisioning writes a creation marker in the existing lifecycle
559
+ outbox **before inserting the tenant**. Only after ownership, billing records
560
+ and every `TENANT_BEING_PROVISIONED` listener succeed does it allow payment
561
+ confirmation. Trials and creations without an invoice require no payment;
562
+ zero-total invoices already marked paid are not paid again. An invoice-backed
563
+ creation becomes committed only after Stripe reports its first invoice paid.
564
+ Consumer failures never roll back committed workspaces.
565
+
566
+ Inventory reconcilers must check the public provisioning gate before creating
567
+ external resources. This check prevents a concurrent inventory scan from
568
+ provisioning a tenant whose membership, hooks or payment are still incomplete.
569
+ It does not replace tenant existence, authorization or suspension checks.
570
+
571
+ ```ts
572
+ import { IsWorkspaceProvisioningCommitted } from
573
+ "@antelopejs/interface-dms-saas/workspace-lifecycle";
574
+
575
+ async function reconcileTenant(tenantId: string): Promise<void> {
576
+ if (!(await IsWorkspaceProvisioningCommitted(tenantId))) return;
577
+ await ensureWorkspaceResources(tenantId);
578
+ }
579
+ ```
580
+
581
+ The gate returns true for legacy/default/bootstrap tenants without a creation
582
+ marker. It returns false for preparing, unpaid or cancelled creations, and
583
+ propagates storage failures; callers must fail closed. Cancellation leaves a
584
+ tombstone so even a partial rollback cannot make an orphaned tenant eligible.
585
+ Do not delete these markers while the tenant may remain in an inventory.
586
+
587
+ Reconciliation recovers a crash after successful payment but before delivery,
588
+ partial consumer fan-out and lost receipts. It may deliver a message again
589
+ when a consumer commits its effect before the receipt is saved. Consumers must
590
+ make their resource creation and ownership linkage idempotent. Delivery skips
591
+ tenants already deleted when the attempt starts; consumers must also tolerate
592
+ deletion racing with an in-flight attempt.
593
+
594
+ A definitive card decline permits rollback only after tenant lifecycle
595
+ admission closes and all required deletion hooks succeed. An incomplete
596
+ closure preserves data, account ownership, and recovery markers. Rollback
597
+ never drops the tenant schema or the lifecycle/invitation tombstones. An
598
+ ambiguous payment error preserves the tenant and account because a timeout can
599
+ hide a successful charge. Reconciliation checks payment status but never starts
600
+ another charge. A crash before payment, an unpaid ambiguous result, or an
601
+ interrupted pre-payment preparation requires payment/provisioning recovery;
602
+ it never emits `created` merely because the tenant exists. HTTP creation requests
603
+ are not made idempotent by the delivery operation ID.
604
+
605
+ These additions require a dms-saas package built from this source revision (or
606
+ a later release containing it), including its lifecycle table fields and worker.
607
+ The previously published `0.2.5` package does not provide the gate or `created`
608
+ contract. Register consumers before startup reconciliation; use the existing
609
+ tenant inventory and gate for bootstrap/backfill rather than treating `created`
610
+ as a historical inventory API.
611
+
612
+ ## Support attachment storage and recovery
613
+
614
+ Configure `supportStorage` with an explicit named file-storage definition. Support
615
+ issues private staged uploads through its tenant-member `/api/saas/support/uploads`
616
+ route and persists the tenant, source key and storage name before returning the
617
+ upload capability. Native `/api/files` routes do not authorize support files.
618
+ Support read routes check ticket/message membership before minting a read URL.
619
+
620
+ Keep every old named storage definition unchanged while its uploads, receipts or
621
+ files remain live. Selecting a new `supportStorage` name affects only new uploads;
622
+ existing receipts retain their original routing. Unknown names fail closed. A name
623
+ does not identify a provider incarnation and cannot detect remapping that same
624
+ name to a different backend. Use isolated nonreused keys and prevent privileged or
625
+ external writers from modifying support objects.
626
+
627
+ The storage adapter must provide write-once uploads and dedicated no-clobber
628
+ `PromoteFile`, with trusted-origin replay and private visibility preservation.
629
+ Promotion moves a staged upload to its canonical key without the staging prefix;
630
+ support never retains an expiring staged key as the published reference. Support
631
+ records positive promotion confirmation before validating final metadata, then
632
+ uses the existing database operation receipt to authorize publication. Published
633
+ prerequisites are the database interface `0.1.6`, the storage interface `0.1.3`,
634
+ and a compatible provider: local `0.1.4` or S3 `0.1.3`, all of which any DMS
635
+ release carrying this module provides. Tests use MongoDB `1.3.0`.
636
+ There is no legacy move/existence fallback.
637
+
638
+ Source admissions remain insert-only and permanent. Rejected work cannot publish,
639
+ even if a delayed promotion finishes. Owner-initiated paginated support recovery
640
+ repeats ordinary deletion of owned rejected sources and positively confirmed
641
+ finals. It never promotes rejected work just to establish cleanup ownership and
642
+ never deletes an unconfirmed or foreign final. Uncertain acknowledgements can
643
+ therefore retain private orphans. Recovery is not autonomous garbage collection;
644
+ operators must repeat complete passes, including after delayed uploads finish.
645
+ Already issued signed read URLs remain valid until their normal expiry.
646
+
647
+ Never-submitted upload receipts have no operation to recover. Configure provider
648
+ staging expiry for abandoned bytes; permanent issuance/admission metadata is not
649
+ automatically collected. Upload capabilities and in-flight writes can outlive a
650
+ cleanup pass, so storage expiry/operational cleanup must account for them. Do not
651
+ delete receipts to free a source for another request or garbage-collect a file
652
+ that a committed support message still references.
653
+
654
+ The earlier draft seal schema has no production installations and is replaced,
655
+ not migrated online. If retaining development fixtures from that draft, stop
656
+ writers and reconcile or discard those disposable support fixtures and their
657
+ private files offline before adopting this schema. Do not reinterpret old seal
658
+ records as confirmed promotion ownership.
@@ -0,0 +1,3 @@
1
+ export * from "./oauth-entry";
2
+ export * from "./plan-permissions-resolver";
3
+ export * from "./subscription-access-gate";