@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.
- package/CLAUDE.md +0 -2
- package/README.md +0 -105
- package/application/commands/integration-commands.js +2 -2
- package/application/commands/user-commands.js +5 -17
- package/credential/use-cases/credential-operations-for-user.js +25 -110
- package/credential/use-cases/reauthorize-credential-for-user.js +8 -15
- package/database/documentdb-utils.js +1 -6
- package/generated/prisma-mongodb/edge.js +4 -15
- package/generated/prisma-mongodb/index-browser.js +1 -12
- package/generated/prisma-mongodb/index.d.ts +86 -2027
- package/generated/prisma-mongodb/index.js +4 -15
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +0 -47
- package/generated/prisma-mongodb/wasm.js +4 -15
- package/generated/prisma-postgresql/edge.js +4 -15
- package/generated/prisma-postgresql/index-browser.js +1 -12
- package/generated/prisma-postgresql/index.d.ts +63 -2162
- package/generated/prisma-postgresql/index.js +4 -15
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +0 -44
- package/generated/prisma-postgresql/wasm.js +4 -15
- package/handlers/app-definition-loader.js +1 -15
- package/index.js +0 -18
- package/integrations/integration-router.js +73 -115
- package/integrations/repositories/integration-repository-documentdb.js +3 -35
- package/integrations/repositories/integration-repository-interface.js +1 -17
- package/integrations/repositories/integration-repository-mongo.js +76 -59
- package/integrations/repositories/integration-repository-postgres.js +76 -62
- package/integrations/tests/doubles/test-integration-repository.js +1 -12
- package/integrations/use-cases/create-integration.js +20 -55
- package/integrations/use-cases/get-integrations-for-user.js +40 -80
- package/integrations/use-cases/index.js +1 -5
- package/integrations/use-cases/integration-operations-for-user.js +24 -55
- package/management-api/management-api-config.js +0 -3
- package/management-api/openapi/components.js +0 -40
- package/management-api/openapi/v2-operations.js +1 -13
- package/management-api/v2/dependencies.js +15 -40
- package/management-api/v2/dto.js +0 -20
- package/management-api/v2/handlers/authorization.js +0 -1
- package/management-api/v2/handlers/credentials.js +2 -6
- package/management-api/v2/handlers/entities.js +7 -10
- package/management-api/v2/handlers/integrations.js +3 -6
- package/management-api/v2/request.js +1 -32
- package/modules/index.js +0 -8
- package/modules/repositories/module-repository-documentdb.js +4 -48
- package/modules/repositories/module-repository-interface.js +2 -19
- package/modules/repositories/module-repository-mongo.js +73 -65
- package/modules/repositories/module-repository-postgres.js +73 -64
- package/modules/use-cases/entity-operations-for-user.js +13 -50
- package/modules/use-cases/entity-types.js +7 -31
- package/modules/use-cases/execute-entity-proxy-request.js +0 -15
- package/modules/use-cases/get-entities-for-user.js +5 -16
- package/modules/use-cases/get-entity-module-for-user.js +3 -23
- package/modules/use-cases/get-entity-options-by-id.js +3 -9
- package/modules/use-cases/get-module.js +3 -9
- package/modules/use-cases/multi-step-authorization.js +12 -39
- package/modules/use-cases/process-authorization-callback.js +18 -52
- package/modules/use-cases/refresh-entity-options.js +3 -9
- package/modules/use-cases/test-module-auth.js +3 -9
- package/package.json +5 -6
- package/prisma-mongodb/schema.prisma +0 -47
- package/prisma-postgresql/schema.prisma +0 -44
- package/types/index.d.ts +0 -1
- package/types/modules/index.d.ts +0 -87
- package/user/repositories/user-repository-documentdb.js +2 -27
- package/user/repositories/user-repository-interface.js +0 -18
- package/user/repositories/user-repository-mongo.js +0 -24
- package/user/repositories/user-repository-postgres.js +0 -18
- package/user/use-cases/authenticate-user.js +1 -7
- package/user/use-cases/get-user-from-adopter-jwt.js +124 -95
- package/user/use-cases/get-user-from-x-frigg-headers.js +80 -83
- package/user/user.js +1 -64
- package/database/organization-where.js +0 -18
- package/database/unique-violation.js +0 -25
- package/integrations/repositories/integration-not-found.js +0 -14
- package/integrations/use-cases/resolve-integration-ownership.js +0 -177
- package/modules/entity-scope.js +0 -15
- package/modules/scope-config.js +0 -192
- package/modules/scope-policy.js +0 -112
- package/modules/scope-resolution.js +0 -288
- package/modules/scope-visibility.js +0 -239
- package/modules/tests/doubles/ownership-matching.js +0 -18
- package/modules/use-cases/authorize-entity-for-user.js +0 -61
- package/modules/use-cases/create-entity-from-credential.js +0 -113
- package/modules/use-cases/manage-access.js +0 -21
- package/prisma-postgresql/migrations/20261015000000_add_organization_membership/migration.sql +0 -26
- package/prisma-postgresql/migrations/20261016000000_add_entity_integration_organization/migration.sql +0 -25
- package/types/user/index.d.ts +0 -134
- package/user/adopter-jwt-config.js +0 -177
- package/user/adopter-jwt-errors.js +0 -59
- package/user/adopter-token-verifier.js +0 -122
- package/user/app-user-helpers.js +0 -97
- package/user/create-user-authentication.js +0 -64
- package/user/membership.js +0 -51
- package/user/repositories/organization-membership-record.js +0 -19
- package/user/repositories/organization-membership-repository-documentdb.js +0 -106
- package/user/repositories/organization-membership-repository-factory.js +0 -42
- package/user/repositories/organization-membership-repository-interface.js +0 -57
- package/user/repositories/organization-membership-repository-mongo.js +0 -13
- package/user/repositories/organization-membership-repository-postgres.js +0 -29
- package/user/repositories/organization-membership-repository-prisma.js +0 -81
- package/user/tests/doubles/adopter-jwt-fixtures.js +0 -220
- package/user/use-cases/ensure-organization-membership.js +0 -92
- package/user/use-cases/find-individual-users-by-organization.js +0 -54
|
@@ -56,14 +56,6 @@ model User {
|
|
|
56
56
|
integrations Integration[]
|
|
57
57
|
processes Process[]
|
|
58
58
|
|
|
59
|
-
// Organization memberships (ADR-056 §3.6). `organizationId` above is the legacy
|
|
60
|
-
// single-org pointer: set on a person's first link, never moved afterwards, and
|
|
61
|
-
// read as an implicit membership when no row exists for it.
|
|
62
|
-
// As an individual: the organizations this person belongs to.
|
|
63
|
-
memberships OrganizationMembership[] @relation("IndividualMemberships")
|
|
64
|
-
// As an organization: the people who belong to it.
|
|
65
|
-
orgMembers OrganizationMembership[] @relation("OrganizationMemberships")
|
|
66
|
-
|
|
67
59
|
@@unique([username, appUserId])
|
|
68
60
|
@@index([type])
|
|
69
61
|
@@index([appUserId])
|
|
@@ -131,14 +123,6 @@ model Entity {
|
|
|
131
123
|
moduleName String?
|
|
132
124
|
externalId String?
|
|
133
125
|
|
|
134
|
-
// Organization this entity was connected in (ADR-056 §3.6): the active
|
|
135
|
-
// organization for `individual`, the owner for `organization`, null for
|
|
136
|
-
// `global`. Null on an `individual` entity is also what every row written
|
|
137
|
-
// before this column existed has, and what `individualAcross: 'all'` writes.
|
|
138
|
-
// Deliberately not a relation: a deleted organization must leave its rows
|
|
139
|
-
// invisible, not turn them into "unscoped" ones (SetNull would do that).
|
|
140
|
-
organizationId Int?
|
|
141
|
-
|
|
142
126
|
data Json @default("{}")
|
|
143
127
|
|
|
144
128
|
createdAt DateTime @default(now())
|
|
@@ -152,7 +136,6 @@ model Entity {
|
|
|
152
136
|
associationObjects AssociationObject[]
|
|
153
137
|
|
|
154
138
|
@@index([userId])
|
|
155
|
-
@@index([userId, organizationId])
|
|
156
139
|
@@index([externalId])
|
|
157
140
|
@@index([moduleName])
|
|
158
141
|
@@index([credentialId])
|
|
@@ -169,11 +152,6 @@ model Integration {
|
|
|
169
152
|
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
170
153
|
status IntegrationStatus @default(IN_CREATION)
|
|
171
154
|
|
|
172
|
-
// Organization this integration was created in (ADR-056 §3.6): the active
|
|
173
|
-
// organization at create time. Null for rows that predate the column. Not a
|
|
174
|
-
// relation, for the same reason as Entity.organizationId.
|
|
175
|
-
organizationId Int?
|
|
176
|
-
|
|
177
155
|
// Configuration and version
|
|
178
156
|
config Json? // Integration configuration object
|
|
179
157
|
version String?
|
|
@@ -197,7 +175,6 @@ model Integration {
|
|
|
197
175
|
processes Process[]
|
|
198
176
|
|
|
199
177
|
@@index([userId])
|
|
200
|
-
@@index([userId, organizationId])
|
|
201
178
|
@@index([status])
|
|
202
179
|
}
|
|
203
180
|
|
|
@@ -483,24 +460,3 @@ model AuthorizationSession {
|
|
|
483
460
|
@@index([userId, entityType])
|
|
484
461
|
@@index([expiresAt])
|
|
485
462
|
}
|
|
486
|
-
|
|
487
|
-
// ============================================================================
|
|
488
|
-
// ORGANIZATION MEMBERSHIP (ADR-056 §3.6)
|
|
489
|
-
// ============================================================================
|
|
490
|
-
|
|
491
|
-
/// One person's membership of one organization. Unique on the pair, so adding a
|
|
492
|
-
/// membership is an idempotent upsert. `orgRole` is the organization role the
|
|
493
|
-
/// adopter token carried when the membership was created (MEMBER when it named none).
|
|
494
|
-
model OrganizationMembership {
|
|
495
|
-
id Int @id @default(autoincrement())
|
|
496
|
-
individualUserId Int
|
|
497
|
-
organizationUserId Int
|
|
498
|
-
orgRole String @default("MEMBER")
|
|
499
|
-
createdAt DateTime @default(now())
|
|
500
|
-
|
|
501
|
-
individualUser User @relation("IndividualMemberships", fields: [individualUserId], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
502
|
-
organizationUser User @relation("OrganizationMemberships", fields: [organizationUserId], references: [id], onDelete: Cascade, onUpdate: NoAction)
|
|
503
|
-
|
|
504
|
-
@@unique([individualUserId, organizationUserId])
|
|
505
|
-
@@index([organizationUserId])
|
|
506
|
-
}
|
|
@@ -132,7 +132,6 @@ exports.Prisma.EntityScalarFieldEnum = {
|
|
|
132
132
|
name: 'name',
|
|
133
133
|
moduleName: 'moduleName',
|
|
134
134
|
externalId: 'externalId',
|
|
135
|
-
organizationId: 'organizationId',
|
|
136
135
|
data: 'data',
|
|
137
136
|
createdAt: 'createdAt',
|
|
138
137
|
updatedAt: 'updatedAt'
|
|
@@ -142,7 +141,6 @@ exports.Prisma.IntegrationScalarFieldEnum = {
|
|
|
142
141
|
id: 'id',
|
|
143
142
|
userId: 'userId',
|
|
144
143
|
status: 'status',
|
|
145
|
-
organizationId: 'organizationId',
|
|
146
144
|
config: 'config',
|
|
147
145
|
version: 'version',
|
|
148
146
|
errors: 'errors',
|
|
@@ -270,14 +268,6 @@ exports.Prisma.AuthorizationSessionScalarFieldEnum = {
|
|
|
270
268
|
updatedAt: 'updatedAt'
|
|
271
269
|
};
|
|
272
270
|
|
|
273
|
-
exports.Prisma.OrganizationMembershipScalarFieldEnum = {
|
|
274
|
-
id: 'id',
|
|
275
|
-
individualUserId: 'individualUserId',
|
|
276
|
-
organizationUserId: 'organizationUserId',
|
|
277
|
-
orgRole: 'orgRole',
|
|
278
|
-
createdAt: 'createdAt'
|
|
279
|
-
};
|
|
280
|
-
|
|
281
271
|
exports.Prisma.SortOrder = {
|
|
282
272
|
asc: 'asc',
|
|
283
273
|
desc: 'desc'
|
|
@@ -352,8 +342,7 @@ exports.Prisma.ModelName = {
|
|
|
352
342
|
AdminScriptExecution: 'AdminScriptExecution',
|
|
353
343
|
ScriptSchedule: 'ScriptSchedule',
|
|
354
344
|
UsageCounter: 'UsageCounter',
|
|
355
|
-
AuthorizationSession: 'AuthorizationSession'
|
|
356
|
-
OrganizationMembership: 'OrganizationMembership'
|
|
345
|
+
AuthorizationSession: 'AuthorizationSession'
|
|
357
346
|
};
|
|
358
347
|
/**
|
|
359
348
|
* Create the Client
|
|
@@ -407,13 +396,13 @@ const config = {
|
|
|
407
396
|
}
|
|
408
397
|
}
|
|
409
398
|
},
|
|
410
|
-
"inlineSchema": "// Frigg Framework - Prisma Schema (PostgreSQL)\n// PostgreSQL database schema for enterprise integration platform\n// Converted from MongoDB schema for relational database support\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma-postgresql\"\n binaryTargets = [\"native\", \"rhel-openssl-3.0.x\"] // native for local dev, rhel for Lambda deployment\n // Library engine (default since Prisma 3.x): Rust query engine loads as a\n // Node-API addon inside the same process. The binary engine forks a child\n // query-engine subprocess and communicates over a local HTTP/IPC pipe with\n // NO client-side timeout — a zombied child wedges the Node process until\n // Lambda's 900s cap. Switching to library eliminates that entire class of\n // silent hangs. See friggframework/frigg#580 for the investigation.\n engineType = \"library\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ============================================================================\n// USER MODELS\n// ============================================================================\n\n/// User model with discriminator pattern support\n/// Replaces Mongoose discriminators (IndividualUser, OrganizationUser)\nmodel User {\n id Int @id @default(autoincrement())\n type UserType\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // IndividualUser fields (nullable for organizations)\n email String?\n username String?\n hashword String? // Bcrypt hashed password (handled in application layer)\n appUserId String?\n organizationId Int?\n\n // Self-referential relation for organization membership\n organization User? @relation(\"OrgMembers\", fields: [organizationId], references: [id], onDelete: NoAction, onUpdate: NoAction)\n members User[] @relation(\"OrgMembers\")\n\n // OrganizationUser fields (nullable for individuals)\n appOrgId String?\n name String?\n\n // Relations\n tokens Token[]\n credentials Credential[]\n entities Entity[]\n integrations Integration[]\n processes Process[]\n\n // Organization memberships (ADR-056 §3.6). `organizationId` above is the legacy\n // single-org pointer: set on a person's first link, never moved afterwards, and\n // read as an implicit membership when no row exists for it.\n // As an individual: the organizations this person belongs to.\n memberships OrganizationMembership[] @relation(\"IndividualMemberships\")\n // As an organization: the people who belong to it.\n orgMembers OrganizationMembership[] @relation(\"OrganizationMemberships\")\n\n @@unique([username, appUserId])\n @@index([type])\n @@index([appUserId])\n @@index([organizationId])\n}\n\nenum UserType {\n INDIVIDUAL\n ORGANIZATION\n}\n\n// ============================================================================\n// AUTHENTICATION MODELS\n// ============================================================================\n\n/// Authentication tokens with expiration\n/// Bcrypt hashed tokens stored (handled in application layer)\nmodel Token {\n id Int @id @default(autoincrement())\n token String // Bcrypt hashed\n created DateTime @default(now())\n expires DateTime?\n userId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n @@index([expires])\n}\n\n// ============================================================================\n// CREDENTIAL & ENTITY MODELS\n// ============================================================================\n\n/// OAuth credentials and API tokens\n/// All sensitive data encrypted with KMS at rest\nmodel Credential {\n id Int @id @default(autoincrement())\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n authIsValid Boolean?\n externalId String?\n\n // Dynamic OAuth fields stored as JSON (encrypted via Prisma middleware)\n // Contains: access_token, refresh_token, domain, expires_in, token_type, etc.\n data Json @default(\"{}\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n entities Entity[]\n\n @@index([userId])\n @@index([externalId])\n}\n\n/// External service entities (API connections)\nmodel Entity {\n id Int @id @default(autoincrement())\n credentialId Int?\n credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n name String?\n moduleName String?\n externalId String?\n\n // Organization this entity was connected in (ADR-056 §3.6): the active\n // organization for `individual`, the owner for `organization`, null for\n // `global`. Null on an `individual` entity is also what every row written\n // before this column existed has, and what `individualAcross: 'all'` writes.\n // Deliberately not a relation: a deleted organization must leave its rows\n // invisible, not turn them into \"unscoped\" ones (SetNull would do that).\n organizationId Int?\n\n data Json @default(\"{}\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations - many-to-many with implicit join tables\n integrations Integration[]\n syncs Sync[]\n\n dataIdentifiers DataIdentifier[]\n associationObjects AssociationObject[]\n\n @@index([userId])\n @@index([userId, organizationId])\n @@index([externalId])\n @@index([moduleName])\n @@index([credentialId])\n}\n\n// ============================================================================\n// INTEGRATION MODELS\n// ============================================================================\n\n/// Main integration configuration and state\nmodel Integration {\n id Int @id @default(autoincrement())\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n status IntegrationStatus @default(IN_CREATION)\n\n // Organization this integration was created in (ADR-056 §3.6): the active\n // organization at create time. Null for rows that predate the column. Not a\n // relation, for the same reason as Entity.organizationId.\n organizationId Int?\n\n // Configuration and version\n config Json? // Integration configuration object\n version String?\n\n // Entity references (many-to-many via implicit join table)\n entities Entity[]\n\n // Message arrays (stored as JSON)\n errors Json @default(\"[]\")\n warnings Json @default(\"[]\")\n info Json @default(\"[]\")\n logs Json @default(\"[]\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n associations Association[]\n syncs Sync[]\n mappings IntegrationMapping[]\n processes Process[]\n\n @@index([userId])\n @@index([userId, organizationId])\n @@index([status])\n}\n\nenum IntegrationStatus {\n ENABLED\n NEEDS_CONFIG\n PROCESSING\n DISABLED\n ERROR\n IN_CREATION\n IN_DELETION\n}\n\n/// Integration-specific data mappings\n/// All mapping data encrypted with KMS\nmodel IntegrationMapping {\n id Int @id @default(autoincrement())\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n sourceId String?\n\n // Encrypted mapping data (handled via Prisma middleware)\n mapping Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([integrationId, sourceId])\n @@index([integrationId])\n @@index([sourceId])\n}\n\n// ============================================================================\n// SYNC MODELS\n// ============================================================================\n\n/// Bidirectional data synchronization tracking\nmodel Sync {\n id Int @id @default(autoincrement())\n integrationId Int?\n integration Integration? @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n\n // Entity references (many-to-many via implicit join table)\n entities Entity[]\n\n hash String\n name String\n\n // Data identifiers (extracted to separate model)\n dataIdentifiers DataIdentifier[]\n\n @@index([integrationId])\n @@index([hash])\n @@index([name])\n}\n\n/// Data identifier for sync operations\n/// Replaces nested array structure in Mongoose\nmodel DataIdentifier {\n id Int @id @default(autoincrement())\n syncId Int?\n sync Sync? @relation(fields: [syncId], references: [id], onDelete: Cascade)\n entityId Int\n entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)\n\n // Identifier data (can be any structure)\n idData Json\n\n hash String\n\n @@index([syncId])\n @@index([entityId])\n @@index([hash])\n}\n\n// ============================================================================\n// ASSOCIATION MODELS\n// ============================================================================\n\n/// Entity associations with cardinality tracking\nmodel Association {\n id Int @id @default(autoincrement())\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n name String\n type AssociationType\n primaryObject String\n\n // Associated objects (extracted to separate model)\n objects AssociationObject[]\n\n @@index([integrationId])\n @@index([name])\n}\n\n/// Association object entry\n/// Replaces nested array structure in Mongoose\nmodel AssociationObject {\n id Int @id @default(autoincrement())\n associationId Int\n association Association @relation(fields: [associationId], references: [id], onDelete: Cascade)\n entityId Int\n entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)\n objectType String\n objId String\n metadata Json? // Optional metadata\n\n @@index([associationId])\n @@index([entityId])\n}\n\nenum AssociationType {\n ONE_TO_MANY\n ONE_TO_ONE\n MANY_TO_ONE\n}\n\n// ============================================================================\n// PROCESS MODELS\n// ============================================================================\n\n/// Generic Process Model - tracks any long-running operation\n/// Used for: CRM syncs, data migrations, bulk operations, etc.\nmodel Process {\n id Int @id @default(autoincrement())\n\n // Core references\n userId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n\n // Process identification\n name String // e.g., \"zoho-crm-contact-sync\", \"pipedrive-lead-sync\"\n type String // e.g., \"CRM_SYNC\", \"DATA_MIGRATION\", \"BULK_OPERATION\"\n\n // State machine\n state String // Current state (integration-defined states)\n\n // Flexible storage\n context Json @default(\"{}\") // Process-specific data (pagination, metadata, etc.)\n results Json @default(\"{}\") // Process results and metrics\n\n // Hierarchy support - self-referential relation\n parentProcessId Int?\n parentProcess Process? @relation(\"ProcessHierarchy\", fields: [parentProcessId], references: [id], onDelete: SetNull)\n childProcesses Process[] @relation(\"ProcessHierarchy\")\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([integrationId])\n @@index([type])\n @@index([state])\n @@index([name])\n @@index([parentProcessId])\n}\n\n// ============================================================================\n// UTILITY MODELS\n// ============================================================================\n\n/// Generic state storage\nmodel State {\n id Int @id @default(autoincrement())\n state Json?\n}\n\n/// AWS API Gateway WebSocket connection tracking\nmodel WebsocketConnection {\n id Int @id @default(autoincrement())\n connectionId String?\n\n @@index([connectionId])\n}\n\n// ============================================================================\n// ADMIN PROCESS MODELS\n// ============================================================================\n\n/// Admin process state machine\nenum AdminScriptExecutionState {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n}\n\n/// Admin process tracking (like Process but without user/integration FK)\n/// Used for: admin scripts, db migrations, system maintenance tasks\nmodel AdminScriptExecution {\n id Int @id @default(autoincrement())\n name String // e.g., \"oauth-token-refresh\", \"db-migration-xyz\"\n type String // e.g., \"ADMIN_SCRIPT\", \"DB_MIGRATION\"\n\n // State machine\n state AdminScriptExecutionState @default(PENDING)\n\n // Flexible storage (mirrors Process model pattern)\n context Json @default(\"{}\") // input, trigger, audit info, script version\n results Json @default(\"{}\") // output, logs, metrics, errors\n\n // Hierarchy support - self-referential relation\n parentExecutionId Int?\n parentExecution AdminScriptExecution? @relation(\"AdminScriptExecutionHierarchy\", fields: [parentExecutionId], references: [id], onDelete: SetNull)\n childExecutions AdminScriptExecution[] @relation(\"AdminScriptExecutionHierarchy\")\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([name, createdAt(sort: Desc)])\n @@index([state])\n @@index([type])\n}\n\n/// Script scheduling configuration for hybrid scheduling (SQS + EventBridge)\nmodel ScriptSchedule {\n id Int @id @default(autoincrement())\n scriptName String @unique\n enabled Boolean @default(false)\n cronExpression String?\n timezone String @default(\"UTC\")\n lastTriggeredAt DateTime?\n nextTriggerAt DateTime?\n\n // External Scheduler (e.g., AWS EventBridge Scheduler)\n externalScheduleId String?\n externalScheduleName String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([enabled])\n}\n\n/// Durable usage counters, deliberately isolated: no userId and no foreign key\n/// to Integration, so a user-scoped query can never return a usage row and usage\n/// history survives integration deletion.\nmodel UsageCounter {\n id Int @id @default(autoincrement())\n\n integrationId String\n integrationType String\n metric String\n window String // e.g. \"day:2026-07-05\" or \"hour:2026-07-05T14\"\n value BigInt @default(0) // BigInt: a busy day/hour counter can exceed 32-bit\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([integrationId, integrationType, metric, window])\n // Covers totals() (metric + window prefix/range, no integrationType filter).\n @@index([metric, window])\n // Covers series() (metric + integrationType + window range).\n @@index([metric, integrationType, window])\n}\n\n// ============================================================================\n// MANAGEMENT API MODELS\n// ============================================================================\n\n/// Multi-step authorization state for Management API v2 (/api/v2/authorize,\n/// /api/v2/credentials/:id/reauthorize). Short-lived: expired rows are removed\n/// opportunistically. stepData is encrypted at rest.\nmodel AuthorizationSession {\n id Int @id @default(autoincrement())\n sessionId String @unique\n userId String\n entityType String\n credentialId String?\n currentStep Int @default(1)\n maxSteps Int\n stepData Json @default(\"{}\")\n expiresAt DateTime\n completed Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId, entityType])\n @@index([expiresAt])\n}\n\n// ============================================================================\n// ORGANIZATION MEMBERSHIP (ADR-056 §3.6)\n// ============================================================================\n\n/// One person's membership of one organization. Unique on the pair, so adding a\n/// membership is an idempotent upsert. `orgRole` is the organization role the\n/// adopter token carried when the membership was created (MEMBER when it named none).\nmodel OrganizationMembership {\n id Int @id @default(autoincrement())\n individualUserId Int\n organizationUserId Int\n orgRole String @default(\"MEMBER\")\n createdAt DateTime @default(now())\n\n individualUser User @relation(\"IndividualMemberships\", fields: [individualUserId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n organizationUser User @relation(\"OrganizationMemberships\", fields: [organizationUserId], references: [id], onDelete: Cascade, onUpdate: NoAction)\n\n @@unique([individualUserId, organizationUserId])\n @@index([organizationUserId])\n}\n",
|
|
411
|
-
"inlineSchemaHash": "
|
|
399
|
+
"inlineSchema": "// Frigg Framework - Prisma Schema (PostgreSQL)\n// PostgreSQL database schema for enterprise integration platform\n// Converted from MongoDB schema for relational database support\n\ngenerator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma-postgresql\"\n binaryTargets = [\"native\", \"rhel-openssl-3.0.x\"] // native for local dev, rhel for Lambda deployment\n // Library engine (default since Prisma 3.x): Rust query engine loads as a\n // Node-API addon inside the same process. The binary engine forks a child\n // query-engine subprocess and communicates over a local HTTP/IPC pipe with\n // NO client-side timeout — a zombied child wedges the Node process until\n // Lambda's 900s cap. Switching to library eliminates that entire class of\n // silent hangs. See friggframework/frigg#580 for the investigation.\n engineType = \"library\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n url = env(\"DATABASE_URL\")\n}\n\n// ============================================================================\n// USER MODELS\n// ============================================================================\n\n/// User model with discriminator pattern support\n/// Replaces Mongoose discriminators (IndividualUser, OrganizationUser)\nmodel User {\n id Int @id @default(autoincrement())\n type UserType\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // IndividualUser fields (nullable for organizations)\n email String?\n username String?\n hashword String? // Bcrypt hashed password (handled in application layer)\n appUserId String?\n organizationId Int?\n\n // Self-referential relation for organization membership\n organization User? @relation(\"OrgMembers\", fields: [organizationId], references: [id], onDelete: NoAction, onUpdate: NoAction)\n members User[] @relation(\"OrgMembers\")\n\n // OrganizationUser fields (nullable for individuals)\n appOrgId String?\n name String?\n\n // Relations\n tokens Token[]\n credentials Credential[]\n entities Entity[]\n integrations Integration[]\n processes Process[]\n\n @@unique([username, appUserId])\n @@index([type])\n @@index([appUserId])\n @@index([organizationId])\n}\n\nenum UserType {\n INDIVIDUAL\n ORGANIZATION\n}\n\n// ============================================================================\n// AUTHENTICATION MODELS\n// ============================================================================\n\n/// Authentication tokens with expiration\n/// Bcrypt hashed tokens stored (handled in application layer)\nmodel Token {\n id Int @id @default(autoincrement())\n token String // Bcrypt hashed\n created DateTime @default(now())\n expires DateTime?\n userId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n @@index([expires])\n}\n\n// ============================================================================\n// CREDENTIAL & ENTITY MODELS\n// ============================================================================\n\n/// OAuth credentials and API tokens\n/// All sensitive data encrypted with KMS at rest\nmodel Credential {\n id Int @id @default(autoincrement())\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n authIsValid Boolean?\n externalId String?\n\n // Dynamic OAuth fields stored as JSON (encrypted via Prisma middleware)\n // Contains: access_token, refresh_token, domain, expires_in, token_type, etc.\n data Json @default(\"{}\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n entities Entity[]\n\n @@index([userId])\n @@index([externalId])\n}\n\n/// External service entities (API connections)\nmodel Entity {\n id Int @id @default(autoincrement())\n credentialId Int?\n credential Credential? @relation(fields: [credentialId], references: [id], onDelete: SetNull)\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n name String?\n moduleName String?\n externalId String?\n\n data Json @default(\"{}\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations - many-to-many with implicit join tables\n integrations Integration[]\n syncs Sync[]\n\n dataIdentifiers DataIdentifier[]\n associationObjects AssociationObject[]\n\n @@index([userId])\n @@index([externalId])\n @@index([moduleName])\n @@index([credentialId])\n}\n\n// ============================================================================\n// INTEGRATION MODELS\n// ============================================================================\n\n/// Main integration configuration and state\nmodel Integration {\n id Int @id @default(autoincrement())\n userId Int?\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n status IntegrationStatus @default(IN_CREATION)\n\n // Configuration and version\n config Json? // Integration configuration object\n version String?\n\n // Entity references (many-to-many via implicit join table)\n entities Entity[]\n\n // Message arrays (stored as JSON)\n errors Json @default(\"[]\")\n warnings Json @default(\"[]\")\n info Json @default(\"[]\")\n logs Json @default(\"[]\")\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Relations\n associations Association[]\n syncs Sync[]\n mappings IntegrationMapping[]\n processes Process[]\n\n @@index([userId])\n @@index([status])\n}\n\nenum IntegrationStatus {\n ENABLED\n NEEDS_CONFIG\n PROCESSING\n DISABLED\n ERROR\n IN_CREATION\n IN_DELETION\n}\n\n/// Integration-specific data mappings\n/// All mapping data encrypted with KMS\nmodel IntegrationMapping {\n id Int @id @default(autoincrement())\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n sourceId String?\n\n // Encrypted mapping data (handled via Prisma middleware)\n mapping Json?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([integrationId, sourceId])\n @@index([integrationId])\n @@index([sourceId])\n}\n\n// ============================================================================\n// SYNC MODELS\n// ============================================================================\n\n/// Bidirectional data synchronization tracking\nmodel Sync {\n id Int @id @default(autoincrement())\n integrationId Int?\n integration Integration? @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n\n // Entity references (many-to-many via implicit join table)\n entities Entity[]\n\n hash String\n name String\n\n // Data identifiers (extracted to separate model)\n dataIdentifiers DataIdentifier[]\n\n @@index([integrationId])\n @@index([hash])\n @@index([name])\n}\n\n/// Data identifier for sync operations\n/// Replaces nested array structure in Mongoose\nmodel DataIdentifier {\n id Int @id @default(autoincrement())\n syncId Int?\n sync Sync? @relation(fields: [syncId], references: [id], onDelete: Cascade)\n entityId Int\n entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)\n\n // Identifier data (can be any structure)\n idData Json\n\n hash String\n\n @@index([syncId])\n @@index([entityId])\n @@index([hash])\n}\n\n// ============================================================================\n// ASSOCIATION MODELS\n// ============================================================================\n\n/// Entity associations with cardinality tracking\nmodel Association {\n id Int @id @default(autoincrement())\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n name String\n type AssociationType\n primaryObject String\n\n // Associated objects (extracted to separate model)\n objects AssociationObject[]\n\n @@index([integrationId])\n @@index([name])\n}\n\n/// Association object entry\n/// Replaces nested array structure in Mongoose\nmodel AssociationObject {\n id Int @id @default(autoincrement())\n associationId Int\n association Association @relation(fields: [associationId], references: [id], onDelete: Cascade)\n entityId Int\n entity Entity @relation(fields: [entityId], references: [id], onDelete: Cascade)\n objectType String\n objId String\n metadata Json? // Optional metadata\n\n @@index([associationId])\n @@index([entityId])\n}\n\nenum AssociationType {\n ONE_TO_MANY\n ONE_TO_ONE\n MANY_TO_ONE\n}\n\n// ============================================================================\n// PROCESS MODELS\n// ============================================================================\n\n/// Generic Process Model - tracks any long-running operation\n/// Used for: CRM syncs, data migrations, bulk operations, etc.\nmodel Process {\n id Int @id @default(autoincrement())\n\n // Core references\n userId Int\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n integrationId Int\n integration Integration @relation(fields: [integrationId], references: [id], onDelete: Cascade)\n\n // Process identification\n name String // e.g., \"zoho-crm-contact-sync\", \"pipedrive-lead-sync\"\n type String // e.g., \"CRM_SYNC\", \"DATA_MIGRATION\", \"BULK_OPERATION\"\n\n // State machine\n state String // Current state (integration-defined states)\n\n // Flexible storage\n context Json @default(\"{}\") // Process-specific data (pagination, metadata, etc.)\n results Json @default(\"{}\") // Process results and metrics\n\n // Hierarchy support - self-referential relation\n parentProcessId Int?\n parentProcess Process? @relation(\"ProcessHierarchy\", fields: [parentProcessId], references: [id], onDelete: SetNull)\n childProcesses Process[] @relation(\"ProcessHierarchy\")\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([integrationId])\n @@index([type])\n @@index([state])\n @@index([name])\n @@index([parentProcessId])\n}\n\n// ============================================================================\n// UTILITY MODELS\n// ============================================================================\n\n/// Generic state storage\nmodel State {\n id Int @id @default(autoincrement())\n state Json?\n}\n\n/// AWS API Gateway WebSocket connection tracking\nmodel WebsocketConnection {\n id Int @id @default(autoincrement())\n connectionId String?\n\n @@index([connectionId])\n}\n\n// ============================================================================\n// ADMIN PROCESS MODELS\n// ============================================================================\n\n/// Admin process state machine\nenum AdminScriptExecutionState {\n PENDING\n RUNNING\n COMPLETED\n FAILED\n}\n\n/// Admin process tracking (like Process but without user/integration FK)\n/// Used for: admin scripts, db migrations, system maintenance tasks\nmodel AdminScriptExecution {\n id Int @id @default(autoincrement())\n name String // e.g., \"oauth-token-refresh\", \"db-migration-xyz\"\n type String // e.g., \"ADMIN_SCRIPT\", \"DB_MIGRATION\"\n\n // State machine\n state AdminScriptExecutionState @default(PENDING)\n\n // Flexible storage (mirrors Process model pattern)\n context Json @default(\"{}\") // input, trigger, audit info, script version\n results Json @default(\"{}\") // output, logs, metrics, errors\n\n // Hierarchy support - self-referential relation\n parentExecutionId Int?\n parentExecution AdminScriptExecution? @relation(\"AdminScriptExecutionHierarchy\", fields: [parentExecutionId], references: [id], onDelete: SetNull)\n childExecutions AdminScriptExecution[] @relation(\"AdminScriptExecutionHierarchy\")\n\n // Timestamps\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([name, createdAt(sort: Desc)])\n @@index([state])\n @@index([type])\n}\n\n/// Script scheduling configuration for hybrid scheduling (SQS + EventBridge)\nmodel ScriptSchedule {\n id Int @id @default(autoincrement())\n scriptName String @unique\n enabled Boolean @default(false)\n cronExpression String?\n timezone String @default(\"UTC\")\n lastTriggeredAt DateTime?\n nextTriggerAt DateTime?\n\n // External Scheduler (e.g., AWS EventBridge Scheduler)\n externalScheduleId String?\n externalScheduleName String?\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([enabled])\n}\n\n/// Durable usage counters, deliberately isolated: no userId and no foreign key\n/// to Integration, so a user-scoped query can never return a usage row and usage\n/// history survives integration deletion.\nmodel UsageCounter {\n id Int @id @default(autoincrement())\n\n integrationId String\n integrationType String\n metric String\n window String // e.g. \"day:2026-07-05\" or \"hour:2026-07-05T14\"\n value BigInt @default(0) // BigInt: a busy day/hour counter can exceed 32-bit\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@unique([integrationId, integrationType, metric, window])\n // Covers totals() (metric + window prefix/range, no integrationType filter).\n @@index([metric, window])\n // Covers series() (metric + integrationType + window range).\n @@index([metric, integrationType, window])\n}\n\n// ============================================================================\n// MANAGEMENT API MODELS\n// ============================================================================\n\n/// Multi-step authorization state for Management API v2 (/api/v2/authorize,\n/// /api/v2/credentials/:id/reauthorize). Short-lived: expired rows are removed\n/// opportunistically. stepData is encrypted at rest.\nmodel AuthorizationSession {\n id Int @id @default(autoincrement())\n sessionId String @unique\n userId String\n entityType String\n credentialId String?\n currentStep Int @default(1)\n maxSteps Int\n stepData Json @default(\"{}\")\n expiresAt DateTime\n completed Boolean @default(false)\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId, entityType])\n @@index([expiresAt])\n}\n",
|
|
400
|
+
"inlineSchemaHash": "b5b35907d408c3f9a975dc44f58791f27fe6c8337f28ba52e13aad72b5f2f4c0",
|
|
412
401
|
"copyEngine": true
|
|
413
402
|
}
|
|
414
403
|
config.dirname = '/'
|
|
415
404
|
|
|
416
|
-
config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"UserType\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"hashword\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"appUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMembers\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMembers\"},{\"name\":\"appOrgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tokens\",\"kind\":\"object\",\"type\":\"Token\",\"relationName\":\"TokenToUser\"},{\"name\":\"credentials\",\"kind\":\"object\",\"type\":\"Credential\",\"relationName\":\"CredentialToUser\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToUser\"},{\"name\":\"integrations\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToUser\"},{\"name\":\"processes\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessToUser\"},{\"name\":\"memberships\",\"kind\":\"object\",\"type\":\"OrganizationMembership\",\"relationName\":\"IndividualMemberships\"},{\"name\":\"orgMembers\",\"kind\":\"object\",\"type\":\"OrganizationMembership\",\"relationName\":\"OrganizationMemberships\"}],\"dbName\":null},\"Token\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"created\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TokenToUser\"}],\"dbName\":null},\"Credential\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"CredentialToUser\"},{\"name\":\"authIsValid\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"externalId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"CredentialToEntity\"}],\"dbName\":null},\"Entity\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"credentialId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"credential\",\"kind\":\"object\",\"type\":\"Credential\",\"relationName\":\"CredentialToEntity\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EntityToUser\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"moduleName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"externalId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"integrations\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"EntityToIntegration\"},{\"name\":\"syncs\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"EntityToSync\"},{\"name\":\"dataIdentifiers\",\"kind\":\"object\",\"type\":\"DataIdentifier\",\"relationName\":\"DataIdentifierToEntity\"},{\"name\":\"associationObjects\",\"kind\":\"object\",\"type\":\"AssociationObject\",\"relationName\":\"AssociationObjectToEntity\"}],\"dbName\":null},\"Integration\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"IntegrationToUser\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"IntegrationStatus\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"config\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToIntegration\"},{\"name\":\"errors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"warnings\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"info\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"logs\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"associations\",\"kind\":\"object\",\"type\":\"Association\",\"relationName\":\"AssociationToIntegration\"},{\"name\":\"syncs\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"IntegrationToSync\"},{\"name\":\"mappings\",\"kind\":\"object\",\"type\":\"IntegrationMapping\",\"relationName\":\"IntegrationToIntegrationMapping\"},{\"name\":\"processes\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"IntegrationToProcess\"}],\"dbName\":null},\"IntegrationMapping\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToIntegrationMapping\"},{\"name\":\"sourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mapping\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Sync\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToSync\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToSync\"},{\"name\":\"hash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"dataIdentifiers\",\"kind\":\"object\",\"type\":\"DataIdentifier\",\"relationName\":\"DataIdentifierToSync\"}],\"dbName\":null},\"DataIdentifier\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"syncId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"sync\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"DataIdentifierToSync\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"entity\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"DataIdentifierToEntity\"},{\"name\":\"idData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"hash\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Association\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"AssociationToIntegration\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"AssociationType\"},{\"name\":\"primaryObject\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"objects\",\"kind\":\"object\",\"type\":\"AssociationObject\",\"relationName\":\"AssociationToAssociationObject\"}],\"dbName\":null},\"AssociationObject\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"associationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"association\",\"kind\":\"object\",\"type\":\"Association\",\"relationName\":\"AssociationToAssociationObject\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"entity\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"AssociationObjectToEntity\"},{\"name\":\"objectType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"objId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":null},\"Process\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ProcessToUser\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToProcess\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"results\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"parentProcessId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentProcess\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessHierarchy\"},{\"name\":\"childProcesses\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessHierarchy\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"State\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":null},\"WebsocketConnection\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connectionId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"AdminScriptExecution\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"enum\",\"type\":\"AdminScriptExecutionState\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"results\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"parentExecutionId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentExecution\",\"kind\":\"object\",\"type\":\"AdminScriptExecution\",\"relationName\":\"AdminScriptExecutionHierarchy\"},{\"name\":\"childExecutions\",\"kind\":\"object\",\"type\":\"AdminScriptExecution\",\"relationName\":\"AdminScriptExecutionHierarchy\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ScriptSchedule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scriptName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"cronExpression\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"timezone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastTriggeredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextTriggerAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"externalScheduleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"externalScheduleName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"UsageCounter\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"integrationType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metric\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"window\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"AuthorizationSession\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entityType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentStep\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxSteps\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"stepData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"OrganizationMembership\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"individualUserId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organizationUserId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"orgRole\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"individualUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"IndividualMemberships\"},{\"name\":\"organizationUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrganizationMemberships\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
|
405
|
+
config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"UserType\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"username\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"hashword\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"appUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"organizationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"organization\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMembers\"},{\"name\":\"members\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"OrgMembers\"},{\"name\":\"appOrgId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"tokens\",\"kind\":\"object\",\"type\":\"Token\",\"relationName\":\"TokenToUser\"},{\"name\":\"credentials\",\"kind\":\"object\",\"type\":\"Credential\",\"relationName\":\"CredentialToUser\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToUser\"},{\"name\":\"integrations\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToUser\"},{\"name\":\"processes\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessToUser\"}],\"dbName\":null},\"Token\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"created\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"expires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"TokenToUser\"}],\"dbName\":null},\"Credential\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"CredentialToUser\"},{\"name\":\"authIsValid\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"externalId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"CredentialToEntity\"}],\"dbName\":null},\"Entity\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"credentialId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"credential\",\"kind\":\"object\",\"type\":\"Credential\",\"relationName\":\"CredentialToEntity\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EntityToUser\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"moduleName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"externalId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"integrations\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"EntityToIntegration\"},{\"name\":\"syncs\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"EntityToSync\"},{\"name\":\"dataIdentifiers\",\"kind\":\"object\",\"type\":\"DataIdentifier\",\"relationName\":\"DataIdentifierToEntity\"},{\"name\":\"associationObjects\",\"kind\":\"object\",\"type\":\"AssociationObject\",\"relationName\":\"AssociationObjectToEntity\"}],\"dbName\":null},\"Integration\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"IntegrationToUser\"},{\"name\":\"status\",\"kind\":\"enum\",\"type\":\"IntegrationStatus\"},{\"name\":\"config\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"version\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToIntegration\"},{\"name\":\"errors\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"warnings\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"info\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"logs\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"associations\",\"kind\":\"object\",\"type\":\"Association\",\"relationName\":\"AssociationToIntegration\"},{\"name\":\"syncs\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"IntegrationToSync\"},{\"name\":\"mappings\",\"kind\":\"object\",\"type\":\"IntegrationMapping\",\"relationName\":\"IntegrationToIntegrationMapping\"},{\"name\":\"processes\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"IntegrationToProcess\"}],\"dbName\":null},\"IntegrationMapping\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToIntegrationMapping\"},{\"name\":\"sourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"mapping\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Sync\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToSync\"},{\"name\":\"entities\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"EntityToSync\"},{\"name\":\"hash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"dataIdentifiers\",\"kind\":\"object\",\"type\":\"DataIdentifier\",\"relationName\":\"DataIdentifierToSync\"}],\"dbName\":null},\"DataIdentifier\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"syncId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"sync\",\"kind\":\"object\",\"type\":\"Sync\",\"relationName\":\"DataIdentifierToSync\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"entity\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"DataIdentifierToEntity\"},{\"name\":\"idData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"hash\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Association\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"AssociationToIntegration\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"enum\",\"type\":\"AssociationType\"},{\"name\":\"primaryObject\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"objects\",\"kind\":\"object\",\"type\":\"AssociationObject\",\"relationName\":\"AssociationToAssociationObject\"}],\"dbName\":null},\"AssociationObject\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"associationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"association\",\"kind\":\"object\",\"type\":\"Association\",\"relationName\":\"AssociationToAssociationObject\"},{\"name\":\"entityId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"entity\",\"kind\":\"object\",\"type\":\"Entity\",\"relationName\":\"AssociationObjectToEntity\"},{\"name\":\"objectType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"objId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metadata\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":null},\"Process\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ProcessToUser\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integration\",\"kind\":\"object\",\"type\":\"Integration\",\"relationName\":\"IntegrationToProcess\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"results\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"parentProcessId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentProcess\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessHierarchy\"},{\"name\":\"childProcesses\",\"kind\":\"object\",\"type\":\"Process\",\"relationName\":\"ProcessHierarchy\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"State\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"state\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":null},\"WebsocketConnection\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"connectionId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"AdminScriptExecution\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"state\",\"kind\":\"enum\",\"type\":\"AdminScriptExecutionState\"},{\"name\":\"context\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"results\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"parentExecutionId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentExecution\",\"kind\":\"object\",\"type\":\"AdminScriptExecution\",\"relationName\":\"AdminScriptExecutionHierarchy\"},{\"name\":\"childExecutions\",\"kind\":\"object\",\"type\":\"AdminScriptExecution\",\"relationName\":\"AdminScriptExecutionHierarchy\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"ScriptSchedule\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"scriptName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"enabled\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"cronExpression\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"timezone\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"lastTriggeredAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"nextTriggerAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"externalScheduleId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"externalScheduleName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"UsageCounter\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"integrationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"integrationType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"metric\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"window\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"BigInt\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"AuthorizationSession\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"entityType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"currentStep\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"maxSteps\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"stepData\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"completed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
|
417
406
|
defineDmmfProperty(exports.Prisma, config.runtimeDataModel)
|
|
418
407
|
config.engineWasm = {
|
|
419
408
|
getRuntime: async () => require('./query_engine_bg.js'),
|
|
@@ -2,7 +2,6 @@ const { findNearestBackendPackageJson } = require('@friggframework/core/utils');
|
|
|
2
2
|
const path = require('node:path');
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const { resolveTelemetryConfig } = require('../telemetry/telemetry-config');
|
|
5
|
-
const { assertAdopterJwtConfig } = require('../user/adopter-jwt-config');
|
|
6
5
|
const { registerDeniedKeys } = require('../logs/denied-keys');
|
|
7
6
|
const {
|
|
8
7
|
extractCredentialFieldsFromModules,
|
|
@@ -11,7 +10,6 @@ const {
|
|
|
11
10
|
getEntityTypeRegistry,
|
|
12
11
|
getEntityTypeDefinitions,
|
|
13
12
|
} = require('../modules/entity-type-registry');
|
|
14
|
-
const { resolveOwnershipConfig } = require('../modules/entity-scope');
|
|
15
13
|
|
|
16
14
|
// Handlers without a database never load the encryption registry, so the
|
|
17
15
|
// credential leaf keys are registered for redaction here too.
|
|
@@ -34,11 +32,9 @@ function registerCredentialLogKeys(appDefinition, moduleDefinitions) {
|
|
|
34
32
|
* @function loadAppDefinition
|
|
35
33
|
* @description Searches for the nearest backend package.json, loads the corresponding index.js file,
|
|
36
34
|
* and extracts the application definition containing integrations and user configuration.
|
|
37
|
-
* @returns {{integrations: Array<object>, entities: object | null, entityTypeRegistry: Map<string, object>, moduleDefinitions: Array<object>,
|
|
35
|
+
* @returns {{integrations: Array<object>, entities: object | null, entityTypeRegistry: Map<string, object>, moduleDefinitions: Array<object>, userConfig: object | null, adminScripts: Array<object>, reports: Array<object>, admin: object, telemetry: object, logging: object | null, managementApi: object}} An object containing the application definition.
|
|
38
36
|
* @throws {Error} Throws error if backend package.json cannot be found.
|
|
39
37
|
* @throws {Error} Throws error if index.js file cannot be found in the backend directory.
|
|
40
|
-
* @throws {Error} Throws error if user.authModes.adopterJwt is enabled without a usable user.jwtConfig.
|
|
41
|
-
* @throws {OwnershipConfigError} Throws if an ownership or scope setting is invalid (ADR-056 §3.1).
|
|
42
38
|
* @example
|
|
43
39
|
* const { integrations, userConfig, telemetry } = loadAppDefinition();
|
|
44
40
|
* console.log(`Found ${integrations.length} integrations`);
|
|
@@ -69,21 +65,12 @@ function loadAppDefinition() {
|
|
|
69
65
|
managementApi = {},
|
|
70
66
|
} = appDefinition;
|
|
71
67
|
|
|
72
|
-
// Fail at load, not on the first request: an adopter-token mode with no
|
|
73
|
-
// key source would otherwise start cleanly and answer every login with 500.
|
|
74
|
-
assertAdopterJwtConfig(userConfig);
|
|
75
|
-
|
|
76
68
|
// Fail fast: a bad `entities` registry (key/name mismatch, conflicting
|
|
77
69
|
// definitions, `$infer: false` with an unregistered module) must stop the
|
|
78
70
|
// app at load, not on the first request that needs a module.
|
|
79
71
|
const entityTypeRegistry = getEntityTypeRegistry(appDefinition);
|
|
80
72
|
const moduleDefinitions = getEntityTypeDefinitions(entityTypeRegistry);
|
|
81
73
|
|
|
82
|
-
// Same reason for entity scopes (ADR-056 §3.1): a mistyped scope, an unknown
|
|
83
|
-
// `individualAcross`, or an organization-owned integration that binds an
|
|
84
|
-
// individual entity stops the app at load.
|
|
85
|
-
const ownership = resolveOwnershipConfig(appDefinition, entityTypeRegistry);
|
|
86
|
-
|
|
87
74
|
registerCredentialLogKeys(appDefinition, moduleDefinitions);
|
|
88
75
|
|
|
89
76
|
// Degrade consistently: an invalid telemetry block must never take down a
|
|
@@ -112,7 +99,6 @@ function loadAppDefinition() {
|
|
|
112
99
|
entities,
|
|
113
100
|
entityTypeRegistry,
|
|
114
101
|
moduleDefinitions,
|
|
115
|
-
ownership,
|
|
116
102
|
userConfig,
|
|
117
103
|
adminScripts,
|
|
118
104
|
reports,
|
package/index.js
CHANGED
|
@@ -25,14 +25,6 @@ const {
|
|
|
25
25
|
UserRepositoryMongo,
|
|
26
26
|
UserRepositoryPostgres,
|
|
27
27
|
} = require('./user/repositories/user-repository-factory');
|
|
28
|
-
const {
|
|
29
|
-
createOrganizationMembershipRepository,
|
|
30
|
-
OrganizationMembershipRepositoryMongo,
|
|
31
|
-
OrganizationMembershipRepositoryPostgres,
|
|
32
|
-
} = require('./user/repositories/organization-membership-repository-factory');
|
|
33
|
-
const {
|
|
34
|
-
EnsureOrganizationMembership,
|
|
35
|
-
} = require('./user/use-cases/ensure-organization-membership');
|
|
36
28
|
const {
|
|
37
29
|
GetUserFromXFriggHeaders,
|
|
38
30
|
} = require('./user/use-cases/get-user-from-x-frigg-headers');
|
|
@@ -109,9 +101,6 @@ const {
|
|
|
109
101
|
ModuleFactory,
|
|
110
102
|
getEntityTypeRegistry,
|
|
111
103
|
EntityRegistryError,
|
|
112
|
-
resolveScope,
|
|
113
|
-
listBindingScopes,
|
|
114
|
-
OwnershipConfigError,
|
|
115
104
|
} = require('./modules/index');
|
|
116
105
|
const application = require('./application');
|
|
117
106
|
const utils = require('./utils');
|
|
@@ -143,10 +132,6 @@ module.exports = {
|
|
|
143
132
|
createUserRepository,
|
|
144
133
|
UserRepositoryMongo,
|
|
145
134
|
UserRepositoryPostgres,
|
|
146
|
-
createOrganizationMembershipRepository,
|
|
147
|
-
OrganizationMembershipRepositoryMongo,
|
|
148
|
-
OrganizationMembershipRepositoryPostgres,
|
|
149
|
-
EnsureOrganizationMembership,
|
|
150
135
|
GetUserFromXFriggHeaders,
|
|
151
136
|
GetUserFromAdopterJwt,
|
|
152
137
|
AuthenticateUser,
|
|
@@ -226,9 +211,6 @@ module.exports = {
|
|
|
226
211
|
ModuleFactory,
|
|
227
212
|
getEntityTypeRegistry,
|
|
228
213
|
EntityRegistryError,
|
|
229
|
-
resolveScope,
|
|
230
|
-
listBindingScopes,
|
|
231
|
-
OwnershipConfigError,
|
|
232
214
|
// queues
|
|
233
215
|
QueuerUtil,
|
|
234
216
|
|