@friggframework/core 2.0.0--canary.686.3e27a92.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 (184) hide show
  1. package/CLAUDE.md +0 -28
  2. package/README.md +0 -105
  3. package/application/commands/integration-commands.js +10 -20
  4. package/application/commands/scheduler-commands.js +7 -11
  5. package/application/commands/user-commands.js +5 -17
  6. package/application/index.js +2 -6
  7. package/core/Worker.js +7 -31
  8. package/core/create-handler.js +0 -9
  9. package/credential/repositories/credential-repository-documentdb.js +0 -34
  10. package/credential/repositories/credential-repository-interface.js +0 -15
  11. package/credential/repositories/credential-repository-mongo.js +0 -23
  12. package/credential/repositories/credential-repository-postgres.js +0 -28
  13. package/database/config.js +24 -48
  14. package/database/documentdb-utils.js +1 -6
  15. package/database/encryption/encryption-config.js +31 -10
  16. package/database/encryption/encryption-schema-registry.js +12 -93
  17. package/database/prisma.js +2 -4
  18. package/generated/prisma-mongodb/edge.js +4 -43
  19. package/generated/prisma-mongodb/index-browser.js +1 -40
  20. package/generated/prisma-mongodb/index.d.ts +111 -4739
  21. package/generated/prisma-mongodb/index.js +4 -43
  22. package/generated/prisma-mongodb/package.json +1 -1
  23. package/generated/prisma-mongodb/schema.prisma +0 -92
  24. package/generated/prisma-mongodb/wasm.js +4 -43
  25. package/generated/prisma-postgresql/edge.js +4 -43
  26. package/generated/prisma-postgresql/index-browser.js +1 -40
  27. package/generated/prisma-postgresql/index.d.ts +33 -4966
  28. package/generated/prisma-postgresql/index.js +4 -43
  29. package/generated/prisma-postgresql/package.json +1 -1
  30. package/generated/prisma-postgresql/schema.prisma +0 -87
  31. package/generated/prisma-postgresql/wasm.js +4 -43
  32. package/handlers/app-definition-loader.js +19 -121
  33. package/handlers/app-handler-helpers.js +3 -25
  34. package/handlers/backend-utils.js +25 -31
  35. package/handlers/middleware/admin-auth.js +1 -14
  36. package/handlers/routers/auth.js +10 -46
  37. package/handlers/routers/health.js +4 -13
  38. package/handlers/routers/integration-defined-routers.js +92 -144
  39. package/handlers/routers/integration-webhook-routers.js +64 -102
  40. package/handlers/workers/integration-defined-workers.js +2 -5
  41. package/index.js +1 -65
  42. package/infrastructure/scheduler/index.js +6 -19
  43. package/infrastructure/scheduler/scheduler-service-factory.js +7 -55
  44. package/integrations/index.js +0 -1
  45. package/integrations/integration-router.js +96 -131
  46. package/integrations/repositories/integration-repository-documentdb.js +3 -35
  47. package/integrations/repositories/integration-repository-interface.js +1 -17
  48. package/integrations/repositories/integration-repository-mongo.js +76 -59
  49. package/integrations/repositories/integration-repository-postgres.js +76 -62
  50. package/integrations/tests/doubles/test-integration-repository.js +1 -12
  51. package/integrations/use-cases/create-integration.js +20 -55
  52. package/integrations/use-cases/get-integrations-for-user.js +40 -80
  53. package/integrations/use-cases/index.js +1 -7
  54. package/integrations/utils/map-integration-dto.js +14 -43
  55. package/modules/index.js +0 -14
  56. package/modules/module-factory.js +0 -12
  57. package/modules/module.js +2 -53
  58. package/modules/repositories/module-repository-documentdb.js +6 -51
  59. package/modules/repositories/module-repository-interface.js +2 -19
  60. package/modules/repositories/module-repository-mongo.js +74 -67
  61. package/modules/repositories/module-repository-postgres.js +74 -66
  62. package/modules/repositories/module-repository.js +1 -2
  63. package/modules/requester/requester.js +2 -27
  64. package/modules/use-cases/get-entities-for-user.js +13 -26
  65. package/modules/use-cases/get-entity-options-by-id.js +4 -10
  66. package/modules/use-cases/get-entity-options-by-type.js +1 -1
  67. package/modules/use-cases/get-module-instance-from-type.js +1 -1
  68. package/modules/use-cases/get-module.js +4 -10
  69. package/modules/use-cases/process-authorization-callback.js +19 -53
  70. package/modules/use-cases/refresh-entity-options.js +4 -10
  71. package/modules/use-cases/test-module-auth.js +4 -10
  72. package/package.json +5 -6
  73. package/prisma-mongodb/schema.prisma +0 -92
  74. package/prisma-postgresql/schema.prisma +0 -87
  75. package/queues/index.js +0 -25
  76. package/types/index.d.ts +0 -2
  77. package/user/repositories/user-repository-documentdb.js +2 -27
  78. package/user/repositories/user-repository-interface.js +0 -18
  79. package/user/repositories/user-repository-mongo.js +0 -24
  80. package/user/repositories/user-repository-postgres.js +0 -18
  81. package/user/use-cases/authenticate-user.js +1 -7
  82. package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
  83. package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
  84. package/user/user.js +1 -64
  85. package/credential/use-cases/credential-operations-for-user.js +0 -202
  86. package/credential/use-cases/reauthorize-credential-for-user.js +0 -73
  87. package/database/organization-where.js +0 -18
  88. package/database/unique-violation.js +0 -25
  89. package/extensions/bootstrap-runner.js +0 -43
  90. package/extensions/extension-loader.js +0 -187
  91. package/extensions/index.js +0 -41
  92. package/extensions/initialize-app.js +0 -123
  93. package/extensions/route-mounter.js +0 -103
  94. package/extensions/schema-composer.js +0 -188
  95. package/infrastructure/scheduler/netlify-scheduler-adapter.js +0 -216
  96. package/infrastructure/scheduler/scheduled-job-repository.js +0 -118
  97. package/integrations/repositories/integration-not-found.js +0 -14
  98. package/integrations/schedule-config.js +0 -80
  99. package/integrations/use-cases/dispatch-ongoing-syncs.js +0 -100
  100. package/integrations/use-cases/integration-operations-for-user.js +0 -256
  101. package/integrations/use-cases/resolve-integration-ownership.js +0 -177
  102. package/management-api/create-management-api-router.js +0 -49
  103. package/management-api/error-response.js +0 -116
  104. package/management-api/management-api-config.js +0 -151
  105. package/management-api/meta-router.js +0 -76
  106. package/management-api/openapi/build-openapi.js +0 -144
  107. package/management-api/openapi/components.js +0 -408
  108. package/management-api/openapi/v1-operations.js +0 -83
  109. package/management-api/openapi/v2-operations.js +0 -264
  110. package/management-api/route-registry.js +0 -411
  111. package/management-api/test-support/http-client.js +0 -39
  112. package/management-api/use-cases/get-management-api-meta.js +0 -57
  113. package/management-api/v1-deprecation.js +0 -120
  114. package/management-api/v2/create-v2-router.js +0 -85
  115. package/management-api/v2/dependencies.js +0 -281
  116. package/management-api/v2/dto.js +0 -143
  117. package/management-api/v2/handlers/authorization.js +0 -94
  118. package/management-api/v2/handlers/credentials.js +0 -33
  119. package/management-api/v2/handlers/entities.js +0 -77
  120. package/management-api/v2/handlers/integrations.js +0 -128
  121. package/management-api/v2/handlers/proxy.js +0 -34
  122. package/management-api/v2/request.js +0 -85
  123. package/management-api/v2/test-support/fake-dependencies.js +0 -103
  124. package/modules/domain/authorization-session.js +0 -144
  125. package/modules/entity-scope.js +0 -15
  126. package/modules/entity-type-registry.js +0 -311
  127. package/modules/proxy/proxy-errors.js +0 -20
  128. package/modules/proxy/proxy-path.js +0 -179
  129. package/modules/proxy/proxy-policy.js +0 -248
  130. package/modules/repositories/authorization-session-repository-documentdb.js +0 -112
  131. package/modules/repositories/authorization-session-repository-factory.js +0 -31
  132. package/modules/repositories/authorization-session-repository-interface.js +0 -47
  133. package/modules/repositories/authorization-session-repository-prisma.js +0 -87
  134. package/modules/repositories/entity-not-found.js +0 -18
  135. package/modules/requester/proxy-request.js +0 -244
  136. package/modules/scope-config.js +0 -192
  137. package/modules/scope-policy.js +0 -112
  138. package/modules/scope-resolution.js +0 -288
  139. package/modules/scope-visibility.js +0 -247
  140. package/modules/tests/doubles/in-memory-authorization-session-repository.js +0 -45
  141. package/modules/tests/doubles/ownership-matching.js +0 -18
  142. package/modules/use-cases/authorize-entity-for-user.js +0 -61
  143. package/modules/use-cases/create-entity-from-credential.js +0 -113
  144. package/modules/use-cases/entity-operations-for-user.js +0 -162
  145. package/modules/use-cases/entity-types.js +0 -139
  146. package/modules/use-cases/execute-entity-proxy-request.js +0 -286
  147. package/modules/use-cases/get-authorization-requirements.js +0 -100
  148. package/modules/use-cases/get-entity-module-for-user.js +0 -113
  149. package/modules/use-cases/manage-access.js +0 -21
  150. package/modules/use-cases/multi-step-authorization.js +0 -329
  151. package/prisma-postgresql/migrations/20261003000000_add_authorization_session/migration.sql +0 -28
  152. package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
  153. package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
  154. package/prisma-postgresql/migrations/20261017000000_add_scheduled_job/migration.sql +0 -28
  155. package/providers/index.js +0 -23
  156. package/providers/resolve-provider.js +0 -93
  157. package/providers/runtime-detection.js +0 -124
  158. package/queues/providers/index.js +0 -11
  159. package/queues/providers/netlify-background-provider.js +0 -150
  160. package/queues/providers/qstash-queue-provider.js +0 -219
  161. package/queues/providers/sqs-queue-provider.js +0 -70
  162. package/queues/queue-client-interface.js +0 -55
  163. package/queues/queue-message-auth.js +0 -193
  164. package/queues/queue-provider-factory.js +0 -101
  165. package/queues/queue-provider.js +0 -65
  166. package/queues/sqs-queue-client.js +0 -81
  167. package/types/modules/index.d.ts +0 -197
  168. package/types/user/index.d.ts +0 -134
  169. package/user/adopter-jwt-config.js +0 -177
  170. package/user/adopter-jwt-errors.js +0 -59
  171. package/user/adopter-token-verifier.js +0 -122
  172. package/user/app-user-helpers.js +0 -97
  173. package/user/create-user-authentication.js +0 -64
  174. package/user/membership.js +0 -51
  175. package/user/repositories/organization-membership-record.js +0 -19
  176. package/user/repositories/organization-membership-repository-documentdb.js +0 -106
  177. package/user/repositories/organization-membership-repository-factory.js +0 -42
  178. package/user/repositories/organization-membership-repository-interface.js +0 -57
  179. package/user/repositories/organization-membership-repository-mongo.js +0 -13
  180. package/user/repositories/organization-membership-repository-postgres.js +0 -29
  181. package/user/repositories/organization-membership-repository-prisma.js +0 -81
  182. package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
  183. package/user/use-cases/ensure-organization-membership.js +0 -92
  184. package/user/use-cases/find-individual-users-by-organization.js +0 -54
@@ -1,101 +0,0 @@
1
- /**
2
- * Queue Provider Factory
3
- *
4
- * Creates a QueueProvider (send / batchSend / parseEvent) for the active
5
- * platform. From friggframework/frigg#545, adapted: #545 resolved every
6
- * provider through resolveProvider(), so an AWS app had to install
7
- * @friggframework/provider-aws. In this stack the AWS SDK is a core
8
- * dependency, so the built-in queues are created here and only an unknown
9
- * name goes through the provider plugin system.
10
- *
11
- * Priority order for determining the provider:
12
- * 1. Explicit `provider` option
13
- * 2. `appDefinition.queue.provider`
14
- * 3. `QUEUE_PROVIDER` environment variable
15
- * 4. Default: SQS
16
- *
17
- * Built-in names:
18
- * - 'sqs' | 'aws' -> SqsQueueProvider
19
- * - 'netlify-background' | 'netlify' -> NetlifyBackgroundProvider
20
- * - 'qstash' -> QStashQueueProvider
21
- * Any other name -> require('@friggframework/provider-<name>').QueueProvider
22
- */
23
-
24
- const QUEUE_PROVIDERS = {
25
- SQS: 'sqs',
26
- NETLIFY_BACKGROUND: 'netlify-background',
27
- QSTASH: 'qstash',
28
- };
29
-
30
- // Platform provider names (appDefinition.provider) that map to a built-in queue.
31
- const PLATFORM_ALIASES = {
32
- aws: QUEUE_PROVIDERS.SQS,
33
- netlify: QUEUE_PROVIDERS.NETLIFY_BACKGROUND,
34
- };
35
-
36
- /**
37
- * Determine the queue provider from the config hierarchy.
38
- *
39
- * @param {Object} [options]
40
- * @param {string} [options.provider]
41
- * @param {Object} [options.appDefinition]
42
- * @returns {string|undefined}
43
- */
44
- function determineProvider(options = {}) {
45
- if (options.provider) {
46
- return options.provider;
47
- }
48
- if (options.appDefinition?.queue?.provider) {
49
- return options.appDefinition.queue.provider;
50
- }
51
- if (process.env.QUEUE_PROVIDER) {
52
- return process.env.QUEUE_PROVIDER;
53
- }
54
- return undefined;
55
- }
56
-
57
- /**
58
- * Create a queue provider instance.
59
- *
60
- * @param {Object} [options]
61
- * @param {string} [options.provider] - Queue provider name
62
- * @param {Object} [options.appDefinition] - reads `queue.provider`
63
- * @param {Object} [options.providerOptions] - passed to the provider constructor
64
- * @returns {import('./queue-provider').QueueProvider}
65
- */
66
- function createQueueProvider(options = {}) {
67
- const explicit = determineProvider(options);
68
- const name = PLATFORM_ALIASES[explicit] || explicit || QUEUE_PROVIDERS.SQS;
69
- const providerOptions = options.providerOptions || {};
70
-
71
- switch (name) {
72
- case QUEUE_PROVIDERS.SQS: {
73
- const { SqsQueueProvider } = require('./providers/sqs-queue-provider');
74
- return new SqsQueueProvider(providerOptions);
75
- }
76
- case QUEUE_PROVIDERS.NETLIFY_BACKGROUND: {
77
- const {
78
- NetlifyBackgroundProvider,
79
- } = require('./providers/netlify-background-provider');
80
- return new NetlifyBackgroundProvider(providerOptions);
81
- }
82
- case QUEUE_PROVIDERS.QSTASH: {
83
- const { QStashQueueProvider } = require('./providers/qstash-queue-provider');
84
- return new QStashQueueProvider(providerOptions);
85
- }
86
- default: {
87
- const { resolveProvider } = require('../providers/resolve-provider');
88
- const provider = resolveProvider(null, { provider: name });
89
- if (!provider.QueueProvider) {
90
- throw new Error(`Provider '${provider.name || name}' does not export a QueueProvider`);
91
- }
92
- return new provider.QueueProvider(providerOptions);
93
- }
94
- }
95
- }
96
-
97
- module.exports = {
98
- createQueueProvider,
99
- determineProvider,
100
- QUEUE_PROVIDERS,
101
- };
@@ -1,65 +0,0 @@
1
- /**
2
- * Queue Provider Interface (Port)
3
- *
4
- * Defines the contract for queue message sending.
5
- * All queue adapters must extend this interface.
6
- *
7
- * Following Frigg's hexagonal architecture pattern:
8
- * - Port defines WHAT the service does (contract)
9
- * - Adapters implement HOW (AWS SQS, Netlify Background Functions, QStash, etc.)
10
- */
11
- class QueueProvider {
12
- /**
13
- * Send a single message to a queue
14
- *
15
- * @param {Object} message - Message payload (will be JSON-serialized)
16
- * @param {string} queueId - Queue identifier (URL, name, or endpoint depending on provider)
17
- * @returns {Promise<Object>} Provider-specific response
18
- */
19
- async send(message, queueId) {
20
- throw new Error('Method send must be implemented by subclass');
21
- }
22
-
23
- /**
24
- * Send a batch of messages to a queue
25
- *
26
- * @param {Object[]} entries - Array of message payloads
27
- * @param {string} queueId - Queue identifier
28
- * @returns {Promise<Object>} Provider-specific response
29
- */
30
- async batchSend(entries, queueId) {
31
- throw new Error('Method batchSend must be implemented by subclass');
32
- }
33
-
34
- /**
35
- * Parse an incoming event into an array of message payloads.
36
- * Each provider has its own event shape (SQS Records, HTTP body, etc.)
37
- *
38
- * @param {Object} event - Raw event from the runtime (Lambda event, HTTP request, etc.)
39
- * @returns {Object[]} Array of parsed message payloads
40
- */
41
- parseEvent(event) {
42
- throw new Error('Method parseEvent must be implemented by subclass');
43
- }
44
-
45
- /**
46
- * Prove an incoming event was sent by Frigg before anything is parsed or
47
- * dispatched. HTTP-delivered queues (Netlify Background Functions,
48
- * QStash) are public URLs, so their adapters check a signature here.
49
- *
50
- * The default refuses: an adapter that does not know how to verify its
51
- * events must not have them run. An adapter whose transport already
52
- * authenticates the caller (SQS triggering a Lambda) overrides this, and
53
- * must not set `verifiesHttpDelivery`: an HTTP entry point (Netlify's
54
- * worker-background) consults only adapters that set it to true, since
55
- * a transport-trust answer says nothing about an HTTP caller.
56
- *
57
- * @param {Object} event - Raw event from the runtime
58
- * @returns {Promise<{ ok: boolean, reason?: string, unsigned?: boolean }>}
59
- */
60
- async verifyEvent(event) {
61
- return { ok: false, reason: 'verification_not_implemented' };
62
- }
63
- }
64
-
65
- module.exports = { QueueProvider };
@@ -1,81 +0,0 @@
1
- /**
2
- * SQS Queue Client (Adapter)
3
- *
4
- * AWS SQS implementation of QueueClientInterface, used by Worker.
5
- *
6
- * In friggframework/frigg#545 this adapter moved to
7
- * @friggframework/provider-aws and Worker required it to be injected. In
8
- * this stack the AWS SDK stays a core dependency, so the adapter lives here,
9
- * Worker defaults to it, and provider-aws re-exports it. The SDK is
10
- * required on first use, not at module load.
11
- */
12
- const { QueueClientInterface } = require('./queue-client-interface');
13
-
14
- let sqsModule = null;
15
- function getSqsModule() {
16
- if (!sqsModule) {
17
- sqsModule = require('@aws-sdk/client-sqs');
18
- }
19
- return sqsModule;
20
- }
21
-
22
- /**
23
- * Client config #545's adapter used: IS_OFFLINE credentials, AWS_REGION and
24
- * AWS_ENDPOINT.
25
- */
26
- function defaultSqsClientConfig() {
27
- const config = {};
28
- if (process.env.IS_OFFLINE) {
29
- config.credentials = {
30
- accessKeyId: 'test-aws-key',
31
- secretAccessKey: 'test-aws-secret',
32
- };
33
- config.region = 'us-east-1';
34
- }
35
- if (!config.region && process.env.AWS_REGION) {
36
- config.region = process.env.AWS_REGION;
37
- }
38
- if (process.env.AWS_ENDPOINT) {
39
- config.endpoint = process.env.AWS_ENDPOINT;
40
- }
41
- return config;
42
- }
43
-
44
- class SqsQueueClient extends QueueClientInterface {
45
- /**
46
- * @param {Object} [options]
47
- * @param {Object} [options.clientConfig] - SQSClient config; defaults to
48
- * defaultSqsClientConfig().
49
- */
50
- constructor({ clientConfig } = {}) {
51
- super();
52
- this._clientConfig = clientConfig;
53
- this._sqs = null;
54
- }
55
-
56
- _client() {
57
- if (!this._sqs) {
58
- const { SQSClient } = getSqsModule();
59
- this._sqs = new SQSClient(this._clientConfig || defaultSqsClientConfig());
60
- }
61
- return this._sqs;
62
- }
63
-
64
- async sendMessage(params) {
65
- const { SendMessageCommand } = getSqsModule();
66
- return this._client().send(new SendMessageCommand(params));
67
- }
68
-
69
- async sendMessageBatch(params) {
70
- const { SendMessageBatchCommand } = getSqsModule();
71
- return this._client().send(new SendMessageBatchCommand(params));
72
- }
73
-
74
- async getQueueUrl(params) {
75
- const { GetQueueUrlCommand } = getSqsModule();
76
- const data = await this._client().send(new GetQueueUrlCommand(params));
77
- return data.QueueUrl;
78
- }
79
- }
80
-
81
- module.exports = { SqsQueueClient, defaultSqsClientConfig };
@@ -1,197 +0,0 @@
1
- declare module "@friggframework/core" {
2
- /** Where an entity type comes from: the app's `entities` map or an integration binding it. */
3
- export type EntityTypeSource =
4
- | { kind: "app" }
5
- | { kind: "integration"; name: string };
6
-
7
- export type EntityScope = "individual" | "organization" | "global";
8
-
9
- /** App-level settings carried from the `entities` entry; empty for an inferred-only type. */
10
- export interface EntityTypeSettings {
11
- scope?: EntityScope | { default?: EntityScope; allow?: EntityScope[] };
12
- proxy?: Record<string, unknown>;
13
- display?: Record<string, unknown>;
14
- }
15
-
16
- export interface EntityTypeEntry {
17
- /** The API module definition. */
18
- definition: any;
19
- /** Frozen. `{ kind: 'app' }` first when registered, then each binding integration. */
20
- sources: readonly EntityTypeSource[];
21
- /** Frozen. */
22
- settings: Readonly<EntityTypeSettings>;
23
- }
24
-
25
- /** Entity type name (the definition's moduleName) to its entry. */
26
- export type EntityTypeRegistry = Map<string, EntityTypeEntry>;
27
-
28
- /** One `appDefinition.entities` entry. The key must equal the definition's moduleName (and getName() when defined). */
29
- export interface EntityRegistration extends EntityTypeSettings {
30
- definition: any;
31
- }
32
-
33
- export interface AppDefinitionEntities {
34
- /** false turns inference off: every module an integration binds must be registered. Default true. */
35
- $infer?: boolean;
36
- [entityType: string]: EntityRegistration | boolean | undefined;
37
- }
38
-
39
- /**
40
- * One level's setting: a scope, or a default plus the scopes a request may
41
- * choose from (ADR-056 §3.1). `global` is never chosen by a tenant request.
42
- */
43
- export type ScopeSetting =
44
- | EntityScope
45
- | { default?: EntityScope; allow?: EntityScope[] };
46
-
47
- /**
48
- * `appDefinition.ownership` (ADR-056 §3, §3.6). Resolution order for a new
49
- * connection: request, binding, integration, entity type (`entities[name].scope`),
50
- * this `scope`, then `organization` for an organization-primary app and
51
- * `individual` otherwise.
52
- */
53
- export interface AppOwnership {
54
- scope?: ScopeSetting;
55
- /**
56
- * `'organization'` (default): an individual entity belongs to the organization
57
- * it was connected in. `'all'`: one connection per person across every
58
- * organization, stored with no `organizationId`.
59
- */
60
- individualAcross?: "organization" | "all";
61
- }
62
-
63
- /** `Definition.ownership` on an integration (ADR-056 §3.1, §3.3). */
64
- export interface IntegrationOwnership {
65
- /** Scope every binding of this integration accepts unless it sets its own. */
66
- scope?: ScopeSetting;
67
- /** `'derive'` (default): organization when every entity it uses is organization-scoped. */
68
- owner?: "derive" | "individual" | "organization";
69
- }
70
-
71
- /** One operation a module or the app lets the entity proxy forward (ADR-052). */
72
- export interface ProxyAllowRule {
73
- method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "*";
74
- /** Relative to the module's base URL. `:param` is one segment; a trailing `/**` is a subtree. */
75
- path: string;
76
- }
77
-
78
- /** `appDefinition.managementApi.proxy`: the entity proxy, POST /api/v2/entities/:id/proxy (ADR-052). */
79
- export interface ManagementApiProxyConfig {
80
- /** Mount the route. Default false. */
81
- enable?: boolean;
82
- /** Upstream timeout in ms; can only be lowered from 25000. */
83
- timeoutMs?: number;
84
- /** Largest request body in bytes; default 1 MiB, at most 10 MiB. */
85
- maxRequestBytes?: number;
86
- /** Largest response body in bytes; can only be lowered from 5 MiB. */
87
- maxResponseBytes?: number;
88
- /**
89
- * Entity scopes the proxy accepts (ADR-056 §3.5). Default `['individual']`.
90
- * Add `'organization'` to let a member with use access proxy through the
91
- * organization's shared credential. `global` is never accepted. An unknown,
92
- * empty or repeated value throws ManagementApiConfigError at load.
93
- */
94
- scopes?: Array<Exclude<EntityScope, "global">>;
95
- /** Per-module allow-list override; `'module'` uses the module's own list. */
96
- modules?: Record<string, { allow: "module" | ProxyAllowRule[] }>;
97
- }
98
-
99
- /** `appDefinition.managementApi` (ADR-052, ADR-053). */
100
- export interface ManagementApiConfig {
101
- /** Serve the deprecated v1 routes. Default true. */
102
- v1?: boolean;
103
- proxy?: ManagementApiProxyConfig;
104
- }
105
-
106
- export interface AppDefinition {
107
- integrations: any[];
108
- /** App-level entity type registry (ADR-059). */
109
- entities?: AppDefinitionEntities;
110
- /** Who owns what a person connects (ADR-056). */
111
- ownership?: AppOwnership;
112
- /** Management API versions and the entity proxy (ADR-052, ADR-053, ADR-056 §3.5). */
113
- managementApi?: ManagementApiConfig;
114
- [key: string]: unknown;
115
- }
116
-
117
- /** Whose a record is and what the caller may do with it (ADR-056 §3.4). */
118
- export interface RecordTenancy {
119
- scope: Exclude<EntityScope, "global">;
120
- owner: { type: Exclude<EntityScope, "global">; id: string };
121
- /** Null for an individual entity connected outside an organization, or under `individualAcross: 'all'`. */
122
- organizationId: string | null;
123
- /** `manage`: create, reauthorize, delete. `use`: bind it, proxy through it. `view`: metadata only. */
124
- access: "manage" | "use" | "view";
125
- }
126
-
127
- /** Which scope a connection gets, and from which level of the order (ADR-056 §3.1). */
128
- export interface ResolvedScope {
129
- scope: EntityScope;
130
- /** Where `scope` came from. `request` when the request chose within the allowed list. */
131
- source: "request" | "binding" | "integration" | "entityType" | "app" | "default";
132
- /** The level that decided what a request may choose from. */
133
- decidedBy: "binding" | "integration" | "entityType" | "app" | "default";
134
- allow: EntityScope[];
135
- }
136
-
137
- /**
138
- * First match wins, each level overriding the ones below it. A request may
139
- * choose only from the deciding level's `allow`; `global` never comes from a
140
- * tenant request. Throws a Boom 400/403 for a request scope that is not allowed.
141
- */
142
- export function resolveScope(levels: {
143
- request?: EntityScope;
144
- binding?: ScopeSetting;
145
- integration?: ScopeSetting;
146
- entityType?: ScopeSetting;
147
- app?: ScopeSetting;
148
- primary?: "individual" | "organization";
149
- }): ResolvedScope;
150
-
151
- /** Every binding of every integration with its resolved scope (for tooling that wants to show the chain). */
152
- export function listBindingScopes(
153
- appDefinition: Pick<AppDefinition, "integrations" | "ownership">,
154
- entityTypeRegistry: EntityTypeRegistry,
155
- primary?: "individual" | "organization"
156
- ): Array<{
157
- integration: string;
158
- binding: string;
159
- moduleName: string | null;
160
- scope: EntityScope;
161
- source: ResolvedScope["source"];
162
- owner: "derive" | "individual" | "organization";
163
- }>;
164
-
165
- /** Invalid ownership or scope setting, thrown at app-definition load. `code` is always `OWNERSHIP_CONFIG_INVALID`. */
166
- export class OwnershipConfigError extends Error {
167
- code: "OWNERSHIP_CONFIG_INVALID";
168
- }
169
-
170
- /**
171
- * Builds the registry from `entities` plus the modules integrations bind.
172
- * Throws EntityRegistryError on an invalid registry.
173
- */
174
- export function getEntityTypeRegistry(
175
- appDefinition?: Pick<AppDefinition, "entities" | "integrations">
176
- ): EntityTypeRegistry;
177
-
178
- /** Invalid `managementApi` setting (today: `proxy.scopes`), thrown at app-definition load. */
179
- export class ManagementApiConfigError extends Error {
180
- code: "MANAGEMENT_API_CONFIG_INVALID";
181
- }
182
-
183
- /**
184
- * @deprecated ADR-059. Use `getEntityTypeRegistry(appDefinition)` and read
185
- * each entry's `definition`. Returns the registry's definitions for these
186
- * integrations (plus registry-only types when `entities` is passed).
187
- */
188
- export function getModulesDefinitionFromIntegrationClasses(
189
- integrationClasses: any[],
190
- entities?: AppDefinitionEntities
191
- ): any[];
192
-
193
- /** Invalid `entities` registry. `code` is always `ENTITY_REGISTRY_INVALID`. */
194
- export class EntityRegistryError extends Error {
195
- code: "ENTITY_REGISTRY_INVALID";
196
- }
197
- }
@@ -1,134 +0,0 @@
1
- declare module "@friggframework/core/user" {
2
- export type AdopterJwtAlgorithm =
3
- | "ES256"
4
- | "ES384"
5
- | "RS256"
6
- | "RS384"
7
- | "RS512"
8
- | "HS256"
9
- | "HS384"
10
- | "HS512";
11
-
12
- /**
13
- * Verification of tokens issued by the adopter's identity system
14
- * (`authModes.adopterJwt`, ADR-056 §2). Set exactly one of `jwksUri` or `secret`.
15
- */
16
- export interface AdopterJwtConfig {
17
- /** https URL of the issuer's JWKS (http only for localhost, 127.0.0.0/8, ::1). */
18
- jwksUri?: string;
19
- /** Shared HMAC secret for HS* tokens. */
20
- secret?: string;
21
- /** Required `iss`. With `jwksUri`, a startup warning is logged when unset. */
22
- issuer?: string;
23
- /** Accepted `aud`. Required with `jwksUri`. */
24
- audience?: string | string[];
25
- /** Allow-list. Default ES256 and RS256 with `jwksUri`, HS256 with `secret`. */
26
- algorithms?: AdopterJwtAlgorithm[];
27
- /** @deprecated Use `algorithms`. Setting both is an error. */
28
- algorithm?: AdopterJwtAlgorithm;
29
- /** Skew allowed on `exp` and `nbf`. Default 30. */
30
- clockToleranceSec?: number;
31
- /** Default `sub`. */
32
- userIdClaim?: string;
33
- /** Default `org_id`. */
34
- orgIdClaim?: string;
35
- /** Default `org_role`. Exposed as `User#getOrgRole()`; stored on a new membership. */
36
- roleClaim?: string;
37
- }
38
-
39
- export interface UserAuthModes {
40
- friggToken?: boolean;
41
- sharedSecret?: boolean;
42
- adopterJwt?: boolean;
43
- }
44
-
45
- /** The `user` block of the app definition. */
46
- export interface UserConfig {
47
- usePassword?: boolean;
48
- primary?: "individual" | "organization";
49
- individualUserRequired?: boolean;
50
- organizationUserRequired?: boolean;
51
- /**
52
- * With `x-frigg` headers, refuse (400) to make a person a member of an
53
- * organization that already existed: anyone not already a member, a
54
- * brand-new `appUserId` included, is rejected. Naming an organization the
55
- * request itself creates is still allowed. Default false (a non-member is
56
- * added).
57
- */
58
- strictMembership?: boolean;
59
- /**
60
- * @deprecated Alias of `strictMembership`, with the same new meaning (it
61
- * used to reject a mismatched individual/organization pair). Logs a warning
62
- * at startup. `strictMembership` wins when both are set.
63
- */
64
- strictUserValidation?: boolean;
65
- /**
66
- * Roles that may manage organization-level things (ADR-056 §3). Default
67
- * `['ADMIN']`. The role is the adopter token's role claim, else the stored
68
- * membership `orgRole`, else `MEMBER` (never admin). A shared-secret
69
- * (`x-frigg` header) caller needs no role, nor does a Frigg bearer token
70
- * unless `orgAdminGateBearerTokens`. Compared case-insensitively.
71
- * Validated at load.
72
- */
73
- orgAdminRoles?: string[];
74
- /**
75
- * Judge Frigg bearer-token callers by role like adopter-token callers.
76
- * Default false: they keep their behaviour from before organization roles.
77
- */
78
- orgAdminGateBearerTokens?: boolean;
79
- authModes?: UserAuthModes;
80
- jwtConfig?: AdopterJwtConfig;
81
- }
82
-
83
- /**
84
- * One person's membership of one organization (ADR-056 §3.6). `implicit` is
85
- * true when it is only the legacy `IndividualUser.organizationId` pointer.
86
- */
87
- export interface OrganizationMembership {
88
- id: string | null;
89
- individualUserId: string;
90
- organizationUserId: string;
91
- /** Defaults to `MEMBER`. */
92
- orgRole: string;
93
- createdAt?: Date;
94
- implicit: boolean;
95
- }
96
-
97
- export interface OrganizationMembershipRepository {
98
- /** The stored row or null: the legacy `organizationId` pointer is not read here. */
99
- findMembership(
100
- individualUserId: string,
101
- organizationUserId: string
102
- ): Promise<OrganizationMembership | null>;
103
- /** Idempotent: adds when absent, never changes an existing membership. */
104
- addMembership(
105
- individualUserId: string,
106
- organizationUserId: string,
107
- options?: { orgRole?: string | null }
108
- ): Promise<OrganizationMembership>;
109
- /** Stored rows only, oldest first; legacy-pointer people are not here. */
110
- listMembershipsForOrganization(
111
- organizationUserId: string
112
- ): Promise<OrganizationMembership[]>;
113
- }
114
-
115
- export function createOrganizationMembershipRepository(): OrganizationMembershipRepository;
116
-
117
- export class User {
118
- /** The primary user's id; under `primary: 'organization'` the ACTIVE organization. */
119
- getId(): string | undefined;
120
- /** The organization this request acts in (token or `x-frigg-apporgid`), or null. */
121
- getActiveOrganizationId(): string | null;
122
- getAppUserId(): string | null;
123
- getAppOrgId(): string | null;
124
- getIndividualUser(): any;
125
- getOrganizationUser(): any;
126
- getPrimaryUser(): any;
127
- /** The organization role from the adopter token for this request, or null. */
128
- getOrgRole(): string | null;
129
- setOrgRole(orgRole: string | null): void;
130
- /** The stored `orgRole` of the membership of the active organization, or null. Used when the token carries no role. */
131
- getMembershipRole(): string | null;
132
- setMembershipRole(membershipRole: string | null): void;
133
- }
134
- }