@friggframework/core 2.0.0--canary.522.cbd3d5a.0 → 2.0.0--canary.517.35ee143.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 (225) hide show
  1. package/CHANGELOG.md +67 -66
  2. package/CLAUDE.md +124 -148
  3. package/README.md +130 -165
  4. package/admin-scripts/index.js +16 -30
  5. package/admin-scripts/repositories/{admin-api-key-repository-documentdb.js → admin-process-repository-documentdb.js} +5 -5
  6. package/admin-scripts/repositories/{admin-api-key-repository-factory.js → admin-process-repository-factory.js} +15 -19
  7. package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
  8. package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
  9. package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
  10. package/admin-scripts/repositories/script-schedule-repository-factory.js +2 -6
  11. package/admin-scripts/repositories/script-schedule-repository-interface.js +14 -36
  12. package/admin-scripts/repositories/script-schedule-repository-mongo.js +13 -25
  13. package/admin-scripts/repositories/script-schedule-repository-postgres.js +13 -25
  14. package/application/commands/admin-script-commands.js +102 -266
  15. package/application/commands/integration-commands.js +6 -12
  16. package/application/index.js +3 -1
  17. package/assertions/get.js +4 -1
  18. package/associations/association.js +57 -59
  19. package/associations/model.js +41 -41
  20. package/core/CLAUDE.md +156 -222
  21. package/core/Worker.js +1 -5
  22. package/credential/repositories/credential-repository-documentdb.js +1 -71
  23. package/credential/repositories/credential-repository-interface.js +2 -8
  24. package/credential/repositories/credential-repository-mongo.js +4 -45
  25. package/credential/repositories/credential-repository-postgres.js +3 -44
  26. package/credential/repositories/credential-repository.js +4 -6
  27. package/credential/use-cases/get-credential-for-user.js +3 -21
  28. package/credential/use-cases/update-authentication-status.js +2 -5
  29. package/database/MONGODB_TRANSACTION_FIX.md +52 -72
  30. package/database/adapters/lambda-invoker.js +7 -8
  31. package/database/config.js +13 -15
  32. package/database/documentdb-encryption-service.js +13 -29
  33. package/database/documentdb-utils.js +12 -21
  34. package/database/encryption/README.md +36 -53
  35. package/database/encryption/encryption-schema-registry.js +9 -21
  36. package/database/encryption/field-encryption-service.js +4 -15
  37. package/database/encryption/logger.js +2 -3
  38. package/database/encryption/prisma-encryption-extension.js +8 -5
  39. package/database/index.js +2 -4
  40. package/database/models/IndividualUser.js +15 -15
  41. package/database/models/OrganizationUser.js +4 -6
  42. package/database/models/UserModel.js +2 -2
  43. package/database/models/WebsocketConnection.js +1 -4
  44. package/database/mongoose.js +2 -2
  45. package/database/prisma.js +14 -22
  46. package/database/repositories/health-check-repository-documentdb.js +7 -22
  47. package/database/repositories/health-check-repository-factory.js +3 -9
  48. package/database/repositories/health-check-repository-interface.js +5 -15
  49. package/database/repositories/health-check-repository-mongodb.js +6 -9
  50. package/database/repositories/health-check-repository-postgres.js +1 -1
  51. package/database/repositories/migration-status-repository-s3.js +5 -10
  52. package/database/use-cases/check-database-health-use-case.js +2 -3
  53. package/database/use-cases/check-database-state-use-case.js +7 -9
  54. package/database/use-cases/get-database-state-via-worker-use-case.js +12 -15
  55. package/database/use-cases/get-migration-status-use-case.js +2 -4
  56. package/database/use-cases/run-database-migration-use-case.js +9 -41
  57. package/database/use-cases/test-encryption-use-case.js +5 -4
  58. package/database/use-cases/trigger-database-migration-use-case.js +8 -9
  59. package/database/utils/mongodb-collection-utils.js +3 -11
  60. package/database/utils/mongodb-schema-init.js +4 -10
  61. package/database/utils/prisma-runner.js +74 -144
  62. package/database/utils/prisma-schema-parser.js +2 -2
  63. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +80 -135
  64. package/encrypt/Cryptor.js +2 -8
  65. package/errors/fetch-error.js +1 -1
  66. package/generated/prisma-mongodb/edge.js +16 -59
  67. package/generated/prisma-mongodb/index-browser.js +12 -62
  68. package/generated/prisma-mongodb/index.d.ts +4850 -8136
  69. package/generated/prisma-mongodb/index.js +16 -59
  70. package/generated/prisma-mongodb/package.json +1 -1
  71. package/generated/prisma-mongodb/schema.prisma +33 -75
  72. package/generated/prisma-mongodb/wasm.js +16 -59
  73. package/generated/prisma-postgresql/edge.js +15 -59
  74. package/generated/prisma-postgresql/index-browser.js +11 -62
  75. package/generated/prisma-postgresql/index.d.ts +5963 -8930
  76. package/generated/prisma-postgresql/index.js +15 -59
  77. package/generated/prisma-postgresql/package.json +1 -1
  78. package/generated/prisma-postgresql/schema.prisma +33 -73
  79. package/generated/prisma-postgresql/wasm.js +15 -59
  80. package/handlers/WEBHOOKS.md +81 -104
  81. package/handlers/app-definition-loader.js +1 -1
  82. package/handlers/app-handler-helpers.js +2 -14
  83. package/handlers/backend-utils.js +1 -0
  84. package/handlers/database-migration-handler.js +45 -64
  85. package/handlers/middleware/admin-auth.js +53 -0
  86. package/handlers/routers/HEALTHCHECK.md +135 -170
  87. package/handlers/routers/auth.js +2 -23
  88. package/handlers/routers/db-migration.handler.js +3 -2
  89. package/handlers/routers/db-migration.js +33 -69
  90. package/handlers/routers/health.js +8 -23
  91. package/handlers/routers/integration-defined-routers.js +4 -4
  92. package/handlers/routers/integration-webhook-routers.js +7 -17
  93. package/handlers/routers/websocket.js +3 -9
  94. package/handlers/use-cases/check-integrations-health-use-case.js +6 -13
  95. package/handlers/workers/db-migration.js +26 -54
  96. package/index.js +9 -5
  97. package/integrations/WEBHOOK-QUICKSTART.md +14 -21
  98. package/integrations/index.js +0 -4
  99. package/integrations/integration-base.js +6 -9
  100. package/integrations/integration-router.js +146 -1817
  101. package/integrations/options.js +20 -47
  102. package/integrations/repositories/integration-repository-documentdb.js +24 -53
  103. package/integrations/repositories/integration-repository-factory.js +2 -6
  104. package/integrations/repositories/integration-repository-interface.js +9 -27
  105. package/integrations/repositories/integration-repository-postgres.js +3 -3
  106. package/integrations/repositories/process-repository-factory.js +1 -0
  107. package/integrations/repositories/process-repository-interface.js +5 -9
  108. package/integrations/repositories/process-repository-mongo.js +3 -7
  109. package/integrations/repositories/process-repository-postgres.js +2 -2
  110. package/integrations/tests/doubles/config-capturing-integration.js +8 -9
  111. package/integrations/tests/doubles/dummy-integration-class.js +8 -81
  112. package/integrations/tests/doubles/test-integration-repository.js +11 -51
  113. package/integrations/use-cases/create-integration.js +32 -36
  114. package/integrations/use-cases/create-process.js +9 -20
  115. package/integrations/use-cases/delete-integration-for-user.js +4 -5
  116. package/integrations/use-cases/get-integration-for-user.js +10 -25
  117. package/integrations/use-cases/get-integration-instance-by-definition.js +7 -13
  118. package/integrations/use-cases/get-integrations-for-user.js +1 -4
  119. package/integrations/use-cases/get-possible-integrations.js +1 -1
  120. package/integrations/use-cases/get-process.js +6 -5
  121. package/integrations/use-cases/index.js +1 -3
  122. package/integrations/use-cases/load-integration-context.js +5 -1
  123. package/integrations/use-cases/update-process-state.js +8 -10
  124. package/integrations/utils/map-integration-dto.js +3 -9
  125. package/jest-setup.js +1 -1
  126. package/jest-teardown.js +1 -1
  127. package/lambda/TimeoutCatcher.js +30 -32
  128. package/lambda/index.js +1 -1
  129. package/logs/index.js +3 -3
  130. package/modules/module.js +1 -3
  131. package/modules/repositories/module-repository-documentdb.js +48 -114
  132. package/modules/repositories/module-repository-interface.js +0 -13
  133. package/modules/repositories/module-repository-mongo.js +6 -46
  134. package/modules/repositories/module-repository-postgres.js +6 -48
  135. package/modules/repositories/module-repository.js +1 -34
  136. package/modules/requester/api-key.js +2 -0
  137. package/modules/requester/basic.js +1 -0
  138. package/modules/requester/oauth-2.js +2 -3
  139. package/modules/test/mock-api/definition.js +10 -15
  140. package/modules/test/mock-api/mocks/hubspot.js +36 -36
  141. package/modules/tests/doubles/test-module-factory.js +4 -10
  142. package/modules/tests/doubles/test-module-repository.js +1 -1
  143. package/modules/use-cases/get-entities-for-user.js +1 -1
  144. package/modules/use-cases/get-entity-options-by-id.js +6 -8
  145. package/modules/use-cases/get-module.js +9 -12
  146. package/modules/use-cases/process-authorization-callback.js +6 -12
  147. package/modules/use-cases/refresh-entity-options.js +6 -8
  148. package/modules/use-cases/test-module-auth.js +6 -8
  149. package/modules/utils/map-module-dto.js +2 -2
  150. package/package.json +5 -7
  151. package/prisma-mongodb/schema.prisma +33 -75
  152. package/prisma-postgresql/schema.prisma +33 -73
  153. package/queues/queuer-util.js +1 -5
  154. package/syncs/model.js +51 -51
  155. package/syncs/repositories/sync-repository-documentdb.js +19 -39
  156. package/syncs/repositories/sync-repository-interface.js +2 -6
  157. package/syncs/repositories/sync-repository-postgres.js +13 -19
  158. package/syncs/sync.js +100 -104
  159. package/token/repositories/token-repository-factory.js +3 -1
  160. package/types/assertions/index.d.ts +72 -72
  161. package/types/associations/index.d.ts +57 -57
  162. package/types/core/index.d.ts +53 -59
  163. package/types/database/index.d.ts +2 -2
  164. package/types/encrypt/index.d.ts +3 -3
  165. package/types/errors/index.d.ts +54 -61
  166. package/types/eslint-config/index.d.ts +40 -40
  167. package/types/integrations/index.d.ts +183 -185
  168. package/types/lambda/index.d.ts +26 -26
  169. package/types/logs/index.d.ts +4 -4
  170. package/types/module-plugin/index.d.ts +237 -239
  171. package/types/prettier-config/index.d.ts +5 -5
  172. package/types/syncs/index.d.ts +108 -102
  173. package/types/test-environment/index.d.ts +14 -14
  174. package/types/tsconfig.json +93 -95
  175. package/user/tests/doubles/test-user-repository.js +2 -5
  176. package/user/use-cases/authenticate-user.js +4 -2
  177. package/user/use-cases/authenticate-with-shared-secret.js +1 -1
  178. package/user/use-cases/create-individual-user.js +7 -8
  179. package/user/use-cases/create-organization-user.js +1 -1
  180. package/user/use-cases/create-token-for-user-id.js +1 -1
  181. package/user/use-cases/get-user-from-adopter-jwt.js +2 -0
  182. package/user/use-cases/get-user-from-bearer-token.js +3 -7
  183. package/user/use-cases/get-user-from-x-frigg-headers.js +11 -14
  184. package/user/use-cases/login-user.js +8 -8
  185. package/user/user.js +4 -18
  186. package/utils/backend-path.js +2 -2
  187. package/utils/index.js +1 -4
  188. package/websocket/repositories/websocket-connection-repository-documentdb.js +8 -21
  189. package/websocket/repositories/websocket-connection-repository-mongo.js +4 -8
  190. package/websocket/repositories/websocket-connection-repository-postgres.js +4 -8
  191. package/websocket/repositories/websocket-connection-repository.js +4 -8
  192. package/admin-scripts/repositories/admin-api-key-repository-interface.js +0 -121
  193. package/admin-scripts/repositories/admin-api-key-repository-mongo.js +0 -155
  194. package/admin-scripts/repositories/admin-api-key-repository-postgres.js +0 -189
  195. package/admin-scripts/repositories/script-execution-repository-documentdb.js +0 -21
  196. package/admin-scripts/repositories/script-execution-repository-factory.js +0 -55
  197. package/admin-scripts/repositories/script-execution-repository-interface.js +0 -193
  198. package/admin-scripts/repositories/script-execution-repository-mongo.js +0 -278
  199. package/admin-scripts/repositories/script-execution-repository-postgres.js +0 -320
  200. package/credential/credential-router.js +0 -262
  201. package/credential/use-cases/delete-credential-for-user.js +0 -50
  202. package/credential/use-cases/list-credentials-for-user.js +0 -31
  203. package/credential/use-cases/reauthorize-credential.js +0 -103
  204. package/handlers/routers/admin.js +0 -450
  205. package/handlers/routers/docs.js +0 -180
  206. package/handlers/routers/middleware/loadUser.js +0 -39
  207. package/handlers/routers/middleware/requireAdmin.js +0 -41
  208. package/handlers/routers/middleware/requireLoggedInUser.js +0 -19
  209. package/integrations/use-cases/execute-proxy-request.js +0 -564
  210. package/modules/domain/entities/AuthorizationSession.js +0 -131
  211. package/modules/domain/entities/index.js +0 -10
  212. package/modules/repositories/authorization-session-repository-factory.js +0 -55
  213. package/modules/repositories/authorization-session-repository-interface.js +0 -75
  214. package/modules/repositories/authorization-session-repository-mongo.js +0 -169
  215. package/modules/repositories/authorization-session-repository-postgres.js +0 -170
  216. package/modules/use-cases/delete-module-entity.js +0 -23
  217. package/modules/use-cases/get-authorization-requirements.js +0 -110
  218. package/modules/use-cases/get-module-entity-by-id.js +0 -16
  219. package/modules/use-cases/process-authorization-step.js +0 -160
  220. package/modules/use-cases/start-authorization-session.js +0 -86
  221. package/modules/use-cases/update-module-entity.js +0 -27
  222. package/openapi/openapi-spec-generator.js +0 -370
  223. package/openapi/openapi-v1.yaml +0 -1360
  224. package/openapi/openapi-v2.yaml +0 -1535
  225. package/user/use-cases/delete-user.js +0 -47
@@ -1,7 +1,7 @@
1
1
  require('dotenv').config();
2
2
  const { Api } = require('./api');
3
3
  const { get } = require('../../../assertions');
4
- const config = { name: 'anapi' };
4
+ const config = { name: 'anapi' }
5
5
 
6
6
  const Definition = {
7
7
  API: Api,
@@ -9,9 +9,7 @@ const Definition = {
9
9
  url: 'http://localhost:3000/redirect/anapi',
10
10
  type: 'oauth2',
11
11
  }),
12
- getName: function () {
13
- return config.name;
14
- },
12
+ getName: function () { return config.name },
15
13
  moduleName: config.name,
16
14
  modelName: 'AnApi',
17
15
  requiredAuthMethods: {
@@ -19,31 +17,28 @@ const Definition = {
19
17
  const code = get(params.data, 'code');
20
18
  return api.getTokenFromCode(code);
21
19
  },
22
- getEntityDetails: async function (
23
- api,
24
- callbackParams,
25
- tokenResponse,
26
- userId
27
- ) {
20
+ getEntityDetails: async function (api, callbackParams, tokenResponse, userId) {
28
21
  const userDetails = await api.getUserDetails();
29
22
  return {
30
23
  identifiers: { externalId: userDetails.portalId, user: userId },
31
24
  details: { name: userDetails.hub_domain },
32
- };
25
+ }
33
26
  },
34
27
  apiPropertiesToPersist: {
35
- credential: ['access_token', 'refresh_token'],
28
+ credential: [
29
+ 'access_token', 'refresh_token'
30
+ ],
36
31
  entity: [],
37
32
  },
38
33
  getCredentialDetails: async function (api, userId) {
39
34
  const userDetails = await api.getUserDetails();
40
35
  return {
41
36
  identifiers: { externalId: userDetails.portalId, user: userId },
42
- details: {},
37
+ details: {}
43
38
  };
44
39
  },
45
40
  testAuthRequest: async function (api) {
46
- return api.getUserDetails();
41
+ return api.getUserDetails()
47
42
  },
48
43
  },
49
44
  env: {
@@ -51,7 +46,7 @@ const Definition = {
51
46
  client_secret: 'test',
52
47
  scope: 'test',
53
48
  redirect_uri: `http://localhost:3000/redirect/anapi`,
54
- },
49
+ }
55
50
  };
56
51
 
57
52
  module.exports = { Definition };
@@ -1,43 +1,43 @@
1
1
  const authorizeResponse = {
2
- base: '/redirect/hubspot',
3
- data: {
4
- code: 'test-code',
5
- state: 'null',
6
- },
7
- };
2
+ "base": "/redirect/hubspot",
3
+ "data": {
4
+ "code": "test-code",
5
+ "state": "null"
6
+ }
7
+ }
8
8
 
9
9
  const tokenResponse = {
10
- token_type: 'bearer',
11
- refresh_token: 'test-refresh-token',
12
- access_token: 'test-access-token',
13
- expires_in: 1800,
14
- };
10
+ "token_type": "bearer",
11
+ "refresh_token": "test-refresh-token",
12
+ "access_token": "test-access-token",
13
+ "expires_in": 1800
14
+ }
15
15
 
16
16
  const userDetailsResponse = {
17
- portalId: 111111111,
18
- timeZone: 'US/Eastern',
19
- accountType: 'DEVELOPER_TEST',
20
- currency: 'USD',
21
- utcOffset: '-05:00',
22
- utcOffsetMilliseconds: -18000000,
23
- token: 'test-token',
24
- user: 'projectteam@lefthook.co',
25
- hub_domain: 'Testing Object Things-dev-44613847.com',
26
- scopes: [
27
- 'content',
28
- 'oauth',
29
- 'crm.objects.contacts.read',
30
- 'crm.objects.contacts.write',
31
- 'crm.objects.companies.write',
32
- 'crm.objects.companies.read',
33
- 'crm.objects.deals.read',
34
- 'crm.schemas.deals.read',
17
+ "portalId": 111111111,
18
+ "timeZone": "US/Eastern",
19
+ "accountType": "DEVELOPER_TEST",
20
+ "currency": "USD",
21
+ "utcOffset": "-05:00",
22
+ "utcOffsetMilliseconds": -18000000,
23
+ "token": "test-token",
24
+ "user": "projectteam@lefthook.co",
25
+ "hub_domain": "Testing Object Things-dev-44613847.com",
26
+ "scopes": [
27
+ "content",
28
+ "oauth",
29
+ "crm.objects.contacts.read",
30
+ "crm.objects.contacts.write",
31
+ "crm.objects.companies.write",
32
+ "crm.objects.companies.read",
33
+ "crm.objects.deals.read",
34
+ "crm.schemas.deals.read"
35
35
  ],
36
- hub_id: 111111111,
37
- app_id: 22222222,
38
- expires_in: 1704,
39
- user_id: 33333333,
40
- token_type: 'access',
41
- };
36
+ "hub_id": 111111111,
37
+ "app_id": 22222222,
38
+ "expires_in": 1704,
39
+ "user_id": 33333333,
40
+ "token_type": "access"
41
+ }
42
42
 
43
- module.exports = { authorizeResponse, tokenResponse, userDetailsResponse };
43
+ module.exports = { authorizeResponse, tokenResponse, userDetailsResponse }
@@ -1,16 +1,10 @@
1
1
  class TestModuleFactory {
2
- constructor() {
3
- this.moduleRepository = {
4
- findEntity: jest.fn().mockResolvedValue(null),
5
- findEntitiesBy: jest.fn().mockResolvedValue([]),
6
- };
7
- }
2
+ constructor() { }
8
3
 
9
4
  async getModuleInstance(entityId, userId) {
5
+ // return minimal stub module with getName and api property
10
6
  return {
11
- getName() {
12
- return 'stubModule';
13
- },
7
+ getName() { return 'stubModule'; },
14
8
  api: {},
15
9
  entityId,
16
10
  userId,
@@ -19,4 +13,4 @@ class TestModuleFactory {
19
13
  }
20
14
  }
21
15
 
22
- module.exports = { TestModuleFactory };
16
+ module.exports = { TestModuleFactory };
@@ -36,4 +36,4 @@ class TestModuleRepository {
36
36
  }
37
37
  }
38
38
 
39
- module.exports = { TestModuleRepository };
39
+ module.exports = { TestModuleRepository };
@@ -29,4 +29,4 @@ class GetEntitiesForUser {
29
29
  }
30
30
  }
31
31
 
32
- module.exports = { GetEntitiesForUser };
32
+ module.exports = { GetEntitiesForUser };
@@ -20,10 +20,9 @@ class GetEntityOptionsById {
20
20
  */
21
21
  async execute(entityId, userIdOrUser) {
22
22
  // Support both userId (backward compatible) and User object (new pattern)
23
- const userId =
24
- typeof userIdOrUser === 'object' && userIdOrUser?.getId
25
- ? userIdOrUser.getId()
26
- : userIdOrUser;
23
+ const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
24
+ ? userIdOrUser.getId()
25
+ : userIdOrUser;
27
26
 
28
27
  const entity = await this.moduleRepository.findEntityById(
29
28
  entityId,
@@ -35,10 +34,9 @@ class GetEntityOptionsById {
35
34
  }
36
35
 
37
36
  // Validate entity ownership
38
- const isOwned =
39
- typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
40
- ? userIdOrUser.ownsUserId(entity.userId)
41
- : entity.userId?.toString() === userId?.toString();
37
+ const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
38
+ ? userIdOrUser.ownsUserId(entity.userId)
39
+ : entity.userId?.toString() === userId?.toString();
42
40
 
43
41
  if (!isOwned) {
44
42
  throw new Error(
@@ -15,10 +15,9 @@ class GetModule {
15
15
  */
16
16
  async execute(entityId, userIdOrUser) {
17
17
  // Support both userId (backward compatible) and User object (new pattern)
18
- const userId =
19
- typeof userIdOrUser === 'object' && userIdOrUser?.getId
20
- ? userIdOrUser.getId()
21
- : userIdOrUser;
18
+ const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
19
+ ? userIdOrUser.getId()
20
+ : userIdOrUser;
22
21
 
23
22
  const entity = await this.moduleRepository.findEntityById(
24
23
  entityId,
@@ -32,10 +31,9 @@ class GetModule {
32
31
  // Validate entity ownership
33
32
  // If User object provided, use ownsUserId to check linked users
34
33
  // Otherwise fall back to simple equality check
35
- const isOwned =
36
- typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
37
- ? userIdOrUser.ownsUserId(entity.userId)
38
- : entity.userId?.toString() === userId?.toString();
34
+ const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
35
+ ? userIdOrUser.ownsUserId(entity.userId)
36
+ : entity.userId?.toString() === userId?.toString();
39
37
 
40
38
  if (!isOwned) {
41
39
  throw new Error(
@@ -45,8 +43,7 @@ class GetModule {
45
43
 
46
44
  const entityType = entity.moduleName;
47
45
  const moduleDefinition = this.moduleDefinitions.find((def) => {
48
- const modelName =
49
- Module.getEntityModelFromDefinition(def).modelName;
46
+ const modelName = Module.getEntityModelFromDefinition(def).modelName;
50
47
  return entityType === modelName;
51
48
  });
52
49
 
@@ -70,8 +67,8 @@ class GetModule {
70
67
  credential: module.credential,
71
68
  externalId: module.entity.externalId,
72
69
  userId: module.entity.user.toString(),
73
- };
70
+ }
74
71
  }
75
72
  }
76
73
 
77
- module.exports = { GetModule };
74
+ module.exports = { GetModule };
@@ -14,7 +14,7 @@ class ProcessAuthorizationCallback {
14
14
  this.moduleDefinitions = moduleDefinitions;
15
15
  }
16
16
 
17
- async execute(userId, entityType, params, isGlobal = false) {
17
+ async execute(userId, entityType, params) {
18
18
  const moduleDefinition = this.moduleDefinitions.find((def) => {
19
19
  return entityType === def.moduleName;
20
20
  });
@@ -70,8 +70,7 @@ class ProcessAuthorizationCallback {
70
70
  const persistedEntity = await this.findOrCreateEntity(
71
71
  entityDetails,
72
72
  entityType,
73
- module.credential.id,
74
- isGlobal
73
+ module.credential.id
75
74
  );
76
75
 
77
76
  return {
@@ -94,22 +93,18 @@ class ProcessAuthorizationCallback {
94
93
  );
95
94
  credentialDetails.details.authIsValid = true;
96
95
 
97
- const persisted = await this.credentialRepository.upsertCredential(
98
- credentialDetails
99
- );
96
+ const persisted = await this.credentialRepository.upsertCredential(credentialDetails);
100
97
  module.credential = persisted;
101
98
  }
102
99
 
103
- async findOrCreateEntity(entityDetails, moduleName, credentialId, isGlobal = false) {
100
+ async findOrCreateEntity(entityDetails, moduleName, credentialId) {
104
101
  const { identifiers, details } = entityDetails;
105
102
 
106
103
  // Support both 'user' and 'userId' field names from module definitions
107
104
  // Some modules use 'user' (legacy), others use 'userId' (newer pattern)
108
105
  const userId = identifiers.user || identifiers.userId;
109
106
 
110
- // For global entities, userId is not required (it will be null)
111
- // For user-specific entities, userId must be provided for security
112
- if (!isGlobal && !userId) {
107
+ if (!userId) {
113
108
  throw new Error(
114
109
  `Module definition for ${moduleName} must return 'user' or 'userId' in identifiers from getEntityDetails(). ` +
115
110
  `Without userId, entity lookup would match across all users (security issue).`
@@ -118,7 +113,7 @@ class ProcessAuthorizationCallback {
118
113
 
119
114
  const existingEntity = await this.moduleRepository.findEntity({
120
115
  externalId: identifiers.externalId,
121
- user: isGlobal ? null : userId,
116
+ user: userId,
122
117
  moduleName: moduleName,
123
118
  });
124
119
 
@@ -131,7 +126,6 @@ class ProcessAuthorizationCallback {
131
126
  ...details,
132
127
  moduleName: moduleName,
133
128
  credential: credentialId,
134
- isGlobal,
135
129
  });
136
130
  }
137
131
  }
@@ -21,10 +21,9 @@ class RefreshEntityOptions {
21
21
  */
22
22
  async execute(entityId, userIdOrUser, options) {
23
23
  // Support both userId (backward compatible) and User object (new pattern)
24
- const userId =
25
- typeof userIdOrUser === 'object' && userIdOrUser?.getId
26
- ? userIdOrUser.getId()
27
- : userIdOrUser;
24
+ const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
25
+ ? userIdOrUser.getId()
26
+ : userIdOrUser;
28
27
 
29
28
  const entity = await this.moduleRepository.findEntityById(
30
29
  entityId,
@@ -36,10 +35,9 @@ class RefreshEntityOptions {
36
35
  }
37
36
 
38
37
  // Validate entity ownership
39
- const isOwned =
40
- typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
41
- ? userIdOrUser.ownsUserId(entity.userId)
42
- : entity.userId?.toString() === userId?.toString();
38
+ const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
39
+ ? userIdOrUser.ownsUserId(entity.userId)
40
+ : entity.userId?.toString() === userId?.toString();
43
41
 
44
42
  if (!isOwned) {
45
43
  throw new Error(
@@ -20,10 +20,9 @@ class TestModuleAuth {
20
20
  */
21
21
  async execute(entityId, userIdOrUser) {
22
22
  // Support both userId (backward compatible) and User object (new pattern)
23
- const userId =
24
- typeof userIdOrUser === 'object' && userIdOrUser?.getId
25
- ? userIdOrUser.getId()
26
- : userIdOrUser;
23
+ const userId = typeof userIdOrUser === 'object' && userIdOrUser?.getId
24
+ ? userIdOrUser.getId()
25
+ : userIdOrUser;
27
26
 
28
27
  const entity = await this.moduleRepository.findEntityById(
29
28
  entityId,
@@ -35,10 +34,9 @@ class TestModuleAuth {
35
34
  }
36
35
 
37
36
  // Validate entity ownership
38
- const isOwned =
39
- typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
40
- ? userIdOrUser.ownsUserId(entity.userId)
41
- : entity.userId?.toString() === userId?.toString();
37
+ const isOwned = typeof userIdOrUser === 'object' && userIdOrUser?.ownsUserId
38
+ ? userIdOrUser.ownsUserId(entity.userId)
39
+ : entity.userId?.toString() === userId?.toString();
42
40
 
43
41
  if (!isOwned) {
44
42
  throw new Error(
@@ -11,8 +11,8 @@ function mapModuleClassToModuleDTO(moduleInstance) {
11
11
  userId: moduleInstance.userId,
12
12
  entity: moduleInstance.entity,
13
13
  credentialId: moduleInstance.credential?._id?.toString(),
14
- type: moduleInstance.getName(),
14
+ type: moduleInstance.getName()
15
15
  };
16
16
  }
17
17
 
18
- module.exports = { mapModuleClassToModuleDTO };
18
+ module.exports = { mapModuleClassToModuleDTO };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.522.cbd3d5a.0",
4
+ "version": "2.0.0--canary.517.35ee143.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -18,7 +18,6 @@
18
18
  "express-async-handler": "^1.2.0",
19
19
  "form-data": "^4.0.0",
20
20
  "fs-extra": "^11.2.0",
21
- "js-yaml": "^4.1.0",
22
21
  "lodash": "4.17.21",
23
22
  "lodash.get": "^4.4.2",
24
23
  "mongoose": "6.11.6",
@@ -39,9 +38,9 @@
39
38
  }
40
39
  },
41
40
  "devDependencies": {
42
- "@friggframework/eslint-config": "2.0.0--canary.522.cbd3d5a.0",
43
- "@friggframework/prettier-config": "2.0.0--canary.522.cbd3d5a.0",
44
- "@friggframework/test": "2.0.0--canary.522.cbd3d5a.0",
41
+ "@friggframework/eslint-config": "2.0.0--canary.517.35ee143.0",
42
+ "@friggframework/prettier-config": "2.0.0--canary.517.35ee143.0",
43
+ "@friggframework/test": "2.0.0--canary.517.35ee143.0",
45
44
  "@prisma/client": "^6.17.0",
46
45
  "@types/lodash": "4.17.15",
47
46
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -54,7 +53,6 @@
54
53
  "prettier": "^2.7.1",
55
54
  "prisma": "^6.17.0",
56
55
  "sinon": "^16.1.1",
57
- "supertest": "^7.1.4",
58
56
  "typescript": "^5.0.2"
59
57
  },
60
58
  "scripts": {
@@ -82,5 +80,5 @@
82
80
  "publishConfig": {
83
81
  "access": "public"
84
82
  },
85
- "gitHead": "cbd3d5a81315519842f308fc0bd786a3f8786b79"
83
+ "gitHead": "35ee143ec0654d0935aee59bf62b882f5f27d8b7"
86
84
  }
@@ -80,26 +80,6 @@ model Token {
80
80
  @@map("Token")
81
81
  }
82
82
 
83
- /// Multi-step authorization session tracking
84
- /// Supports OTP flows and multi-stage authentication (e.g., Nagaris)
85
- model AuthorizationSession {
86
- id String @id @default(auto()) @map("_id") @db.ObjectId
87
- sessionId String @unique
88
- userId String
89
- entityType String
90
- currentStep Int @default(1)
91
- maxSteps Int
92
- stepData Json @default("{}")
93
- expiresAt DateTime
94
- completed Boolean @default(false)
95
- createdAt DateTime @default(now())
96
- updatedAt DateTime @updatedAt
97
-
98
- @@index([userId, entityType])
99
- @@index([expiresAt])
100
- @@map("AuthorizationSession")
101
- }
102
-
103
83
  // ============================================================================
104
84
  // CREDENTIAL & ENTITY MODELS
105
85
  // ============================================================================
@@ -138,7 +118,6 @@ model Entity {
138
118
  name String?
139
119
  moduleName String?
140
120
  externalId String?
141
- isGlobal Boolean @default(false)
142
121
 
143
122
  createdAt DateTime @default(now())
144
123
  updatedAt DateTime @updatedAt
@@ -157,8 +136,6 @@ model Entity {
157
136
  @@index([externalId])
158
137
  @@index([moduleName])
159
138
  @@index([credentialId])
160
- @@index([isGlobal])
161
- @@index([isGlobal, moduleName])
162
139
  @@map("Entity")
163
140
  }
164
141
 
@@ -383,70 +360,51 @@ model WebsocketConnection {
383
360
  }
384
361
 
385
362
  // ============================================================================
386
- // ADMIN SCRIPT RUNNER MODELS
363
+ // ADMIN PROCESS MODELS
387
364
  // ============================================================================
388
365
 
389
- enum ScriptExecutionStatus {
366
+ /// Admin process state machine
367
+ enum AdminProcessState {
390
368
  PENDING
391
369
  RUNNING
392
370
  COMPLETED
393
371
  FAILED
394
- TIMEOUT
395
- CANCELLED
396
372
  }
397
373
 
398
- enum ScriptTrigger {
374
+ /// Admin trigger types
375
+ enum AdminTrigger {
399
376
  MANUAL
400
377
  SCHEDULED
401
378
  QUEUE
402
379
  WEBHOOK
403
380
  }
404
381
 
405
- /// Admin API keys for script execution authentication
406
- /// Key hashes stored with bcrypt
407
- model AdminApiKey {
408
- id String @id @default(auto()) @map("_id") @db.ObjectId
409
- keyHash String @unique // bcrypt hashed
410
- keyLast4 String // Last 4 chars for display
411
- name String // Human-readable name
412
- scopes String[] // ['scripts:execute', 'scripts:read']
413
- expiresAt DateTime?
414
- createdBy String? // User/admin who created
415
- lastUsedAt DateTime?
416
- isActive Boolean @default(true)
417
- createdAt DateTime @default(now())
418
- updatedAt DateTime @updatedAt
419
-
420
- @@index([isActive])
421
- @@map("AdminApiKey")
422
- }
382
+ /// Admin process tracking (like Process but without user/integration FK)
383
+ /// Used for: admin scripts, db migrations, system maintenance tasks
384
+ model AdminProcess {
385
+ id String @id @default(auto()) @map("_id") @db.ObjectId
386
+ name String // e.g., "oauth-token-refresh", "db-migration-xyz"
387
+ type String // e.g., "ADMIN_SCRIPT", "DB_MIGRATION"
423
388
 
424
- /// Script execution tracking and audit log
425
- model ScriptExecution {
426
- id String @id @default(auto()) @map("_id") @db.ObjectId
427
- scriptName String
428
- scriptVersion String?
429
- status ScriptExecutionStatus @default(PENDING)
430
- trigger ScriptTrigger
431
- mode String @default("async") // "sync" | "async"
432
- input Json?
433
- output Json?
434
- logs Json[] // [{level, message, data, timestamp}]
435
- metricsStartTime DateTime?
436
- metricsEndTime DateTime?
437
- metricsDurationMs Int?
438
- errorName String?
439
- errorMessage String?
440
- errorStack String?
441
- auditApiKeyName String?
442
- auditApiKeyLast4 String?
443
- auditIpAddress String?
444
- createdAt DateTime @default(now())
445
- updatedAt DateTime @updatedAt
446
-
447
- @@index([scriptName, createdAt(sort: Desc)])
448
- @@index([status])
449
- @@map("ScriptExecution")
389
+ // State machine
390
+ state AdminProcessState @default(PENDING)
391
+
392
+ // Flexible storage (mirrors Process model pattern)
393
+ context Json @default("{}") // input, trigger, audit info, script version
394
+ results Json @default("{}") // output, logs, metrics, errors
395
+
396
+ // Hierarchy support
397
+ childProcesses String[] @db.ObjectId
398
+ parentProcessId String? @db.ObjectId
399
+
400
+ // Timestamps
401
+ createdAt DateTime @default(now())
402
+ updatedAt DateTime @updatedAt
403
+
404
+ @@index([name, createdAt(sort: Desc)])
405
+ @@index([state])
406
+ @@index([type])
407
+ @@map("AdminProcess")
450
408
  }
451
409
 
452
410
  /// Script scheduling configuration for hybrid scheduling (SQS + EventBridge)
@@ -459,9 +417,9 @@ model ScriptSchedule {
459
417
  lastTriggeredAt DateTime?
460
418
  nextTriggerAt DateTime?
461
419
 
462
- // AWS EventBridge Schedule (if provisioned)
463
- awsScheduleArn String?
464
- awsScheduleName String?
420
+ // External Scheduler (e.g., AWS EventBridge Scheduler)
421
+ externalScheduleId String?
422
+ externalScheduleName String?
465
423
 
466
424
  createdAt DateTime @default(now())
467
425
  updatedAt DateTime @updatedAt