@friggframework/core 2.0.0--canary.685.a13fdab.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 (106) hide show
  1. package/CLAUDE.md +0 -25
  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 -24
  23. package/index.js +0 -22
  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 +2 -71
  35. package/management-api/openapi/components.js +0 -40
  36. package/management-api/openapi/v2-operations.js +4 -16
  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 +6 -51
  46. package/modules/repositories/module-repository-interface.js +2 -19
  47. package/modules/repositories/module-repository-mongo.js +74 -67
  48. package/modules/repositories/module-repository-postgres.js +74 -66
  49. package/modules/repositories/module-repository.js +1 -2
  50. package/modules/use-cases/entity-operations-for-user.js +13 -50
  51. package/modules/use-cases/entity-types.js +7 -31
  52. package/modules/use-cases/execute-entity-proxy-request.js +3 -50
  53. package/modules/use-cases/get-entities-for-user.js +5 -16
  54. package/modules/use-cases/get-entity-module-for-user.js +5 -32
  55. package/modules/use-cases/get-entity-options-by-id.js +3 -9
  56. package/modules/use-cases/get-module.js +3 -9
  57. package/modules/use-cases/multi-step-authorization.js +12 -39
  58. package/modules/use-cases/process-authorization-callback.js +18 -52
  59. package/modules/use-cases/refresh-entity-options.js +3 -9
  60. package/modules/use-cases/test-module-auth.js +3 -9
  61. package/package.json +5 -6
  62. package/prisma-mongodb/schema.prisma +0 -47
  63. package/prisma-postgresql/schema.prisma +0 -44
  64. package/types/index.d.ts +0 -1
  65. package/types/modules/index.d.ts +0 -129
  66. package/user/repositories/user-repository-documentdb.js +2 -27
  67. package/user/repositories/user-repository-interface.js +0 -18
  68. package/user/repositories/user-repository-mongo.js +0 -24
  69. package/user/repositories/user-repository-postgres.js +0 -18
  70. package/user/use-cases/authenticate-user.js +1 -7
  71. package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
  72. package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
  73. package/user/user.js +1 -64
  74. package/database/organization-where.js +0 -18
  75. package/database/unique-violation.js +0 -25
  76. package/integrations/repositories/integration-not-found.js +0 -14
  77. package/integrations/use-cases/resolve-integration-ownership.js +0 -177
  78. package/modules/entity-scope.js +0 -15
  79. package/modules/repositories/entity-not-found.js +0 -18
  80. package/modules/scope-config.js +0 -192
  81. package/modules/scope-policy.js +0 -112
  82. package/modules/scope-resolution.js +0 -288
  83. package/modules/scope-visibility.js +0 -247
  84. package/modules/tests/doubles/ownership-matching.js +0 -18
  85. package/modules/use-cases/authorize-entity-for-user.js +0 -61
  86. package/modules/use-cases/create-entity-from-credential.js +0 -113
  87. package/modules/use-cases/manage-access.js +0 -21
  88. package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
  89. package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
  90. package/types/user/index.d.ts +0 -134
  91. package/user/adopter-jwt-config.js +0 -177
  92. package/user/adopter-jwt-errors.js +0 -59
  93. package/user/adopter-token-verifier.js +0 -122
  94. package/user/app-user-helpers.js +0 -97
  95. package/user/create-user-authentication.js +0 -64
  96. package/user/membership.js +0 -51
  97. package/user/repositories/organization-membership-record.js +0 -19
  98. package/user/repositories/organization-membership-repository-documentdb.js +0 -106
  99. package/user/repositories/organization-membership-repository-factory.js +0 -42
  100. package/user/repositories/organization-membership-repository-interface.js +0 -57
  101. package/user/repositories/organization-membership-repository-mongo.js +0 -13
  102. package/user/repositories/organization-membership-repository-postgres.js +0 -29
  103. package/user/repositories/organization-membership-repository-prisma.js +0 -81
  104. package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
  105. package/user/use-cases/ensure-organization-membership.js +0 -92
  106. package/user/use-cases/find-individual-users-by-organization.js +0 -54
@@ -29,18 +29,13 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
29
29
  getEntityTypeRegistry,
30
30
  getEntityTypeDefinitions,
31
31
  } = require('../../modules/entity-type-registry');
32
- const { createScopePolicy } = require('../../modules/scope-policy');
33
- const {
34
- AuthorizeEntityForUser,
35
- } = require('../../modules/use-cases/authorize-entity-for-user');
36
- const {
37
- ResolveIntegrationOwnership,
38
- } = require('../../integrations/use-cases/resolve-integration-ownership');
32
+ const { GetUserFromBearerToken } = require('../../user/use-cases/get-user-from-bearer-token');
33
+ const { GetUserFromXFriggHeaders } = require('../../user/use-cases/get-user-from-x-frigg-headers');
34
+ const { GetUserFromAdopterJwt } = require('../../user/use-cases/get-user-from-adopter-jwt');
39
35
  const {
40
36
  AuthenticateWithSharedSecret,
41
37
  } = require('../../user/use-cases/authenticate-with-shared-secret');
42
38
  const { AuthenticateUser } = require('../../user/use-cases/authenticate-user');
43
- const { buildUserAuthentication } = require('../../user/create-user-authentication');
44
39
  const { CreateIntegration } = require('../../integrations/use-cases/create-integration');
45
40
  const { UpdateIntegration } = require('../../integrations/use-cases/update-integration');
46
41
  const {
@@ -92,11 +87,6 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
92
87
  appDefinition.entityTypeRegistry ??
93
88
  getEntityTypeRegistry(appDefinition);
94
89
  const moduleDefinitions = getEntityTypeDefinitions(registry);
95
- // Ownership by scope (ADR-056 §3): one object every use case asks.
96
- const scopePolicy = createScopePolicy({
97
- ownership: appDefinition.ownership,
98
- entityTypeRegistry: registry,
99
- });
100
90
 
101
91
  const moduleRepository = createModuleRepository();
102
92
  const integrationRepository = createIntegrationRepository();
@@ -105,7 +95,9 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
105
95
  const authorizationSessionRepository = createAuthorizationSessionRepository();
106
96
 
107
97
  const authenticateUser = new AuthenticateUser({
108
- ...buildUserAuthentication({ userConfig, userRepository }),
98
+ getUserFromBearerToken: new GetUserFromBearerToken({ userRepository, userConfig }),
99
+ getUserFromXFriggHeaders: new GetUserFromXFriggHeaders({ userRepository, userConfig }),
100
+ getUserFromAdopterJwt: new GetUserFromAdopterJwt({ userRepository, userConfig }),
109
101
  authenticateWithSharedSecret: new AuthenticateWithSharedSecret(),
110
102
  userConfig,
111
103
  });
@@ -119,12 +111,10 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
119
111
  const getEntityModuleForUser = new GetEntityModuleForUser({
120
112
  moduleRepository,
121
113
  moduleDefinitions,
122
- scopePolicy,
123
114
  });
124
115
  const getCredentialForUser = new credentialOps.GetCredentialForUserV2({
125
116
  credentialRepository,
126
117
  moduleRepository,
127
- scopePolicy,
128
118
  });
129
119
  const getAuthorizationRequirements = new GetAuthorizationRequirements({
130
120
  moduleDefinitions,
@@ -138,22 +128,17 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
138
128
  moduleDefinitions,
139
129
  getAuthorizationRequirements,
140
130
  authorizationSessionRepository,
141
- authorizeEntityForUser: new AuthorizeEntityForUser({
142
- scopePolicy,
143
- processAuthorizationCallback: new ProcessAuthorizationCallback({
144
- moduleRepository,
145
- credentialRepository,
146
- integrationRepository,
147
- moduleDefinitions,
148
- }),
131
+ processAuthorizationCallback: new ProcessAuthorizationCallback({
132
+ moduleRepository,
133
+ credentialRepository,
134
+ integrationRepository,
135
+ moduleDefinitions,
149
136
  }),
150
137
  moduleRepository,
151
138
  credentialRepository,
152
- scopePolicy,
153
139
  });
154
140
  const getOwnedIntegrationRecord = new integrationOps.GetOwnedIntegrationRecord({
155
141
  integrationRepository,
156
- scopePolicy,
157
142
  });
158
143
  const getIntegrationInstanceForUser = new integrationOps.GetIntegrationInstanceForUser({
159
144
  getOwnedIntegrationRecord,
@@ -163,7 +148,6 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
163
148
  return {
164
149
  config,
165
150
  moduleDefinitions,
166
- scopePolicy,
167
151
  repositories: {
168
152
  moduleRepository,
169
153
  integrationRepository,
@@ -179,7 +163,6 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
179
163
  integrationClasses,
180
164
  moduleFactory,
181
165
  moduleRepository,
182
- scopePolicy,
183
166
  }),
184
167
  getPossibleIntegrations: new GetPossibleIntegrations({ integrationClasses }),
185
168
  createIntegrationForUser: new integrationOps.CreateIntegrationForUser({
@@ -188,11 +171,7 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
188
171
  integrationClasses,
189
172
  moduleFactory,
190
173
  }),
191
- resolveIntegrationOwnership: new ResolveIntegrationOwnership({
192
- moduleRepository,
193
- integrationClasses,
194
- scopePolicy,
195
- }),
174
+ getEntityModuleForUser,
196
175
  integrationClasses,
197
176
  }),
198
177
  getIntegrationInstanceForUser,
@@ -224,10 +203,7 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
224
203
 
225
204
  // Entities
226
205
  getEntityModuleForUser,
227
- listEntitiesForUser: new entityOps.ListEntitiesForUser({
228
- moduleRepository,
229
- scopePolicy,
230
- }),
206
+ listEntitiesForUser: new entityOps.ListEntitiesForUser({ moduleRepository }),
231
207
  getEntityForUser: new entityOps.GetEntityForUser({ getEntityModuleForUser }),
232
208
  deleteEntityForUser: new entityOps.DeleteEntityForUser({
233
209
  getEntityModuleForUser,
@@ -239,15 +215,14 @@ function buildV2Dependencies({ appDefinition, config, entityTypeRegistry }) {
239
215
  refreshEntityOptionsForUser: new entityOps.RefreshEntityOptionsForUser({
240
216
  getEntityModuleForUser,
241
217
  }),
242
- listEntityTypes: new ListEntityTypes({ entityTypeRegistry: registry, scopePolicy }),
243
- getEntityType: new GetEntityType({ entityTypeRegistry: registry, scopePolicy }),
218
+ listEntityTypes: new ListEntityTypes({ entityTypeRegistry: registry }),
219
+ getEntityType: new GetEntityType({ entityTypeRegistry: registry }),
244
220
  getAuthorizationRequirements,
245
221
 
246
222
  // Credentials
247
223
  listCredentialsForUser: new credentialOps.ListCredentialsForUser({
248
224
  credentialRepository,
249
225
  moduleRepository,
250
- scopePolicy,
251
226
  }),
252
227
  getCredentialForUser,
253
228
  deleteCredentialForUser: new credentialOps.DeleteCredentialForUser({
@@ -13,20 +13,6 @@ const idOf = (value) => {
13
13
  return String(value);
14
14
  };
15
15
 
16
- /**
17
- * `{ scope, owner, organizationId, access }` (ADR-056 §3.4): whose a record is
18
- * and what the caller may do with it. Empty when the use case did not say.
19
- */
20
- function tenancyFields(tenancy) {
21
- if (!tenancy) return {};
22
- return {
23
- scope: tenancy.scope,
24
- owner: tenancy.owner,
25
- organizationId: tenancy.organizationId ?? null,
26
- access: tenancy.access,
27
- };
28
- }
29
-
30
16
  /** An entity (connected account). */
31
17
  function toEntityDto(entity) {
32
18
  const credential =
@@ -44,7 +30,6 @@ function toEntityDto(entity) {
44
30
  typeof credential?.authIsValid === 'boolean'
45
31
  ? credential.authIsValid
46
32
  : null,
47
- ...tenancyFields(entity.tenancy),
48
33
  };
49
34
  }
50
35
 
@@ -57,7 +42,6 @@ function toIntegrationDto(integration) {
57
42
  config: integration.config ?? {},
58
43
  version: integration.version ?? null,
59
44
  messages: integration.messages ?? {},
60
- ...tenancyFields(integration.tenancy),
61
45
  };
62
46
  }
63
47
 
@@ -75,8 +59,6 @@ const CREDENTIAL_METADATA = new Set([
75
59
  'type',
76
60
  'entityIds',
77
61
  'status',
78
- // Added by the credential use cases (ADR-056 §3.4); never provider data.
79
- 'tenancy',
80
62
  ]);
81
63
 
82
64
  /**
@@ -128,13 +110,11 @@ function maskCredential(credential) {
128
110
  entityCount: entityIds.length,
129
111
  createdAt: toIso(credential.createdAt),
130
112
  updatedAt: toIso(credential.updatedAt),
131
- ...tenancyFields(credential.tenancy),
132
113
  data,
133
114
  };
134
115
  }
135
116
 
136
117
  module.exports = {
137
- tenancyFields,
138
118
  toEntityDto,
139
119
  toIntegrationDto,
140
120
  maskCredential,
@@ -63,7 +63,6 @@ function createAuthorizationHandlers(useCases) {
63
63
  data: body.data,
64
64
  step,
65
65
  sessionId,
66
- scope: optionalString(body.scope, 'scope'),
67
66
  });
68
67
  res.json(toAuthorizationResponse(result));
69
68
  },
@@ -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,14 +3,12 @@ const {
3
3
  toObjectId,
4
4
  fromObjectId,
5
5
  findMany,
6
- findManyDrained,
7
6
  findOne,
8
7
  insertOne,
9
8
  updateOne,
10
9
  deleteOne,
11
10
  } = require('../../database/documentdb-utils');
12
11
  const { ModuleRepositoryInterface } = require('./module-repository-interface');
13
- const { entityNotFoundError } = require('./entity-not-found');
14
12
  const { DocumentDBEncryptionService } = require('../../database/documentdb-encryption-service');
15
13
 
16
14
  /**
@@ -35,11 +33,11 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
35
33
  async findEntityById(entityId) {
36
34
  const objectId = toObjectId(entityId);
37
35
  if (!objectId) {
38
- throw entityNotFoundError(entityId);
36
+ throw new Error(`Entity ${entityId} not found`);
39
37
  }
40
38
  const doc = await findOne(this.prisma, 'Entity', { _id: objectId });
41
39
  if (!doc) {
42
- throw entityNotFoundError(entityId);
40
+ throw new Error(`Entity ${entityId} not found`);
43
41
  }
44
42
  const credential = await this._fetchCredential(doc.credentialId);
45
43
  return this._mapEntity(doc, credential);
@@ -78,29 +76,6 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
78
76
  return docs.map((doc) => this._mapEntity(doc, credentialMap.get(fromObjectId(doc.credentialId)) || null));
79
77
  }
80
78
 
81
- /**
82
- * Find entities matching any of the owner/organization pairs, in one query.
83
- * `organizationId: null` matches rows with no organization (a raw MongoDB
84
- * `null` also matches a missing field). The caller (a use case) decides
85
- * which pairs; this only runs them.
86
- *
87
- * @param {Array<{userId: string, organizationId: (string|null)}>} clauses
88
- * @returns {Promise<Array>}
89
- */
90
- async findEntitiesByOwnership(clauses) {
91
- if (!Array.isArray(clauses) || clauses.length === 0) return [];
92
- // Drained: a list can hold more than the first cursor batch (~101).
93
- const docs = await findManyDrained(this.prisma, 'Entity', {
94
- $or: clauses.map(({ userId, organizationId }) => ({
95
- userId: toObjectId(userId),
96
- organizationId:
97
- organizationId === null ? null : toObjectId(organizationId),
98
- })),
99
- });
100
- const credentialMap = await this._fetchCredentialsBulk(docs.map((doc) => doc.credentialId));
101
- return docs.map((doc) => this._mapEntity(doc, credentialMap.get(fromObjectId(doc.credentialId)) || null));
102
- }
103
-
104
79
  async unsetCredential(entityId) {
105
80
  const objectId = toObjectId(entityId);
106
81
  if (!objectId) return false;
@@ -140,14 +115,7 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
140
115
  );
141
116
  }
142
117
 
143
- /**
144
- * @param {Object} entityData
145
- * @param {{organizationId?: (string|null)}} [tenancy] - the organization the entity
146
- * belongs to (ADR-056 §3.6). A separate argument, not a field of `entityData`,
147
- * because `entityData` carries provider fields and one named `organizationId`
148
- * must not be taken for ours.
149
- */
150
- async createEntity(entityData, tenancy = {}) {
118
+ async createEntity(entityData) {
151
119
  const {
152
120
  user,
153
121
  userId,
@@ -165,7 +133,6 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
165
133
  name: name ?? null,
166
134
  moduleName: moduleName ?? null,
167
135
  externalId: externalId ?? null,
168
- organizationId: toObjectId(tenancy.organizationId) || null,
169
136
  data: dynamicData,
170
137
  };
171
138
  const insertedId = await insertOne(this.prisma, 'Entity', document);
@@ -280,9 +247,8 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
280
247
  const objectIds = ids.map(id => toObjectId(id)).filter(Boolean);
281
248
  if (objectIds.length === 0) return new Map();
282
249
 
283
- // Raw read to bypass the Prisma encryption extension. Drained:
284
- // more ids than the first cursor batch must all come back.
285
- const rawCredentials = await findManyDrained(this.prisma, 'Credential', {
250
+ // Use raw findMany to bypass Prisma encryption extension
251
+ const rawCredentials = await findMany(this.prisma, 'Credential', {
286
252
  _id: { $in: objectIds }
287
253
  });
288
254
 
@@ -363,30 +329,19 @@ class ModuleRepositoryDocumentDB extends ModuleRepositoryInterface {
363
329
  if (filter.name) query.name = filter.name;
364
330
  if (filter.moduleName) query.moduleName = filter.moduleName;
365
331
  if (filter.externalId) query.externalId = filter.externalId;
366
- // `null` means "no organization"; absent means "any". A raw MongoDB
367
- // `{ field: null }` matches both a null value and a missing field.
368
- if (filter.organizationId !== undefined) {
369
- query.organizationId =
370
- filter.organizationId === null
371
- ? null
372
- : toObjectId(filter.organizationId);
373
- }
374
332
  return query;
375
333
  }
376
334
 
377
335
  _mapEntity(doc, credential) {
378
336
  const dynamicData = doc?.data || {};
379
337
  return {
380
- // First, so no stored provider field can replace a column below
381
- // (identity, owner or organization decide who sees the entity).
382
- ...dynamicData,
383
338
  id: fromObjectId(doc?._id),
384
339
  credential,
385
340
  userId: fromObjectId(doc?.userId),
386
341
  name: doc?.name ?? null,
387
342
  externalId: doc?.externalId ?? null,
388
343
  moduleName: doc?.moduleName ?? null,
389
- organizationId: fromObjectId(doc?.organizationId) ?? null,
344
+ ...dynamicData,
390
345
  };
391
346
  }
392
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