@rytass/bpm-core-nestjs-module 0.1.0

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 (460) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +837 -0
  4. package/package.json +168 -0
  5. package/src/index.d.ts +14 -0
  6. package/src/index.js +18 -0
  7. package/src/index.js.map +1 -0
  8. package/src/lib/attachment/attachment-options.d.ts +44 -0
  9. package/src/lib/attachment/attachment-options.js +62 -0
  10. package/src/lib/attachment/attachment-options.js.map +1 -0
  11. package/src/lib/attachment/attachment-storage.provider.d.ts +4 -0
  12. package/src/lib/attachment/attachment-storage.provider.js +35 -0
  13. package/src/lib/attachment/attachment-storage.provider.js.map +1 -0
  14. package/src/lib/attachment/attachment-storage.token.d.ts +3 -0
  15. package/src/lib/attachment/attachment-storage.token.js +5 -0
  16. package/src/lib/attachment/attachment-storage.token.js.map +1 -0
  17. package/src/lib/attachment/attachment.controller.d.ts +8 -0
  18. package/src/lib/attachment/attachment.controller.js +38 -0
  19. package/src/lib/attachment/attachment.controller.js.map +1 -0
  20. package/src/lib/attachment/attachment.entity.d.ts +14 -0
  21. package/src/lib/attachment/attachment.entity.js +74 -0
  22. package/src/lib/attachment/attachment.entity.js.map +1 -0
  23. package/src/lib/attachment/attachment.module.d.ts +27 -0
  24. package/src/lib/attachment/attachment.module.js +103 -0
  25. package/src/lib/attachment/attachment.module.js.map +1 -0
  26. package/src/lib/attachment/attachment.mutations.d.ts +8 -0
  27. package/src/lib/attachment/attachment.mutations.js +35 -0
  28. package/src/lib/attachment/attachment.mutations.js.map +1 -0
  29. package/src/lib/attachment/attachment.queries.d.ts +9 -0
  30. package/src/lib/attachment/attachment.queries.js +78 -0
  31. package/src/lib/attachment/attachment.queries.js.map +1 -0
  32. package/src/lib/attachment/attachment.service.d.ts +49 -0
  33. package/src/lib/attachment/attachment.service.js +276 -0
  34. package/src/lib/attachment/attachment.service.js.map +1 -0
  35. package/src/lib/attachment/dto/upload-attachment.input.d.ts +11 -0
  36. package/src/lib/attachment/dto/upload-attachment.input.js +68 -0
  37. package/src/lib/attachment/dto/upload-attachment.input.js.map +1 -0
  38. package/src/lib/attachment/index.d.ts +5 -0
  39. package/src/lib/attachment/index.js +9 -0
  40. package/src/lib/attachment/index.js.map +1 -0
  41. package/src/lib/bpm/bpm-root.module.d.ts +155 -0
  42. package/src/lib/bpm/bpm-root.module.js +170 -0
  43. package/src/lib/bpm/bpm-root.module.js.map +1 -0
  44. package/src/lib/bpm/index.d.ts +1 -0
  45. package/src/lib/bpm/index.js +5 -0
  46. package/src/lib/bpm/index.js.map +1 -0
  47. package/src/lib/bpm-auth/bpm-auth-context.d.ts +24 -0
  48. package/src/lib/bpm-auth/bpm-auth-context.extractor.d.ts +4 -0
  49. package/src/lib/bpm-auth/bpm-auth-context.extractor.js +69 -0
  50. package/src/lib/bpm-auth/bpm-auth-context.extractor.js.map +1 -0
  51. package/src/lib/bpm-auth/bpm-auth-context.js +15 -0
  52. package/src/lib/bpm-auth/bpm-auth-context.js.map +1 -0
  53. package/src/lib/bpm-auth/bpm-auth.authorization.d.ts +12 -0
  54. package/src/lib/bpm-auth/bpm-auth.authorization.js +67 -0
  55. package/src/lib/bpm-auth/bpm-auth.authorization.js.map +1 -0
  56. package/src/lib/bpm-auth/bpm-auth.decorators.d.ts +3 -0
  57. package/src/lib/bpm-auth/bpm-auth.decorators.js +11 -0
  58. package/src/lib/bpm-auth/bpm-auth.decorators.js.map +1 -0
  59. package/src/lib/bpm-auth/bpm-auth.guard.d.ts +7 -0
  60. package/src/lib/bpm-auth/bpm-auth.guard.js +24 -0
  61. package/src/lib/bpm-auth/bpm-auth.guard.js.map +1 -0
  62. package/src/lib/bpm-auth/bpm-auth.module.d.ts +6 -0
  63. package/src/lib/bpm-auth/bpm-auth.module.js +69 -0
  64. package/src/lib/bpm-auth/bpm-auth.module.js.map +1 -0
  65. package/src/lib/bpm-auth/bpm-auth.options.d.ts +11 -0
  66. package/src/lib/bpm-auth/bpm-auth.options.js +3 -0
  67. package/src/lib/bpm-auth/bpm-auth.options.js.map +1 -0
  68. package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.d.ts +10 -0
  69. package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.js +40 -0
  70. package/src/lib/bpm-auth/configurable-bpm-auth-context.accessor.js.map +1 -0
  71. package/src/lib/bpm-auth/index.d.ts +6 -0
  72. package/src/lib/bpm-auth/index.js +10 -0
  73. package/src/lib/bpm-auth/index.js.map +1 -0
  74. package/src/lib/common/filters/all-exceptions.filter.d.ts +25 -0
  75. package/src/lib/common/filters/all-exceptions.filter.js +93 -0
  76. package/src/lib/common/filters/all-exceptions.filter.js.map +1 -0
  77. package/src/lib/common/index.d.ts +1 -0
  78. package/src/lib/common/index.js +5 -0
  79. package/src/lib/common/index.js.map +1 -0
  80. package/src/lib/common/iso-duration.d.ts +1 -0
  81. package/src/lib/common/iso-duration.js +27 -0
  82. package/src/lib/common/iso-duration.js.map +1 -0
  83. package/src/lib/condition/condition.module.d.ts +2 -0
  84. package/src/lib/condition/condition.module.js +16 -0
  85. package/src/lib/condition/condition.module.js.map +1 -0
  86. package/src/lib/condition/condition.service.d.ts +16 -0
  87. package/src/lib/condition/condition.service.js +82 -0
  88. package/src/lib/condition/condition.service.js.map +1 -0
  89. package/src/lib/condition/index.d.ts +2 -0
  90. package/src/lib/condition/index.js +6 -0
  91. package/src/lib/condition/index.js.map +1 -0
  92. package/src/lib/database/data-source.d.ts +4 -0
  93. package/src/lib/database/data-source.js +7 -0
  94. package/src/lib/database/data-source.js.map +1 -0
  95. package/src/lib/database/index.d.ts +2 -0
  96. package/src/lib/database/index.js +6 -0
  97. package/src/lib/database/index.js.map +1 -0
  98. package/src/lib/database/migration-runner.d.ts +1 -0
  99. package/src/lib/database/migration-runner.js +23 -0
  100. package/src/lib/database/migration-runner.js.map +1 -0
  101. package/src/lib/database/typeorm.config.d.ts +14 -0
  102. package/src/lib/database/typeorm.config.js +135 -0
  103. package/src/lib/database/typeorm.config.js.map +1 -0
  104. package/src/lib/delegation/delegation-rule.entity.d.ts +19 -0
  105. package/src/lib/delegation/delegation-rule.entity.js +99 -0
  106. package/src/lib/delegation/delegation-rule.entity.js.map +1 -0
  107. package/src/lib/delegation/delegation.enums.d.ts +10 -0
  108. package/src/lib/delegation/delegation.enums.js +23 -0
  109. package/src/lib/delegation/delegation.enums.js.map +1 -0
  110. package/src/lib/delegation/delegation.module.d.ts +2 -0
  111. package/src/lib/delegation/delegation.module.js +22 -0
  112. package/src/lib/delegation/delegation.module.js.map +1 -0
  113. package/src/lib/delegation/delegation.mutations.d.ts +11 -0
  114. package/src/lib/delegation/delegation.mutations.js +87 -0
  115. package/src/lib/delegation/delegation.mutations.js.map +1 -0
  116. package/src/lib/delegation/delegation.queries.d.ts +10 -0
  117. package/src/lib/delegation/delegation.queries.js +91 -0
  118. package/src/lib/delegation/delegation.queries.js.map +1 -0
  119. package/src/lib/delegation/delegation.service.d.ts +56 -0
  120. package/src/lib/delegation/delegation.service.js +268 -0
  121. package/src/lib/delegation/delegation.service.js.map +1 -0
  122. package/src/lib/delegation/dto/delegation-rule.input.d.ts +24 -0
  123. package/src/lib/delegation/dto/delegation-rule.input.js +143 -0
  124. package/src/lib/delegation/dto/delegation-rule.input.js.map +1 -0
  125. package/src/lib/delegation/index.d.ts +5 -0
  126. package/src/lib/delegation/index.js +9 -0
  127. package/src/lib/delegation/index.js.map +1 -0
  128. package/src/lib/form/dto/form-definition.input.d.ts +21 -0
  129. package/src/lib/form/dto/form-definition.input.js +103 -0
  130. package/src/lib/form/dto/form-definition.input.js.map +1 -0
  131. package/src/lib/form/form-definition-version.entity.d.ts +17 -0
  132. package/src/lib/form/form-definition-version.entity.js +84 -0
  133. package/src/lib/form/form-definition-version.entity.js.map +1 -0
  134. package/src/lib/form/form-definition.entity.d.ts +13 -0
  135. package/src/lib/form/form-definition.entity.js +66 -0
  136. package/src/lib/form/form-definition.entity.js.map +1 -0
  137. package/src/lib/form/form-schema-lint.object.d.ts +4 -0
  138. package/src/lib/form/form-schema-lint.object.js +20 -0
  139. package/src/lib/form/form-schema-lint.object.js.map +1 -0
  140. package/src/lib/form/form-schema.validator.d.ts +13 -0
  141. package/src/lib/form/form-schema.validator.js +354 -0
  142. package/src/lib/form/form-schema.validator.js.map +1 -0
  143. package/src/lib/form/form.enums.d.ts +9 -0
  144. package/src/lib/form/form.enums.js +22 -0
  145. package/src/lib/form/form.enums.js.map +1 -0
  146. package/src/lib/form/form.module.d.ts +2 -0
  147. package/src/lib/form/form.module.js +27 -0
  148. package/src/lib/form/form.module.js.map +1 -0
  149. package/src/lib/form/form.mutations.d.ts +14 -0
  150. package/src/lib/form/form.mutations.js +88 -0
  151. package/src/lib/form/form.mutations.js.map +1 -0
  152. package/src/lib/form/form.queries.d.ts +16 -0
  153. package/src/lib/form/form.queries.js +96 -0
  154. package/src/lib/form/form.queries.js.map +1 -0
  155. package/src/lib/form/form.service.d.ts +35 -0
  156. package/src/lib/form/form.service.js +297 -0
  157. package/src/lib/form/form.service.js.map +1 -0
  158. package/src/lib/form/index.d.ts +8 -0
  159. package/src/lib/form/index.js +12 -0
  160. package/src/lib/form/index.js.map +1 -0
  161. package/src/lib/identity/identity-options.d.ts +13 -0
  162. package/src/lib/identity/identity-options.js +20 -0
  163. package/src/lib/identity/identity-options.js.map +1 -0
  164. package/src/lib/identity/identity.module.d.ts +17 -0
  165. package/src/lib/identity/identity.module.js +65 -0
  166. package/src/lib/identity/identity.module.js.map +1 -0
  167. package/src/lib/identity/identity.queries.d.ts +12 -0
  168. package/src/lib/identity/identity.queries.js +79 -0
  169. package/src/lib/identity/identity.queries.js.map +1 -0
  170. package/src/lib/identity/identity.service.d.ts +22 -0
  171. package/src/lib/identity/identity.service.js +141 -0
  172. package/src/lib/identity/identity.service.js.map +1 -0
  173. package/src/lib/identity/index.d.ts +3 -0
  174. package/src/lib/identity/index.js +7 -0
  175. package/src/lib/identity/index.js.map +1 -0
  176. package/src/lib/identity/member-base.adapter.d.ts +95 -0
  177. package/src/lib/identity/member-base.adapter.js +137 -0
  178. package/src/lib/identity/member-base.adapter.js.map +1 -0
  179. package/src/lib/identity/member-metadata-cache.entity.d.ts +8 -0
  180. package/src/lib/identity/member-metadata-cache.entity.js +39 -0
  181. package/src/lib/identity/member-metadata-cache.entity.js.map +1 -0
  182. package/src/lib/identity/member-profile.object.d.ts +8 -0
  183. package/src/lib/identity/member-profile.object.js +37 -0
  184. package/src/lib/identity/member-profile.object.js.map +1 -0
  185. package/src/lib/identity/member-resolver.interface.d.ts +41 -0
  186. package/src/lib/identity/member-resolver.interface.js +19 -0
  187. package/src/lib/identity/member-resolver.interface.js.map +1 -0
  188. package/src/lib/migrations/0000000000000-enable-postgres-extensions.d.ts +6 -0
  189. package/src/lib/migrations/0000000000000-enable-postgres-extensions.js +17 -0
  190. package/src/lib/migrations/0000000000000-enable-postgres-extensions.js.map +1 -0
  191. package/src/lib/migrations/0000000001000-identity-organization-foundation.d.ts +6 -0
  192. package/src/lib/migrations/0000000001000-identity-organization-foundation.js +97 -0
  193. package/src/lib/migrations/0000000001000-identity-organization-foundation.js.map +1 -0
  194. package/src/lib/migrations/0000000002000-form-builder-foundation.d.ts +6 -0
  195. package/src/lib/migrations/0000000002000-form-builder-foundation.js +66 -0
  196. package/src/lib/migrations/0000000002000-form-builder-foundation.js.map +1 -0
  197. package/src/lib/migrations/0000000003000-approval-template-foundation.d.ts +6 -0
  198. package/src/lib/migrations/0000000003000-approval-template-foundation.js +70 -0
  199. package/src/lib/migrations/0000000003000-approval-template-foundation.js.map +1 -0
  200. package/src/lib/migrations/0000000004000-workflow-engine-foundation.d.ts +6 -0
  201. package/src/lib/migrations/0000000004000-workflow-engine-foundation.js +134 -0
  202. package/src/lib/migrations/0000000004000-workflow-engine-foundation.js.map +1 -0
  203. package/src/lib/migrations/0000000005000-delegation-rules.d.ts +6 -0
  204. package/src/lib/migrations/0000000005000-delegation-rules.js +46 -0
  205. package/src/lib/migrations/0000000005000-delegation-rules.js.map +1 -0
  206. package/src/lib/migrations/0000000006000-notifications-sla.d.ts +6 -0
  207. package/src/lib/migrations/0000000006000-notifications-sla.js +70 -0
  208. package/src/lib/migrations/0000000006000-notifications-sla.js.map +1 -0
  209. package/src/lib/migrations/0000000007000-signatures-attachments.d.ts +6 -0
  210. package/src/lib/migrations/0000000007000-signatures-attachments.js +93 -0
  211. package/src/lib/migrations/0000000007000-signatures-attachments.js.map +1 -0
  212. package/src/lib/migrations/0000000008000-approval-template-categories.d.ts +6 -0
  213. package/src/lib/migrations/0000000008000-approval-template-categories.js +92 -0
  214. package/src/lib/migrations/0000000008000-approval-template-categories.js.map +1 -0
  215. package/src/lib/migrations/0000000009000-task-candidates.d.ts +6 -0
  216. package/src/lib/migrations/0000000009000-task-candidates.js +97 -0
  217. package/src/lib/migrations/0000000009000-task-candidates.js.map +1 -0
  218. package/src/lib/migrations/0000000010000-notification-delivery-state.d.ts +6 -0
  219. package/src/lib/migrations/0000000010000-notification-delivery-state.js +38 -0
  220. package/src/lib/migrations/0000000010000-notification-delivery-state.js.map +1 -0
  221. package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.d.ts +6 -0
  222. package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.js +22 -0
  223. package/src/lib/migrations/0000000011000-remove-attachment-encryption-key.js.map +1 -0
  224. package/src/lib/migrations/0000000012000-notification-sla-idempotency.d.ts +6 -0
  225. package/src/lib/migrations/0000000012000-notification-sla-idempotency.js +21 -0
  226. package/src/lib/migrations/0000000012000-notification-sla-idempotency.js.map +1 -0
  227. package/src/lib/migrations/0000000013000-workflow-query-indexes.d.ts +6 -0
  228. package/src/lib/migrations/0000000013000-workflow-query-indexes.js +80 -0
  229. package/src/lib/migrations/0000000013000-workflow-query-indexes.js.map +1 -0
  230. package/src/lib/migrations/index.d.ts +16 -0
  231. package/src/lib/migrations/index.js +49 -0
  232. package/src/lib/migrations/index.js.map +1 -0
  233. package/src/lib/notification/dto/notification-preference.input.d.ts +9 -0
  234. package/src/lib/notification/dto/notification-preference.input.js +53 -0
  235. package/src/lib/notification/dto/notification-preference.input.js.map +1 -0
  236. package/src/lib/notification/index.d.ts +7 -0
  237. package/src/lib/notification/index.js +11 -0
  238. package/src/lib/notification/index.js.map +1 -0
  239. package/src/lib/notification/notification-delivery-scheduler.service.d.ts +13 -0
  240. package/src/lib/notification/notification-delivery-scheduler.service.js +53 -0
  241. package/src/lib/notification/notification-delivery-scheduler.service.js.map +1 -0
  242. package/src/lib/notification/notification-delivery.service.d.ts +23 -0
  243. package/src/lib/notification/notification-delivery.service.js +245 -0
  244. package/src/lib/notification/notification-delivery.service.js.map +1 -0
  245. package/src/lib/notification/notification-dispatcher.token.d.ts +7 -0
  246. package/src/lib/notification/notification-dispatcher.token.js +5 -0
  247. package/src/lib/notification/notification-dispatcher.token.js.map +1 -0
  248. package/src/lib/notification/notification-options.d.ts +215 -0
  249. package/src/lib/notification/notification-options.js +128 -0
  250. package/src/lib/notification/notification-options.js.map +1 -0
  251. package/src/lib/notification/notification-options.module.d.ts +23 -0
  252. package/src/lib/notification/notification-options.module.js +41 -0
  253. package/src/lib/notification/notification-options.module.js.map +1 -0
  254. package/src/lib/notification/notification-preference.entity.d.ts +10 -0
  255. package/src/lib/notification/notification-preference.entity.js +50 -0
  256. package/src/lib/notification/notification-preference.entity.js.map +1 -0
  257. package/src/lib/notification/notification-sla-scheduler.service.d.ts +13 -0
  258. package/src/lib/notification/notification-sla-scheduler.service.js +51 -0
  259. package/src/lib/notification/notification-sla-scheduler.service.js.map +1 -0
  260. package/src/lib/notification/notification-template.d.ts +13 -0
  261. package/src/lib/notification/notification-template.js +61 -0
  262. package/src/lib/notification/notification-template.js.map +1 -0
  263. package/src/lib/notification/notification.entity.d.ts +23 -0
  264. package/src/lib/notification/notification.entity.js +122 -0
  265. package/src/lib/notification/notification.entity.js.map +1 -0
  266. package/src/lib/notification/notification.enums.d.ts +24 -0
  267. package/src/lib/notification/notification.enums.js +45 -0
  268. package/src/lib/notification/notification.enums.js.map +1 -0
  269. package/src/lib/notification/notification.module.d.ts +2 -0
  270. package/src/lib/notification/notification.module.js +45 -0
  271. package/src/lib/notification/notification.module.js.map +1 -0
  272. package/src/lib/notification/notification.mutations.d.ts +11 -0
  273. package/src/lib/notification/notification.mutations.js +64 -0
  274. package/src/lib/notification/notification.mutations.js.map +1 -0
  275. package/src/lib/notification/notification.queries.d.ts +11 -0
  276. package/src/lib/notification/notification.queries.js +77 -0
  277. package/src/lib/notification/notification.queries.js.map +1 -0
  278. package/src/lib/notification/notification.service.d.ts +81 -0
  279. package/src/lib/notification/notification.service.js +621 -0
  280. package/src/lib/notification/notification.service.js.map +1 -0
  281. package/src/lib/organization/dto/manager-resolution.input.d.ts +18 -0
  282. package/src/lib/organization/dto/manager-resolution.input.js +107 -0
  283. package/src/lib/organization/dto/manager-resolution.input.js.map +1 -0
  284. package/src/lib/organization/dto/membership.input.d.ts +16 -0
  285. package/src/lib/organization/dto/membership.input.js +99 -0
  286. package/src/lib/organization/dto/membership.input.js.map +1 -0
  287. package/src/lib/organization/dto/org-unit.input.d.ts +24 -0
  288. package/src/lib/organization/dto/org-unit.input.js +119 -0
  289. package/src/lib/organization/dto/org-unit.input.js.map +1 -0
  290. package/src/lib/organization/dto/position.input.d.ts +13 -0
  291. package/src/lib/organization/dto/position.input.js +70 -0
  292. package/src/lib/organization/dto/position.input.js.map +1 -0
  293. package/src/lib/organization/index.d.ts +12 -0
  294. package/src/lib/organization/index.js +16 -0
  295. package/src/lib/organization/index.js.map +1 -0
  296. package/src/lib/organization/json-metadata.d.ts +1 -0
  297. package/src/lib/organization/json-metadata.js +14 -0
  298. package/src/lib/organization/json-metadata.js.map +1 -0
  299. package/src/lib/organization/manager-resolution.entity.d.ts +11 -0
  300. package/src/lib/organization/manager-resolution.entity.js +55 -0
  301. package/src/lib/organization/manager-resolution.entity.js.map +1 -0
  302. package/src/lib/organization/membership.entity.d.ts +11 -0
  303. package/src/lib/organization/membership.entity.js +60 -0
  304. package/src/lib/organization/membership.entity.js.map +1 -0
  305. package/src/lib/organization/org-unit-tree-commit-result.object.d.ts +4 -0
  306. package/src/lib/organization/org-unit-tree-commit-result.object.js +17 -0
  307. package/src/lib/organization/org-unit-tree-commit-result.object.js.map +1 -0
  308. package/src/lib/organization/org-unit.entity.d.ts +13 -0
  309. package/src/lib/organization/org-unit.entity.js +64 -0
  310. package/src/lib/organization/org-unit.entity.js.map +1 -0
  311. package/src/lib/organization/organization-summary.object.d.ts +6 -0
  312. package/src/lib/organization/organization-summary.object.js +28 -0
  313. package/src/lib/organization/organization-summary.object.js.map +1 -0
  314. package/src/lib/organization/organization.enums.d.ts +11 -0
  315. package/src/lib/organization/organization.enums.js +22 -0
  316. package/src/lib/organization/organization.enums.js.map +1 -0
  317. package/src/lib/organization/organization.module.d.ts +2 -0
  318. package/src/lib/organization/organization.module.js +35 -0
  319. package/src/lib/organization/organization.module.js.map +1 -0
  320. package/src/lib/organization/organization.mutations.d.ts +26 -0
  321. package/src/lib/organization/organization.mutations.js +148 -0
  322. package/src/lib/organization/organization.mutations.js.map +1 -0
  323. package/src/lib/organization/organization.queries.d.ts +23 -0
  324. package/src/lib/organization/organization.queries.js +202 -0
  325. package/src/lib/organization/organization.queries.js.map +1 -0
  326. package/src/lib/organization/organization.service.d.ts +102 -0
  327. package/src/lib/organization/organization.service.js +751 -0
  328. package/src/lib/organization/organization.service.js.map +1 -0
  329. package/src/lib/organization/position.entity.d.ts +9 -0
  330. package/src/lib/organization/position.entity.js +48 -0
  331. package/src/lib/organization/position.entity.js.map +1 -0
  332. package/src/lib/organization/resolved-manager.object.d.ts +4 -0
  333. package/src/lib/organization/resolved-manager.object.js +20 -0
  334. package/src/lib/organization/resolved-manager.object.js.map +1 -0
  335. package/src/lib/signature/index.d.ts +4 -0
  336. package/src/lib/signature/index.js +8 -0
  337. package/src/lib/signature/index.js.map +1 -0
  338. package/src/lib/signature/signature-options.d.ts +33 -0
  339. package/src/lib/signature/signature-options.js +51 -0
  340. package/src/lib/signature/signature-options.js.map +1 -0
  341. package/src/lib/signature/signature-verification.object.d.ts +6 -0
  342. package/src/lib/signature/signature-verification.object.js +28 -0
  343. package/src/lib/signature/signature-verification.object.js.map +1 -0
  344. package/src/lib/signature/signature.entity.d.ts +16 -0
  345. package/src/lib/signature/signature.entity.js +88 -0
  346. package/src/lib/signature/signature.entity.js.map +1 -0
  347. package/src/lib/signature/signature.module.d.ts +11 -0
  348. package/src/lib/signature/signature.module.js +60 -0
  349. package/src/lib/signature/signature.module.js.map +1 -0
  350. package/src/lib/signature/signature.queries.d.ts +11 -0
  351. package/src/lib/signature/signature.queries.js +46 -0
  352. package/src/lib/signature/signature.queries.js.map +1 -0
  353. package/src/lib/signature/signature.service.d.ts +25 -0
  354. package/src/lib/signature/signature.service.js +124 -0
  355. package/src/lib/signature/signature.service.js.map +1 -0
  356. package/src/lib/template/approval-template-category.entity.d.ts +9 -0
  357. package/src/lib/template/approval-template-category.entity.js +49 -0
  358. package/src/lib/template/approval-template-category.entity.js.map +1 -0
  359. package/src/lib/template/approval-template-version.entity.d.ts +21 -0
  360. package/src/lib/template/approval-template-version.entity.js +106 -0
  361. package/src/lib/template/approval-template-version.entity.js.map +1 -0
  362. package/src/lib/template/approval-template.entity.d.ts +14 -0
  363. package/src/lib/template/approval-template.entity.js +74 -0
  364. package/src/lib/template/approval-template.entity.js.map +1 -0
  365. package/src/lib/template/dto/approval-template.input.d.ts +36 -0
  366. package/src/lib/template/dto/approval-template.input.js +187 -0
  367. package/src/lib/template/dto/approval-template.input.js.map +1 -0
  368. package/src/lib/template/index.d.ts +8 -0
  369. package/src/lib/template/index.js +12 -0
  370. package/src/lib/template/index.js.map +1 -0
  371. package/src/lib/template/template.enums.d.ts +14 -0
  372. package/src/lib/template/template.enums.js +31 -0
  373. package/src/lib/template/template.enums.js.map +1 -0
  374. package/src/lib/template/template.module.d.ts +2 -0
  375. package/src/lib/template/template.module.js +33 -0
  376. package/src/lib/template/template.module.js.map +1 -0
  377. package/src/lib/template/template.mutations.d.ts +20 -0
  378. package/src/lib/template/template.mutations.js +139 -0
  379. package/src/lib/template/template.mutations.js.map +1 -0
  380. package/src/lib/template/template.queries.d.ts +16 -0
  381. package/src/lib/template/template.queries.js +133 -0
  382. package/src/lib/template/template.queries.js.map +1 -0
  383. package/src/lib/template/template.service.d.ts +64 -0
  384. package/src/lib/template/template.service.js +521 -0
  385. package/src/lib/template/template.service.js.map +1 -0
  386. package/src/lib/template/workflow-definition.validator.d.ts +9 -0
  387. package/src/lib/template/workflow-definition.validator.js +362 -0
  388. package/src/lib/template/workflow-definition.validator.js.map +1 -0
  389. package/src/lib/testing/cel-js.jest.d.ts +15 -0
  390. package/src/lib/testing/cel-js.jest.js +27 -0
  391. package/src/lib/testing/cel-js.jest.js.map +1 -0
  392. package/src/lib/workflow-engine/activity-log.entity.d.ts +12 -0
  393. package/src/lib/workflow-engine/activity-log.entity.js +62 -0
  394. package/src/lib/workflow-engine/activity-log.entity.js.map +1 -0
  395. package/src/lib/workflow-engine/approval-instance-page-info.object.d.ts +8 -0
  396. package/src/lib/workflow-engine/approval-instance-page-info.object.js +36 -0
  397. package/src/lib/workflow-engine/approval-instance-page-info.object.js.map +1 -0
  398. package/src/lib/workflow-engine/approval-instance.entity.d.ts +22 -0
  399. package/src/lib/workflow-engine/approval-instance.entity.js +113 -0
  400. package/src/lib/workflow-engine/approval-instance.entity.js.map +1 -0
  401. package/src/lib/workflow-engine/dto/cancel-approval-instance.input.d.ts +5 -0
  402. package/src/lib/workflow-engine/dto/cancel-approval-instance.input.js +29 -0
  403. package/src/lib/workflow-engine/dto/cancel-approval-instance.input.js.map +1 -0
  404. package/src/lib/workflow-engine/dto/decide-task.input.d.ts +9 -0
  405. package/src/lib/workflow-engine/dto/decide-task.input.js +47 -0
  406. package/src/lib/workflow-engine/dto/decide-task.input.js.map +1 -0
  407. package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.d.ts +6 -0
  408. package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js +34 -0
  409. package/src/lib/workflow-engine/dto/dry-run-approval-workflow.input.js.map +1 -0
  410. package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.d.ts +6 -0
  411. package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.js +34 -0
  412. package/src/lib/workflow-engine/dto/resubmit-approval-instance.input.js.map +1 -0
  413. package/src/lib/workflow-engine/dto/submit-approval-instance.input.d.ts +7 -0
  414. package/src/lib/workflow-engine/dto/submit-approval-instance.input.js +40 -0
  415. package/src/lib/workflow-engine/dto/submit-approval-instance.input.js.map +1 -0
  416. package/src/lib/workflow-engine/index.d.ts +20 -0
  417. package/src/lib/workflow-engine/index.js +24 -0
  418. package/src/lib/workflow-engine/index.js.map +1 -0
  419. package/src/lib/workflow-engine/task-candidate.entity.d.ts +14 -0
  420. package/src/lib/workflow-engine/task-candidate.entity.js +72 -0
  421. package/src/lib/workflow-engine/task-candidate.entity.js.map +1 -0
  422. package/src/lib/workflow-engine/task-decision.entity.d.ts +12 -0
  423. package/src/lib/workflow-engine/task-decision.entity.js +60 -0
  424. package/src/lib/workflow-engine/task-decision.entity.js.map +1 -0
  425. package/src/lib/workflow-engine/task.entity.d.ts +20 -0
  426. package/src/lib/workflow-engine/task.entity.js +109 -0
  427. package/src/lib/workflow-engine/task.entity.js.map +1 -0
  428. package/src/lib/workflow-engine/workflow-condition-evaluator.d.ts +5 -0
  429. package/src/lib/workflow-engine/workflow-condition-evaluator.js +107 -0
  430. package/src/lib/workflow-engine/workflow-condition-evaluator.js.map +1 -0
  431. package/src/lib/workflow-engine/workflow-dashboard-summary.object.d.ts +8 -0
  432. package/src/lib/workflow-engine/workflow-dashboard-summary.object.js +36 -0
  433. package/src/lib/workflow-engine/workflow-dashboard-summary.object.js.map +1 -0
  434. package/src/lib/workflow-engine/workflow-dry-run.object.d.ts +21 -0
  435. package/src/lib/workflow-engine/workflow-dry-run.object.js +86 -0
  436. package/src/lib/workflow-engine/workflow-dry-run.object.js.map +1 -0
  437. package/src/lib/workflow-engine/workflow-engine.enums.d.ts +58 -0
  438. package/src/lib/workflow-engine/workflow-engine.enums.js +95 -0
  439. package/src/lib/workflow-engine/workflow-engine.enums.js.map +1 -0
  440. package/src/lib/workflow-engine/workflow-engine.module.d.ts +9 -0
  441. package/src/lib/workflow-engine/workflow-engine.module.js +76 -0
  442. package/src/lib/workflow-engine/workflow-engine.module.js.map +1 -0
  443. package/src/lib/workflow-engine/workflow-engine.mutations.d.ts +19 -0
  444. package/src/lib/workflow-engine/workflow-engine.mutations.js +106 -0
  445. package/src/lib/workflow-engine/workflow-engine.mutations.js.map +1 -0
  446. package/src/lib/workflow-engine/workflow-engine.queries.d.ts +29 -0
  447. package/src/lib/workflow-engine/workflow-engine.queries.js +225 -0
  448. package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -0
  449. package/src/lib/workflow-engine/workflow-engine.service.d.ts +145 -0
  450. package/src/lib/workflow-engine/workflow-engine.service.js +2785 -0
  451. package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -0
  452. package/src/lib/workflow-engine/workflow-engine.tokens.d.ts +9 -0
  453. package/src/lib/workflow-engine/workflow-engine.tokens.js +5 -0
  454. package/src/lib/workflow-engine/workflow-engine.tokens.js.map +1 -0
  455. package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.d.ts +18 -0
  456. package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js +39 -0
  457. package/src/lib/workflow-engine/workflow-service-task-dispatcher.token.js.map +1 -0
  458. package/src/lib/workflow-engine/workflow-token.entity.d.ts +10 -0
  459. package/src/lib/workflow-engine/workflow-token.entity.js +50 -0
  460. package/src/lib/workflow-engine/workflow-token.entity.js.map +1 -0
package/README.md ADDED
@@ -0,0 +1,837 @@
1
+ # @rytass/bpm-core-nestjs-module
2
+
3
+ Embeddable NestJS module for BPM approval workflows.
4
+
5
+ This package provides the backend BPM domain layer: GraphQL resolvers, TypeORM
6
+ entities, migrations, workflow execution, approval tasks, form definitions,
7
+ approval templates, organization/member lookup contracts, delegation,
8
+ notifications, SLA handling, attachments, and decision signatures.
9
+
10
+ It is designed to be embedded into a host NestJS application. The host
11
+ application owns runtime infrastructure such as GraphQL setup, TypeORM
12
+ connection setup, auth/session handling, Vault or secret loading, member
13
+ directory integration, storage adapters, and deployment.
14
+
15
+ ## Package Status
16
+
17
+ Current version: `0.0.1`
18
+
19
+ The package is intended for NestJS backend hosts. It does not include the
20
+ Next.js backoffice UI and does not provide a production auth system by itself.
21
+
22
+ Frontend / cross-framework consumers should use
23
+ [`@rytass/bpm-core-client`](../bpm-core-client/README.md) for the GraphQL
24
+ transport, REST auth client, and pre-baked typed operations against this
25
+ backend module.
26
+
27
+ ## Install
28
+
29
+ ```bash
30
+ pnpm add @rytass/bpm-core-nestjs-module @rytass/bpm-core-shared
31
+ pnpm add @nestjs/common @nestjs/core @nestjs/graphql @nestjs/typeorm graphql typeorm reflect-metadata
32
+ pnpm add pg
33
+ ```
34
+
35
+ **TypeScript moduleResolution**: prefer `node16`, `nodenext`, or `bundler` in
36
+ your `tsconfig.json` so the package's `exports` field is honored. Classic
37
+ `moduleResolution: "node"` also works through the `typesVersions` fallback
38
+ shipped with this package, but is on TypeScript's long-term deprecation
39
+ path — new hosts should opt in to modern resolution.
40
+
41
+ If your host uses Apollo GraphQL:
42
+
43
+ ```bash
44
+ pnpm add @nestjs/apollo @apollo/server
45
+ ```
46
+
47
+ If your host uses Vault-backed database settings:
48
+
49
+ ```bash
50
+ pnpm add @rytass/secret-adapter-vault-nestjs
51
+ ```
52
+
53
+ ## Runtime Responsibilities
54
+
55
+ `@rytass/bpm-core-nestjs-module` owns BPM domain behavior.
56
+
57
+ Your host application must provide:
58
+
59
+ - A NestJS application runtime.
60
+ - A configured `GraphQLModule`.
61
+ - A configured TypeORM `DataSource` / `TypeOrmModule`.
62
+ - Auth/session/JWT logic.
63
+ - A `BPMAuthContext` bridge from the request execution context.
64
+ - A `BPM_MEMBER_RESOLVER` provider for member metadata lookup.
65
+ - Attachment storage configuration when local storage is not acceptable.
66
+ - A dedicated worker or host dispatcher when email/webhook/SLA work should not
67
+ run inside API replicas.
68
+ - Production secrets for attachment URL signing, signatures, SMTP, webhook, and Vault.
69
+
70
+ The package intentionally stores member IDs instead of owning user accounts.
71
+ Member profiles, roles, permissions, and email addresses are resolved by the
72
+ host.
73
+
74
+ ## Quick Start
75
+
76
+ The host must wire the same authenticated member into both GraphQL context and
77
+ `BPMRootModule`. BPM expects host root-level routing — do **not** call Nest's
78
+ `setGlobalPrefix()`. BPM controllers (notably `AttachmentController`) hardcode
79
+ relative paths and use `attachmentRoutePrefix` to mount themselves; if you
80
+ want a prefix in production URLs, set `attachmentRoutePrefix` or push the
81
+ prefix into a reverse proxy.
82
+
83
+ A minimal host module looks like this:
84
+
85
+ ```ts
86
+ import { Module } from '@nestjs/common';
87
+ import { GraphQLModule } from '@nestjs/graphql';
88
+ import { TypeOrmModule } from '@nestjs/typeorm';
89
+ import { ApolloDriver, type ApolloDriverConfig } from '@nestjs/apollo';
90
+ import { BPMRootModule, BPM_MEMBER_RESOLVER, buildTypeOrmModuleOptions } from '@rytass/bpm-core-nestjs-module';
91
+ import { VaultModule, VaultService } from '@rytass/secret-adapter-vault-nestjs';
92
+ import type { Request } from 'express';
93
+ import { buildBPMAuthContextFromExecutionContext } from './bpm-auth-context';
94
+ import { HostAuthModule } from './host-auth.module';
95
+ import { HostBPMMemberResolver } from './host-bpm-member.resolver';
96
+ import { HostSessionService } from './host-session.service';
97
+
98
+ @Module({
99
+ imports: [
100
+ HostAuthModule,
101
+ VaultModule.forRoot({
102
+ path: process.env.VAULT_PATH ?? 'bpm_core/develop',
103
+ }),
104
+ TypeOrmModule.forRootAsync({
105
+ imports: [VaultModule],
106
+ inject: [VaultService],
107
+ useFactory: buildTypeOrmModuleOptions,
108
+ }),
109
+ GraphQLModule.forRootAsync<ApolloDriverConfig>({
110
+ driver: ApolloDriver,
111
+ imports: [HostAuthModule],
112
+ inject: [HostSessionService],
113
+ useFactory: (sessionService: HostSessionService) => ({
114
+ autoSchemaFile: true,
115
+ context: async ({ req }: { readonly req?: Request }) => ({
116
+ bpmAuthContext: await sessionService.readBPMAuthContextFromRequest(req),
117
+ req,
118
+ }),
119
+ driver: ApolloDriver,
120
+ path: '/graphql',
121
+ sortSchema: true,
122
+ }),
123
+ }),
124
+ BPMRootModule.forRoot({
125
+ imports: [HostAuthModule],
126
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
127
+ memberResolverProvider: {
128
+ provide: BPM_MEMBER_RESOLVER,
129
+ useExisting: HostBPMMemberResolver,
130
+ },
131
+ }),
132
+ ],
133
+ })
134
+ export class AppModule {}
135
+ ```
136
+
137
+ ## Auth Context
138
+
139
+ BPM guards and mutations need the current BPM member. The host may provide the
140
+ context in the GraphQL context object and expose it through
141
+ `authContextFactory`.
142
+
143
+ ```ts
144
+ import type { ExecutionContext } from '@nestjs/common';
145
+ import { GqlExecutionContext } from '@nestjs/graphql';
146
+ import type { BPMAuthContext } from '@rytass/bpm-core-nestjs-module';
147
+
148
+ interface HostGraphQLContext {
149
+ readonly bpmAuthContext?: BPMAuthContext | null;
150
+ readonly req?: {
151
+ readonly bpmAuthContext?: BPMAuthContext | null;
152
+ };
153
+ }
154
+
155
+ export function buildBPMAuthContextFromExecutionContext(context?: ExecutionContext): BPMAuthContext | null {
156
+ if (!context) {
157
+ return null;
158
+ }
159
+
160
+ const graphqlContext = GqlExecutionContext.create(context).getContext<HostGraphQLContext | undefined>();
161
+
162
+ return graphqlContext?.bpmAuthContext ?? graphqlContext?.req?.bpmAuthContext ?? null;
163
+ }
164
+ ```
165
+
166
+ `BPMAuthContext` shape:
167
+
168
+ ```ts
169
+ export interface BPMAuthContext {
170
+ readonly memberId: string;
171
+ readonly metadata: Readonly<Record<string, unknown>>;
172
+ readonly permissions: readonly string[];
173
+ readonly roles: readonly string[];
174
+ }
175
+ ```
176
+
177
+ BPM also exports param decorators so host resolvers don't need to call
178
+ `authContextFactory` directly:
179
+
180
+ ```ts
181
+ import {
182
+ BPMAuthenticated,
183
+ BPMCurrentAuthContext,
184
+ BPMCurrentMemberId,
185
+ type BPMAuthContext,
186
+ } from '@rytass/bpm-core-nestjs-module';
187
+
188
+ @Resolver()
189
+ class HostResolver {
190
+ @Query(() => HostSummary)
191
+ @BPMAuthenticated()
192
+ hostSummary(
193
+ @BPMCurrentAuthContext() auth: BPMAuthContext,
194
+ @BPMCurrentMemberId() memberId: string,
195
+ ): HostSummary {
196
+ return buildHostSummary(auth, memberId);
197
+ }
198
+ }
199
+ ```
200
+
201
+ ## Role and Permission Contract
202
+
203
+ BPM guards inspect `BPMAuthContext.roles` and `BPMAuthContext.permissions` with
204
+ exact-string matching. The host must inject one of the following strings to
205
+ clear admin / designer guards; otherwise BPM resolvers reject with
206
+ `ForbiddenException`.
207
+
208
+ | Tier | Accepted roles or permissions | Guards / decorators / helpers |
209
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
210
+ | Admin | `roles: ['BPM_ADMIN']`; or `permissions` contains one of `bpm:*`, `bpm:admin`, `bpm.admin`, `bpm:admin:*` | `BPMAdminGuard`, `@BPMAdminOnly()`, `isBPMAdmin(authContext)` |
211
+ | Designer | Includes admin; or `roles: ['BPM_DESIGNER']`; or `permissions` contains one of `bpm:design`, `bpm.design`, `bpm.form.design`, `bpm.template.design`, `bpm:form:design`, `bpm:template:design` | `BPMDesignerGuard`, `@BPMDesignerOnly()`, `isBPMDesigner(authContext)` |
212
+ | Authenticated | `BPMAuthContext.memberId` is non-empty | `BPMAuthenticatedGuard`, `@BPMAuthenticated()` |
213
+
214
+ `@BPMAdminOnly()` and `@BPMDesignerOnly()` already chain
215
+ `BPMAuthenticatedGuard`. The host does not need to add `@BPMAuthenticated()`
216
+ on top of them.
217
+
218
+ ## Member Resolver
219
+
220
+ The package resolves display names, email addresses, and approver candidates
221
+ through `BPM_MEMBER_RESOLVER`.
222
+
223
+ For a member-base-like directory, prefer the package helper. It creates a Nest
224
+ provider without forcing BPM to depend on the host identity package:
225
+
226
+ ```ts
227
+ import { Injectable, type InjectionToken, type Provider } from '@nestjs/common';
228
+ import { BPM_MEMBER_RESOLVER, type BPMMemberBaseDirectory, createBPMMemberBaseResolverProvider } from '@rytass/bpm-core-nestjs-module';
229
+
230
+ interface HostMember {
231
+ readonly email: string;
232
+ readonly id: string;
233
+ readonly name: string;
234
+ readonly permissions: readonly string[];
235
+ readonly roles: readonly string[];
236
+ }
237
+
238
+ @Injectable()
239
+ export class HostMemberDirectory implements BPMMemberBaseDirectory<HostMember> {
240
+ async resolveMember(memberId: string): Promise<HostMember | null> {
241
+ return findHostMember(memberId);
242
+ }
243
+
244
+ async searchMembers(searchText: string): Promise<readonly HostMember[]> {
245
+ return searchHostMembers(searchText);
246
+ }
247
+ }
248
+
249
+ export const HOST_MEMBER_DIRECTORY: InjectionToken<BPMMemberBaseDirectory<HostMember>> = Symbol('HOST_MEMBER_DIRECTORY');
250
+
251
+ export const hostMemberProviders: readonly Provider[] = [
252
+ {
253
+ provide: HOST_MEMBER_DIRECTORY,
254
+ useClass: HostMemberDirectory,
255
+ },
256
+ createBPMMemberBaseResolverProvider({
257
+ adapterOptions: {
258
+ readEmail: (member): string => member.email,
259
+ readMemberId: (member): string => member.id,
260
+ readName: (member): string => member.name,
261
+ },
262
+ directoryToken: HOST_MEMBER_DIRECTORY,
263
+ provide: BPM_MEMBER_RESOLVER,
264
+ }),
265
+ ];
266
+ ```
267
+
268
+ Required resolver contract:
269
+
270
+ ```ts
271
+ export interface BPMMemberResolver {
272
+ resolve(memberId: string): Promise<MemberMetadata>;
273
+ resolveMany(memberIds: readonly string[]): Promise<ReadonlyMap<string, MemberMetadata>>;
274
+ search?(searchText: string): Promise<readonly MemberMetadata[]>;
275
+ }
276
+ ```
277
+
278
+ ## Root Module Configuration
279
+
280
+ Use `BPMRootModule.forRoot()` for static configuration or
281
+ `BPMRootModule.forRootAsync()` when values come from Vault, ConfigService, KMS,
282
+ or another secret provider.
283
+
284
+ ```ts
285
+ BPMRootModule.forRootAsync({
286
+ imports: [ConfigModule],
287
+ inject: [ConfigService],
288
+ memberResolverProvider: {
289
+ provide: BPM_MEMBER_RESOLVER,
290
+ useClass: HostBPMMemberResolver,
291
+ },
292
+ useFactory: (config: ConfigService) => ({
293
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
294
+ attachmentPublicBaseUrl: config.getOrThrow<string>('BPM_API_PUBLIC_URL'),
295
+ attachmentSignedUrlSecret: config.getOrThrow<string>('BPM_ATTACHMENT_SIGNING_SECRET'),
296
+ attachmentSignedUrlTtlSeconds: 300,
297
+ identityMemberMetadataCacheTtlMs: 300_000,
298
+ notificationEmailEnabled: 'auto',
299
+ notificationEmailFrom: config.get<string>('BPM_NOTIFICATION_FROM'),
300
+ notificationEmailSmtpHost: config.get<string>('BPM_SMTP_HOST'),
301
+ notificationEmailSmtpPassword: config.get<string>('BPM_SMTP_PASSWORD'),
302
+ notificationEmailSmtpPort: Number(config.get<string>('BPM_SMTP_PORT')),
303
+ notificationEmailSmtpSecure: false,
304
+ notificationEmailSmtpUsername: config.get<string>('BPM_SMTP_USERNAME'),
305
+ notificationWebhookEnabled: 'auto',
306
+ notificationWebhookEndpointUrl: config.get<string>('BPM_WEBHOOK_URL'),
307
+ notificationWebhookSigningSecret: config.get<string>('BPM_WEBHOOK_SIGNING_SECRET'),
308
+ signatureCurrentKeyVersion: 1,
309
+ signatureKeyProvider: {
310
+ readKey: (keyVersion: number): string => config.getOrThrow<string>(`BPM_SIGNATURE_KEY_V${keyVersion}`),
311
+ },
312
+ signatureTimestampProvider: {
313
+ createTimestampToken: ({ signedAt, signedPayloadHash }): Buffer => Buffer.from(JSON.stringify({ signedAt, signedPayloadHash }), 'utf8'),
314
+ },
315
+ }),
316
+ });
317
+ ```
318
+
319
+ ### Configuration Reference
320
+
321
+ | Option | Default | Description |
322
+ | ------------------------------------------------ | ------------------------------ | -------------------------------------------------------------- |
323
+ | `authContextFactory` | `undefined` | Reads `BPMAuthContext` from NestJS `ExecutionContext`. |
324
+ | `memberResolverProvider` | required | Provider for `BPM_MEMBER_RESOLVER`. |
325
+ | `attachmentStorageProvider` | local `.storage/attachments` | Host-provided `@rytass/storages` adapter. |
326
+ | `workflowServiceTaskDispatcherProvider` | built-in `fetch` dispatcher | Host provider for executable workflow `WEBHOOK` service tasks. |
327
+ | `attachmentRoutePrefix` | `/attachments` | Drives both the BPM signed URL path and the Nest controller mount path for `AttachmentController`. Must be set at module wiring time (see "Attachment Storage" below). |
328
+ | `attachmentStorageProviderId` | `local` | Value stored on attachment metadata for the active adapter. |
329
+ | `attachmentPublicBaseUrl` | `http://localhost:17603` | Public base URL for signed attachment URLs. |
330
+ | `attachmentSignedUrlSecret` | local development secret | HMAC secret for signed attachment download/preview tokens. |
331
+ | `attachmentSignedUrlTtlSeconds` | `300` | Signed attachment URL lifetime in seconds. |
332
+ | `identityMemberMetadataCacheTtlMs` | `300000` | Member metadata cache TTL. |
333
+ | `notificationInAppEnabled` | `true` | Enables in-app notification records. |
334
+ | `notificationEmailEnabled` | `auto` | Enables email when SMTP settings are complete. |
335
+ | `notificationEmailSmtpHost` | `null` | SMTP host. |
336
+ | `notificationEmailSmtpPort` | `null` | SMTP port. |
337
+ | `notificationEmailSmtpSecure` | `false` | `true` for implicit TLS, `false` for STARTTLS. |
338
+ | `notificationEmailSmtpUsername` | `null` | SMTP username. |
339
+ | `notificationEmailSmtpPassword` | `null` | SMTP password or app password. |
340
+ | `notificationEmailFrom` | `null` | Email sender address. |
341
+ | `notificationWebhookEnabled` | `auto` | Enables webhook when URL and signing secret are complete. |
342
+ | `notificationWebhookEndpointUrl` | `null` | Default webhook endpoint URL. |
343
+ | `notificationWebhookSigningSecret` | `null` | HMAC secret for webhook payload signatures. |
344
+ | `notificationDeliverySchedulerEnabled` | `false` | Runs pending email/webhook delivery loop in this process. |
345
+ | `notificationDeliveryScanIntervalMs` | `30000` | Delivery scheduler interval. |
346
+ | `notificationDeliveryBatchSize` | `25` | Maximum pending notifications per delivery scan. |
347
+ | `notificationDeliveryMaxAttempts` | `3` | Attempts before a notification is marked failed. |
348
+ | `notificationDeliveryRetryBaseDelayMs` | `60000` | Base retry delay multiplied by attempt count. |
349
+ | `notificationSlaSchedulerEnabled` | `false` | Runs automatic SLA scan loop in this process. |
350
+ | `notificationSlaScanIntervalMs` | `60000` | SLA scheduler interval. |
351
+ | `notificationSlaTimeoutRemindEnabled` | `true` | Enables SLA timeout `REMIND`. |
352
+ | `notificationSlaTimeoutAutoApproveEnabled` | `false` | Enables SLA timeout `AUTO_APPROVE`. |
353
+ | `notificationSlaTimeoutEscalateEnabled` | `false` | Enables SLA timeout `ESCALATE`. |
354
+ | `notificationSlaTimeoutTerminateInstanceEnabled` | `false` | Enables SLA timeout `TERMINATE_INSTANCE`. |
355
+ | `notificationTemplateEngine` | `simple` | `simple` only — `handlebars` is reserved and currently rendered as `simple`. |
356
+ | `notificationDefaultChannels` | `[IN_APP]` | Fallback channels when a workflow node has no channel list. |
357
+ | `notificationDefaultEmailDigestMode` | `INSTANT` | Default digest mode for missing preferences. |
358
+ | `notificationDefaultInAppPreferenceEnabled` | `true` | Default in-app preference for missing preferences. |
359
+ | `notificationDefaultEmailPreferenceEnabled` | `true` | Default email preference for missing preferences. |
360
+ | `signatureCurrentKeyVersion` | `1` | Key version used for new signatures. |
361
+ | `signatureKeyProvider` | local development key provider | Host key provider for signing and verification. |
362
+ | `signatureTimestampProvider` | mock timestamp provider | Host timestamp token provider. |
363
+
364
+ Production deployments should override all local development secrets.
365
+
366
+ ## Database Setup
367
+
368
+ The package exports helpers for Vault-backed TypeORM setup:
369
+
370
+ ```ts
371
+ import { TypeOrmModule } from '@nestjs/typeorm';
372
+ import { VaultModule, VaultService } from '@rytass/secret-adapter-vault-nestjs';
373
+ import { buildTypeOrmModuleOptions } from '@rytass/bpm-core-nestjs-module';
374
+
375
+ TypeOrmModule.forRootAsync({
376
+ imports: [VaultModule],
377
+ inject: [VaultService],
378
+ useFactory: buildTypeOrmModuleOptions,
379
+ });
380
+ ```
381
+
382
+ Expected Vault keys:
383
+
384
+ | Key | Description |
385
+ | ----------- | -------------------------- |
386
+ | `DB_HOST` | PostgreSQL host. |
387
+ | `DB_PORT` | PostgreSQL port, optional. |
388
+ | `DB_NAME` | PostgreSQL database name. |
389
+ | `DB_USER` | PostgreSQL username. |
390
+ | `DB_PASS` | PostgreSQL password. |
391
+ | `DB_SCHEMA` | PostgreSQL schema. |
392
+
393
+ `buildTypeOrmModuleOptions` adds `autoLoadEntities: true` so the NestJS
394
+ `TypeOrmModule` picks up BPM entities through each domain module's
395
+ `TypeOrmModule.forFeature`. `buildBPMDataSourceOptions()` returns
396
+ `entities: []` because TypeORM CLI tooling reads entities from the host's own
397
+ glob; if you plan to run `typeorm migration:generate` or
398
+ `typeorm migration:show` from a script, attach BPM entities to the data
399
+ source yourself.
400
+
401
+ Use `buildBPMDataSourceOptions()` when your host already has database secrets
402
+ and does not want the Vault adapter:
403
+
404
+ ```ts
405
+ import { buildBPMDataSourceOptions } from '@rytass/bpm-core-nestjs-module';
406
+
407
+ const dataSourceOptions = buildBPMDataSourceOptions({
408
+ database: 'bpm_core',
409
+ host: '127.0.0.1',
410
+ password: 'secret',
411
+ port: 5432,
412
+ schema: 'bpm_core_staging',
413
+ username: 'bpm_core_staging',
414
+ });
415
+ ```
416
+
417
+ The local migration CLI helper can also read Vault directly from environment
418
+ variables:
419
+
420
+ ```bash
421
+ VAULT_HOST=https://vault.example.com \
422
+ VAULT_ACCOUNT=your-account \
423
+ VAULT_PASSWORD=your-password \
424
+ VAULT_PATH=bpm_core/develop \
425
+ pnpm typeorm migration:run
426
+ ```
427
+
428
+ Required environment variables for direct Vault loading:
429
+
430
+ | Variable | Description |
431
+ | ---------------- | ----------------------------------- |
432
+ | `VAULT_HOST` | Vault HTTP base URL. |
433
+ | `VAULT_ACCOUNT` | Vault userpass account. |
434
+ | `VAULT_PASSWORD` | Vault userpass password. |
435
+ | `VAULT_PATH` | Vault KV path, defaults to develop. |
436
+
437
+ ## Migrations
438
+
439
+ This package ships TypeORM migrations under `src/lib/migrations`.
440
+
441
+ For this repository:
442
+
443
+ ```bash
444
+ pnpm migration:run
445
+ ```
446
+
447
+ For an external host, import the class list instead of relying on a repository
448
+ source glob:
449
+
450
+ ```ts
451
+ import { BPM_CORE_MIGRATIONS } from '@rytass/bpm-core-nestjs-module/migrations';
452
+ ```
453
+
454
+ `buildBPMDataSourceOptions()`, `buildDataSourceOptionsFromVaultEnv()`, and
455
+ `buildTypeOrmModuleOptions()` use this exported migration list. Runtime
456
+ `TypeOrmModule` setup still keeps `migrationsRun: false`; run migrations
457
+ explicitly during deploy.
458
+
459
+ The first migration attempts to create required PostgreSQL extensions
460
+ (`uuid-ossp`, `ltree`) if they do not exist. Hosts that cannot grant
461
+ `CREATE EXTENSION` should pre-provision those extensions in the target database
462
+ before running BPM migrations. Schema selection comes from the TypeORM `schema`
463
+ option, so multi-schema hosts should run the same migration list once per BPM
464
+ schema/user pair.
465
+
466
+ Do not enable `synchronize` in production.
467
+
468
+ ## Attachment Storage
469
+
470
+ By default, attachments use local storage under `.storage/attachments`. For
471
+ production, provide an `@rytass/storages` compatible adapter:
472
+
473
+ ```ts
474
+ BPMRootModule.forRoot({
475
+ attachmentStorageProvider: {
476
+ provide: ATTACHMENT_STORAGE,
477
+ useFactory: (): AttachmentStorage => createYourStorageAdapter(),
478
+ },
479
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
480
+ memberResolverProvider: {
481
+ provide: BPM_MEMBER_RESOLVER,
482
+ useClass: HostBPMMemberResolver,
483
+ },
484
+ });
485
+ ```
486
+
487
+ Signed attachment URLs are served by BPM's attachment controller. Configure
488
+ `attachmentPublicBaseUrl`, `attachmentRoutePrefix`,
489
+ `attachmentSignedUrlSecret`, and `attachmentSignedUrlTtlSeconds` for production.
490
+ Set `attachmentStorageProviderId` when replacing local storage so attachment
491
+ metadata does not incorrectly say `local`.
492
+
493
+ `attachmentRoutePrefix` controls two things at the same time:
494
+
495
+ 1. The path BPM bakes into signed URLs
496
+ (`${publicBaseUrl}${routePrefix}/:id/download`).
497
+ 2. The Nest controller mount path. `AttachmentModule.forRoot` /
498
+ `forRootAsync` call `Reflect.defineMetadata(PATH_METADATA, ...)` on
499
+ `AttachmentController` so the controller actually serves on the same path
500
+ the signed URL points to.
501
+
502
+ The default is `/attachments`, matching the BPM controller's relative
503
+ declaration. BPM no longer assumes the host calls `setGlobalPrefix('api')`;
504
+ do not enable `setGlobalPrefix` on a BPM host. To expose the attachment
505
+ endpoint under a different prefix, set `attachmentRoutePrefix` (for example
506
+ `/internal/bpm/attachments`) — BPM rewrites both the controller path and the
507
+ signed URL accordingly. Alternative URL shaping should happen at a reverse
508
+ proxy (Nginx, Cloudflare, k8s ingress), not via Nest globalPrefix.
509
+
510
+ Because Nest reads controller path metadata synchronously at application
511
+ bootstrap, `attachmentRoutePrefix` must be supplied at module wiring time:
512
+
513
+ - `BPMRootModule.forRoot` reads `options.attachmentRoutePrefix` directly.
514
+ - `BPMRootModule.forRootAsync` exposes `attachmentRoutePrefix` at the
515
+ top-level (sibling of `useFactory`), not as part of the async factory
516
+ return.
517
+ - A process can only mount BPM under a single prefix. Multi-tenant hosts that
518
+ want different prefixes per tenant should run separate processes.
519
+
520
+ ## Notifications and SLA
521
+
522
+ BPM creates in-app notifications by default. Email and webhook delivery are
523
+ disabled unless enough configuration is present or explicitly enabled.
524
+
525
+ The `auto` setting on `notificationEmailEnabled` only activates email delivery
526
+ when **all** of the following are non-empty strings:
527
+
528
+ - `notificationEmailSmtpHost`
529
+ - `notificationEmailSmtpPort`
530
+ - `notificationEmailSmtpUsername`
531
+ - `notificationEmailSmtpPassword`
532
+ - `notificationEmailFrom`
533
+
534
+ If any one of those is missing, email stays off even on `auto`. Webhook
535
+ `auto` requires both `notificationWebhookEndpointUrl` and
536
+ `notificationWebhookSigningSecret`.
537
+
538
+ `notificationTemplateEngine: 'handlebars'` is currently a reserved value; the
539
+ runtime template renderer still uses the built-in `simple` renderer regardless
540
+ of this setting. Leave it as `simple` until the Handlebars implementation is
541
+ wired.
542
+
543
+ Delivery and SLA schedulers are disabled by default. Enable them only in a
544
+ dedicated worker process or in a single-replica host that intentionally owns
545
+ background work:
546
+
547
+ ```ts
548
+ BPMRootModule.forRoot({
549
+ notificationDeliverySchedulerEnabled: true,
550
+ notificationSlaSchedulerEnabled: true,
551
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
552
+ memberResolverProvider: {
553
+ provide: BPM_MEMBER_RESOLVER,
554
+ useClass: HostBPMMemberResolver,
555
+ },
556
+ });
557
+ ```
558
+
559
+ BPM claims pending delivery rows with `FOR UPDATE SKIP LOCKED` and records
560
+ SLA notifications with an idempotency index, but a dedicated worker is still
561
+ the recommended production topology.
562
+
563
+ Hosts can replace built-in SMTP and signed webhook dispatch by providing
564
+ `BPM_NOTIFICATION_DISPATCHER` from an imported host module. The dispatcher can
565
+ publish to an existing mail service, queue, tenant router, or event bus:
566
+
567
+ ```ts
568
+ import { BPM_NOTIFICATION_DISPATCHER } from '@rytass/bpm-core-nestjs-module/notification';
569
+
570
+ @Module({
571
+ providers: [
572
+ {
573
+ provide: BPM_NOTIFICATION_DISPATCHER,
574
+ useClass: HostNotificationDispatcher,
575
+ },
576
+ ],
577
+ exports: [BPM_NOTIFICATION_DISPATCHER],
578
+ })
579
+ export class HostNotificationModule {}
580
+ ```
581
+
582
+ Workflow service tasks are a separate integration point from notification
583
+ delivery. `WEBHOOK` service-task nodes run inside the workflow engine and use
584
+ `BPM_WORKFLOW_SERVICE_TASK_DISPATCHER`. The default dispatcher sends a JSON
585
+ `POST` with `fetch`; wrapper apps can replace it when outbound workflow actions
586
+ must be signed, queued, audited, or routed through an internal integration
587
+ service.
588
+
589
+ `BPMRootModule.forRoot` / `forRootAsync` forward the host `imports` to the
590
+ internal `WorkflowEngineModule.forRoot`, so the dispatcher provider may use
591
+ `useFactory` plus `inject` to read host-side tokens such as Vault secrets or
592
+ shared integration bus instances. Providers do not have to live in a
593
+ `@Global()` module to be injectable from the dispatcher.
594
+
595
+ ```ts
596
+ import { Injectable } from '@nestjs/common';
597
+ import {
598
+ BPMRootModule,
599
+ BPM_MEMBER_RESOLVER,
600
+ BPM_WORKFLOW_SERVICE_TASK_DISPATCHER,
601
+ BPMWorkflowServiceTaskDispatcher,
602
+ BPMWorkflowWebhookDispatchInput,
603
+ BPMWorkflowWebhookDispatchResult,
604
+ } from '@rytass/bpm-core-nestjs-module';
605
+
606
+ interface IntegrationBusResult {
607
+ readonly accepted: boolean;
608
+ readonly reason?: string;
609
+ }
610
+
611
+ interface IntegrationBus {
612
+ enqueue(
613
+ topic: string,
614
+ payload: Readonly<Record<string, unknown>>,
615
+ ): Promise<IntegrationBusResult>;
616
+ }
617
+
618
+ @Injectable()
619
+ class HostWorkflowServiceTaskDispatcher implements BPMWorkflowServiceTaskDispatcher {
620
+ constructor(private readonly integrationBus: IntegrationBus) {}
621
+
622
+ async dispatchWebhook(
623
+ input: BPMWorkflowWebhookDispatchInput,
624
+ ): Promise<BPMWorkflowWebhookDispatchResult> {
625
+ const result = await this.integrationBus.enqueue('bpm.workflow.webhook', {
626
+ headers: input.headers ?? {},
627
+ payload: input.payload,
628
+ url: input.url,
629
+ });
630
+
631
+ return {
632
+ ok: result.accepted,
633
+ status: result.accepted ? 202 : null,
634
+ error: result.accepted ? undefined : result.reason,
635
+ };
636
+ }
637
+ }
638
+
639
+ BPMRootModule.forRoot({
640
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
641
+ memberResolverProvider: {
642
+ provide: BPM_MEMBER_RESOLVER,
643
+ useClass: HostBPMMemberResolver,
644
+ },
645
+ workflowServiceTaskDispatcherProvider: {
646
+ provide: BPM_WORKFLOW_SERVICE_TASK_DISPATCHER,
647
+ useClass: HostWorkflowServiceTaskDispatcher,
648
+ },
649
+ });
650
+ ```
651
+
652
+ SLA timeout actions that change workflow state are disabled by default:
653
+
654
+ - `AUTO_APPROVE`
655
+ - `ESCALATE`
656
+ - `TERMINATE_INSTANCE`
657
+
658
+ Enable them only after the host application's business policy is explicit.
659
+
660
+ ## Signatures
661
+
662
+ Decision signatures use HMAC-SHA256 and are chained through the previous
663
+ signature hash. Production hosts should provide a durable key provider and real
664
+ timestamp provider:
665
+
666
+ ```ts
667
+ BPMRootModule.forRoot({
668
+ signatureCurrentKeyVersion: 2,
669
+ signatureKeyProvider: {
670
+ readKey: async (keyVersion: number): Promise<string | null> => readKeyFromKmsOrVault(keyVersion),
671
+ },
672
+ signatureTimestampProvider: {
673
+ createTimestampToken: async ({ signedAt, signedPayloadHash }): Promise<Buffer> => requestTimestampTokenFromTsa({ signedAt, signedPayloadHash }),
674
+ },
675
+ authContextFactory: buildBPMAuthContextFromExecutionContext,
676
+ memberResolverProvider: {
677
+ provide: BPM_MEMBER_RESOLVER,
678
+ useClass: HostBPMMemberResolver,
679
+ },
680
+ });
681
+ ```
682
+
683
+ Keep old signature keys readable after rotation. Verification needs the key
684
+ version stored on each signature row.
685
+
686
+ Both `readKey` and `createTimestampToken` accept either a synchronous return
687
+ or a `Promise`; the example above uses async because production KMS / TSA
688
+ clients are typically network-bound. Returning a synchronous value is fine
689
+ for in-memory or local-file providers.
690
+
691
+ ## GraphQL Surface
692
+
693
+ Importing `BPMRootModule` registers GraphQL resolvers for:
694
+
695
+ - Organization units, positions, memberships, manager resolution, and summary.
696
+ - Member profile lookup and member metadata cache inspection.
697
+ - Form definitions and form definition versions.
698
+ - Approval templates, template versions, categories, validation, and dry run.
699
+ - Workflow instances, tokens, tasks, task candidates, decisions, activity logs,
700
+ submit/process/approve/return/cancel/resubmit operations.
701
+ - Delegation rule CRUD and transfer support.
702
+ - Notifications, unread counts, preferences, and read status.
703
+ - Attachments, signed download URLs, and signed preview URLs.
704
+ - Decision signatures and signature-chain verification.
705
+
706
+ The schema is generated by NestJS GraphQL code-first decorators. Configure the
707
+ host `GraphQLModule` with `autoSchemaFile` if you want NestJS to generate the
708
+ schema at runtime.
709
+
710
+ ## Shared Types
711
+
712
+ Workflow, form, condition, identity, organization, and status contracts live in
713
+ `@rytass/bpm-core-shared`.
714
+
715
+ ```ts
716
+ import type { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';
717
+ import type { FormSchema } from '@rytass/bpm-core-shared/form';
718
+ ```
719
+
720
+ Use shared contracts when building UI clients or host-side integration tests.
721
+
722
+ ## Import Paths
723
+
724
+ The package root is the canonical import path for common host-facing APIs.
725
+ Stable feature subpaths are also published for narrower imports such as
726
+ migrations or notification dispatcher tokens.
727
+
728
+ ```ts
729
+ import {
730
+ AllExceptionsFilter,
731
+ BPMAdminGuard,
732
+ BPMAdminOnly,
733
+ BPMAuthenticated,
734
+ BPMAuthenticatedGuard,
735
+ BPMCurrentAuthContext,
736
+ BPMCurrentMemberId,
737
+ BPMDesignerGuard,
738
+ BPMDesignerOnly,
739
+ BPMRootModule,
740
+ buildTypeOrmModuleOptions,
741
+ createBPMMemberBaseResolverProvider,
742
+ } from '@rytass/bpm-core-nestjs-module';
743
+
744
+ import { BPM_CORE_MIGRATIONS } from '@rytass/bpm-core-nestjs-module/migrations';
745
+ import { BPM_NOTIFICATION_DISPATCHER } from '@rytass/bpm-core-nestjs-module/notification';
746
+ ```
747
+
748
+ `AllExceptionsFilter` is the BPM-aware global exception filter the wrapper
749
+ app uses on its NestJS bootstrap; hosts that want consistent GraphQL/HTTP
750
+ error responses can call `app.useGlobalFilters(new AllExceptionsFilter())`.
751
+
752
+ Use root imports for module wiring, guards, options, and adapter helpers.
753
+ Feature subpaths are intended for narrow integration tokens or migration lists.
754
+ Do not treat internal domain services as the primary host API unless their
755
+ method contracts are explicitly documented.
756
+
757
+ Do not import from internal compiled paths such as
758
+ `@rytass/bpm-core-nestjs-module/src/lib/...`.
759
+
760
+ ## Local Development
761
+
762
+ From this repository, use the wrapper app to run the backend and client:
763
+
764
+ ```bash
765
+ pnpm install
766
+ pnpm demo:reset
767
+ pnpm api
768
+ pnpm client
769
+ ```
770
+
771
+ `pnpm demo:reset` runs migrations before resetting and seeding develop data. Use
772
+ `pnpm migration:run` separately only when you need migrations without resetting
773
+ the wrapper-app seed scenario.
774
+
775
+ Default local service URLs:
776
+
777
+ - API: `http://localhost:17603`
778
+ - GraphQL: `http://localhost:17603/graphql`
779
+ - Client: `http://localhost:17602`
780
+
781
+ The normal local flow uses Vault-backed develop secrets. `docker compose` is not
782
+ required for local verification.
783
+
784
+ `pnpm demo:reset` is a repository wrapper-app command, not a package feature. It
785
+ resets the develop schema and seeds a Taiwan manufacturing scenario through
786
+ `apps/api/tools/reset-demo-data.ts`, including DB-backed test members in
787
+ `api_test_members`. Staging uses the same script through `pnpm staging:reset`
788
+ with `VAULT_PATH=bpm_core/staging`.
789
+
790
+ ## Verification
791
+
792
+ Before publishing:
793
+
794
+ ```bash
795
+ pnpm nx test bpm-core --runInBand
796
+ pnpm nx typecheck bpm-core
797
+ pnpm nx build bpm-core
798
+ ```
799
+
800
+ Repository-wide checks:
801
+
802
+ ```bash
803
+ pnpm typecheck
804
+ pnpm lint
805
+ pnpm test
806
+ pnpm build
807
+ ```
808
+
809
+ ## Publishing Checklist
810
+
811
+ 1. Confirm package metadata in `libs/bpm-core/package.json`.
812
+ 2. Confirm `@rytass/bpm-core-shared` is published at the required version.
813
+ 3. Run `pnpm nx build bpm-core`.
814
+ 4. Inspect `dist/libs/bpm-core/package.json`.
815
+ 5. Confirm `dist/libs/bpm-core/README.md` is present.
816
+ 6. Confirm `src/index.ts` exports every intended public API.
817
+ 7. Publish from the built package directory:
818
+
819
+ ```bash
820
+ cd dist/libs/bpm-core
821
+ npm publish --access public
822
+ ```
823
+
824
+ ## Production Notes
825
+
826
+ - Replace all local fallback secrets before production.
827
+ - Use a production storage adapter instead of local filesystem storage.
828
+ - Keep old signature keys available for verification after key rotation.
829
+ - Keep in-process schedulers disabled in API replicas unless a dedicated worker
830
+ is not available.
831
+ - Do not enable TypeORM `synchronize` in production.
832
+ - Ensure GraphQL auth context is available for protected operations.
833
+ - Run migrations before serving traffic with a new package version.
834
+
835
+ ## License
836
+
837
+ MIT