@friggframework/core 2.0.0--canary.684.0da024b.0 → 2.0.0--canary.679.a2bcc2f.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 (104) hide show
  1. package/CLAUDE.md +0 -2
  2. package/README.md +0 -105
  3. package/application/commands/integration-commands.js +2 -2
  4. package/application/commands/user-commands.js +5 -17
  5. package/credential/use-cases/credential-operations-for-user.js +25 -110
  6. package/credential/use-cases/reauthorize-credential-for-user.js +8 -15
  7. package/database/documentdb-utils.js +1 -6
  8. package/generated/prisma-mongodb/edge.js +4 -15
  9. package/generated/prisma-mongodb/index-browser.js +1 -12
  10. package/generated/prisma-mongodb/index.d.ts +86 -2027
  11. package/generated/prisma-mongodb/index.js +4 -15
  12. package/generated/prisma-mongodb/package.json +1 -1
  13. package/generated/prisma-mongodb/schema.prisma +0 -47
  14. package/generated/prisma-mongodb/wasm.js +4 -15
  15. package/generated/prisma-postgresql/edge.js +4 -15
  16. package/generated/prisma-postgresql/index-browser.js +1 -12
  17. package/generated/prisma-postgresql/index.d.ts +63 -2162
  18. package/generated/prisma-postgresql/index.js +4 -15
  19. package/generated/prisma-postgresql/package.json +1 -1
  20. package/generated/prisma-postgresql/schema.prisma +0 -44
  21. package/generated/prisma-postgresql/wasm.js +4 -15
  22. package/handlers/app-definition-loader.js +1 -15
  23. package/index.js +0 -18
  24. package/integrations/integration-router.js +73 -115
  25. package/integrations/repositories/integration-repository-documentdb.js +3 -35
  26. package/integrations/repositories/integration-repository-interface.js +1 -17
  27. package/integrations/repositories/integration-repository-mongo.js +76 -59
  28. package/integrations/repositories/integration-repository-postgres.js +76 -62
  29. package/integrations/tests/doubles/test-integration-repository.js +1 -12
  30. package/integrations/use-cases/create-integration.js +20 -55
  31. package/integrations/use-cases/get-integrations-for-user.js +40 -80
  32. package/integrations/use-cases/index.js +1 -5
  33. package/integrations/use-cases/integration-operations-for-user.js +24 -55
  34. package/management-api/management-api-config.js +0 -3
  35. package/management-api/openapi/components.js +0 -40
  36. package/management-api/openapi/v2-operations.js +1 -13
  37. package/management-api/v2/dependencies.js +15 -40
  38. package/management-api/v2/dto.js +0 -20
  39. package/management-api/v2/handlers/authorization.js +0 -1
  40. package/management-api/v2/handlers/credentials.js +2 -6
  41. package/management-api/v2/handlers/entities.js +7 -10
  42. package/management-api/v2/handlers/integrations.js +3 -6
  43. package/management-api/v2/request.js +1 -32
  44. package/modules/index.js +0 -8
  45. package/modules/repositories/module-repository-documentdb.js +4 -48
  46. package/modules/repositories/module-repository-interface.js +2 -19
  47. package/modules/repositories/module-repository-mongo.js +73 -65
  48. package/modules/repositories/module-repository-postgres.js +73 -64
  49. package/modules/use-cases/entity-operations-for-user.js +13 -50
  50. package/modules/use-cases/entity-types.js +7 -31
  51. package/modules/use-cases/execute-entity-proxy-request.js +0 -15
  52. package/modules/use-cases/get-entities-for-user.js +5 -16
  53. package/modules/use-cases/get-entity-module-for-user.js +3 -23
  54. package/modules/use-cases/get-entity-options-by-id.js +3 -9
  55. package/modules/use-cases/get-module.js +3 -9
  56. package/modules/use-cases/multi-step-authorization.js +12 -39
  57. package/modules/use-cases/process-authorization-callback.js +18 -52
  58. package/modules/use-cases/refresh-entity-options.js +3 -9
  59. package/modules/use-cases/test-module-auth.js +3 -9
  60. package/package.json +5 -6
  61. package/prisma-mongodb/schema.prisma +0 -47
  62. package/prisma-postgresql/schema.prisma +0 -44
  63. package/types/index.d.ts +0 -1
  64. package/types/modules/index.d.ts +0 -87
  65. package/user/repositories/user-repository-documentdb.js +2 -27
  66. package/user/repositories/user-repository-interface.js +0 -18
  67. package/user/repositories/user-repository-mongo.js +0 -24
  68. package/user/repositories/user-repository-postgres.js +0 -18
  69. package/user/use-cases/authenticate-user.js +1 -7
  70. package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
  71. package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
  72. package/user/user.js +1 -64
  73. package/database/organization-where.js +0 -18
  74. package/database/unique-violation.js +0 -25
  75. package/integrations/repositories/integration-not-found.js +0 -14
  76. package/integrations/use-cases/resolve-integration-ownership.js +0 -177
  77. package/modules/entity-scope.js +0 -15
  78. package/modules/scope-config.js +0 -192
  79. package/modules/scope-policy.js +0 -112
  80. package/modules/scope-resolution.js +0 -288
  81. package/modules/scope-visibility.js +0 -239
  82. package/modules/tests/doubles/ownership-matching.js +0 -18
  83. package/modules/use-cases/authorize-entity-for-user.js +0 -61
  84. package/modules/use-cases/create-entity-from-credential.js +0 -113
  85. package/modules/use-cases/manage-access.js +0 -21
  86. package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
  87. package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
  88. package/types/user/index.d.ts +0 -134
  89. package/user/adopter-jwt-config.js +0 -177
  90. package/user/adopter-jwt-errors.js +0 -59
  91. package/user/adopter-token-verifier.js +0 -122
  92. package/user/app-user-helpers.js +0 -97
  93. package/user/create-user-authentication.js +0 -64
  94. package/user/membership.js +0 -51
  95. package/user/repositories/organization-membership-record.js +0 -19
  96. package/user/repositories/organization-membership-repository-documentdb.js +0 -106
  97. package/user/repositories/organization-membership-repository-factory.js +0 -42
  98. package/user/repositories/organization-membership-repository-interface.js +0 -57
  99. package/user/repositories/organization-membership-repository-mongo.js +0 -13
  100. package/user/repositories/organization-membership-repository-postgres.js +0 -29
  101. package/user/repositories/organization-membership-repository-prisma.js +0 -81
  102. package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
  103. package/user/use-cases/ensure-organization-membership.js +0 -92
  104. package/user/use-cases/find-individual-users-by-organization.js +0 -54
@@ -1,5 +1,4 @@
1
1
  const { maskCredential } = require('../dto');
2
- const { parseListFilters } = require('../request');
3
2
 
4
3
  /** Management API v2 credential handlers, keyed by operationId. */
5
4
  function createCredentialHandlers(useCases) {
@@ -7,11 +6,8 @@ function createCredentialHandlers(useCases) {
7
6
  useCases;
8
7
 
9
8
  return {
10
- async listCredentials(req, res, user) {
11
- const credentials = await listCredentialsForUser.execute(
12
- user,
13
- parseListFilters(req.query)
14
- );
9
+ async listCredentials(_req, res, user) {
10
+ const credentials = await listCredentialsForUser.execute(user);
15
11
  res.json({ credentials: credentials.map(maskCredential) });
16
12
  },
17
13
 
@@ -1,5 +1,5 @@
1
1
  const { toEntityDto } = require('../dto');
2
- const { objectBody, parseStep, parseListFilters } = require('../request');
2
+ const { objectBody, parseStep } = require('../request');
3
3
 
4
4
  /** Management API v2 entity and entity-type handlers, keyed by operationId. */
5
5
  function createEntityHandlers(useCases) {
@@ -16,20 +16,17 @@ function createEntityHandlers(useCases) {
16
16
  } = useCases;
17
17
 
18
18
  return {
19
- async listEntities(req, res, user) {
20
- const entities = await listEntitiesForUser.execute(
21
- user,
22
- parseListFilters(req.query)
23
- );
19
+ async listEntities(_req, res, user) {
20
+ const entities = await listEntitiesForUser.execute(user);
24
21
  res.json({ entities: entities.map(toEntityDto) });
25
22
  },
26
23
 
27
- async listEntityTypes(_req, res, user) {
28
- res.json({ types: await listEntityTypes.execute({ user }) });
24
+ async listEntityTypes(_req, res) {
25
+ res.json({ types: await listEntityTypes.execute() });
29
26
  },
30
27
 
31
- async getEntityType(req, res, user) {
32
- res.json(await getEntityType.execute(req.params.entityType, { user }));
28
+ async getEntityType(req, res) {
29
+ res.json(await getEntityType.execute(req.params.entityType));
33
30
  },
34
31
 
35
32
  // Describes a step's requirements without starting an authorization
@@ -1,5 +1,5 @@
1
1
  const { toIntegrationDto } = require('../dto');
2
- const { objectBody, optionalString, parseListFilters } = require('../request');
2
+ const { objectBody, optionalString } = require('../request');
3
3
 
4
4
  /**
5
5
  * Management API v2 integration handlers, keyed by registry operationId.
@@ -27,11 +27,8 @@ function createIntegrationHandlers(useCases) {
27
27
  );
28
28
 
29
29
  return {
30
- async listIntegrations(req, res, user) {
31
- const integrations = await getIntegrationsForUser.execute(
32
- user,
33
- parseListFilters(req.query)
34
- );
30
+ async listIntegrations(_req, res, user) {
31
+ const integrations = await getIntegrationsForUser.execute(user.getId());
35
32
  res.json({ integrations: integrations.map(toIntegrationDto) });
36
33
  },
37
34
 
@@ -1,5 +1,4 @@
1
1
  const Boom = require('@hapi/boom');
2
- const { LIST_OWNERS } = require('../../modules/scope-visibility');
3
2
 
4
3
  /** The JSON body as an object, or a 400 VALIDATION_ERROR. */
5
4
  function objectBody(req) {
@@ -52,34 +51,4 @@ function optionalString(value, name) {
52
51
  return value;
53
52
  }
54
53
 
55
- const LIST_SCOPES = ['individual', 'organization'];
56
-
57
- /**
58
- * `?scope=individual|organization` and `?owner=me|org` on a list (ADR-056
59
- * §3.4). Anything else is a 400.
60
- */
61
- function parseListFilters(query = {}) {
62
- const scope = optionalString(query.scope, 'scope');
63
- const owner = optionalString(query.owner, 'owner');
64
- if (scope !== undefined && !LIST_SCOPES.includes(scope)) {
65
- throw Boom.badRequest(`scope must be one of ${LIST_SCOPES.join(', ')}`, {
66
- code: 'VALIDATION_ERROR',
67
- details: { field: 'scope' },
68
- });
69
- }
70
- if (owner !== undefined && !Object.hasOwn(LIST_OWNERS, owner)) {
71
- throw Boom.badRequest('owner must be me or org', {
72
- code: 'VALIDATION_ERROR',
73
- details: { field: 'owner' },
74
- });
75
- }
76
- return { scope, owner };
77
- }
78
-
79
- module.exports = {
80
- objectBody,
81
- requireFields,
82
- parseStep,
83
- optionalString,
84
- parseListFilters,
85
- };
54
+ module.exports = { objectBody, requireFields, parseStep, optionalString };
package/modules/index.js CHANGED
@@ -8,11 +8,6 @@ const {
8
8
  getEntityTypeRegistry,
9
9
  EntityRegistryError,
10
10
  } = require('./entity-type-registry');
11
- const {
12
- resolveScope,
13
- listBindingScopes,
14
- OwnershipConfigError,
15
- } = require('./entity-scope');
16
11
 
17
12
  module.exports = {
18
13
  ApiKeyRequester,
@@ -23,7 +18,4 @@ module.exports = {
23
18
  ModuleFactory,
24
19
  getEntityTypeRegistry,
25
20
  EntityRegistryError,
26
- resolveScope,
27
- listBindingScopes,
28
- OwnershipConfigError,
29
21
  };
@@ -3,7 +3,6 @@ const {
3
3
  toObjectId,
4
4
  fromObjectId,
5
5
  findMany,
6
- findManyDrained,
7
6
  findOne,
8
7
  insertOne,
9
8
  updateOne,
@@ -77,29 +76,6 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
77
76
  return docs.map((doc) => this._mapEntity(doc, credentialMap.get(fromObjectId(doc.credentialId)) || null));
78
77
  }
79
78
 
80
- /**
81
- * Find entities matching any of the owner/organization pairs, in one query.
82
- * `organizationId: null` matches rows with no organization (a raw MongoDB
83
- * `null` also matches a missing field). The caller (a use case) decides
84
- * which pairs; this only runs them.
85
- *
86
- * @param {Array<{userId: string, organizationId: (string|null)}>} clauses
87
- * @returns {Promise<Array>}
88
- */
89
- async findEntitiesByOwnership(clauses) {
90
- if (!Array.isArray(clauses) || clauses.length === 0) return [];
91
- // Drained: a list can hold more than the first cursor batch (~101).
92
- const docs = await findManyDrained(this.prisma, 'Entity', {
93
- $or: clauses.map(({ userId, organizationId }) => ({
94
- userId: toObjectId(userId),
95
- organizationId:
96
- organizationId === null ? null : toObjectId(organizationId),
97
- })),
98
- });
99
- const credentialMap = await this._fetchCredentialsBulk(docs.map((doc) => doc.credentialId));
100
- return docs.map((doc) => this._mapEntity(doc, credentialMap.get(fromObjectId(doc.credentialId)) || null));
101
- }
102
-
103
79
  async unsetCredential(entityId) {
104
80
  const objectId = toObjectId(entityId);
105
81
  if (!objectId) return false;
@@ -139,14 +115,7 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
139
115
  );
140
116
  }
141
117
 
142
- /**
143
- * @param {Object} entityData
144
- * @param {{organizationId?: (string|null)}} [tenancy] - the organization the entity
145
- * belongs to (ADR-056 §3.6). A separate argument, not a field of `entityData`,
146
- * because `entityData` carries provider fields and one named `organizationId`
147
- * must not be taken for ours.
148
- */
149
- async createEntity(entityData, tenancy = {}) {
118
+ async createEntity(entityData) {
150
119
  const {
151
120
  user,
152
121
  userId,
@@ -164,7 +133,6 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
164
133
  name: name ?? null,
165
134
  moduleName: moduleName ?? null,
166
135
  externalId: externalId ?? null,
167
- organizationId: toObjectId(tenancy.organizationId) || null,
168
136
  data: dynamicData,
169
137
  };
170
138
  const insertedId = await insertOne(this.prisma, 'Entity', document);
@@ -279,9 +247,8 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
279
247
  const objectIds = ids.map(id => toObjectId(id)).filter(Boolean);
280
248
  if (objectIds.length === 0) return new Map();
281
249
 
282
- // Raw read to bypass the Prisma encryption extension. Drained:
283
- // more ids than the first cursor batch must all come back.
284
- const rawCredentials = await findManyDrained(this.prisma, 'Credential', {
250
+ // Use raw findMany to bypass Prisma encryption extension
251
+ const rawCredentials = await findMany(this.prisma, 'Credential', {
285
252
  _id: { $in: objectIds }
286
253
  });
287
254
 
@@ -362,30 +329,19 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
362
329
  if (filter.name) query.name = filter.name;
363
330
  if (filter.moduleName) query.moduleName = filter.moduleName;
364
331
  if (filter.externalId) query.externalId = filter.externalId;
365
- // `null` means "no organization"; absent means "any". A raw MongoDB
366
- // `{ field: null }` matches both a null value and a missing field.
367
- if (filter.organizationId !== undefined) {
368
- query.organizationId =
369
- filter.organizationId === null
370
- ? null
371
- : toObjectId(filter.organizationId);
372
- }
373
332
  return query;
374
333
  }
375
334
 
376
335
  _mapEntity(doc, credential) {
377
336
  const dynamicData = doc?.data || {};
378
337
  return {
379
- // First, so no stored provider field can replace a column below
380
- // (identity, owner or organization decide who sees the entity).
381
- ...dynamicData,
382
338
  id: fromObjectId(doc?._id),
383
339
  credential,
384
340
  userId: fromObjectId(doc?.userId),
385
341
  name: doc?.name ?? null,
386
342
  externalId: doc?.externalId ?? null,
387
343
  moduleName: doc?.moduleName ?? null,
388
- organizationId: fromObjectId(doc?.organizationId) ?? null,
344
+ ...dynamicData,
389
345
  };
390
346
  }
391
347
  }
@@ -67,21 +67,6 @@ class ModuleRepositoryInterface {
67
67
  );
68
68
  }
69
69
 
70
- /**
71
- * Find entities matching any of the owner/organization pairs, in one query
72
- * (ADR-056 §3.6). `organizationId: null` matches rows with no organization.
73
- * Which pairs is decided by the caller (modules/entity-scope.js), not here.
74
- *
75
- * @param {Array<{userId: string|number, organizationId: (string|number|null)}>} clauses
76
- * @returns {Promise<Array>} Array of entity objects
77
- * @abstract
78
- */
79
- async findEntitiesByOwnership(clauses) {
80
- throw new Error(
81
- 'Method findEntitiesByOwnership must be implemented by subclass'
82
- );
83
- }
84
-
85
70
  /**
86
71
  * Unset credential from entity
87
72
  *
@@ -125,13 +110,11 @@ class ModuleRepositoryInterface {
125
110
  /**
126
111
  * Create a new entity
127
112
  *
128
- * @param {Object} entityData - Entity data (provider fields included)
129
- * @param {{organizationId?: (string|number|null)}} [tenancy] - the organization
130
- * the entity belongs to (ADR-056 §3.6), kept apart from `entityData`
113
+ * @param {Object} entityData - Entity data
131
114
  * @returns {Promise<Object>} Created entity object
132
115
  * @abstract
133
116
  */
134
- async createEntity(entityData, tenancy) {
117
+ async createEntity(entityData) {
135
118
  throw new Error('Method createEntity must be implemented by subclass');
136
119
  }
137
120
 
@@ -1,5 +1,4 @@
1
1
  const { prisma } = require('../../database/prisma');
2
- const { organizationWhere } = require('../../database/organization-where');
3
2
  const { ModuleRepositoryInterface } = require('./module-repository-interface');
4
3
 
5
4
  /**
@@ -77,26 +76,6 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
77
76
  return credentialMap;
78
77
  }
79
78
 
80
- /**
81
- * The one place a stored entity row becomes the entity the application sees.
82
- * The provider's `data` is spread FIRST and every column is pinned after it:
83
- * a stored `id`, `userId` or `organizationId` in `data` must not decide who
84
- * owns the entity or who sees it.
85
- * @private
86
- */
87
- _mapEntity(row, credential) {
88
- return {
89
- ...(row.data || {}),
90
- id: row.id,
91
- credential,
92
- userId: row.userId,
93
- name: row.name,
94
- externalId: row.externalId,
95
- moduleName: row.moduleName,
96
- organizationId: row.organizationId ?? null,
97
- };
98
- }
99
-
100
79
  /**
101
80
  * Find entity by ID with credential
102
81
  * Replaces: Entity.findById(entityId).populate('credential')
@@ -116,7 +95,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
116
95
 
117
96
  const credential = await this._fetchCredential(entity.credentialId);
118
97
 
119
- return this._mapEntity(entity, credential);
98
+ return {
99
+ id: entity.id,
100
+ credential,
101
+ userId: entity.userId,
102
+ name: entity.name,
103
+ externalId: entity.externalId,
104
+ moduleName: entity.moduleName,
105
+ ...(entity.data || {}),
106
+ };
120
107
  }
121
108
 
122
109
  /**
@@ -134,7 +121,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
134
121
  const credentialIds = entities.map(e => e.credentialId).filter(Boolean);
135
122
  const credentialMap = await this._fetchCredentialsBulk(credentialIds);
136
123
 
137
- return entities.map((e) => (this._mapEntity(e, credentialMap.get(e.credentialId) || null)));
124
+ return entities.map((e) => ({
125
+ id: e.id,
126
+ credential: credentialMap.get(e.credentialId) || null,
127
+ userId: e.userId,
128
+ name: e.name,
129
+ externalId: e.externalId,
130
+ moduleName: e.moduleName,
131
+ ...(e.data || {}),
132
+ }));
138
133
  }
139
134
 
140
135
  /**
@@ -152,7 +147,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
152
147
  const credentialIds = entities.map(e => e.credentialId).filter(Boolean);
153
148
  const credentialMap = await this._fetchCredentialsBulk(credentialIds);
154
149
 
155
- return entities.map((e) => (this._mapEntity(e, credentialMap.get(e.credentialId) || null)));
150
+ return entities.map((e) => ({
151
+ id: e.id,
152
+ credential: credentialMap.get(e.credentialId) || null,
153
+ userId: e.userId,
154
+ name: e.name,
155
+ externalId: e.externalId,
156
+ moduleName: e.moduleName,
157
+ ...(e.data || {}),
158
+ }));
156
159
  }
157
160
 
158
161
  /**
@@ -174,32 +177,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
174
177
  const credentialIds = entities.map(e => e.credentialId).filter(Boolean);
175
178
  const credentialMap = await this._fetchCredentialsBulk(credentialIds);
176
179
 
177
- return entities.map((e) => (this._mapEntity(e, credentialMap.get(e.credentialId) || null)));
178
- }
179
-
180
- /**
181
- * Find entities matching any of the owner/organization pairs, in one query.
182
- * `organizationId: null` matches rows with no organization. The caller
183
- * (a use case) decides which pairs; this only runs them.
184
- *
185
- * @param {Array<{userId: string, organizationId: (string|null)}>} clauses
186
- * @returns {Promise<Array>} Array of entity objects with string IDs
187
- */
188
- async findEntitiesByOwnership(clauses) {
189
- if (!Array.isArray(clauses) || clauses.length === 0) return [];
190
- const entities = await this.prisma.entity.findMany({
191
- where: {
192
- OR: clauses.map(({ userId, organizationId }) => ({
193
- userId,
194
- ...organizationWhere(organizationId),
195
- })),
196
- },
197
- });
198
-
199
- const credentialIds = entities.map(e => e.credentialId).filter(Boolean);
200
- const credentialMap = await this._fetchCredentialsBulk(credentialIds);
201
-
202
- return entities.map((e) => (this._mapEntity(e, credentialMap.get(e.credentialId) || null)));
180
+ return entities.map((e) => ({
181
+ id: e.id,
182
+ credential: credentialMap.get(e.credentialId) || null,
183
+ userId: e.userId,
184
+ name: e.name,
185
+ externalId: e.externalId,
186
+ moduleName: e.moduleName,
187
+ ...(e.data || {}),
188
+ }));
203
189
  }
204
190
 
205
191
  /**
@@ -237,7 +223,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
237
223
 
238
224
  const credential = await this._fetchCredential(entity.credentialId);
239
225
 
240
- return this._mapEntity(entity, credential);
226
+ return {
227
+ id: entity.id,
228
+ credential,
229
+ userId: entity.userId,
230
+ name: entity.name,
231
+ externalId: entity.externalId,
232
+ moduleName: entity.moduleName,
233
+ ...(entity.data || {}),
234
+ };
241
235
  }
242
236
 
243
237
  /**
@@ -257,7 +251,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
257
251
  .filter(Boolean);
258
252
  const credentialMap = await this._fetchCredentialsBulk(credentialIds);
259
253
 
260
- return entities.map((e) => (this._mapEntity(e, credentialMap.get(e.credentialId) || null)));
254
+ return entities.map((e) => ({
255
+ id: e.id,
256
+ credential: credentialMap.get(e.credentialId) || null,
257
+ userId: e.userId,
258
+ name: e.name,
259
+ externalId: e.externalId,
260
+ moduleName: e.moduleName,
261
+ ...(e.data || {}),
262
+ }));
261
263
  }
262
264
 
263
265
  /**
@@ -265,13 +267,9 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
265
267
  * Replaces: Entity.create(entityData)
266
268
  *
267
269
  * @param {Object} entityData - Entity data
268
- * @param {{organizationId?: (string|null)}} [tenancy] - the organization the entity
269
- * belongs to (ADR-056 §3.6). A separate argument, not a field of `entityData`,
270
- * because `entityData` carries provider fields and one named `organizationId`
271
- * must not be taken for ours.
272
270
  * @returns {Promise<Object>} Created entity object with string IDs
273
271
  */
274
- async createEntity(entityData, tenancy = {}) {
272
+ async createEntity(entityData) {
275
273
  const {
276
274
  user,
277
275
  userId,
@@ -289,7 +287,6 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
289
287
  name,
290
288
  moduleName,
291
289
  externalId,
292
- organizationId: tenancy.organizationId ?? null,
293
290
  data: dynamicData,
294
291
  };
295
292
 
@@ -299,7 +296,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
299
296
 
300
297
  const credentialObj = await this._fetchCredential(entity.credentialId);
301
298
 
302
- return this._mapEntity(entity, credentialObj);
299
+ return {
300
+ id: entity.id,
301
+ credential: credentialObj,
302
+ userId: entity.userId,
303
+ name: entity.name,
304
+ externalId: entity.externalId,
305
+ moduleName: entity.moduleName,
306
+ ...(entity.data || {}),
307
+ };
303
308
  }
304
309
 
305
310
  /**
@@ -353,7 +358,15 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
353
358
 
354
359
  const credentialObj = await this._fetchCredential(entity.credentialId);
355
360
 
356
- return this._mapEntity(entity, credentialObj);
361
+ return {
362
+ id: entity.id,
363
+ credential: credentialObj,
364
+ userId: entity.userId,
365
+ name: entity.name,
366
+ externalId: entity.externalId,
367
+ moduleName: entity.moduleName,
368
+ ...(entity.data || {}),
369
+ };
357
370
  } catch (error) {
358
371
  if (error.code === 'P2025') {
359
372
  return null;
@@ -416,11 +429,6 @@ class ModuleRepositoryMongo extends ModuleRepositoryInterface {
416
429
  if (filter.moduleName) where.moduleName = filter.moduleName;
417
430
  if (filter.externalId) where.externalId = this._toString(filter.externalId);
418
431
 
419
- // `null` means "no organization"; absent means "any".
420
- if (filter.organizationId !== undefined) {
421
- Object.assign(where, organizationWhere(filter.organizationId));
422
- }
423
-
424
432
  return where;
425
433
  }
426
434
  }