@friggframework/core 2.0.0--canary.680.6bacd26.0 → 2.0.0--canary.663.8de669c.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 (86) hide show
  1. package/CHANGELOG.md +0 -11
  2. package/application/commands/integration-commands.js +8 -18
  3. package/application/index.js +2 -6
  4. package/credential/repositories/credential-repository-documentdb.js +0 -34
  5. package/credential/repositories/credential-repository-interface.js +0 -15
  6. package/credential/repositories/credential-repository-mongo.js +0 -23
  7. package/credential/repositories/credential-repository-postgres.js +0 -28
  8. package/database/encryption/README.md +0 -2
  9. package/database/encryption/encryption-schema-registry.js +12 -41
  10. package/database/encryption/field-encryption-service.js +5 -69
  11. package/generated/prisma-mongodb/edge.js +4 -20
  12. package/generated/prisma-mongodb/index-browser.js +1 -17
  13. package/generated/prisma-mongodb/index.d.ts +95 -1543
  14. package/generated/prisma-mongodb/index.js +4 -20
  15. package/generated/prisma-mongodb/package.json +1 -1
  16. package/generated/prisma-mongodb/schema.prisma +0 -27
  17. package/generated/prisma-mongodb/wasm.js +4 -20
  18. package/generated/prisma-postgresql/edge.js +4 -20
  19. package/generated/prisma-postgresql/index-browser.js +1 -17
  20. package/generated/prisma-postgresql/index.d.ts +84 -1565
  21. package/generated/prisma-postgresql/index.js +4 -20
  22. package/generated/prisma-postgresql/package.json +1 -1
  23. package/generated/prisma-postgresql/schema.prisma +0 -26
  24. package/generated/prisma-postgresql/wasm.js +4 -20
  25. package/handlers/app-definition-loader.js +8 -19
  26. package/handlers/app-handler-helpers.js +3 -25
  27. package/handlers/backend-utils.js +25 -31
  28. package/handlers/middleware/admin-auth.js +1 -14
  29. package/handlers/routers/auth.js +3 -11
  30. package/handlers/routers/health.js +4 -11
  31. package/handlers/workers/integration-defined-workers.js +2 -5
  32. package/index.js +2 -4
  33. package/integrations/index.js +4 -0
  34. package/integrations/integration-router.js +23 -16
  35. package/integrations/utils/map-integration-dto.js +15 -1
  36. package/modules/index.js +0 -6
  37. package/modules/requester/requester.js +2 -27
  38. package/package.json +5 -5
  39. package/prisma-mongodb/schema.prisma +0 -27
  40. package/prisma-postgresql/schema.prisma +0 -26
  41. package/types/index.d.ts +0 -1
  42. package/credential/use-cases/credential-operations-for-user.js +0 -117
  43. package/credential/use-cases/reauthorize-credential-for-user.js +0 -66
  44. package/database/encryption/test-support/fake-ciphertext.js +0 -15
  45. package/integrations/use-cases/integration-operations-for-user.js +0 -225
  46. package/management-api/create-management-api-router.js +0 -49
  47. package/management-api/error-response.js +0 -116
  48. package/management-api/management-api-config.js +0 -82
  49. package/management-api/meta-router.js +0 -57
  50. package/management-api/openapi/build-openapi.js +0 -144
  51. package/management-api/openapi/components.js +0 -368
  52. package/management-api/openapi/v1-operations.js +0 -83
  53. package/management-api/openapi/v2-operations.js +0 -252
  54. package/management-api/route-registry.js +0 -294
  55. package/management-api/test-support/http-client.js +0 -39
  56. package/management-api/use-cases/get-management-api-meta.js +0 -57
  57. package/management-api/v1-deprecation.js +0 -120
  58. package/management-api/v2/create-v2-router.js +0 -85
  59. package/management-api/v2/dependencies.js +0 -256
  60. package/management-api/v2/dto.js +0 -123
  61. package/management-api/v2/handlers/authorization.js +0 -93
  62. package/management-api/v2/handlers/credentials.js +0 -29
  63. package/management-api/v2/handlers/entities.js +0 -74
  64. package/management-api/v2/handlers/integrations.js +0 -125
  65. package/management-api/v2/handlers/proxy.js +0 -34
  66. package/management-api/v2/request.js +0 -54
  67. package/management-api/v2/test-support/fake-dependencies.js +0 -103
  68. package/modules/domain/authorization-session.js +0 -144
  69. package/modules/entity-type-registry.js +0 -311
  70. package/modules/proxy/proxy-errors.js +0 -20
  71. package/modules/proxy/proxy-path.js +0 -179
  72. package/modules/proxy/proxy-policy.js +0 -248
  73. package/modules/repositories/authorization-session-repository-documentdb.js +0 -112
  74. package/modules/repositories/authorization-session-repository-factory.js +0 -31
  75. package/modules/repositories/authorization-session-repository-interface.js +0 -47
  76. package/modules/repositories/authorization-session-repository-prisma.js +0 -87
  77. package/modules/requester/proxy-request.js +0 -244
  78. package/modules/tests/doubles/in-memory-authorization-session-repository.js +0 -45
  79. package/modules/use-cases/entity-operations-for-user.js +0 -125
  80. package/modules/use-cases/entity-types.js +0 -115
  81. package/modules/use-cases/execute-entity-proxy-request.js +0 -239
  82. package/modules/use-cases/get-authorization-requirements.js +0 -100
  83. package/modules/use-cases/get-entity-module-for-user.js +0 -86
  84. package/modules/use-cases/multi-step-authorization.js +0 -302
  85. package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +0 -28
  86. package/types/modules/index.d.ts +0 -58
@@ -1,368 +0,0 @@
1
- /**
2
- * OpenAPI components for the Management API documents. The shapes match what
3
- * the v2 handlers return (management-api/v2/dto.js) and are reconciled with
4
- * packages/schemas/schemas/api-*.schema.json (a test checks the two agree).
5
- */
6
-
7
- const ref = (name) => ({ $ref: `#/components/schemas/${name}` });
8
-
9
- const nullable = (schema) => ({ ...schema, nullable: true });
10
-
11
- const errorBody = {
12
- type: 'object',
13
- required: ['error'],
14
- properties: {
15
- error: {
16
- type: 'object',
17
- required: ['code', 'message'],
18
- properties: {
19
- code: {
20
- type: 'string',
21
- description:
22
- 'Machine-readable code, e.g. VALIDATION_ERROR, NOT_FOUND, ENTITY_NOT_FOUND, AUTHORIZATION_SESSION_NOT_FOUND, PROXY_NOT_ALLOWED. New codes may be added.',
23
- },
24
- message: { type: 'string' },
25
- details: { description: 'Optional structured details' },
26
- },
27
- },
28
- },
29
- };
30
-
31
- const authorizationRequirements = {
32
- type: 'object',
33
- required: ['type', 'data', 'step', 'totalSteps', 'isMultiStep'],
34
- properties: {
35
- type: {
36
- type: 'string',
37
- description: 'oauth2, api-key, basic, form, or a module-specific step type (e.g. email, otp)',
38
- },
39
- data: {
40
- type: 'object',
41
- description:
42
- 'Step data: { url } for OAuth2, { jsonSchema, uiSchema } for forms',
43
- additionalProperties: true,
44
- },
45
- step: { type: 'integer', minimum: 1 },
46
- totalSteps: { type: 'integer', minimum: 1 },
47
- isMultiStep: { type: 'boolean' },
48
- sessionId: {
49
- type: 'string',
50
- description: 'Present for multi-step flows; send it with every later step',
51
- },
52
- },
53
- };
54
-
55
- const SCHEMAS = {
56
- Error: errorBody,
57
-
58
- Integration: {
59
- type: 'object',
60
- required: ['id', 'entities', 'status', 'config'],
61
- properties: {
62
- id: { type: 'string' },
63
- entities: {
64
- type: 'array',
65
- items: {},
66
- description: 'Entity ids (or entity summaries) the integration connects',
67
- },
68
- status: nullable({ type: 'string', description: 'e.g. ENABLED, DISABLED, ERROR, NEEDS_CONFIG' }),
69
- config: { type: 'object', additionalProperties: true },
70
- version: nullable({ type: 'string' }),
71
- messages: { type: 'object', additionalProperties: true },
72
- },
73
- },
74
- ListIntegrationsResponse: {
75
- type: 'object',
76
- required: ['integrations'],
77
- properties: { integrations: { type: 'array', items: ref('Integration') } },
78
- },
79
- ListIntegrationOptionsResponse: {
80
- type: 'object',
81
- required: ['integrations'],
82
- properties: {
83
- integrations: {
84
- type: 'array',
85
- items: { type: 'object', additionalProperties: true },
86
- description: 'Integration types this app offers (each integration Definition option details)',
87
- },
88
- },
89
- },
90
- CreateIntegrationRequest: {
91
- type: 'object',
92
- required: ['entities', 'config'],
93
- properties: {
94
- entities: {
95
- type: 'array',
96
- items: { type: 'string' },
97
- description: 'Ids of entities the caller owns',
98
- },
99
- config: {
100
- type: 'object',
101
- required: ['type'],
102
- properties: { type: { type: 'string', description: 'Integration name' } },
103
- additionalProperties: true,
104
- },
105
- },
106
- },
107
- UpdateIntegrationRequest: {
108
- type: 'object',
109
- required: ['config'],
110
- properties: { config: { type: 'object', additionalProperties: true } },
111
- },
112
- AuthTestResult: {
113
- type: 'object',
114
- required: ['status'],
115
- properties: {
116
- status: { type: 'string', enum: ['ok', 'failed'] },
117
- errors: { type: 'array', items: { type: 'object', additionalProperties: true } },
118
- },
119
- },
120
-
121
- Entity: {
122
- type: 'object',
123
- required: ['id', 'type', 'userId'],
124
- properties: {
125
- id: { type: 'string' },
126
- type: nullable({ type: 'string', description: 'Module name' }),
127
- name: nullable({ type: 'string' }),
128
- externalId: nullable({ type: 'string' }),
129
- credentialId: nullable({ type: 'string' }),
130
- userId: nullable({ type: 'string' }),
131
- authIsValid: nullable({ type: 'boolean' }),
132
- },
133
- },
134
- ListEntitiesResponse: {
135
- type: 'object',
136
- required: ['entities'],
137
- properties: { entities: { type: 'array', items: ref('Entity') } },
138
- },
139
- EntityType: {
140
- type: 'object',
141
- required: ['type', 'name', 'authType', 'isMultiStep', 'stepCount', 'usedBy'],
142
- properties: {
143
- type: { type: 'string' },
144
- name: { type: 'string' },
145
- description: { type: 'string' },
146
- usedBy: {
147
- type: 'array',
148
- items: { type: 'string' },
149
- description:
150
- 'Names of the integrations that bind this entity type. Empty for a type registered only in appDefinition.entities.',
151
- },
152
- authType: { type: 'string', description: 'oauth2, oauth1, api-key, basic or custom' },
153
- isMultiStep: { type: 'boolean' },
154
- stepCount: { type: 'integer', minimum: 1 },
155
- capabilities: {},
156
- },
157
- },
158
- ListEntityTypesResponse: {
159
- type: 'object',
160
- required: ['types'],
161
- properties: { types: { type: 'array', items: ref('EntityType') } },
162
- },
163
-
164
- Credential: {
165
- type: 'object',
166
- required: ['id', 'type', 'userId', 'authIsValid'],
167
- description: 'Every provider field in data is masked; values never leave the server.',
168
- properties: {
169
- id: { type: 'string' },
170
- type: nullable({ type: 'string', description: 'Module name, from the entities using it' }),
171
- externalId: nullable({ type: 'string' }),
172
- userId: nullable({ type: 'string' }),
173
- authIsValid: nullable({ type: 'boolean' }),
174
- entityIds: { type: 'array', items: { type: 'string' } },
175
- entityCount: { type: 'integer', minimum: 0 },
176
- createdAt: nullable({ type: 'string', format: 'date-time' }),
177
- updatedAt: nullable({ type: 'string', format: 'date-time' }),
178
- data: {
179
- type: 'object',
180
- additionalProperties: true,
181
- description: 'Masked provider fields, e.g. { "access_token": "****WXYZ" }',
182
- },
183
- },
184
- },
185
- ListCredentialsResponse: {
186
- type: 'object',
187
- required: ['credentials'],
188
- properties: { credentials: { type: 'array', items: ref('Credential') } },
189
- },
190
-
191
- AuthorizationRequirements: authorizationRequirements,
192
- AuthorizeRequest: {
193
- type: 'object',
194
- required: ['entityType', 'data'],
195
- properties: {
196
- entityType: { type: 'string', description: 'Module name' },
197
- data: { type: 'object', additionalProperties: true, description: 'OAuth callback params or step form data' },
198
- step: { type: 'integer', minimum: 1, default: 1 },
199
- sessionId: { type: 'string', description: 'Required for step 2 and later' },
200
- },
201
- },
202
- ReauthorizeRequest: {
203
- type: 'object',
204
- required: ['data'],
205
- properties: {
206
- data: { type: 'object', additionalProperties: true },
207
- step: { type: 'integer', minimum: 1, default: 1 },
208
- sessionId: { type: 'string' },
209
- },
210
- },
211
- AuthorizeComplete: {
212
- type: 'object',
213
- required: ['status', 'entity', 'credential'],
214
- properties: {
215
- status: { type: 'string', enum: ['complete'] },
216
- entity: ref('Entity'),
217
- credential: ref('Credential'),
218
- previousCredentialId: {
219
- type: 'string',
220
- description: 'Re-authorization only: the credential being renewed, when the provider account changed and a new credential was stored',
221
- },
222
- },
223
- },
224
- AuthorizePending: {
225
- type: 'object',
226
- required: ['status', 'step', 'totalSteps', 'sessionId', 'requirements'],
227
- properties: {
228
- status: { type: 'string', enum: ['pending'] },
229
- step: { type: 'integer', minimum: 2 },
230
- totalSteps: { type: 'integer', minimum: 2 },
231
- sessionId: { type: 'string' },
232
- requirements: ref('AuthorizationRequirements'),
233
- message: { type: 'string', description: 'e.g. "Code sent to your email"' },
234
- },
235
- },
236
- AuthorizeResponse: {
237
- oneOf: [ref('AuthorizeComplete'), ref('AuthorizePending')],
238
- discriminator: { propertyName: 'status' },
239
- },
240
-
241
- ProxyRequest: {
242
- type: 'object',
243
- required: ['method', 'path'],
244
- properties: {
245
- method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },
246
- path: {
247
- type: 'string',
248
- pattern: '^/',
249
- description:
250
- "Path relative to the module's base URL. No //, backslashes, ? or #, dot segments, encoded separators or double encoding. The host always comes from the module.",
251
- },
252
- query: {
253
- type: 'object',
254
- additionalProperties: {
255
- oneOf: [
256
- { type: 'string' },
257
- { type: 'number' },
258
- { type: 'boolean' },
259
- { type: 'array', items: { type: 'string' } },
260
- ],
261
- },
262
- description: 'Array values are sent comma-separated',
263
- },
264
- headers: {
265
- type: 'object',
266
- additionalProperties: { type: 'string' },
267
- description:
268
- 'Only accept, content-type, accept-language, if-match, if-none-match and module-listed headers are forwarded. Credential, Host and forwarding headers are refused.',
269
- },
270
- body: { description: 'JSON value or string; POST, PUT, PATCH and DELETE only' },
271
- },
272
- },
273
- ProxyResponse: {
274
- type: 'object',
275
- required: ['success', 'status', 'headers', 'data'],
276
- properties: {
277
- success: { type: 'boolean', description: 'False for relayed upstream 4xx' },
278
- status: { type: 'integer', description: 'Upstream status; also the HTTP status of this response' },
279
- headers: { type: 'object', additionalProperties: { type: 'string' } },
280
- data: { description: 'Parsed JSON, text, or base64 when dataEncoding is set' },
281
- dataEncoding: { type: 'string', enum: ['base64'] },
282
- },
283
- },
284
- ProxyError: {
285
- type: 'object',
286
- required: ['success', 'status', 'error'],
287
- properties: {
288
- success: { type: 'boolean', enum: [false] },
289
- status: { type: 'integer' },
290
- error: errorBody.properties.error,
291
- },
292
- },
293
-
294
- ApiMeta: {
295
- type: 'object',
296
- required: ['api', 'capabilities'],
297
- properties: {
298
- api: {
299
- type: 'object',
300
- required: ['versions', 'preferred'],
301
- properties: {
302
- versions: {
303
- type: 'object',
304
- additionalProperties: {
305
- type: 'object',
306
- required: ['status', 'openapi'],
307
- properties: {
308
- status: { type: 'string', enum: ['stable', 'beta', 'deprecated', 'disabled'] },
309
- deprecatedAt: { type: 'string', format: 'date' },
310
- sunset: nullable({ type: 'string', format: 'date' }),
311
- openapi: { type: 'string' },
312
- },
313
- },
314
- },
315
- preferred: { type: 'string' },
316
- },
317
- },
318
- capabilities: {
319
- type: 'array',
320
- items: { type: 'string' },
321
- description: 'Stable feature flags, e.g. credentials, multiStepAuthorize, entityProxy',
322
- },
323
- frigg: {
324
- type: 'object',
325
- description: 'Only for callers with x-frigg-admin-api-key',
326
- properties: { coreVersion: { type: 'string' } },
327
- },
328
- },
329
- },
330
- };
331
-
332
- const errorResponse = (description) => ({
333
- description,
334
- content: { 'application/json': { schema: ref('Error') } },
335
- });
336
-
337
- const RESPONSES = {
338
- BadRequest: errorResponse('Invalid request (VALIDATION_ERROR, INVALID_JSON, INVALID_STEP, ...)'),
339
- Unauthorized: errorResponse('Missing or invalid authentication'),
340
- Forbidden: errorResponse('Not allowed'),
341
- NotFound: errorResponse('Not found, or not owned by the caller'),
342
- Conflict: errorResponse('Conflicts with the current state'),
343
- Gone: errorResponse('This API version is disabled for the app'),
344
- BadGateway: errorResponse('The provider failed'),
345
- };
346
-
347
- const SECURITY_SCHEMES = {
348
- bearerAuth: {
349
- type: 'http',
350
- scheme: 'bearer',
351
- description: 'Frigg user token (POST /user/login) or, when enabled, an adopter JWT',
352
- },
353
- friggApiKey: {
354
- type: 'apiKey',
355
- in: 'header',
356
- name: 'x-frigg-api-key',
357
- description:
358
- 'Backend-to-backend shared secret. Send x-frigg-appuserid (and x-frigg-apporgid for organisation users) to act for a user.',
359
- },
360
- adminApiKey: {
361
- type: 'apiKey',
362
- in: 'header',
363
- name: 'x-frigg-admin-api-key',
364
- description: 'Admin key; on /api/meta it only adds the core version',
365
- },
366
- };
367
-
368
- module.exports = { SCHEMAS, RESPONSES, SECURITY_SCHEMES, ref };
@@ -1,83 +0,0 @@
1
- /**
2
- * Documentation for the frozen Management API v1 routes, keyed by
3
- * "METHOD path" as in the route registry. Each names its v2 replacement
4
- * (docs/reference/api-reference.md has the full migration table).
5
- */
6
-
7
- const any = { description: 'Response body as returned by v1' };
8
- const v1 = (operationId, summary, replacement, extra = {}) => ({
9
- operationId,
10
- summary,
11
- description: replacement ? `Deprecated. Use ${replacement}.` : 'Deprecated.',
12
- responses: { 200: any },
13
- ...extra,
14
- });
15
-
16
- const V1_OPERATIONS = {
17
- 'GET /api/integrations': v1(
18
- 'v1ListIntegrations',
19
- 'List integrations, integration options and authorized entities in one response',
20
- 'GET /api/v2/integrations, GET /api/v2/integrations/options and GET /api/v2/entities'
21
- ),
22
- 'POST /api/integrations': v1('v1CreateIntegration', 'Create an integration', 'POST /api/v2/integrations', {
23
- responses: { 201: any },
24
- }),
25
- 'PATCH /api/integrations/:integrationId': v1('v1UpdateIntegration', 'Update an integration', 'PATCH /api/v2/integrations/{integrationId}'),
26
- 'DELETE /api/integrations/:integrationId': v1('v1DeleteIntegration', 'Delete an integration', 'DELETE /api/v2/integrations/{integrationId}', {
27
- responses: { 204: any },
28
- }),
29
- 'GET /api/integrations/:integrationId/config/options': v1(
30
- 'v1GetIntegrationConfigOptions',
31
- 'Get config options',
32
- 'GET /api/v2/integrations/{integrationId}/config/options'
33
- ),
34
- 'POST /api/integrations/:integrationId/config/options/refresh': v1(
35
- 'v1RefreshIntegrationConfigOptions',
36
- 'Refresh config options',
37
- 'POST /api/v2/integrations/{integrationId}/config/options/refresh'
38
- ),
39
- 'ANY /api/integrations/:integrationId/actions': v1(
40
- 'v1ListIntegrationActions',
41
- 'List user actions (any method)',
42
- 'GET /api/v2/integrations/{integrationId}/actions'
43
- ),
44
- 'ANY /api/integrations/:integrationId/actions/:actionId/options': v1(
45
- 'v1GetIntegrationActionOptions',
46
- 'Get user action options (any method)',
47
- 'POST /api/v2/integrations/{integrationId}/actions/{actionId}/options'
48
- ),
49
- 'POST /api/integrations/:integrationId/actions/:actionId/options/refresh': v1(
50
- 'v1RefreshIntegrationActionOptions',
51
- 'Refresh user action options',
52
- 'POST /api/v2/integrations/{integrationId}/actions/{actionId}/options/refresh'
53
- ),
54
- 'POST /api/integrations/:integrationId/actions/:actionId': v1(
55
- 'v1RunIntegrationAction',
56
- 'Run an integration event',
57
- 'POST /api/v2/integrations/{integrationId}/actions/{actionId} (user actions only)'
58
- ),
59
- 'GET /api/integrations/:integrationId': v1('v1GetIntegration', 'Get an integration', 'GET /api/v2/integrations/{integrationId}'),
60
- 'GET /api/integrations/:integrationId/test-auth': v1(
61
- 'v1TestIntegrationAuth',
62
- 'Test integration auth',
63
- 'GET /api/v2/integrations/{integrationId}/test-auth'
64
- ),
65
- 'GET /api/authorize': v1('v1GetAuthorizeRequirements', 'Get authorization requirements', 'GET /api/v2/authorize'),
66
- 'POST /api/authorize': v1('v1Authorize', 'Authorize an entity', 'POST /api/v2/authorize'),
67
- 'POST /api/entity': v1('v1CreateEntity', 'Create an entity from a credential', 'POST /api/v2/authorize (authorization creates the entity)'),
68
- 'GET /api/entity/options/:credentialId': v1(
69
- 'v1GetEntityOptionsByCredential',
70
- 'Get entity options for a credential',
71
- 'GET /api/v2/entities/{entityId}/options'
72
- ),
73
- 'GET /api/entities/:entityId/test-auth': v1('v1TestEntityAuth', 'Test entity auth', 'GET /api/v2/entities/{entityId}/test-auth'),
74
- 'GET /api/entities/:entityId': v1('v1GetEntity', 'Get an entity', 'GET /api/v2/entities/{entityId}'),
75
- 'POST /api/entities/:entityId/options': v1('v1GetEntityOptions', 'Get entity options', 'GET /api/v2/entities/{entityId}/options'),
76
- 'POST /api/entities/:entityId/options/refresh': v1(
77
- 'v1RefreshEntityOptions',
78
- 'Refresh entity options',
79
- 'POST /api/v2/entities/{entityId}/options/refresh'
80
- ),
81
- };
82
-
83
- module.exports = { V1_OPERATIONS };