@memberjunction/server 6.1.0-edge.1 → 6.1.0-edge.3

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 (261) hide show
  1. package/LICENSE +180 -4
  2. package/dist/auth/AuthProviderCatalogRouter.d.ts +31 -0
  3. package/dist/auth/AuthProviderCatalogRouter.d.ts.map +1 -0
  4. package/dist/auth/AuthProviderCatalogRouter.js +69 -0
  5. package/dist/auth/AuthProviderCatalogRouter.js.map +1 -0
  6. package/dist/auth/AuthProviderEngine.d.ts +96 -0
  7. package/dist/auth/AuthProviderEngine.d.ts.map +1 -0
  8. package/dist/auth/AuthProviderEngine.js +245 -0
  9. package/dist/auth/AuthProviderEngine.js.map +1 -0
  10. package/dist/auth/exampleNewUserSubClass.js +1 -1
  11. package/dist/auth/exampleNewUserSubClass.js.map +1 -1
  12. package/dist/auth/index.d.ts +11 -0
  13. package/dist/auth/index.d.ts.map +1 -1
  14. package/dist/auth/index.js +65 -18
  15. package/dist/auth/index.js.map +1 -1
  16. package/dist/auth/initializeProviders.d.ts +64 -1
  17. package/dist/auth/initializeProviders.d.ts.map +1 -1
  18. package/dist/auth/initializeProviders.js +117 -5
  19. package/dist/auth/initializeProviders.js.map +1 -1
  20. package/dist/auth/magicLink/MagicLinkService.js +1 -1
  21. package/dist/auth/magicLink/MagicLinkService.js.map +1 -1
  22. package/dist/auth/newUsers.js +1 -1
  23. package/dist/auth/newUsers.js.map +1 -1
  24. package/dist/config.d.ts +89 -0
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +52 -35
  27. package/dist/config.js.map +1 -1
  28. package/dist/context.js +2 -2
  29. package/dist/context.js.map +1 -1
  30. package/dist/generated/generated.d.ts +540 -1595
  31. package/dist/generated/generated.d.ts.map +1 -1
  32. package/dist/generated/generated.js +2755 -16857
  33. package/dist/generated/generated.js.map +1 -1
  34. package/dist/generic/ResolverBase.d.ts +20 -4
  35. package/dist/generic/ResolverBase.d.ts.map +1 -1
  36. package/dist/generic/ResolverBase.js +58 -21
  37. package/dist/generic/ResolverBase.js.map +1 -1
  38. package/dist/generic/RunViewResolver.d.ts +4 -0
  39. package/dist/generic/RunViewResolver.d.ts.map +1 -1
  40. package/dist/generic/RunViewResolver.js +31 -0
  41. package/dist/generic/RunViewResolver.js.map +1 -1
  42. package/dist/index.d.ts +3 -0
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +183 -54
  45. package/dist/index.js.map +1 -1
  46. package/dist/integration/RSUProgressBridge.d.ts +83 -0
  47. package/dist/integration/RSUProgressBridge.d.ts.map +1 -0
  48. package/dist/integration/RSUProgressBridge.js +230 -0
  49. package/dist/integration/RSUProgressBridge.js.map +1 -0
  50. package/dist/integration/SchemaRefreshLaunch.d.ts +52 -0
  51. package/dist/integration/SchemaRefreshLaunch.d.ts.map +1 -0
  52. package/dist/integration/SchemaRefreshLaunch.js +50 -0
  53. package/dist/integration/SchemaRefreshLaunch.js.map +1 -0
  54. package/dist/logging/secretRedactor.d.ts +9 -0
  55. package/dist/logging/secretRedactor.d.ts.map +1 -1
  56. package/dist/logging/secretRedactor.js +39 -0
  57. package/dist/logging/secretRedactor.js.map +1 -1
  58. package/dist/middleware/BaseServerMiddleware.d.ts +5 -0
  59. package/dist/middleware/BaseServerMiddleware.d.ts.map +1 -1
  60. package/dist/middleware/BaseServerMiddleware.js +5 -0
  61. package/dist/middleware/BaseServerMiddleware.js.map +1 -1
  62. package/dist/providerConfigUnits.d.ts +20 -0
  63. package/dist/providerConfigUnits.d.ts.map +1 -0
  64. package/dist/providerConfigUnits.js +22 -0
  65. package/dist/providerConfigUnits.js.map +1 -0
  66. package/dist/realtimeWidget/WidgetSessionService.js +1 -1
  67. package/dist/realtimeWidget/WidgetSessionService.js.map +1 -1
  68. package/dist/realtimeWidget/widgetGuestElevation.js +1 -1
  69. package/dist/realtimeWidget/widgetGuestElevation.js.map +1 -1
  70. package/dist/resolvers/ActionResolver.d.ts.map +1 -1
  71. package/dist/resolvers/ActionResolver.js +12 -0
  72. package/dist/resolvers/ActionResolver.js.map +1 -1
  73. package/dist/resolvers/ComponentRegistryResolver.js +1 -1
  74. package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
  75. package/dist/resolvers/EntityPermissionResolver.js +1 -1
  76. package/dist/resolvers/EntityPermissionResolver.js.map +1 -1
  77. package/dist/resolvers/FileResolver.d.ts +34 -4
  78. package/dist/resolvers/FileResolver.d.ts.map +1 -1
  79. package/dist/resolvers/FileResolver.js +218 -28
  80. package/dist/resolvers/FileResolver.js.map +1 -1
  81. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +85 -3
  82. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  83. package/dist/resolvers/IntegrationDiscoveryResolver.js +302 -82
  84. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  85. package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
  86. package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
  87. package/dist/resolvers/QueryResolver.d.ts +5 -4
  88. package/dist/resolvers/QueryResolver.d.ts.map +1 -1
  89. package/dist/resolvers/QueryResolver.js +29 -14
  90. package/dist/resolvers/QueryResolver.js.map +1 -1
  91. package/dist/resolvers/QuerySystemUserResolver.d.ts +12 -3
  92. package/dist/resolvers/QuerySystemUserResolver.d.ts.map +1 -1
  93. package/dist/resolvers/QuerySystemUserResolver.js +33 -14
  94. package/dist/resolvers/QuerySystemUserResolver.js.map +1 -1
  95. package/dist/resolvers/RealtimeClientSessionResolver.d.ts +10 -0
  96. package/dist/resolvers/RealtimeClientSessionResolver.d.ts.map +1 -1
  97. package/dist/resolvers/RealtimeClientSessionResolver.js +5 -0
  98. package/dist/resolvers/RealtimeClientSessionResolver.js.map +1 -1
  99. package/dist/resolvers/RunAIAgentResolver.d.ts +3 -1
  100. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  101. package/dist/resolvers/RunAIAgentResolver.js +20 -7
  102. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  103. package/dist/resolvers/SearchEntitiesResolver.js +1 -1
  104. package/dist/resolvers/SearchEntitiesResolver.js.map +1 -1
  105. package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
  106. package/dist/resolvers/SqlLoggingConfigResolver.js +1 -1
  107. package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
  108. package/dist/resolvers/SyncRolesUsersResolver.js +2 -2
  109. package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
  110. package/dist/resolvers/TaskGraphFrameResolver.d.ts +18 -0
  111. package/dist/resolvers/TaskGraphFrameResolver.d.ts.map +1 -1
  112. package/dist/resolvers/TaskGraphFrameResolver.js +75 -0
  113. package/dist/resolvers/TaskGraphFrameResolver.js.map +1 -1
  114. package/dist/resolvers/UserFavoriteResolver.js +1 -1
  115. package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
  116. package/dist/resolvers/UserResolver.d.ts +19 -17
  117. package/dist/resolvers/UserResolver.d.ts.map +1 -1
  118. package/dist/resolvers/UserResolver.js +66 -67
  119. package/dist/resolvers/UserResolver.js.map +1 -1
  120. package/dist/resolvers/currentUserRoles.d.ts +19 -0
  121. package/dist/resolvers/currentUserRoles.d.ts.map +1 -0
  122. package/dist/resolvers/currentUserRoles.js +36 -0
  123. package/dist/resolvers/currentUserRoles.js.map +1 -0
  124. package/dist/rest/MediaAccessKeys.d.ts +17 -0
  125. package/dist/rest/MediaAccessKeys.d.ts.map +1 -1
  126. package/dist/rest/MediaAccessKeys.js +42 -1
  127. package/dist/rest/MediaAccessKeys.js.map +1 -1
  128. package/dist/rest/MediaStreamHandler.d.ts +3 -2
  129. package/dist/rest/MediaStreamHandler.d.ts.map +1 -1
  130. package/dist/rest/MediaStreamHandler.js +83 -2
  131. package/dist/rest/MediaStreamHandler.js.map +1 -1
  132. package/dist/rest/OAuthCallbackHandler.d.ts +49 -1
  133. package/dist/rest/OAuthCallbackHandler.d.ts.map +1 -1
  134. package/dist/rest/OAuthCallbackHandler.js +130 -44
  135. package/dist/rest/OAuthCallbackHandler.js.map +1 -1
  136. package/dist/rest/SignatureWebhookHandler.js +1 -1
  137. package/dist/rest/SignatureWebhookHandler.js.map +1 -1
  138. package/dist/rest/UploadTokenManager.d.ts +90 -0
  139. package/dist/rest/UploadTokenManager.d.ts.map +1 -0
  140. package/dist/rest/UploadTokenManager.js +156 -0
  141. package/dist/rest/UploadTokenManager.js.map +1 -0
  142. package/dist/services/DurableEntityActionTaskSubmitter.d.ts +26 -0
  143. package/dist/services/DurableEntityActionTaskSubmitter.d.ts.map +1 -0
  144. package/dist/services/DurableEntityActionTaskSubmitter.js +55 -0
  145. package/dist/services/DurableEntityActionTaskSubmitter.js.map +1 -0
  146. package/dist/services/IntegrationSyncWorkerService.d.ts +48 -0
  147. package/dist/services/IntegrationSyncWorkerService.d.ts.map +1 -0
  148. package/dist/services/IntegrationSyncWorkerService.js +132 -0
  149. package/dist/services/IntegrationSyncWorkerService.js.map +1 -0
  150. package/dist/services/ScheduledJobsService.js +1 -1
  151. package/dist/services/ScheduledJobsService.js.map +1 -1
  152. package/dist/services/StartTaskGraphDispatcher.d.ts +0 -10
  153. package/dist/services/StartTaskGraphDispatcher.d.ts.map +1 -1
  154. package/dist/services/StartTaskGraphDispatcher.js +37 -2
  155. package/dist/services/StartTaskGraphDispatcher.js.map +1 -1
  156. package/dist/services/TaskGraphActionRunner.d.ts +34 -0
  157. package/dist/services/TaskGraphActionRunner.d.ts.map +1 -0
  158. package/dist/services/TaskGraphActionRunner.js +95 -0
  159. package/dist/services/TaskGraphActionRunner.js.map +1 -0
  160. package/dist/services/TaskGraphAgentRunner.d.ts +20 -0
  161. package/dist/services/TaskGraphAgentRunner.d.ts.map +1 -1
  162. package/dist/services/TaskGraphAgentRunner.js +53 -0
  163. package/dist/services/TaskGraphAgentRunner.js.map +1 -1
  164. package/dist/services/TaskGraphContinuationDeliverer.d.ts.map +1 -1
  165. package/dist/services/TaskGraphContinuationDeliverer.js +12 -1
  166. package/dist/services/TaskGraphContinuationDeliverer.js.map +1 -1
  167. package/dist/services/TaskGraphPromptRunner.d.ts +31 -0
  168. package/dist/services/TaskGraphPromptRunner.d.ts.map +1 -0
  169. package/dist/services/TaskGraphPromptRunner.js +134 -0
  170. package/dist/services/TaskGraphPromptRunner.js.map +1 -0
  171. package/dist/telephony/RingCentralTelephonyService.js +1 -1
  172. package/dist/telephony/RingCentralTelephonyService.js.map +1 -1
  173. package/dist/telephony/TwilioTelephonyRouter.js +1 -1
  174. package/dist/telephony/TwilioTelephonyRouter.js.map +1 -1
  175. package/dist/telephony/VonageTelephonyRouter.js +1 -1
  176. package/dist/telephony/VonageTelephonyRouter.js.map +1 -1
  177. package/dist/types.d.ts +6 -0
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/types.js.map +1 -1
  180. package/package.json +91 -91
  181. package/src/__tests__/APIKeyScopeAuth.test.ts +475 -0
  182. package/src/__tests__/AuthProviderEngine.test.ts +278 -0
  183. package/src/__tests__/EntityCRUDHandler.test.ts +378 -0
  184. package/src/__tests__/IntegrationSyncWorkerService.test.ts +275 -0
  185. package/src/__tests__/OAuthCallbackHandler.openRedirect.test.ts +117 -0
  186. package/src/__tests__/OAuthCallbackHandler.xss.test.ts +4 -1
  187. package/src/__tests__/RESTEndpointHandler.test.ts +672 -0
  188. package/src/__tests__/RSUProgressBridge.test.ts +250 -0
  189. package/src/__tests__/RealtimeBridgeResolver.test.ts +10 -2
  190. package/src/__tests__/RealtimeClientSessionResolver.test.ts +1 -1
  191. package/src/__tests__/ResolverBase.frozenRecordMapping.test.ts +133 -0
  192. package/src/__tests__/ResolverBase.transportMapping.test.ts +289 -0
  193. package/src/__tests__/SchemaRefreshLaunch.test.ts +114 -0
  194. package/src/__tests__/SessionManager.test.ts +1 -1
  195. package/src/__tests__/UserResolver.currentUser.test.ts +87 -0
  196. package/src/__tests__/ViewOperationsHandler.test.ts +277 -0
  197. package/src/__tests__/WidgetSessionService.test.ts +1 -1
  198. package/src/__tests__/config-units.test.ts +74 -0
  199. package/src/__tests__/databaseAbstraction.test.ts +1 -1
  200. package/src/__tests__/initializeProviders.refresh.test.ts +146 -0
  201. package/src/__tests__/magicLinkService.provisionLog.test.ts +1 -1
  202. package/src/__tests__/mjapi-bootstrap.test.ts +0 -6
  203. package/src/__tests__/newUsers.test.ts +726 -0
  204. package/src/__tests__/resolverBase.rls.test.ts +3 -0
  205. package/src/__tests__/secretRedactor.failOpen.test.ts +135 -0
  206. package/src/__tests__/uploadTokenManager.test.ts +159 -0
  207. package/src/__tests__/widgetGuestElevation.test.ts +1 -1
  208. package/src/auth/AuthProviderCatalogRouter.ts +76 -0
  209. package/src/auth/AuthProviderEngine.ts +253 -0
  210. package/src/auth/exampleNewUserSubClass.ts +1 -1
  211. package/src/auth/index.ts +69 -21
  212. package/src/auth/initializeProviders.ts +128 -7
  213. package/src/auth/magicLink/MagicLinkService.ts +1 -1
  214. package/src/auth/newUsers.ts +1 -1
  215. package/src/config.ts +55 -36
  216. package/src/context.ts +2 -2
  217. package/src/generated/generated.ts +2038 -10529
  218. package/src/generic/ResolverBase.ts +63 -21
  219. package/src/generic/RunViewResolver.ts +31 -0
  220. package/src/index.ts +199 -56
  221. package/src/integration/RSUProgressBridge.ts +248 -0
  222. package/src/integration/SchemaRefreshLaunch.ts +77 -0
  223. package/src/logging/secretRedactor.ts +43 -0
  224. package/src/middleware/BaseServerMiddleware.ts +5 -0
  225. package/src/providerConfigUnits.ts +21 -0
  226. package/src/realtimeWidget/WidgetSessionService.ts +1 -1
  227. package/src/realtimeWidget/widgetGuestElevation.ts +1 -1
  228. package/src/resolvers/ActionResolver.ts +13 -0
  229. package/src/resolvers/ComponentRegistryResolver.ts +1 -1
  230. package/src/resolvers/EntityPermissionResolver.ts +1 -1
  231. package/src/resolvers/FileResolver.ts +200 -40
  232. package/src/resolvers/IntegrationDiscoveryResolver.ts +328 -70
  233. package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
  234. package/src/resolvers/QueryResolver.ts +25 -11
  235. package/src/resolvers/QuerySystemUserResolver.ts +28 -13
  236. package/src/resolvers/RealtimeClientSessionResolver.ts +13 -0
  237. package/src/resolvers/RunAIAgentResolver.ts +21 -6
  238. package/src/resolvers/SearchEntitiesResolver.ts +1 -1
  239. package/src/resolvers/SqlLoggingConfigResolver.ts +1 -2
  240. package/src/resolvers/SyncRolesUsersResolver.ts +2 -2
  241. package/src/resolvers/TaskGraphFrameResolver.ts +67 -0
  242. package/src/resolvers/UserFavoriteResolver.ts +1 -1
  243. package/src/resolvers/UserResolver.ts +99 -60
  244. package/src/resolvers/currentUserRoles.ts +47 -0
  245. package/src/rest/MediaAccessKeys.ts +47 -1
  246. package/src/rest/MediaStreamHandler.ts +98 -3
  247. package/src/rest/OAuthCallbackHandler.ts +150 -42
  248. package/src/rest/SignatureWebhookHandler.ts +1 -1
  249. package/src/rest/UploadTokenManager.ts +211 -0
  250. package/src/services/DurableEntityActionTaskSubmitter.ts +78 -0
  251. package/src/services/IntegrationSyncWorkerService.ts +141 -0
  252. package/src/services/ScheduledJobsService.ts +1 -1
  253. package/src/services/StartTaskGraphDispatcher.ts +38 -1
  254. package/src/services/TaskGraphActionRunner.ts +99 -0
  255. package/src/services/TaskGraphAgentRunner.ts +58 -1
  256. package/src/services/TaskGraphContinuationDeliverer.ts +11 -1
  257. package/src/services/TaskGraphPromptRunner.ts +144 -0
  258. package/src/telephony/RingCentralTelephonyService.ts +1 -1
  259. package/src/telephony/TwilioTelephonyRouter.ts +1 -1
  260. package/src/telephony/VonageTelephonyRouter.ts +1 -1
  261. package/src/types.ts +6 -0
@@ -0,0 +1,156 @@
1
+ /**
2
+ * @fileoverview Ephemeral in-memory staged upload token manager.
3
+ *
4
+ * Provides a secure, single-use, time-to-live (TTL) bounded staging area for raw
5
+ * binary upload buffers received via REST streaming before being committed through
6
+ * the GraphQL `UploadStorageFile` pipeline.
7
+ *
8
+ * Security properties:
9
+ * - Single-use nonce: Token and buffer are atomically destroyed on first consumption.
10
+ * - User binding: Tokens are bound to the authenticated User ID that uploaded them.
11
+ * - Auto-eviction: Abandoned tokens are automatically evicted from RAM after the TTL.
12
+ * - Memory caps: Enforces per-file max size (default 100MB) and total pool capacity (default 500MB).
13
+ *
14
+ * @module @memberjunction/server/rest/UploadTokenManager
15
+ */
16
+ import { BaseSingleton, UUIDsEqual } from '@memberjunction/global';
17
+ import { LogError } from '@memberjunction/core';
18
+ import { randomBytes } from 'node:crypto';
19
+ /**
20
+ * Ephemeral In-Memory Staged Upload Token Manager.
21
+ *
22
+ * Architecture & Deployment Topology Note:
23
+ * This implementation maintains staged buffers in-process RAM with a 5-minute sliding TTL.
24
+ * In a clustered/multi-replica deployment behind a load balancer, sticky sessions (or routing
25
+ * the subsequent GraphQL `UploadStorageFile` commit to the same node) are recommended.
26
+ * For shared-memory multi-node clustering, an external ephemeral store (such as Redis)
27
+ * can be plugged in behind this interface.
28
+ */
29
+ export class UploadTokenManager extends BaseSingleton {
30
+ // Public constructor required by BaseSingleton
31
+ constructor() {
32
+ super();
33
+ this._staged = new Map();
34
+ this._totalMemoryBytes = 0;
35
+ this.defaultTtlSeconds = 300; // 5 minutes
36
+ this.maxFileSizeBytes = 100 * 1024 * 1024; // 100 MB
37
+ this.maxUserMemoryBytes = 150 * 1024 * 1024; // 150 MB per user
38
+ this.maxPoolMemoryBytes = 500 * 1024 * 1024; // 500 MB
39
+ }
40
+ static get Instance() {
41
+ return UploadTokenManager.getInstance();
42
+ }
43
+ /**
44
+ * Calculates total active staged bytes currently held for a given user.
45
+ */
46
+ GetUserMemoryBytes(userId) {
47
+ let total = 0;
48
+ for (const entry of this._staged.values()) {
49
+ if (UUIDsEqual(entry.userId, userId)) {
50
+ total += entry.contentLength;
51
+ }
52
+ }
53
+ return total;
54
+ }
55
+ /**
56
+ * Stages a raw binary buffer in RAM, returning a single-use cryptographic token.
57
+ *
58
+ * @throws Error if buffer exceeds single file limit, per-user quota, or global pool memory capacity.
59
+ */
60
+ Stage(params) {
61
+ const size = params.buffer.length;
62
+ if (size > this.maxFileSizeBytes) {
63
+ throw new Error(`Staged upload exceeds maximum allowed file size of ${Math.round(this.maxFileSizeBytes / (1024 * 1024))}MB (received ${Math.round(size / (1024 * 1024))}MB).`);
64
+ }
65
+ const userCurrentBytes = this.GetUserMemoryBytes(params.userId);
66
+ if (userCurrentBytes + size > this.maxUserMemoryBytes) {
67
+ throw new Error(`Per-user upload memory quota reached (${Math.round(userCurrentBytes / (1024 * 1024))}MB / ${Math.round(this.maxUserMemoryBytes / (1024 * 1024))}MB used). Please wait for active uploads to finalize.`);
68
+ }
69
+ if (this._totalMemoryBytes + size > this.maxPoolMemoryBytes) {
70
+ throw new Error(`Staged upload memory capacity reached (${Math.round(this._totalMemoryBytes / (1024 * 1024))}MB / ${Math.round(this.maxPoolMemoryBytes / (1024 * 1024))}MB used). Please try again shortly.`);
71
+ }
72
+ const token = 'upt_' + randomBytes(32).toString('hex');
73
+ const ttl = params.ttlSeconds || this.defaultTtlSeconds;
74
+ const now = Date.now();
75
+ const expiresAt = now + ttl * 1000;
76
+ const timer = setTimeout(() => {
77
+ this.Evict(token);
78
+ }, ttl * 1000);
79
+ // Unref timer so it doesn't hold open process shutdown in tests or CLI
80
+ if (typeof timer.unref === 'function') {
81
+ timer.unref();
82
+ }
83
+ const entry = {
84
+ token,
85
+ buffer: params.buffer,
86
+ fileName: params.fileName,
87
+ mimeType: params.mimeType,
88
+ contentLength: size,
89
+ userId: params.userId,
90
+ createdAt: now,
91
+ expiresAt,
92
+ timer,
93
+ };
94
+ this._staged.set(token, entry);
95
+ this._totalMemoryBytes += size;
96
+ return token;
97
+ }
98
+ /**
99
+ * Atomically consumes and evicts a staged upload token.
100
+ *
101
+ * @param token The staged upload token.
102
+ * @param claimingUserId The user ID claiming this token. If provided, must match the user who uploaded it.
103
+ * @returns The staged buffer and metadata, or null if the token is invalid, expired, or claimed by the wrong user.
104
+ */
105
+ Consume(token, claimingUserId) {
106
+ if (!token || !this._staged.has(token)) {
107
+ return null;
108
+ }
109
+ const entry = this._staged.get(token);
110
+ // Security check: verify user ownership using UUIDsEqual for robust ID normalization
111
+ if (claimingUserId && entry.userId && !UUIDsEqual(entry.userId, claimingUserId)) {
112
+ LogError(`[UploadTokenManager] Security violation: User '${claimingUserId}' attempted to claim upload token owned by User '${entry.userId}'.`);
113
+ // Evict immediately to prevent further probing
114
+ this.Evict(token);
115
+ return null;
116
+ }
117
+ // Atomic consumption & memory reclamation
118
+ this.Evict(token);
119
+ return {
120
+ buffer: entry.buffer,
121
+ fileName: entry.fileName,
122
+ mimeType: entry.mimeType,
123
+ contentLength: entry.contentLength,
124
+ };
125
+ }
126
+ /**
127
+ * Evicts a token from RAM and reclaims memory.
128
+ */
129
+ Evict(token) {
130
+ const entry = this._staged.get(token);
131
+ if (!entry) {
132
+ return false;
133
+ }
134
+ clearTimeout(entry.timer);
135
+ this._staged.delete(token);
136
+ this._totalMemoryBytes = Math.max(0, this._totalMemoryBytes - entry.contentLength);
137
+ return true;
138
+ }
139
+ /** Total RAM in bytes currently consumed by all active staged uploads. */
140
+ get TotalMemoryBytes() {
141
+ return this._totalMemoryBytes;
142
+ }
143
+ /** Count of currently active staged uploads. */
144
+ get ActiveCount() {
145
+ return this._staged.size;
146
+ }
147
+ /** Clears all active staged uploads. */
148
+ Clear() {
149
+ for (const [, entry] of this._staged) {
150
+ clearTimeout(entry.timer);
151
+ }
152
+ this._staged.clear();
153
+ this._totalMemoryBytes = 0;
154
+ }
155
+ }
156
+ //# sourceMappingURL=UploadTokenManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UploadTokenManager.js","sourceRoot":"","sources":["../../src/rest/UploadTokenManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview MJServer's implementation of the `DurableEntityActionSubmitter` seam.
3
+ *
4
+ * Turns one After* entity-action dispatch into a single-node durable task graph, which is D14's
5
+ * whole answer to "run this durably": not a new queue, the substrate that already has a claim
6
+ * protocol, restart recovery and orphan reclaim.
7
+ *
8
+ * Registered at boot beside the dispatcher, because the two are one capability — a submitter with
9
+ * no dispatcher writes rows nobody picks up, which is worse than staying inline.
10
+ *
11
+ * @module @memberjunction/server
12
+ */
13
+ import type { DurableEntityActionRequest, DurableEntityActionSubmission, DurableEntityActionSubmitter } from '@memberjunction/actions-base';
14
+ import { type ProviderFactory } from '@memberjunction/task-graph';
15
+ export declare class DurableEntityActionTaskSubmitter implements DurableEntityActionSubmitter {
16
+ private readonly providerFactory;
17
+ private readonly environmentID;
18
+ /**
19
+ * @param environmentID which environment the tasks belong to. Defaults to the platform default
20
+ * because a save has no environment of its own to inherit — the record's entity is global, and
21
+ * inventing a per-save environment would put a durable dispatch somewhere nobody looks.
22
+ */
23
+ constructor(providerFactory: ProviderFactory, environmentID?: string);
24
+ Submit(request: DurableEntityActionRequest): Promise<DurableEntityActionSubmission>;
25
+ }
26
+ //# sourceMappingURL=DurableEntityActionTaskSubmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DurableEntityActionTaskSubmitter.d.ts","sourceRoot":"","sources":["../../src/services/DurableEntityActionTaskSubmitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EACR,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC/B,MAAM,8BAA8B,CAAC;AAItC,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAEpF,qBAAa,gCAAiC,YAAW,4BAA4B;IAO7E,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAPlC;;;;OAIG;gBAEkB,eAAe,EAAE,eAAe,EAChC,aAAa,GAAE,MAAyD;IAGhF,MAAM,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,6BAA6B,CAAC;CA4CnG"}
@@ -0,0 +1,55 @@
1
+ import { LogError } from '@memberjunction/core';
2
+ import { TaskNode } from '@memberjunction/ai-core-plus';
3
+ import { MJEnvironmentEntityExtended } from '@memberjunction/core-entities';
4
+ import { TaskGraphService } from '@memberjunction/task-graph';
5
+ export class DurableEntityActionTaskSubmitter {
6
+ /**
7
+ * @param environmentID which environment the tasks belong to. Defaults to the platform default
8
+ * because a save has no environment of its own to inherit — the record's entity is global, and
9
+ * inventing a per-save environment would put a durable dispatch somewhere nobody looks.
10
+ */
11
+ constructor(providerFactory, environmentID = MJEnvironmentEntityExtended.DefaultEnvironmentID) {
12
+ this.providerFactory = providerFactory;
13
+ this.environmentID = environmentID;
14
+ }
15
+ async Submit(request) {
16
+ try {
17
+ const spec = {
18
+ workflowName: `${request.ActionName} — ${request.EntityName}`,
19
+ reasoning: `Durable dispatch of entity action binding ${request.EntityActionID} on ` +
20
+ `${request.EntityName} (${request.RecordID}), fired by ${request.InvocationType}.`,
21
+ tasks: [
22
+ TaskNode.Action({
23
+ tempId: 'action',
24
+ name: request.ActionName,
25
+ description: `Run ${request.ActionName} for ${request.EntityName} ${request.RecordID}.`,
26
+ dependsOn: [],
27
+ inputPayload: request.RedactedParams,
28
+ }, { actionName: request.ActionName }),
29
+ ],
30
+ // Nothing to say to anyone: this graph exists because a record was saved, not
31
+ // because a person asked a question. Defaulting to 'message' would post an
32
+ // orphaned result into whichever conversation happened to be nearby.
33
+ continuation: 'none',
34
+ // The point of the exercise. A one-node graph constant-folds to in-run execution by
35
+ // default (D9), which is exactly the fire-and-forget behaviour being escaped.
36
+ durable: true,
37
+ };
38
+ const provider = await this.providerFactory.CreateProvider();
39
+ const result = await new TaskGraphService().Submit(spec, {
40
+ EnvironmentID: this.environmentID,
41
+ ContextUser: request.ContextUser,
42
+ Provider: provider,
43
+ });
44
+ return result.Success
45
+ ? { Success: true, ParentTaskID: result.ParentTaskID }
46
+ : { Success: false, ErrorMessage: result.ErrorMessage };
47
+ }
48
+ catch (e) {
49
+ const message = e instanceof Error ? e.message : String(e);
50
+ LogError(`[DurableEntityActionTaskSubmitter] Submission failed for binding ${request.EntityActionID}: ${message}`);
51
+ return { Success: false, ErrorMessage: message };
52
+ }
53
+ }
54
+ }
55
+ //# sourceMappingURL=DurableEntityActionTaskSubmitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DurableEntityActionTaskSubmitter.js","sourceRoot":"","sources":["../../src/services/DurableEntityActionTaskSubmitter.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAsB,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAwB,MAAM,4BAA4B,CAAC;AAEpF,MAAM,OAAO,gCAAgC;IACzC;;;;OAIG;IACH,YACqB,eAAgC,EAChC,gBAAwB,2BAA2B,CAAC,oBAAoB;QADxE,oBAAe,GAAf,eAAe,CAAiB;QAChC,kBAAa,GAAb,aAAa,CAA2D;IAC1F,CAAC;IAEG,KAAK,CAAC,MAAM,CAAC,OAAmC;QACnD,IAAI,CAAC;YACD,MAAM,IAAI,GAAkB;gBACxB,YAAY,EAAE,GAAG,OAAO,CAAC,UAAU,MAAM,OAAO,CAAC,UAAU,EAAE;gBAC7D,SAAS,EACL,6CAA6C,OAAO,CAAC,cAAc,MAAM;oBACzE,GAAG,OAAO,CAAC,UAAU,KAAK,OAAO,CAAC,QAAQ,eAAe,OAAO,CAAC,cAAc,GAAG;gBACtF,KAAK,EAAE;oBACH,QAAQ,CAAC,MAAM,CACX;wBACI,MAAM,EAAE,QAAQ;wBAChB,IAAI,EAAE,OAAO,CAAC,UAAU;wBACxB,WAAW,EAAE,OAAO,OAAO,CAAC,UAAU,QAAQ,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,QAAQ,GAAG;wBACvF,SAAS,EAAE,EAAE;wBACb,YAAY,EAAE,OAAO,CAAC,cAAc;qBACvC,EACD,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CACrC;iBACJ;gBACD,8EAA8E;gBAC9E,2EAA2E;gBAC3E,qEAAqE;gBACrE,YAAY,EAAE,MAAM;gBACpB,oFAAoF;gBACpF,8EAA8E;gBAC9E,OAAO,EAAE,IAAI;aAChB,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC;YAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,gBAAgB,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE;gBACrD,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,QAAQ,EAAE,QAAQ;aACrB,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC,OAAO;gBACjB,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE;gBACtD,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;QAChE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3D,QAAQ,CAAC,oEAAoE,OAAO,CAAC,cAAc,KAAK,OAAO,EAAE,CAAC,CAAC;YACnH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;QACrD,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @fileoverview Worker-mode poll loop for durable integration sync runs (PR 1 item 8).
3
+ * @module MJServer/services
4
+ */
5
+ import { IntegrationSyncWorkerConfig } from '../config.js';
6
+ /**
7
+ * Polls `CompanyIntegrationRun` for `Status='Queued'` rows, claims each one atomically,
8
+ * executes it, and releases — the enqueue/execute split that lets a sync outlive the
9
+ * request that asked for it.
10
+ *
11
+ * Multiple workers (in this process or others) may poll the same queue: the claim sproc
12
+ * admits exactly one, and every loser simply moves on to the next candidate. Nothing here
13
+ * assumes it is the only worker.
14
+ */
15
+ export declare class IntegrationSyncWorkerService {
16
+ private config;
17
+ private systemUser;
18
+ private timer;
19
+ private isRunning;
20
+ private polling;
21
+ /** Run IDs currently executing in THIS process — bounds concurrency and prevents self-collision. */
22
+ private inFlight;
23
+ constructor(config: IntegrationSyncWorkerConfig);
24
+ get IsEnabled(): boolean;
25
+ get IsRunning(): boolean;
26
+ /** Number of queued runs this worker is currently executing. */
27
+ get InFlightCount(): number;
28
+ /** Resolve the system user the worker executes syncs as. */
29
+ Initialize(): Promise<void>;
30
+ /** Begin polling the queue. */
31
+ Start(): void;
32
+ /**
33
+ * Stop polling. In-flight runs are left to finish on their own — their leases are
34
+ * renewed by the engine's heartbeat, so killing them here would only strand rows.
35
+ */
36
+ Stop(): void;
37
+ /**
38
+ * One poll pass: fetch claimable candidates up to the free concurrency slots and start
39
+ * each. Overlapping passes are suppressed so a slow query can't stack up timers.
40
+ */
41
+ private pollOnce;
42
+ /**
43
+ * Execute one queued run in the background. Losing the claim race is normal — the run
44
+ * is simply someone else's — so it is logged as information, never as an error.
45
+ */
46
+ private startRun;
47
+ }
48
+ //# sourceMappingURL=IntegrationSyncWorkerService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationSyncWorkerService.d.ts","sourceRoot":"","sources":["../../src/services/IntegrationSyncWorkerService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAE3D;;;;;;;;GAQG;AACH,qBAAa,4BAA4B;IACrC,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,oGAAoG;IACpG,OAAO,CAAC,QAAQ,CAAqB;gBAEzB,MAAM,EAAE,2BAA2B;IAI/C,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,IAAW,SAAS,IAAI,OAAO,CAE9B;IAED,gEAAgE;IAChE,IAAW,aAAa,IAAI,MAAM,CAEjC;IAED,4DAA4D;IAC/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWxC,+BAA+B;IACxB,KAAK,IAAI,IAAI;IAoBpB;;;OAGG;IACI,IAAI,IAAI,IAAI;IAUnB;;;OAGG;YACW,QAAQ;IAoBtB;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAoBnB"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @fileoverview Worker-mode poll loop for durable integration sync runs (PR 1 item 8).
3
+ * @module MJServer/services
4
+ */
5
+ import { LogError, LogStatus } from '@memberjunction/core';
6
+ import { UserCache } from '@memberjunction/generic-database-provider';
7
+ import { IntegrationEngine } from '@memberjunction/integration-engine';
8
+ /**
9
+ * Polls `CompanyIntegrationRun` for `Status='Queued'` rows, claims each one atomically,
10
+ * executes it, and releases — the enqueue/execute split that lets a sync outlive the
11
+ * request that asked for it.
12
+ *
13
+ * Multiple workers (in this process or others) may poll the same queue: the claim sproc
14
+ * admits exactly one, and every loser simply moves on to the next candidate. Nothing here
15
+ * assumes it is the only worker.
16
+ */
17
+ export class IntegrationSyncWorkerService {
18
+ constructor(config) {
19
+ this.systemUser = null;
20
+ this.timer = null;
21
+ this.isRunning = false;
22
+ this.polling = false;
23
+ /** Run IDs currently executing in THIS process — bounds concurrency and prevents self-collision. */
24
+ this.inFlight = new Set();
25
+ this.config = config;
26
+ }
27
+ get IsEnabled() {
28
+ return this.config.enabled;
29
+ }
30
+ get IsRunning() {
31
+ return this.isRunning;
32
+ }
33
+ /** Number of queued runs this worker is currently executing. */
34
+ get InFlightCount() {
35
+ return this.inFlight.size;
36
+ }
37
+ /** Resolve the system user the worker executes syncs as. */
38
+ async Initialize() {
39
+ if (!this.config.enabled)
40
+ return;
41
+ const email = this.config.systemUserEmail;
42
+ this.systemUser = UserCache.Users.find(u => u.Email?.toLowerCase() === email.toLowerCase()) ?? null;
43
+ if (!this.systemUser) {
44
+ throw new Error(`[IntegrationSyncWorker] System user not found with email: ${email}`);
45
+ }
46
+ await IntegrationEngine.Instance.Config(false, this.systemUser);
47
+ }
48
+ /** Begin polling the queue. */
49
+ Start() {
50
+ if (!this.config.enabled || this.isRunning)
51
+ return;
52
+ if (!this.systemUser) {
53
+ throw new Error('[IntegrationSyncWorker] Not initialized — call Initialize() first');
54
+ }
55
+ this.isRunning = true;
56
+ this.timer = setInterval(() => void this.pollOnce(), this.config.pollingIntervalMs);
57
+ // Standard level, NOT verboseOnly: this states a deployment-shaping fact — that this process
58
+ // executes queued syncs — and it's one line per process lifetime. Stop() already logs at
59
+ // standard level, so hiding Start() produced logs showing a worker stopping that never
60
+ // started, and no way to confirm from logs that a deployment is in worker mode at all.
61
+ LogStatus(`🔄 Integration Sync Worker: polling every ${Math.round(this.config.pollingIntervalMs / 1000)}s, ` +
62
+ `up to ${this.config.maxConcurrentRuns} concurrent run(s)`);
63
+ // Don't wait a full interval to drain a queue that already has work.
64
+ void this.pollOnce();
65
+ }
66
+ /**
67
+ * Stop polling. In-flight runs are left to finish on their own — their leases are
68
+ * renewed by the engine's heartbeat, so killing them here would only strand rows.
69
+ */
70
+ Stop() {
71
+ if (!this.isRunning)
72
+ return;
73
+ if (this.timer) {
74
+ clearInterval(this.timer);
75
+ this.timer = null;
76
+ }
77
+ this.isRunning = false;
78
+ LogStatus(`[IntegrationSyncWorker] Stopped polling (${this.inFlight.size} run(s) still in flight)`);
79
+ }
80
+ /**
81
+ * One poll pass: fetch claimable candidates up to the free concurrency slots and start
82
+ * each. Overlapping passes are suppressed so a slow query can't stack up timers.
83
+ */
84
+ async pollOnce() {
85
+ if (this.polling || !this.isRunning || !this.systemUser)
86
+ return;
87
+ const slots = this.config.maxConcurrentRuns - this.inFlight.size;
88
+ if (slots <= 0)
89
+ return;
90
+ this.polling = true;
91
+ try {
92
+ const candidates = await IntegrationEngine.PollQueuedRuns(this.systemUser, slots);
93
+ for (const candidate of candidates) {
94
+ if (this.inFlight.has(candidate.ID))
95
+ continue;
96
+ this.startRun(candidate.ID);
97
+ }
98
+ }
99
+ catch (err) {
100
+ LogError(`[IntegrationSyncWorker] Poll failed`, undefined, err);
101
+ }
102
+ finally {
103
+ this.polling = false;
104
+ }
105
+ }
106
+ /**
107
+ * Execute one queued run in the background. Losing the claim race is normal — the run
108
+ * is simply someone else's — so it is logged as information, never as an error.
109
+ */
110
+ startRun(runID) {
111
+ if (!this.systemUser)
112
+ return;
113
+ this.inFlight.add(runID);
114
+ void IntegrationEngine.Instance
115
+ .ExecuteQueuedRun(runID, this.systemUser)
116
+ .then(result => {
117
+ if (result.Success) {
118
+ LogStatus(`[IntegrationSyncWorker] Run ${runID} completed: ${result.RecordsProcessed} record(s) processed`);
119
+ }
120
+ else {
121
+ LogStatus(`[IntegrationSyncWorker] Run ${runID} did not complete: ${result.ErrorMessage ?? 'unknown reason'}`);
122
+ }
123
+ })
124
+ .catch(err => {
125
+ LogError(`[IntegrationSyncWorker] Run ${runID} threw`, undefined, err);
126
+ })
127
+ .finally(() => {
128
+ this.inFlight.delete(runID);
129
+ });
130
+ }
131
+ }
132
+ //# sourceMappingURL=IntegrationSyncWorkerService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrationSyncWorkerService.js","sourceRoot":"","sources":["../../src/services/IntegrationSyncWorkerService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAY,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,2CAA2C,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAGvE;;;;;;;;GAQG;AACH,MAAM,OAAO,4BAA4B;IASrC,YAAY,MAAmC;QAPvC,eAAU,GAAoB,IAAI,CAAC;QACnC,UAAK,GAA0B,IAAI,CAAC;QACpC,cAAS,GAAG,KAAK,CAAC;QAClB,YAAO,GAAG,KAAK,CAAC;QACxB,oGAAoG;QAC5F,aAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QAGjC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACzB,CAAC;IAED,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC/B,CAAC;IAED,IAAW,SAAS;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,gEAAgE;IAChE,IAAW,aAAa;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;IAC9B,CAAC;IAED,4DAA4D;IACrD,KAAK,CAAC,UAAU;QACnB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO;QAEjC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;QAC1C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,IAAI,CAAC;QACpG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,6DAA6D,KAAK,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACpE,CAAC;IAED,+BAA+B;IACxB,KAAK;QACR,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QACnD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACpF,6FAA6F;QAC7F,yFAAyF;QACzF,uFAAuF;QACvF,uFAAuF;QACvF,SAAS,CACL,6CAA6C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC,KAAK;YAClG,SAAS,IAAI,CAAC,MAAM,CAAC,iBAAiB,oBAAoB,CAC7D,CAAC;QACF,qEAAqE;QACrE,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;IACzB,CAAC;IAED;;;OAGG;IACI,IAAI;QACP,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO;QAC5B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,SAAS,CAAC,4CAA4C,IAAI,CAAC,QAAQ,CAAC,IAAI,0BAA0B,CAAC,CAAC;IACxG,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,QAAQ;QAClB,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAEhE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACjE,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO;QAEvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAClF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBAAE,SAAS;gBAC9C,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,QAAQ,CAAC,qCAAqC,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACzB,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,QAAQ,CAAC,KAAa;QAC1B,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO;QAE7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,KAAK,iBAAiB,CAAC,QAAQ;aAC1B,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC;aACxC,IAAI,CAAC,MAAM,CAAC,EAAE;YACX,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,SAAS,CAAC,+BAA+B,KAAK,eAAe,MAAM,CAAC,gBAAgB,sBAAsB,CAAC,CAAC;YAChH,CAAC;iBAAM,CAAC;gBACJ,SAAS,CAAC,+BAA+B,KAAK,sBAAsB,MAAM,CAAC,YAAY,IAAI,gBAAgB,EAAE,CAAC,CAAC;YACnH,CAAC;QACL,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,CAAC,EAAE;YACT,QAAQ,CAAC,+BAA+B,KAAK,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;QAC3E,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACV,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACX,CAAC;CACJ"}
@@ -3,7 +3,7 @@
3
3
  * @module MJServer/services
4
4
  */
5
5
  import { LogError, LogStatus, LogStatusEx } from '@memberjunction/core';
6
- import { UserCache } from '@memberjunction/sqlserver-dataprovider';
6
+ import { UserCache } from '@memberjunction/generic-database-provider';
7
7
  import { SchedulingEngine } from '@memberjunction/scheduling-engine';
8
8
  /**
9
9
  * Service for managing scheduled jobs lifecycle
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduledJobsService.js","sourceRoot":"","sources":["../../src/services/ScheduledJobsService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ScheduledJobsService.js","sourceRoot":"","sources":["../../src/services/ScheduledJobsService.ts"],"names":[],"mappings":"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"}
@@ -19,15 +19,5 @@
19
19
  import { UserInfo } from '@memberjunction/core';
20
20
  import { TaskGraphDispatcher } from '@memberjunction/task-graph';
21
21
  import sql from 'mssql';
22
- /**
23
- * Starts one dispatcher for this process and returns it.
24
- *
25
- * The instance ID must be stable for the process lifetime and distinct per instance — it is what
26
- * lets reconciliation tell "my own orphaned work, reclaim it" from "another live instance's work,
27
- * leave it alone". `pid` plus hostname satisfies both: stable while the process lives, and never
28
- * reused by a peer.
29
- *
30
- * The dispatcher self-registers with `ShutdownRegistry`, so the caller does not wire teardown.
31
- */
32
22
  export declare function StartTaskGraphDispatcher(pool: sql.ConnectionPool, contextUser: UserInfo, instanceID?: string): Promise<TaskGraphDispatcher>;
33
23
  //# sourceMappingURL=StartTaskGraphDispatcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StartTaskGraphDispatcher.d.ts","sourceRoot":"","sources":["../../src/services/StartTaskGraphDispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAA2B,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,GAAG,MAAM,OAAO,CAAC;AAOxB;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC1C,IAAI,EAAE,GAAG,CAAC,cAAc,EACxB,WAAW,EAAE,QAAQ,EACrB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC,CAmB9B"}
1
+ {"version":3,"file":"StartTaskGraphDispatcher.d.ts","sourceRoot":"","sources":["../../src/services/StartTaskGraphDispatcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAA2B,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,OAAO,GAAG,MAAM,OAAO,CAAC;AAkCxB,wBAAsB,wBAAwB,CAC1C,IAAI,EAAE,GAAG,CAAC,cAAc,EACxB,WAAW,EAAE,QAAQ,EACrB,UAAU,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,mBAAmB,CAAC,CAsC9B"}
@@ -1,6 +1,11 @@
1
1
  import { LoadTaskGraphOperations, TaskGraphDispatcher } from '@memberjunction/task-graph';
2
+ import { TaskGraphPromptRunner } from './TaskGraphPromptRunner.js';
3
+ import { DurableEntityActionRegistry } from '@memberjunction/actions-base';
2
4
  import { CreateTaskGraphProviderFactory } from './TaskGraphProviderFactory.js';
5
+ import { TaskGraphActionRunner } from './TaskGraphActionRunner.js';
3
6
  import { TaskGraphAgentRunner } from './TaskGraphAgentRunner.js';
7
+ import { randomBytes } from 'node:crypto';
8
+ import { DurableEntityActionTaskSubmitter } from './DurableEntityActionTaskSubmitter.js';
4
9
  import { TaskGraphContinuationDeliverer } from './TaskGraphContinuationDeliverer.js';
5
10
  import { PubSubManager } from '../generic/PubSubManager.js';
6
11
  import { TaskGraphFrameBroadcaster } from '../resolvers/TaskGraphFrameResolver.js';
@@ -14,18 +19,48 @@ import { TaskGraphFrameBroadcaster } from '../resolvers/TaskGraphFrameResolver.j
14
19
  *
15
20
  * The dispatcher self-registers with `ShutdownRegistry`, so the caller does not wire teardown.
16
21
  */
22
+ /**
23
+ * A per-process identity for the claim protocol.
24
+ *
25
+ * Host and pid are kept because they are what a human reads in a log; the random suffix is what
26
+ * makes the value actually unique. Generated once per call, so a restart is a new instance — which
27
+ * is correct: the previous process's claims should expire rather than be inherited.
28
+ */
29
+ function defaultInstanceID() {
30
+ const host = process.env.HOSTNAME ?? 'mjapi';
31
+ const entropy = randomBytes(4).toString('hex');
32
+ return `${host}-${process.pid}-${entropy}`;
33
+ }
17
34
  export async function StartTaskGraphDispatcher(pool, contextUser, instanceID) {
18
35
  LoadTaskGraphOperations();
19
36
  const providerFactory = CreateTaskGraphProviderFactory(pool);
20
37
  const pubSub = PubSubManager.Instance.PubSubEngine;
21
- const dispatcher = new TaskGraphDispatcher(providerFactory, new TaskGraphAgentRunner(), contextUser, { InstanceID: instanceID ?? `${process.env.HOSTNAME ?? 'mjapi'}-${process.pid}` },
38
+ const dispatcher = new TaskGraphDispatcher(providerFactory, new TaskGraphAgentRunner(), contextUser,
39
+ // A RANDOM SUFFIX, because host+pid is not unique in the deployments this runs in (C2).
40
+ // `HOSTNAME` is not exported to child processes under systemd or pm2, and a containerised
41
+ // process is routinely pid 1 — so two hosts default to the same `mjapi-1`. A shared instance
42
+ // id defeats every `ClaimedBy=@me` guard at once: A's heartbeat renews B's lease, and A's
43
+ // stale terminal write lands over B's live execution. An explicit `instanceID` still wins,
44
+ // for hosts that have a real identity to supply.
45
+ { InstanceID: instanceID ?? defaultInstanceID() },
22
46
  // Without this the dispatcher had nowhere to deliver: a finished graph logged its outcome,
23
47
  // marked itself delivered, and said nothing to the conversation that asked for it.
24
48
  new TaskGraphContinuationDeliverer(providerFactory, contextUser),
25
49
  // Live signal. Supplied only when a PubSub engine exists — in a worker or a test there is
26
50
  // nobody to publish to, and the dispatcher runs identically without one.
27
- pubSub ? new TaskGraphFrameBroadcaster(pubSub) : undefined);
51
+ pubSub ? new TaskGraphFrameBroadcaster(pubSub) : undefined,
52
+ // Action nodes — the third execution shape, beside agents and people. Durable After* entity
53
+ // actions land as these.
54
+ new TaskGraphActionRunner(),
55
+ // Prompt nodes. Without this a Flow agent with a Prompt step submits and then
56
+ // stalls on a task nothing can execute — which is why the shipped User Onboarding
57
+ // Flow Agent could not run at all before this seam existed.
58
+ new TaskGraphPromptRunner());
28
59
  await dispatcher.Start();
60
+ // Registered only AFTER the dispatcher is running, and only here. A submitter without a
61
+ // dispatcher writes Task rows nobody picks up — strictly worse than staying inline, because the
62
+ // work is now both undone and invisible in the place it used to be logged.
63
+ DurableEntityActionRegistry.Instance.Register(new DurableEntityActionTaskSubmitter(providerFactory));
29
64
  return dispatcher;
30
65
  }
31
66
  //# sourceMappingURL=StartTaskGraphDispatcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StartTaskGraphDispatcher.js","sourceRoot":"","sources":["../../src/services/StartTaskGraphDispatcher.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAE1F,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAEnF;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC1C,IAAwB,EACxB,WAAqB,EACrB,UAAmB;IAEnB,uBAAuB,EAAE,CAAC;IAE1B,MAAM,eAAe,GAAG,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,mBAAmB,CACtC,eAAe,EACf,IAAI,oBAAoB,EAAE,EAC1B,WAAW,EACX,EAAE,UAAU,EAAE,UAAU,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE;IACjF,2FAA2F;IAC3F,mFAAmF;IACnF,IAAI,8BAA8B,CAAC,eAAe,EAAE,WAAW,CAAC;IAChE,0FAA0F;IAC1F,yEAAyE;IACzE,MAAM,CAAC,CAAC,CAAC,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAC7D,CAAC;IACF,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IACzB,OAAO,UAAU,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"StartTaskGraphDispatcher.js","sourceRoot":"","sources":["../../src/services/StartTaskGraphDispatcher.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,+BAA+B,CAAC;AAC/E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAEnF;;;;;;;;;GASG;AACH;;;;;;GAMG;AACH,SAAS,iBAAiB;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC;IAC7C,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC1C,IAAwB,EACxB,WAAqB,EACrB,UAAmB;IAEnB,uBAAuB,EAAE,CAAC;IAE1B,MAAM,eAAe,GAAG,8BAA8B,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,mBAAmB,CACtC,eAAe,EACf,IAAI,oBAAoB,EAAE,EAC1B,WAAW;IACX,wFAAwF;IACxF,0FAA0F;IAC1F,6FAA6F;IAC7F,0FAA0F;IAC1F,2FAA2F;IAC3F,iDAAiD;IACjD,EAAE,UAAU,EAAE,UAAU,IAAI,iBAAiB,EAAE,EAAE;IACjD,2FAA2F;IAC3F,mFAAmF;IACnF,IAAI,8BAA8B,CAAC,eAAe,EAAE,WAAW,CAAC;IAChE,0FAA0F;IAC1F,yEAAyE;IACzE,MAAM,CAAC,CAAC,CAAC,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;IAC1D,4FAA4F;IAC5F,yBAAyB;IACzB,IAAI,qBAAqB,EAAE;IAC3B,8EAA8E;IAC9E,kFAAkF;IAClF,4DAA4D;IAC5D,IAAI,qBAAqB,EAAE,CAC9B,CAAC;IACF,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;IAEzB,wFAAwF;IACxF,gGAAgG;IAChG,2EAA2E;IAC3E,2BAA2B,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,gCAAgC,CAAC,eAAe,CAAC,CAAC,CAAC;IAErG,OAAO,UAAU,CAAC;AACtB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { TaskActionRunner, TaskActionRunParams, TaskActionRunResult } from '@memberjunction/task-graph';
2
+ export declare class TaskGraphActionRunner implements TaskActionRunner {
3
+ RunActionForTask(params: TaskActionRunParams): Promise<TaskActionRunResult>;
4
+ /**
5
+ * Projects the action's parameters onto the flat result a workflow step is expected to produce.
6
+ *
7
+ * **Why not return `result.Params` as-is.** That is an `ActionParam[]`, and every consumer of a
8
+ * step's output addresses fields BY NAME: an output mapping says `{"CurrentPrice": "stockPrice"}`,
9
+ * and a branch condition then reads `payload.stockPrice`. Handed an array, the mapping finds no
10
+ * `CurrentPrice`, writes nothing, and the condition evaluates against `undefined` — which is
11
+ * falsy rather than erroneous, so the workflow takes the other branch and reports success. That
12
+ * is exactly what the Demo workflow did: step 1 completed with an output payload of `{}` and
13
+ * every downstream branch was skipped, with nothing anywhere reporting a problem.
14
+ *
15
+ * Only `Output` and `Both` params are included. Echoing the inputs back would let a step's own
16
+ * parameters masquerade as its results, so an output mapping could "succeed" by reading the
17
+ * value the step was given rather than the one it produced.
18
+ */
19
+ private buildOutput;
20
+ /**
21
+ * Rebuilds the action's parameters from the task's stored payload.
22
+ *
23
+ * **The values here have been through redaction**, because `Task.InputPayload` is persistent,
24
+ * user-visible storage and nothing writes a raw `ActionParam[]` there. A parameter the binding
25
+ * marked as not-logged therefore arrives absent rather than secret — the action sees a missing
26
+ * value, which is the honest consequence of choosing not to persist it, and the reason durable
27
+ * dispatch is opt-in per binding rather than the default.
28
+ *
29
+ * Dependency outputs are merged underneath the task's own input so a node's explicit parameters
30
+ * always win over an upstream node that happened to emit the same key.
31
+ */
32
+ private buildParams;
33
+ }
34
+ //# sourceMappingURL=TaskGraphActionRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskGraphActionRunner.d.ts","sourceRoot":"","sources":["../../src/services/TaskGraphActionRunner.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAE7G,qBAAa,qBAAsB,YAAW,gBAAgB;IAC7C,gBAAgB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAmCxF;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,WAAW;IAQnB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,WAAW;CAUtB"}