libre-webui 0.21.2 → 0.22.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/README.md +308 -328
- package/backend/dist/cli/migrateSqliteToPostgres.d.ts +2 -0
- package/backend/dist/cli/migrateSqliteToPostgres.d.ts.map +1 -0
- package/backend/dist/cli/migrateSqliteToPostgres.js +113 -0
- package/backend/dist/cli/migrateSqliteToPostgres.js.map +1 -0
- package/backend/dist/cli/recoveryBackup.d.ts +3 -0
- package/backend/dist/cli/recoveryBackup.d.ts.map +1 -0
- package/backend/dist/cli/recoveryBackup.js +251 -0
- package/backend/dist/cli/recoveryBackup.js.map +1 -0
- package/backend/dist/cli/recoveryInventory.d.ts +2 -0
- package/backend/dist/cli/recoveryInventory.d.ts.map +1 -0
- package/backend/dist/cli/recoveryInventory.js +109 -0
- package/backend/dist/cli/recoveryInventory.js.map +1 -0
- package/backend/dist/db.d.ts +27 -0
- package/backend/dist/db.d.ts.map +1 -1
- package/backend/dist/db.js +333 -16
- package/backend/dist/db.js.map +1 -1
- package/backend/dist/env.d.ts.map +1 -1
- package/backend/dist/env.js +12 -2
- package/backend/dist/env.js.map +1 -1
- package/backend/dist/index.d.ts.map +1 -1
- package/backend/dist/index.js +235 -47
- package/backend/dist/index.js.map +1 -1
- package/backend/dist/main.d.ts +2 -0
- package/backend/dist/main.d.ts.map +1 -0
- package/backend/dist/main.js +137 -0
- package/backend/dist/main.js.map +1 -0
- package/backend/dist/middleware/auth.d.ts.map +1 -1
- package/backend/dist/middleware/auth.js +7 -3
- package/backend/dist/middleware/auth.js.map +1 -1
- package/backend/dist/middleware/chatCancellationAdmission.d.ts +7 -0
- package/backend/dist/middleware/chatCancellationAdmission.d.ts.map +1 -0
- package/backend/dist/middleware/chatCancellationAdmission.js +17 -0
- package/backend/dist/middleware/chatCancellationAdmission.js.map +1 -0
- package/backend/dist/middleware/coordinatedRateLimit.d.ts +18 -0
- package/backend/dist/middleware/coordinatedRateLimit.d.ts.map +1 -0
- package/backend/dist/middleware/coordinatedRateLimit.js +52 -0
- package/backend/dist/middleware/coordinatedRateLimit.js.map +1 -0
- package/backend/dist/middleware/sharedRateLimit.d.ts +26 -0
- package/backend/dist/middleware/sharedRateLimit.d.ts.map +1 -0
- package/backend/dist/middleware/sharedRateLimit.js +99 -0
- package/backend/dist/middleware/sharedRateLimit.js.map +1 -0
- package/backend/dist/models/personaModel.d.ts +1 -26
- package/backend/dist/models/personaModel.d.ts.map +1 -1
- package/backend/dist/models/personaModel.js +54 -247
- package/backend/dist/models/personaModel.js.map +1 -1
- package/backend/dist/models/userModel.d.ts +23 -66
- package/backend/dist/models/userModel.d.ts.map +1 -1
- package/backend/dist/models/userModel.js +110 -187
- package/backend/dist/models/userModel.js.map +1 -1
- package/backend/dist/persistence/chatGenerationTypes.d.ts +24 -0
- package/backend/dist/persistence/chatGenerationTypes.d.ts.map +1 -0
- package/backend/dist/persistence/chatGenerationTypes.js +7 -0
- package/backend/dist/persistence/chatGenerationTypes.js.map +1 -0
- package/backend/dist/persistence/extensionTypes.d.ts +185 -0
- package/backend/dist/persistence/extensionTypes.d.ts.map +1 -0
- package/backend/dist/persistence/extensionTypes.js +13 -0
- package/backend/dist/persistence/extensionTypes.js.map +1 -0
- package/backend/dist/persistence/identityDeletionTypes.d.ts +16 -0
- package/backend/dist/persistence/identityDeletionTypes.d.ts.map +1 -0
- package/backend/dist/persistence/identityDeletionTypes.js +7 -0
- package/backend/dist/persistence/identityDeletionTypes.js.map +1 -0
- package/backend/dist/persistence/index.d.ts +48 -0
- package/backend/dist/persistence/index.d.ts.map +1 -0
- package/backend/dist/persistence/index.js +159 -0
- package/backend/dist/persistence/index.js.map +1 -0
- package/backend/dist/persistence/postgresConfig.d.ts +32 -0
- package/backend/dist/persistence/postgresConfig.d.ts.map +1 -0
- package/backend/dist/persistence/postgresConfig.js +91 -0
- package/backend/dist/persistence/postgresConfig.js.map +1 -0
- package/backend/dist/persistence/postgresCoreMigration.d.ts +8 -0
- package/backend/dist/persistence/postgresCoreMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresCoreMigration.js +179 -0
- package/backend/dist/persistence/postgresCoreMigration.js.map +1 -0
- package/backend/dist/persistence/postgresDatabase.d.ts +40 -0
- package/backend/dist/persistence/postgresDatabase.d.ts.map +1 -0
- package/backend/dist/persistence/postgresDatabase.js +148 -0
- package/backend/dist/persistence/postgresDatabase.js.map +1 -0
- package/backend/dist/persistence/postgresExtensionMigration.d.ts +4 -0
- package/backend/dist/persistence/postgresExtensionMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresExtensionMigration.js +143 -0
- package/backend/dist/persistence/postgresExtensionMigration.js.map +1 -0
- package/backend/dist/persistence/postgresExtensionRepositories.d.ts +6 -0
- package/backend/dist/persistence/postgresExtensionRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/postgresExtensionRepositories.js +550 -0
- package/backend/dist/persistence/postgresExtensionRepositories.js.map +1 -0
- package/backend/dist/persistence/postgresImportState.d.ts +9 -0
- package/backend/dist/persistence/postgresImportState.d.ts.map +1 -0
- package/backend/dist/persistence/postgresImportState.js +64 -0
- package/backend/dist/persistence/postgresImportState.js.map +1 -0
- package/backend/dist/persistence/postgresMigrationRegistry.d.ts +4 -0
- package/backend/dist/persistence/postgresMigrationRegistry.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrationRegistry.js +33 -0
- package/backend/dist/persistence/postgresMigrationRegistry.js.map +1 -0
- package/backend/dist/persistence/postgresMigrationTypes.d.ts +24 -0
- package/backend/dist/persistence/postgresMigrationTypes.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrationTypes.js +7 -0
- package/backend/dist/persistence/postgresMigrationTypes.js.map +1 -0
- package/backend/dist/persistence/postgresMigrations.d.ts +15 -0
- package/backend/dist/persistence/postgresMigrations.d.ts.map +1 -0
- package/backend/dist/persistence/postgresMigrations.js +333 -0
- package/backend/dist/persistence/postgresMigrations.js.map +1 -0
- package/backend/dist/persistence/postgresPersistence.d.ts +17 -0
- package/backend/dist/persistence/postgresPersistence.d.ts.map +1 -0
- package/backend/dist/persistence/postgresPersistence.js +332 -0
- package/backend/dist/persistence/postgresPersistence.js.map +1 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.d.ts +4 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.d.ts.map +1 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.js +40 -0
- package/backend/dist/persistence/postgresPluginDefinitionMigration.js.map +1 -0
- package/backend/dist/persistence/postgresResourceRepositories.d.ts +7 -0
- package/backend/dist/persistence/postgresResourceRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/postgresResourceRepositories.js +776 -0
- package/backend/dist/persistence/postgresResourceRepositories.js.map +1 -0
- package/backend/dist/persistence/postgresSchemaInspector.d.ts +14 -0
- package/backend/dist/persistence/postgresSchemaInspector.d.ts.map +1 -0
- package/backend/dist/persistence/postgresSchemaInspector.js +817 -0
- package/backend/dist/persistence/postgresSchemaInspector.js.map +1 -0
- package/backend/dist/persistence/resourceTypes.d.ts +207 -0
- package/backend/dist/persistence/resourceTypes.d.ts.map +1 -0
- package/backend/dist/persistence/resourceTypes.js +38 -0
- package/backend/dist/persistence/resourceTypes.js.map +1 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.d.ts +4 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.js +494 -0
- package/backend/dist/persistence/sqliteExtensionRepositories.js.map +1 -0
- package/backend/dist/persistence/sqliteMigrations.d.ts +93 -0
- package/backend/dist/persistence/sqliteMigrations.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteMigrations.js +2232 -0
- package/backend/dist/persistence/sqliteMigrations.js.map +1 -0
- package/backend/dist/persistence/sqlitePersistence.d.ts +23 -0
- package/backend/dist/persistence/sqlitePersistence.d.ts.map +1 -0
- package/backend/dist/persistence/sqlitePersistence.js +596 -0
- package/backend/dist/persistence/sqlitePersistence.js.map +1 -0
- package/backend/dist/persistence/sqliteResourceRepositories.d.ts +4 -0
- package/backend/dist/persistence/sqliteResourceRepositories.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteResourceRepositories.js +663 -0
- package/backend/dist/persistence/sqliteResourceRepositories.js.map +1 -0
- package/backend/dist/persistence/sqliteSyncExecutor.d.ts +5 -0
- package/backend/dist/persistence/sqliteSyncExecutor.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteSyncExecutor.js +19 -0
- package/backend/dist/persistence/sqliteSyncExecutor.js.map +1 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.d.ts +80 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.d.ts.map +1 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.js +1543 -0
- package/backend/dist/persistence/sqliteToPostgresMigration.js.map +1 -0
- package/backend/dist/persistence/types.d.ts +131 -0
- package/backend/dist/persistence/types.d.ts.map +1 -0
- package/backend/dist/persistence/types.js +18 -0
- package/backend/dist/persistence/types.js.map +1 -0
- package/backend/dist/persistence/voiceProfileNameLookup.d.ts +9 -0
- package/backend/dist/persistence/voiceProfileNameLookup.d.ts.map +1 -0
- package/backend/dist/persistence/voiceProfileNameLookup.js +15 -0
- package/backend/dist/persistence/voiceProfileNameLookup.js.map +1 -0
- package/backend/dist/platform/coordination/index.d.ts +7 -0
- package/backend/dist/platform/coordination/index.d.ts.map +1 -0
- package/backend/dist/platform/coordination/index.js +24 -0
- package/backend/dist/platform/coordination/index.js.map +1 -0
- package/backend/dist/platform/coordination/localCoordinator.d.ts +49 -0
- package/backend/dist/platform/coordination/localCoordinator.d.ts.map +1 -0
- package/backend/dist/platform/coordination/localCoordinator.js +380 -0
- package/backend/dist/platform/coordination/localCoordinator.js.map +1 -0
- package/backend/dist/platform/coordination/redisCoordinator.d.ts +83 -0
- package/backend/dist/platform/coordination/redisCoordinator.d.ts.map +1 -0
- package/backend/dist/platform/coordination/redisCoordinator.js +726 -0
- package/backend/dist/platform/coordination/redisCoordinator.js.map +1 -0
- package/backend/dist/platform/coordination/service.d.ts +11 -0
- package/backend/dist/platform/coordination/service.d.ts.map +1 -0
- package/backend/dist/platform/coordination/service.js +55 -0
- package/backend/dist/platform/coordination/service.js.map +1 -0
- package/backend/dist/platform/coordination/sharedAdmission.d.ts +53 -0
- package/backend/dist/platform/coordination/sharedAdmission.d.ts.map +1 -0
- package/backend/dist/platform/coordination/sharedAdmission.js +194 -0
- package/backend/dist/platform/coordination/sharedAdmission.js.map +1 -0
- package/backend/dist/platform/coordination/types.d.ts +76 -0
- package/backend/dist/platform/coordination/types.d.ts.map +1 -0
- package/backend/dist/platform/coordination/types.js +32 -0
- package/backend/dist/platform/coordination/types.js.map +1 -0
- package/backend/dist/platform/events/durableEventGateway.d.ts +54 -0
- package/backend/dist/platform/events/durableEventGateway.d.ts.map +1 -0
- package/backend/dist/platform/events/durableEventGateway.js +262 -0
- package/backend/dist/platform/events/durableEventGateway.js.map +1 -0
- package/backend/dist/platform/events/index.d.ts +3 -0
- package/backend/dist/platform/events/index.d.ts.map +1 -0
- package/backend/dist/platform/events/index.js +8 -0
- package/backend/dist/platform/events/index.js.map +1 -0
- package/backend/dist/platform/events/service.d.ts +8 -0
- package/backend/dist/platform/events/service.d.ts.map +1 -0
- package/backend/dist/platform/events/service.js +25 -0
- package/backend/dist/platform/events/service.js.map +1 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.js +55 -0
- package/backend/dist/platform/jobs/chatGenerationEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.js +38 -0
- package/backend/dist/platform/jobs/documentIngestionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/domainJobContracts.d.ts +30 -0
- package/backend/dist/platform/jobs/domainJobContracts.d.ts.map +1 -0
- package/backend/dist/platform/jobs/domainJobContracts.js +53 -0
- package/backend/dist/platform/jobs/domainJobContracts.js.map +1 -0
- package/backend/dist/platform/jobs/domainJobHandlers.d.ts +11 -0
- package/backend/dist/platform/jobs/domainJobHandlers.d.ts.map +1 -0
- package/backend/dist/platform/jobs/domainJobHandlers.js +612 -0
- package/backend/dist/platform/jobs/domainJobHandlers.js.map +1 -0
- package/backend/dist/platform/jobs/durableEventIdentity.d.ts +8 -0
- package/backend/dist/platform/jobs/durableEventIdentity.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableEventIdentity.js +33 -0
- package/backend/dist/platform/jobs/durableEventIdentity.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntime.d.ts +57 -0
- package/backend/dist/platform/jobs/durableJobRuntime.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntime.js +131 -0
- package/backend/dist/platform/jobs/durableJobRuntime.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.d.ts +28 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.js +62 -0
- package/backend/dist/platform/jobs/durableJobRuntimeBackend.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobService.d.ts +85 -0
- package/backend/dist/platform/jobs/durableJobService.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobService.js +726 -0
- package/backend/dist/platform/jobs/durableJobService.js.map +1 -0
- package/backend/dist/platform/jobs/durableJobTypes.d.ts +195 -0
- package/backend/dist/platform/jobs/durableJobTypes.d.ts.map +1 -0
- package/backend/dist/platform/jobs/durableJobTypes.js +72 -0
- package/backend/dist/platform/jobs/durableJobTypes.js.map +1 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.d.ts +87 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.d.ts.map +1 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js +429 -0
- package/backend/dist/platform/jobs/embeddedDurableJobWorker.js.map +1 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.js +36 -0
- package/backend/dist/platform/jobs/identityDeletionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/index.d.ts +18 -0
- package/backend/dist/platform/jobs/index.d.ts.map +1 -0
- package/backend/dist/platform/jobs/index.js +34 -0
- package/backend/dist/platform/jobs/index.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.d.ts +4 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.js +25 -0
- package/backend/dist/platform/jobs/postgresDurableEventIdempotencyMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.d.ts +4 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.js +23 -0
- package/backend/dist/platform/jobs/postgresDurableEventReplayIndexMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.d.ts +11 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.js +106 -0
- package/backend/dist/platform/jobs/postgresDurableJobMigration.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.d.ts +88 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.js +1185 -0
- package/backend/dist/platform/jobs/postgresDurableJobRepository.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.d.ts +86 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.js +696 -0
- package/backend/dist/platform/jobs/postgresDurableJobService.js.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.d.ts +53 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.d.ts.map +1 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js +393 -0
- package/backend/dist/platform/jobs/postgresDurableJobWorker.js.map +1 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.js +43 -0
- package/backend/dist/platform/jobs/resourceDeletionEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.d.ts +166 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.d.ts.map +1 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.js +1008 -0
- package/backend/dist/platform/jobs/sqliteDurableJobRepository.js.map +1 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.d.ts +4 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.js +46 -0
- package/backend/dist/platform/jobs/videoGenerationEnqueuer.js.map +1 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.d.ts +3 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.d.ts.map +1 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.js +38 -0
- package/backend/dist/platform/jobs/workExecutionEnqueuer.js.map +1 -0
- package/backend/dist/platform/ollamaRuntimeConfig.d.ts +40 -0
- package/backend/dist/platform/ollamaRuntimeConfig.d.ts.map +1 -0
- package/backend/dist/platform/ollamaRuntimeConfig.js +72 -0
- package/backend/dist/platform/ollamaRuntimeConfig.js.map +1 -0
- package/backend/dist/platform/recovery/backupArchive.d.ts +120 -0
- package/backend/dist/platform/recovery/backupArchive.d.ts.map +1 -0
- package/backend/dist/platform/recovery/backupArchive.js +842 -0
- package/backend/dist/platform/recovery/backupArchive.js.map +1 -0
- package/backend/dist/platform/recovery/index.d.ts +3 -0
- package/backend/dist/platform/recovery/index.d.ts.map +1 -0
- package/backend/dist/platform/recovery/index.js +8 -0
- package/backend/dist/platform/recovery/index.js.map +1 -0
- package/backend/dist/platform/recovery/teamBackupArchive.d.ts +98 -0
- package/backend/dist/platform/recovery/teamBackupArchive.d.ts.map +1 -0
- package/backend/dist/platform/recovery/teamBackupArchive.js +1203 -0
- package/backend/dist/platform/recovery/teamBackupArchive.js.map +1 -0
- package/backend/dist/platform/runtimeConfig.d.ts +70 -0
- package/backend/dist/platform/runtimeConfig.d.ts.map +1 -0
- package/backend/dist/platform/runtimeConfig.js +205 -0
- package/backend/dist/platform/runtimeConfig.js.map +1 -0
- package/backend/dist/platform/storage/aesGcmKeyring.d.ts +26 -0
- package/backend/dist/platform/storage/aesGcmKeyring.d.ts.map +1 -0
- package/backend/dist/platform/storage/aesGcmKeyring.js +135 -0
- package/backend/dist/platform/storage/aesGcmKeyring.js.map +1 -0
- package/backend/dist/platform/storage/blobReferenceRepository.d.ts +36 -0
- package/backend/dist/platform/storage/blobReferenceRepository.d.ts.map +1 -0
- package/backend/dist/platform/storage/blobReferenceRepository.js +117 -0
- package/backend/dist/platform/storage/blobReferenceRepository.js.map +1 -0
- package/backend/dist/platform/storage/blobStore.d.ts +111 -0
- package/backend/dist/platform/storage/blobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/blobStore.js +46 -0
- package/backend/dist/platform/storage/blobStore.js.map +1 -0
- package/backend/dist/platform/storage/documentVectorIndex.d.ts +44 -0
- package/backend/dist/platform/storage/documentVectorIndex.d.ts.map +1 -0
- package/backend/dist/platform/storage/documentVectorIndex.js +110 -0
- package/backend/dist/platform/storage/documentVectorIndex.js.map +1 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.d.ts +82 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.d.ts.map +1 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.js +583 -0
- package/backend/dist/platform/storage/durableBlobQuotaPolicy.js.map +1 -0
- package/backend/dist/platform/storage/index.d.ts +19 -0
- package/backend/dist/platform/storage/index.d.ts.map +1 -0
- package/backend/dist/platform/storage/index.js +35 -0
- package/backend/dist/platform/storage/index.js.map +1 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.d.ts +120 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.js +1205 -0
- package/backend/dist/platform/storage/localEncryptedBlobStore.js.map +1 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.d.ts +12 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.d.ts.map +1 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.js +25 -0
- package/backend/dist/platform/storage/personaMemoryIndexing.js.map +1 -0
- package/backend/dist/platform/storage/pgVectorStore.d.ts +37 -0
- package/backend/dist/platform/storage/pgVectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/pgVectorStore.js +493 -0
- package/backend/dist/platform/storage/pgVectorStore.js.map +1 -0
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts +244 -0
- package/backend/dist/platform/storage/platformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/platformDomainRepositories.js +7 -0
- package/backend/dist/platform/storage/platformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/platformStorageRuntime.d.ts +35 -0
- package/backend/dist/platform/storage/platformStorageRuntime.d.ts.map +1 -0
- package/backend/dist/platform/storage/platformStorageRuntime.js +299 -0
- package/backend/dist/platform/storage/platformStorageRuntime.js.map +1 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.d.ts +4 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js +1017 -0
- package/backend/dist/platform/storage/postgresPlatformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.d.ts +4 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.d.ts.map +1 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.js +40 -0
- package/backend/dist/platform/storage/postgresResourceDeletionLifecycleMigration.js.map +1 -0
- package/backend/dist/platform/storage/resourceContentCleanup.d.ts +29 -0
- package/backend/dist/platform/storage/resourceContentCleanup.d.ts.map +1 -0
- package/backend/dist/platform/storage/resourceContentCleanup.js +100 -0
- package/backend/dist/platform/storage/resourceContentCleanup.js.map +1 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.d.ts +14 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.d.ts.map +1 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.js +31 -0
- package/backend/dist/platform/storage/resourceDeletionLifecycle.js.map +1 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.d.ts +140 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.js +1309 -0
- package/backend/dist/platform/storage/s3EncryptedBlobStore.js.map +1 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts +71 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js +766 -0
- package/backend/dist/platform/storage/sqliteEncryptedVectorStore.js.map +1 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.d.ts +4 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js +1037 -0
- package/backend/dist/platform/storage/sqlitePlatformDomainRepositories.js.map +1 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.d.ts +25 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.d.ts.map +1 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.js +1292 -0
- package/backend/dist/platform/storage/sqliteToTeamStorageMigration.js.map +1 -0
- package/backend/dist/platform/storage/storageFactory.d.ts +81 -0
- package/backend/dist/platform/storage/storageFactory.d.ts.map +1 -0
- package/backend/dist/platform/storage/storageFactory.js +518 -0
- package/backend/dist/platform/storage/storageFactory.js.map +1 -0
- package/backend/dist/platform/storage/storageSchemaContracts.d.ts +22 -0
- package/backend/dist/platform/storage/storageSchemaContracts.d.ts.map +1 -0
- package/backend/dist/platform/storage/storageSchemaContracts.js +299 -0
- package/backend/dist/platform/storage/storageSchemaContracts.js.map +1 -0
- package/backend/dist/platform/storage/vectorStore.d.ts +117 -0
- package/backend/dist/platform/storage/vectorStore.d.ts.map +1 -0
- package/backend/dist/platform/storage/vectorStore.js +40 -0
- package/backend/dist/platform/storage/vectorStore.js.map +1 -0
- package/backend/dist/platform/workPersistence/index.d.ts +9 -0
- package/backend/dist/platform/workPersistence/index.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/index.js +14 -0
- package/backend/dist/platform/workPersistence/index.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.d.ts +9 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.js +47 -0
- package/backend/dist/platform/workPersistence/postgresWorkLifecycleMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.d.ts +3 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.js +28 -0
- package/backend/dist/platform/workPersistence/postgresWorkMessageContentMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.d.ts +3 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.js +101 -0
- package/backend/dist/platform/workPersistence/postgresWorkMigration.js.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.d.ts +79 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.js +521 -0
- package/backend/dist/platform/workPersistence/postgresWorkPersistence.js.map +1 -0
- package/backend/dist/platform/workPersistence/service.d.ts +6 -0
- package/backend/dist/platform/workPersistence/service.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/service.js +27 -0
- package/backend/dist/platform/workPersistence/service.js.map +1 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.d.ts +77 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.js +463 -0
- package/backend/dist/platform/workPersistence/sqliteWorkPersistence.js.map +1 -0
- package/backend/dist/platform/workPersistence/types.d.ts +159 -0
- package/backend/dist/platform/workPersistence/types.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/types.js +13 -0
- package/backend/dist/platform/workPersistence/types.js.map +1 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.d.ts +13 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.js +7 -0
- package/backend/dist/platform/workPersistence/workExecutionTypes.js.map +1 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.d.ts +8 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.js +25 -0
- package/backend/dist/platform/workPersistence/workMessageContentCodec.js.map +1 -0
- package/backend/dist/platform/workPersistence/workTextSafety.d.ts +3 -0
- package/backend/dist/platform/workPersistence/workTextSafety.d.ts.map +1 -0
- package/backend/dist/platform/workPersistence/workTextSafety.js +8 -0
- package/backend/dist/platform/workPersistence/workTextSafety.js.map +1 -0
- package/backend/dist/routes/agentCli.js +1 -1
- package/backend/dist/routes/agentCli.js.map +1 -1
- package/backend/dist/routes/artifacts.d.ts.map +1 -1
- package/backend/dist/routes/artifacts.js +2 -1
- package/backend/dist/routes/artifacts.js.map +1 -1
- package/backend/dist/routes/auth.d.ts.map +1 -1
- package/backend/dist/routes/auth.js +64 -18
- package/backend/dist/routes/auth.js.map +1 -1
- package/backend/dist/routes/chat.d.ts.map +1 -1
- package/backend/dist/routes/chat.js +519 -85
- package/backend/dist/routes/chat.js.map +1 -1
- package/backend/dist/routes/documents.d.ts.map +1 -1
- package/backend/dist/routes/documents.js +136 -28
- package/backend/dist/routes/documents.js.map +1 -1
- package/backend/dist/routes/embeddings.d.ts.map +1 -1
- package/backend/dist/routes/embeddings.js +2 -1
- package/backend/dist/routes/embeddings.js.map +1 -1
- package/backend/dist/routes/health.d.ts +3 -0
- package/backend/dist/routes/health.d.ts.map +1 -0
- package/backend/dist/routes/health.js +52 -0
- package/backend/dist/routes/health.js.map +1 -0
- package/backend/dist/routes/huggingfaceHub.d.ts.map +1 -1
- package/backend/dist/routes/huggingfaceHub.js +2 -1
- package/backend/dist/routes/huggingfaceHub.js.map +1 -1
- package/backend/dist/routes/imageGen.d.ts.map +1 -1
- package/backend/dist/routes/imageGen.js +42 -10
- package/backend/dist/routes/imageGen.js.map +1 -1
- package/backend/dist/routes/jobs.d.ts +3 -0
- package/backend/dist/routes/jobs.d.ts.map +1 -0
- package/backend/dist/routes/jobs.js +117 -0
- package/backend/dist/routes/jobs.js.map +1 -0
- package/backend/dist/routes/libreClaw.d.ts.map +1 -1
- package/backend/dist/routes/libreClaw.js +10 -7
- package/backend/dist/routes/libreClaw.js.map +1 -1
- package/backend/dist/routes/media.d.ts.map +1 -1
- package/backend/dist/routes/media.js +523 -77
- package/backend/dist/routes/media.js.map +1 -1
- package/backend/dist/routes/notes.d.ts.map +1 -1
- package/backend/dist/routes/notes.js +21 -21
- package/backend/dist/routes/notes.js.map +1 -1
- package/backend/dist/routes/ollama.d.ts.map +1 -1
- package/backend/dist/routes/ollama.js +40 -12
- package/backend/dist/routes/ollama.js.map +1 -1
- package/backend/dist/routes/personas.d.ts.map +1 -1
- package/backend/dist/routes/personas.js +4 -2
- package/backend/dist/routes/personas.js.map +1 -1
- package/backend/dist/routes/plugins.d.ts.map +1 -1
- package/backend/dist/routes/plugins.js +79 -51
- package/backend/dist/routes/plugins.js.map +1 -1
- package/backend/dist/routes/preferences.d.ts.map +1 -1
- package/backend/dist/routes/preferences.js +290 -25
- package/backend/dist/routes/preferences.js.map +1 -1
- package/backend/dist/routes/search.d.ts.map +1 -1
- package/backend/dist/routes/search.js +23 -14
- package/backend/dist/routes/search.js.map +1 -1
- package/backend/dist/routes/stt.d.ts +9 -0
- package/backend/dist/routes/stt.d.ts.map +1 -0
- package/backend/dist/routes/stt.js +217 -0
- package/backend/dist/routes/stt.js.map +1 -0
- package/backend/dist/routes/systemDiagnostics.d.ts.map +1 -1
- package/backend/dist/routes/systemDiagnostics.js +2 -1
- package/backend/dist/routes/systemDiagnostics.js.map +1 -1
- package/backend/dist/routes/tts.d.ts.map +1 -1
- package/backend/dist/routes/tts.js +577 -28
- package/backend/dist/routes/tts.js.map +1 -1
- package/backend/dist/routes/users.d.ts.map +1 -1
- package/backend/dist/routes/users.js +16 -25
- package/backend/dist/routes/users.js.map +1 -1
- package/backend/dist/routes/work.d.ts.map +1 -1
- package/backend/dist/routes/work.js +167 -113
- package/backend/dist/routes/work.js.map +1 -1
- package/backend/dist/services/agentAccessService.d.ts +2 -2
- package/backend/dist/services/agentAccessService.d.ts.map +1 -1
- package/backend/dist/services/agentAccessService.js +5 -14
- package/backend/dist/services/agentAccessService.js.map +1 -1
- package/backend/dist/services/agentCliService.d.ts +3 -2
- package/backend/dist/services/agentCliService.d.ts.map +1 -1
- package/backend/dist/services/agentCliService.js +44 -16
- package/backend/dist/services/agentCliService.js.map +1 -1
- package/backend/dist/services/assistantCompletionService.d.ts +2 -1
- package/backend/dist/services/assistantCompletionService.d.ts.map +1 -1
- package/backend/dist/services/assistantCompletionService.js +7 -3
- package/backend/dist/services/assistantCompletionService.js.map +1 -1
- package/backend/dist/services/authService.d.ts +7 -2
- package/backend/dist/services/authService.d.ts.map +1 -1
- package/backend/dist/services/authService.js +23 -10
- package/backend/dist/services/authService.js.map +1 -1
- package/backend/dist/services/chatGenerationService.d.ts +5 -4
- package/backend/dist/services/chatGenerationService.d.ts.map +1 -1
- package/backend/dist/services/chatGenerationService.js +23 -17
- package/backend/dist/services/chatGenerationService.js.map +1 -1
- package/backend/dist/services/chatRequestService.d.ts +4 -3
- package/backend/dist/services/chatRequestService.d.ts.map +1 -1
- package/backend/dist/services/chatRequestService.js +3 -3
- package/backend/dist/services/chatRequestService.js.map +1 -1
- package/backend/dist/services/chatService.d.ts +66 -16
- package/backend/dist/services/chatService.d.ts.map +1 -1
- package/backend/dist/services/chatService.js +402 -111
- package/backend/dist/services/chatService.js.map +1 -1
- package/backend/dist/services/codexOAuthService.d.ts +2 -2
- package/backend/dist/services/codexOAuthService.d.ts.map +1 -1
- package/backend/dist/services/codexOAuthService.js +63 -7
- package/backend/dist/services/codexOAuthService.js.map +1 -1
- package/backend/dist/services/dataArchiveService.d.ts +88 -0
- package/backend/dist/services/dataArchiveService.d.ts.map +1 -0
- package/backend/dist/services/dataArchiveService.js +1027 -0
- package/backend/dist/services/dataArchiveService.js.map +1 -0
- package/backend/dist/services/documentService.d.ts +67 -14
- package/backend/dist/services/documentService.d.ts.map +1 -1
- package/backend/dist/services/documentService.js +938 -193
- package/backend/dist/services/documentService.js.map +1 -1
- package/backend/dist/services/durableChatCompletion.d.ts +16 -0
- package/backend/dist/services/durableChatCompletion.d.ts.map +1 -0
- package/backend/dist/services/durableChatCompletion.js +34 -0
- package/backend/dist/services/durableChatCompletion.js.map +1 -0
- package/backend/dist/services/durableChatGenerationService.d.ts +19 -0
- package/backend/dist/services/durableChatGenerationService.d.ts.map +1 -0
- package/backend/dist/services/durableChatGenerationService.js +341 -0
- package/backend/dist/services/durableChatGenerationService.js.map +1 -0
- package/backend/dist/services/embeddingService.d.ts +1 -1
- package/backend/dist/services/embeddingService.d.ts.map +1 -1
- package/backend/dist/services/embeddingService.js +16 -13
- package/backend/dist/services/embeddingService.js.map +1 -1
- package/backend/dist/services/encryptionService.d.ts +28 -1
- package/backend/dist/services/encryptionService.d.ts.map +1 -1
- package/backend/dist/services/encryptionService.js +131 -51
- package/backend/dist/services/encryptionService.js.map +1 -1
- package/backend/dist/services/followUpService.d.ts +1 -1
- package/backend/dist/services/followUpService.d.ts.map +1 -1
- package/backend/dist/services/followUpService.js +1 -1
- package/backend/dist/services/followUpService.js.map +1 -1
- package/backend/dist/services/galleryService.d.ts +38 -37
- package/backend/dist/services/galleryService.d.ts.map +1 -1
- package/backend/dist/services/galleryService.js +356 -251
- package/backend/dist/services/galleryService.js.map +1 -1
- package/backend/dist/services/healthService.d.ts +65 -0
- package/backend/dist/services/healthService.d.ts.map +1 -0
- package/backend/dist/services/healthService.js +379 -0
- package/backend/dist/services/healthService.js.map +1 -0
- package/backend/dist/services/legacyCiphertextIntegrity.d.ts +40 -0
- package/backend/dist/services/legacyCiphertextIntegrity.d.ts.map +1 -0
- package/backend/dist/services/legacyCiphertextIntegrity.js +406 -0
- package/backend/dist/services/legacyCiphertextIntegrity.js.map +1 -0
- package/backend/dist/services/mediaGenerationJobService.d.ts +27 -5
- package/backend/dist/services/mediaGenerationJobService.d.ts.map +1 -1
- package/backend/dist/services/mediaGenerationJobService.js +185 -55
- package/backend/dist/services/mediaGenerationJobService.js.map +1 -1
- package/backend/dist/services/memoryService.d.ts +7 -83
- package/backend/dist/services/memoryService.d.ts.map +1 -1
- package/backend/dist/services/memoryService.js +428 -573
- package/backend/dist/services/memoryService.js.map +1 -1
- package/backend/dist/services/memoryUtils.d.ts.map +1 -1
- package/backend/dist/services/memoryUtils.js +8 -1
- package/backend/dist/services/memoryUtils.js.map +1 -1
- package/backend/dist/services/modelAccessService.d.ts +3 -3
- package/backend/dist/services/modelAccessService.d.ts.map +1 -1
- package/backend/dist/services/modelAccessService.js +8 -16
- package/backend/dist/services/modelAccessService.js.map +1 -1
- package/backend/dist/services/mutationEngineService.d.ts +0 -7
- package/backend/dist/services/mutationEngineService.d.ts.map +1 -1
- package/backend/dist/services/mutationEngineService.js +7 -78
- package/backend/dist/services/mutationEngineService.js.map +1 -1
- package/backend/dist/services/ollamaService.d.ts +4 -4
- package/backend/dist/services/ollamaService.d.ts.map +1 -1
- package/backend/dist/services/ollamaService.js +97 -34
- package/backend/dist/services/ollamaService.js.map +1 -1
- package/backend/dist/services/personaService.d.ts.map +1 -1
- package/backend/dist/services/personaService.js +19 -54
- package/backend/dist/services/personaService.js.map +1 -1
- package/backend/dist/services/pluginActivationService.d.ts +6 -5
- package/backend/dist/services/pluginActivationService.d.ts.map +1 -1
- package/backend/dist/services/pluginActivationService.js +36 -76
- package/backend/dist/services/pluginActivationService.js.map +1 -1
- package/backend/dist/services/pluginAudioGenerationService.d.ts +11 -6
- package/backend/dist/services/pluginAudioGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginAudioGenerationService.js +74 -16
- package/backend/dist/services/pluginAudioGenerationService.js.map +1 -1
- package/backend/dist/services/pluginCacheInvalidation.d.ts +38 -0
- package/backend/dist/services/pluginCacheInvalidation.d.ts.map +1 -0
- package/backend/dist/services/pluginCacheInvalidation.js +198 -0
- package/backend/dist/services/pluginCacheInvalidation.js.map +1 -0
- package/backend/dist/services/pluginCapabilityRegistryService.d.ts +3 -3
- package/backend/dist/services/pluginCapabilityRegistryService.d.ts.map +1 -1
- package/backend/dist/services/pluginCapabilityRegistryService.js +11 -7
- package/backend/dist/services/pluginCapabilityRegistryService.js.map +1 -1
- package/backend/dist/services/pluginCredentialsService.d.ts +9 -8
- package/backend/dist/services/pluginCredentialsService.d.ts.map +1 -1
- package/backend/dist/services/pluginCredentialsService.js +48 -89
- package/backend/dist/services/pluginCredentialsService.js.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.d.ts +8 -7
- package/backend/dist/services/pluginEmbeddingService.d.ts.map +1 -1
- package/backend/dist/services/pluginEmbeddingService.js +13 -11
- package/backend/dist/services/pluginEmbeddingService.js.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.d.ts +10 -8
- package/backend/dist/services/pluginImageGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginImageGenerationService.js +119 -14
- package/backend/dist/services/pluginImageGenerationService.js.map +1 -1
- package/backend/dist/services/pluginSTTService.d.ts +47 -0
- package/backend/dist/services/pluginSTTService.d.ts.map +1 -0
- package/backend/dist/services/pluginSTTService.js +199 -0
- package/backend/dist/services/pluginSTTService.js.map +1 -0
- package/backend/dist/services/pluginService.d.ts +94 -40
- package/backend/dist/services/pluginService.d.ts.map +1 -1
- package/backend/dist/services/pluginService.js +799 -274
- package/backend/dist/services/pluginService.js.map +1 -1
- package/backend/dist/services/pluginTTSService.d.ts +26 -8
- package/backend/dist/services/pluginTTSService.d.ts.map +1 -1
- package/backend/dist/services/pluginTTSService.js +277 -25
- package/backend/dist/services/pluginTTSService.js.map +1 -1
- package/backend/dist/services/pluginUsageService.d.ts +4 -4
- package/backend/dist/services/pluginUsageService.d.ts.map +1 -1
- package/backend/dist/services/pluginUsageService.js +44 -93
- package/backend/dist/services/pluginUsageService.js.map +1 -1
- package/backend/dist/services/pluginVariablesService.d.ts +14 -7
- package/backend/dist/services/pluginVariablesService.d.ts.map +1 -1
- package/backend/dist/services/pluginVariablesService.js +116 -81
- package/backend/dist/services/pluginVariablesService.js.map +1 -1
- package/backend/dist/services/pluginVideoGenerationService.d.ts +19 -8
- package/backend/dist/services/pluginVideoGenerationService.d.ts.map +1 -1
- package/backend/dist/services/pluginVideoGenerationService.js +116 -20
- package/backend/dist/services/pluginVideoGenerationService.js.map +1 -1
- package/backend/dist/services/preferencesService.d.ts +31 -21
- package/backend/dist/services/preferencesService.d.ts.map +1 -1
- package/backend/dist/services/preferencesService.js +104 -102
- package/backend/dist/services/preferencesService.js.map +1 -1
- package/backend/dist/services/recoveryInventoryService.d.ts +244 -0
- package/backend/dist/services/recoveryInventoryService.d.ts.map +1 -0
- package/backend/dist/services/recoveryInventoryService.js +1436 -0
- package/backend/dist/services/recoveryInventoryService.js.map +1 -0
- package/backend/dist/services/simpleGitHubOAuth.js +3 -3
- package/backend/dist/services/simpleGitHubOAuth.js.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.d.ts.map +1 -1
- package/backend/dist/services/simpleHuggingFaceOAuth.js +3 -3
- package/backend/dist/services/simpleHuggingFaceOAuth.js.map +1 -1
- package/backend/dist/services/systemDiagnosticsService.d.ts.map +1 -1
- package/backend/dist/services/systemDiagnosticsService.js +2 -2
- package/backend/dist/services/systemDiagnosticsService.js.map +1 -1
- package/backend/dist/services/systemSettingsService.d.ts +5 -0
- package/backend/dist/services/systemSettingsService.d.ts.map +1 -0
- package/backend/dist/services/systemSettingsService.js +24 -0
- package/backend/dist/services/systemSettingsService.js.map +1 -0
- package/backend/dist/services/titleGenerationService.d.ts +1 -1
- package/backend/dist/services/titleGenerationService.d.ts.map +1 -1
- package/backend/dist/services/titleGenerationService.js +15 -4
- package/backend/dist/services/titleGenerationService.js.map +1 -1
- package/backend/dist/services/voiceProfileService.d.ts +44 -0
- package/backend/dist/services/voiceProfileService.d.ts.map +1 -0
- package/backend/dist/services/voiceProfileService.js +195 -0
- package/backend/dist/services/voiceProfileService.js.map +1 -0
- package/backend/dist/services/webSearchService.d.ts +7 -7
- package/backend/dist/services/webSearchService.d.ts.map +1 -1
- package/backend/dist/services/webSearchService.js +40 -35
- package/backend/dist/services/webSearchService.js.map +1 -1
- package/backend/dist/services/websocketTicketService.d.ts +39 -0
- package/backend/dist/services/websocketTicketService.d.ts.map +1 -0
- package/backend/dist/services/websocketTicketService.js +183 -0
- package/backend/dist/services/websocketTicketService.js.map +1 -0
- package/backend/dist/services/workAccessService.d.ts +3 -3
- package/backend/dist/services/workAccessService.d.ts.map +1 -1
- package/backend/dist/services/workAccessService.js +8 -16
- package/backend/dist/services/workAccessService.js.map +1 -1
- package/backend/dist/services/workAdminService.d.ts +3 -3
- package/backend/dist/services/workAdminService.d.ts.map +1 -1
- package/backend/dist/services/workAdminService.js +4 -4
- package/backend/dist/services/workAdminService.js.map +1 -1
- package/backend/dist/services/workAgentService.d.ts +25 -1
- package/backend/dist/services/workAgentService.d.ts.map +1 -1
- package/backend/dist/services/workAgentService.js +294 -126
- package/backend/dist/services/workAgentService.js.map +1 -1
- package/backend/dist/services/workEventService.d.ts +15 -2
- package/backend/dist/services/workEventService.d.ts.map +1 -1
- package/backend/dist/services/workEventService.js +201 -3
- package/backend/dist/services/workEventService.js.map +1 -1
- package/backend/dist/services/workKubernetesDriver.d.ts +8 -7
- package/backend/dist/services/workKubernetesDriver.d.ts.map +1 -1
- package/backend/dist/services/workKubernetesDriver.js +65 -21
- package/backend/dist/services/workKubernetesDriver.js.map +1 -1
- package/backend/dist/services/workModelProviderService.d.ts +2 -2
- package/backend/dist/services/workModelProviderService.d.ts.map +1 -1
- package/backend/dist/services/workModelProviderService.js +38 -34
- package/backend/dist/services/workModelProviderService.js.map +1 -1
- package/backend/dist/services/workPolicyService.d.ts +7 -7
- package/backend/dist/services/workPolicyService.d.ts.map +1 -1
- package/backend/dist/services/workPolicyService.js +50 -51
- package/backend/dist/services/workPolicyService.js.map +1 -1
- package/backend/dist/services/workPreviewProxyService.d.ts +8 -8
- package/backend/dist/services/workPreviewProxyService.d.ts.map +1 -1
- package/backend/dist/services/workPreviewProxyService.js +47 -44
- package/backend/dist/services/workPreviewProxyService.js.map +1 -1
- package/backend/dist/services/workRuntimeDriver.d.ts +21 -18
- package/backend/dist/services/workRuntimeDriver.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeDriver.js +69 -20
- package/backend/dist/services/workRuntimeDriver.js.map +1 -1
- package/backend/dist/services/workRuntimeService.d.ts +18 -13
- package/backend/dist/services/workRuntimeService.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeService.js +438 -194
- package/backend/dist/services/workRuntimeService.js.map +1 -1
- package/backend/dist/services/workRuntimeShared.d.ts +2 -0
- package/backend/dist/services/workRuntimeShared.d.ts.map +1 -1
- package/backend/dist/services/workRuntimeShared.js.map +1 -1
- package/backend/dist/services/workTaskService.d.ts +42 -36
- package/backend/dist/services/workTaskService.d.ts.map +1 -1
- package/backend/dist/services/workTaskService.js +445 -350
- package/backend/dist/services/workTaskService.js.map +1 -1
- package/backend/dist/services/workTerminalService.d.ts +1 -1
- package/backend/dist/services/workTerminalService.d.ts.map +1 -1
- package/backend/dist/services/workTerminalService.js +33 -6
- package/backend/dist/services/workTerminalService.js.map +1 -1
- package/backend/dist/storage.d.ts +72 -40
- package/backend/dist/storage.d.ts.map +1 -1
- package/backend/dist/storage.js +312 -660
- package/backend/dist/storage.js.map +1 -1
- package/backend/dist/types/index.d.ts +28 -0
- package/backend/dist/types/index.d.ts.map +1 -1
- package/backend/dist/types/index.js.map +1 -1
- package/backend/dist/types/work.d.ts +7 -2
- package/backend/dist/types/work.d.ts.map +1 -1
- package/backend/dist/utils/chatCancellation.d.ts +48 -0
- package/backend/dist/utils/chatCancellation.d.ts.map +1 -0
- package/backend/dist/utils/chatCancellation.js +152 -0
- package/backend/dist/utils/chatCancellation.js.map +1 -0
- package/backend/dist/utils/chatDocumentContext.d.ts +1 -1
- package/backend/dist/utils/chatDocumentContext.d.ts.map +1 -1
- package/backend/dist/utils/chatDocumentContext.js +11 -5
- package/backend/dist/utils/chatDocumentContext.js.map +1 -1
- package/backend/dist/utils/chatStreamCoalescer.d.ts +15 -0
- package/backend/dist/utils/chatStreamCoalescer.d.ts.map +1 -0
- package/backend/dist/utils/chatStreamCoalescer.js +59 -0
- package/backend/dist/utils/chatStreamCoalescer.js.map +1 -0
- package/backend/dist/utils/dataDirectory.d.ts +49 -0
- package/backend/dist/utils/dataDirectory.d.ts.map +1 -0
- package/backend/dist/utils/dataDirectory.js +291 -0
- package/backend/dist/utils/dataDirectory.js.map +1 -0
- package/backend/dist/utils/generationUtils.d.ts.map +1 -1
- package/backend/dist/utils/generationUtils.js +18 -6
- package/backend/dist/utils/generationUtils.js.map +1 -1
- package/backend/dist/utils/jwt.d.ts.map +1 -1
- package/backend/dist/utils/jwt.js +2 -3
- package/backend/dist/utils/jwt.js.map +1 -1
- package/backend/dist/utils/ollamaModelDefaults.d.ts.map +1 -1
- package/backend/dist/utils/ollamaModelDefaults.js +2 -7
- package/backend/dist/utils/ollamaModelDefaults.js.map +1 -1
- package/backend/dist/utils/ollamaStreaming.d.ts +2 -1
- package/backend/dist/utils/ollamaStreaming.d.ts.map +1 -1
- package/backend/dist/utils/ollamaStreaming.js +49 -11
- package/backend/dist/utils/ollamaStreaming.js.map +1 -1
- package/backend/dist/utils/pluginConnectionVariables.d.ts.map +1 -1
- package/backend/dist/utils/pluginConnectionVariables.js +11 -3
- package/backend/dist/utils/pluginConnectionVariables.js.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.d.ts.map +1 -1
- package/backend/dist/utils/pluginDefinitionTrust.js +4 -3
- package/backend/dist/utils/pluginDefinitionTrust.js.map +1 -1
- package/backend/dist/utils/pluginStreaming.d.ts +2 -1
- package/backend/dist/utils/pluginStreaming.d.ts.map +1 -1
- package/backend/dist/utils/pluginStreaming.js +5 -1
- package/backend/dist/utils/pluginStreaming.js.map +1 -1
- package/backend/dist/utils/pluginUpload.d.ts +1 -0
- package/backend/dist/utils/pluginUpload.d.ts.map +1 -1
- package/backend/dist/utils/pluginUpload.js +9 -2
- package/backend/dist/utils/pluginUpload.js.map +1 -1
- package/backend/dist/utils/pluginValidation.d.ts.map +1 -1
- package/backend/dist/utils/pluginValidation.js +29 -1
- package/backend/dist/utils/pluginValidation.js.map +1 -1
- package/backend/dist/utils/sttAudioUpload.d.ts +24 -0
- package/backend/dist/utils/sttAudioUpload.d.ts.map +1 -0
- package/backend/dist/utils/sttAudioUpload.js +500 -0
- package/backend/dist/utils/sttAudioUpload.js.map +1 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.d.ts +34 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.d.ts.map +1 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.js +224 -0
- package/backend/dist/utils/ttsVoiceCloneUpload.js.map +1 -0
- package/backend/dist/utils/websocketMessages.d.ts +2 -1
- package/backend/dist/utils/websocketMessages.d.ts.map +1 -1
- package/backend/dist/utils/websocketMessages.js +16 -2
- package/backend/dist/utils/websocketMessages.js.map +1 -1
- package/backend/dist/websocketServer.d.ts +4 -1
- package/backend/dist/websocketServer.d.ts.map +1 -1
- package/backend/dist/websocketServer.js +290 -44
- package/backend/dist/websocketServer.js.map +1 -1
- package/backend/dist/workTerminalServer.d.ts +9 -0
- package/backend/dist/workTerminalServer.d.ts.map +1 -1
- package/backend/dist/workTerminalServer.js +221 -52
- package/backend/dist/workTerminalServer.js.map +1 -1
- package/backend/dist/worker.d.ts +2 -0
- package/backend/dist/worker.d.ts.map +1 -0
- package/backend/dist/worker.js +250 -0
- package/backend/dist/worker.js.map +1 -0
- package/backend/package.json +19 -9
- package/bin/cli.js +126 -99
- package/bin/runtime-paths.js +108 -0
- package/frontend/dist/artifact-runtime/.build-fingerprint +1 -1
- package/frontend/dist/artifact-runtime/framer-motion.js +5 -5
- package/frontend/dist/artifact-runtime/lucide-react.js +1 -1
- package/frontend/dist/assets/index-CUhEG7E2.js +33 -0
- package/frontend/dist/assets/index-kxtZQLV6.css +1 -0
- package/frontend/dist/assets/{markdown-math-ClQbWekD.css → markdown-math-ClTedVi7.css} +1 -1
- package/frontend/dist/index.html +36 -18
- package/frontend/dist/js/{ArtifactContainer-C_UdeK4k.js → ArtifactContainer-BTEDhBnv.js} +1 -1
- package/frontend/dist/js/{ArtifactDemoPage-D3AuvuR5.js → ArtifactDemoPage-B0gN3YTl.js} +1 -1
- package/frontend/dist/js/{ArtifactSandboxFrame-BiXl9iGD.js → ArtifactSandboxFrame-CLBXQkZs.js} +3 -3
- package/frontend/dist/js/{ArtifactSlideOutPanel-CvgS3sfQ.js → ArtifactSlideOutPanel-CfqHPFdE.js} +1 -1
- package/frontend/dist/js/{Button-DcBM7gdH.js → Button-BV44cTnj.js} +1 -1
- package/frontend/dist/js/ChatPage-DIkAXZWA.js +23 -0
- package/frontend/dist/js/{FirstTimeSetup-B9742i3H.js → FirstTimeSetup-B8phXGNA.js} +1 -1
- package/frontend/dist/js/GalleryPage-W4uI043I.js +1 -0
- package/frontend/dist/js/HomePage-DlxehbyO.js +1 -0
- package/frontend/dist/js/{LibreClawPage-Ds6pqEyk.js → LibreClawPage-CgD0_G_F.js} +1 -1
- package/frontend/dist/js/{ModelManagerModals-BBNg2fxs.js → ModelManagerModals-D7jIT3v1.js} +1 -1
- package/frontend/dist/js/{ModelSelector-CJfJYwxh.js → ModelSelector-BYxJU1UV.js} +1 -1
- package/frontend/dist/js/ModelsPage-C4XdCKP5.js +2 -0
- package/frontend/dist/js/NotesPage-CDECOl4V.js +1 -0
- package/frontend/dist/js/{OptimizedSyntaxHighlighter-CWYUn9Oe.js → OptimizedSyntaxHighlighter-XwqZEoTf.js} +1 -1
- package/frontend/dist/js/{PersonasPage-CbQVv9OM.js → PersonasPage-CjSLPrgS.js} +2 -2
- package/frontend/dist/js/PluginUsagePage-DJOXJuH4.js +1 -0
- package/frontend/dist/js/RichMessageContent-Debeh6bi.js +3 -0
- package/frontend/dist/js/SettingsModal-cUqAeYUP.js +1 -0
- package/frontend/dist/js/{SettingsToggle-Uz2jvV64.js → SettingsToggle-WTa0rgvY.js} +1 -1
- package/frontend/dist/js/{SystemPage-CIBDZTWB.js → SystemPage-DxPw0GS7.js} +1 -1
- package/frontend/dist/js/UserManagementPage-CEdYFe_Z.js +1 -0
- package/frontend/dist/js/WorkPage-DDVeuG_9.js +6 -0
- package/frontend/dist/js/api-IzobHGND.js +14 -0
- package/frontend/dist/js/appStore-DKwC2vgn.js +2 -0
- package/frontend/dist/js/ar-xTSvTq05.js +2 -0
- package/frontend/dist/js/authStore-OaTuapL7.js +4 -0
- package/frontend/dist/js/{babel-CmENXdZw.js → babel-D24oDI9y.js} +1 -1
- package/frontend/dist/js/bn-iYAsohEA.js +2 -0
- package/frontend/dist/js/chatStore-DXGUVLXD.js +3 -0
- package/frontend/dist/js/{config-CV8L89A5.js → config-DPEEuTAe.js} +1 -1
- package/frontend/dist/js/cs-YBHN88Hb.js +2 -0
- package/frontend/dist/js/da-D7qlLy_k.js +2 -0
- package/frontend/dist/js/de-DV671k2c.js +2 -0
- package/frontend/dist/js/es-kyBgzNq-.js +2 -0
- package/frontend/dist/js/{estree-Lx6fK8Ug.js → estree-ChwJsD2w.js} +1 -1
- package/frontend/dist/js/fr-Cw1vut7I.js +2 -0
- package/frontend/dist/js/hi-DWEFC024.js +2 -0
- package/frontend/dist/js/{html-Dx5reqmV.js → html-DFrVjciF.js} +1 -1
- package/frontend/dist/js/id-DlMHjjy0.js +2 -0
- package/frontend/dist/js/is-B9E_a7dG.js +2 -0
- package/frontend/dist/js/it-DawmVbLC.js +2 -0
- package/frontend/dist/js/ja-DmVvwY3W.js +2 -0
- package/frontend/dist/js/ko-DzOPpkVs.js +2 -0
- package/frontend/dist/js/{markdown-Bd5G8zQB.js → markdown-FLLx7b67.js} +1 -1
- package/frontend/dist/js/markdown-core-BmPPZiuD.js +31 -0
- package/frontend/dist/js/{markdown-math-B7FlYsmr.js → markdown-math-mH7AZ_mb.js} +6 -6
- package/frontend/dist/js/{messageCodeStyles-CUWSpffv.js → messageCodeStyles-CBkkZY4n.js} +1 -1
- package/frontend/dist/js/ms-DpsaOPht.js +2 -0
- package/frontend/dist/js/nl-B1d8W22n.js +2 -0
- package/frontend/dist/js/pl-nCncRVgt.js +2 -0
- package/frontend/dist/js/{postcss-B5WIGhAY.js → postcss-Bx9CTcIc.js} +1 -1
- package/frontend/dist/js/pt-DHw8fGuu.js +2 -0
- package/frontend/dist/js/{react-vendor-DPNXrO-8.js → react-vendor-C5yShNlM.js} +1 -1
- package/frontend/dist/js/{router-vendor-Ca9zqOqT.js → router-vendor-CbPDks39.js} +1 -1
- package/frontend/dist/js/ru-Derl_YP_.js +2 -0
- package/frontend/dist/js/{standalone-DLNXiOUi.js → standalone-i8-5bg5p.js} +1 -1
- package/frontend/dist/js/sv-pJAfBVo0.js +2 -0
- package/frontend/dist/js/{syntax-highlight-Ca9bHsaz.js → syntax-highlight-3EEX6CGL.js} +3 -3
- package/frontend/dist/js/th-C_7fIGnk.js +2 -0
- package/frontend/dist/js/tr-CPqsJvaP.js +2 -0
- package/frontend/dist/js/{typescript-YKxslwSt.js → typescript-CQ3x-Uni.js} +1 -1
- package/frontend/dist/js/{ui-Dw6jDKxN.js → ui-BHhR3Vok.js} +2 -2
- package/frontend/dist/js/ui-vendor-D3Ahl1x5.js +177 -0
- package/frontend/dist/js/uk-3o8P_kFi.js +2 -0
- package/frontend/dist/js/{useTranslation-t1quV8ce.js → useTranslation-C3ei3mJq.js} +1 -1
- package/frontend/dist/js/{utils-iKndEgla.js → utils-CuC1beTY.js} +1 -1
- package/frontend/dist/js/{utils-vendor-1zob7nK9.js → utils-vendor-BBa8OxtB.js} +1 -1
- package/frontend/dist/js/vi-Dv6N7OVD.js +2 -0
- package/frontend/dist/js/{workApi-LrQmhNxb.js → workApi-Czu69yWS.js} +2 -2
- package/frontend/dist/js/{yaml-QD4znPfZ.js → yaml-DioTxVLA.js} +1 -1
- package/frontend/dist/js/zh-qg5iqtPi.js +2 -0
- package/package.json +16 -5
- package/plugins/huggingface.json +12 -3
- package/plugins/llama-cpp.json +18 -6
- package/plugins/longcat-audiodit.json +114 -0
- package/plugins/openai.json +18 -0
- package/frontend/dist/assets/index-CN7wpzUO.js +0 -26
- package/frontend/dist/assets/index-Dqkx5o2y.css +0 -1
- package/frontend/dist/js/ChatPage-DBEi-FSO.js +0 -16
- package/frontend/dist/js/GalleryPage-BL0x_xl7.js +0 -1
- package/frontend/dist/js/HomePage-Ukn2Y-BG.js +0 -1
- package/frontend/dist/js/ModelsPage-CDPJM-LA.js +0 -2
- package/frontend/dist/js/NotesPage-DJ-_MSI1.js +0 -1
- package/frontend/dist/js/PluginUsagePage-D69rQvFl.js +0 -1
- package/frontend/dist/js/RichMessageContent-DfuCu6PB.js +0 -3
- package/frontend/dist/js/SettingsModal-D87lWSx4.js +0 -1
- package/frontend/dist/js/UserManagementPage-DzMnFKDG.js +0 -1
- package/frontend/dist/js/WorkPage-D84JNdjS.js +0 -6
- package/frontend/dist/js/api-DhmVEJr2.js +0 -14
- package/frontend/dist/js/appStore-BsqeY2tS.js +0 -2
- package/frontend/dist/js/ar-BgCHB9_9.js +0 -2
- package/frontend/dist/js/authStore-DanfaPdm.js +0 -4
- package/frontend/dist/js/bn-Cr8_opuR.js +0 -2
- package/frontend/dist/js/chatStore-C25ywAXQ.js +0 -3
- package/frontend/dist/js/cs-Bb9gXpfH.js +0 -2
- package/frontend/dist/js/da-JfdGHjAw.js +0 -2
- package/frontend/dist/js/de-CczkCOVx.js +0 -2
- package/frontend/dist/js/es-n_0cjhn7.js +0 -2
- package/frontend/dist/js/fr-Pno128cn.js +0 -2
- package/frontend/dist/js/hi-DBCdcL4p.js +0 -2
- package/frontend/dist/js/id-85QDk-wA.js +0 -2
- package/frontend/dist/js/is-9MuKmBft.js +0 -2
- package/frontend/dist/js/it-C5mz9I3H.js +0 -2
- package/frontend/dist/js/ja-Cu90QTBd.js +0 -2
- package/frontend/dist/js/ko-CSdgcMgq.js +0 -2
- package/frontend/dist/js/markdown-core-DHnR5Hw8.js +0 -16
- package/frontend/dist/js/ms-IQMi6HBU.js +0 -2
- package/frontend/dist/js/nl-BwpdTgvn.js +0 -2
- package/frontend/dist/js/pl-zq8ctKrQ.js +0 -2
- package/frontend/dist/js/pt-BIQu7dBu.js +0 -2
- package/frontend/dist/js/ru-BT5-Z0F9.js +0 -2
- package/frontend/dist/js/sv-B1_q6-Uj.js +0 -2
- package/frontend/dist/js/th-BiLLwq0A.js +0 -2
- package/frontend/dist/js/tr-NZbkkeKs.js +0 -2
- package/frontend/dist/js/ui-vendor-xUzKqAXI.js +0 -177
- package/frontend/dist/js/uk-CGu1pg-F.js +0 -2
- package/frontend/dist/js/vi-ClvH5JZg.js +0 -2
- package/frontend/dist/js/zh-Jgjy3uAG.js +0 -2
|
@@ -0,0 +1,2232 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Libre WebUI
|
|
3
|
+
* Copyright (C) 2025 Kroonen AI, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at:
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { SQLITE_BLOB_QUOTA_SCHEMA_SQL, SQLITE_BLOB_REFERENCE_SCHEMA_SQL, } from '../platform/storage/storageSchemaContracts.js';
|
|
18
|
+
export { SQLITE_BLOB_QUOTA_SCHEMA_SQL, SQLITE_BLOB_REFERENCE_SCHEMA_SQL, } from '../platform/storage/storageSchemaContracts.js';
|
|
19
|
+
const MIGRATION_TABLE = '_libre_schema_migrations';
|
|
20
|
+
const LEGACY_REQUIRED_SCHEMA = {
|
|
21
|
+
users: [
|
|
22
|
+
'id',
|
|
23
|
+
'username',
|
|
24
|
+
'email',
|
|
25
|
+
'password_hash',
|
|
26
|
+
'role',
|
|
27
|
+
'account_status',
|
|
28
|
+
'approved_at',
|
|
29
|
+
'approved_by',
|
|
30
|
+
'avatar',
|
|
31
|
+
'created_at',
|
|
32
|
+
'updated_at',
|
|
33
|
+
],
|
|
34
|
+
personas: [
|
|
35
|
+
'id',
|
|
36
|
+
'user_id',
|
|
37
|
+
'name',
|
|
38
|
+
'description',
|
|
39
|
+
'model',
|
|
40
|
+
'parameters',
|
|
41
|
+
'avatar',
|
|
42
|
+
'background',
|
|
43
|
+
'embedding_model',
|
|
44
|
+
'memory_settings',
|
|
45
|
+
'mutation_settings',
|
|
46
|
+
'created_at',
|
|
47
|
+
'updated_at',
|
|
48
|
+
],
|
|
49
|
+
sessions: [
|
|
50
|
+
'id',
|
|
51
|
+
'user_id',
|
|
52
|
+
'title',
|
|
53
|
+
'model',
|
|
54
|
+
'persona_id',
|
|
55
|
+
'provider_type',
|
|
56
|
+
'provider_id',
|
|
57
|
+
'created_at',
|
|
58
|
+
'updated_at',
|
|
59
|
+
'archived',
|
|
60
|
+
'settings',
|
|
61
|
+
'folder_id',
|
|
62
|
+
'pinned',
|
|
63
|
+
],
|
|
64
|
+
session_folders: ['id', 'user_id', 'name', 'created_at', 'updated_at'],
|
|
65
|
+
knowledge_collections: ['id', 'user_id', 'name', 'created_at', 'updated_at'],
|
|
66
|
+
notes: ['id', 'user_id', 'title', 'content', 'created_at', 'updated_at'],
|
|
67
|
+
session_messages: [
|
|
68
|
+
'id',
|
|
69
|
+
'session_id',
|
|
70
|
+
'role',
|
|
71
|
+
'content',
|
|
72
|
+
'thinking',
|
|
73
|
+
'timestamp',
|
|
74
|
+
'message_index',
|
|
75
|
+
'model',
|
|
76
|
+
'provider_metadata',
|
|
77
|
+
'images',
|
|
78
|
+
'statistics',
|
|
79
|
+
'artifacts',
|
|
80
|
+
'parent_id',
|
|
81
|
+
'branch_index',
|
|
82
|
+
'is_active',
|
|
83
|
+
'rating',
|
|
84
|
+
],
|
|
85
|
+
documents: [
|
|
86
|
+
'id',
|
|
87
|
+
'user_id',
|
|
88
|
+
'filename',
|
|
89
|
+
'title',
|
|
90
|
+
'content',
|
|
91
|
+
'file_type',
|
|
92
|
+
'size',
|
|
93
|
+
'session_id',
|
|
94
|
+
'collection_id',
|
|
95
|
+
'metadata',
|
|
96
|
+
'uploaded_at',
|
|
97
|
+
'created_at',
|
|
98
|
+
'updated_at',
|
|
99
|
+
],
|
|
100
|
+
document_chunks: [
|
|
101
|
+
'id',
|
|
102
|
+
'document_id',
|
|
103
|
+
'chunk_index',
|
|
104
|
+
'content',
|
|
105
|
+
'start_char',
|
|
106
|
+
'end_char',
|
|
107
|
+
'embedding',
|
|
108
|
+
'created_at',
|
|
109
|
+
],
|
|
110
|
+
user_preferences: [
|
|
111
|
+
'id',
|
|
112
|
+
'user_id',
|
|
113
|
+
'key',
|
|
114
|
+
'value',
|
|
115
|
+
'created_at',
|
|
116
|
+
'updated_at',
|
|
117
|
+
],
|
|
118
|
+
system_settings: ['key', 'value', 'updated_at'],
|
|
119
|
+
plugin_credentials: [
|
|
120
|
+
'id',
|
|
121
|
+
'user_id',
|
|
122
|
+
'plugin_id',
|
|
123
|
+
'api_key',
|
|
124
|
+
'routing_auth_fingerprint',
|
|
125
|
+
'created_at',
|
|
126
|
+
'updated_at',
|
|
127
|
+
],
|
|
128
|
+
plugin_variables: [
|
|
129
|
+
'id',
|
|
130
|
+
'user_id',
|
|
131
|
+
'plugin_id',
|
|
132
|
+
'variable_name',
|
|
133
|
+
'variable_value',
|
|
134
|
+
'is_encrypted',
|
|
135
|
+
'created_at',
|
|
136
|
+
'updated_at',
|
|
137
|
+
],
|
|
138
|
+
plugin_discovered_models: [
|
|
139
|
+
'user_id',
|
|
140
|
+
'plugin_id',
|
|
141
|
+
'models_json',
|
|
142
|
+
'updated_at',
|
|
143
|
+
],
|
|
144
|
+
plugin_discovered_capability_models: [
|
|
145
|
+
'user_id',
|
|
146
|
+
'plugin_id',
|
|
147
|
+
'capability',
|
|
148
|
+
'models_json',
|
|
149
|
+
'updated_at',
|
|
150
|
+
],
|
|
151
|
+
plugin_activations: ['user_id', 'plugin_id', 'activated_at'],
|
|
152
|
+
plugin_definition_approvals: [
|
|
153
|
+
'plugin_id',
|
|
154
|
+
'definition_fingerprint',
|
|
155
|
+
'source_path',
|
|
156
|
+
'approved_by_user_id',
|
|
157
|
+
'approved_at',
|
|
158
|
+
],
|
|
159
|
+
plugin_usage_events: [
|
|
160
|
+
'id',
|
|
161
|
+
'user_id',
|
|
162
|
+
'plugin_id',
|
|
163
|
+
'plugin_name',
|
|
164
|
+
'capability',
|
|
165
|
+
'model',
|
|
166
|
+
'status',
|
|
167
|
+
'prompt_tokens',
|
|
168
|
+
'completion_tokens',
|
|
169
|
+
'total_tokens',
|
|
170
|
+
'input_units',
|
|
171
|
+
'output_units',
|
|
172
|
+
'unit_kind',
|
|
173
|
+
'duration_ms',
|
|
174
|
+
'created_at',
|
|
175
|
+
],
|
|
176
|
+
voice_profiles: [
|
|
177
|
+
'id',
|
|
178
|
+
'user_id',
|
|
179
|
+
'name',
|
|
180
|
+
'plugin_id',
|
|
181
|
+
'model',
|
|
182
|
+
'routing_fingerprint',
|
|
183
|
+
'reference_audio',
|
|
184
|
+
'reference_text',
|
|
185
|
+
'audio_mime_type',
|
|
186
|
+
'audio_format',
|
|
187
|
+
'audio_size',
|
|
188
|
+
'consent_confirmed_at',
|
|
189
|
+
'created_at',
|
|
190
|
+
'updated_at',
|
|
191
|
+
],
|
|
192
|
+
generated_images: [
|
|
193
|
+
'id',
|
|
194
|
+
'user_id',
|
|
195
|
+
'kind',
|
|
196
|
+
'prompt',
|
|
197
|
+
'model',
|
|
198
|
+
'plugin_id',
|
|
199
|
+
'image_data',
|
|
200
|
+
'mime_type',
|
|
201
|
+
'size',
|
|
202
|
+
'quality',
|
|
203
|
+
'metadata',
|
|
204
|
+
'created_at',
|
|
205
|
+
],
|
|
206
|
+
media_generation_jobs: [
|
|
207
|
+
'id',
|
|
208
|
+
'user_id',
|
|
209
|
+
'provider_job_id',
|
|
210
|
+
'plugin_id',
|
|
211
|
+
'model',
|
|
212
|
+
'prompt',
|
|
213
|
+
'status',
|
|
214
|
+
'options_json',
|
|
215
|
+
'gallery_id',
|
|
216
|
+
'error',
|
|
217
|
+
'created_at',
|
|
218
|
+
'updated_at',
|
|
219
|
+
],
|
|
220
|
+
work_policies: [
|
|
221
|
+
'id',
|
|
222
|
+
'name',
|
|
223
|
+
'image',
|
|
224
|
+
'memory_limit',
|
|
225
|
+
'cpu_limit',
|
|
226
|
+
'pids_limit',
|
|
227
|
+
'network_default',
|
|
228
|
+
'workspace_size',
|
|
229
|
+
'idle_timeout_ms',
|
|
230
|
+
'created_at',
|
|
231
|
+
'updated_at',
|
|
232
|
+
],
|
|
233
|
+
work_tasks: [
|
|
234
|
+
'id',
|
|
235
|
+
'user_id',
|
|
236
|
+
'title',
|
|
237
|
+
'model',
|
|
238
|
+
'provider_type',
|
|
239
|
+
'provider_id',
|
|
240
|
+
'status',
|
|
241
|
+
'network_enabled',
|
|
242
|
+
'volume_name',
|
|
243
|
+
'container_name',
|
|
244
|
+
'host_path',
|
|
245
|
+
'preview_url',
|
|
246
|
+
'preview_status',
|
|
247
|
+
'policy_id',
|
|
248
|
+
'created_at',
|
|
249
|
+
'updated_at',
|
|
250
|
+
],
|
|
251
|
+
work_runs: [
|
|
252
|
+
'id',
|
|
253
|
+
'task_id',
|
|
254
|
+
'model',
|
|
255
|
+
'provider_type',
|
|
256
|
+
'provider_id',
|
|
257
|
+
'status',
|
|
258
|
+
'error',
|
|
259
|
+
'created_at',
|
|
260
|
+
'started_at',
|
|
261
|
+
'finished_at',
|
|
262
|
+
],
|
|
263
|
+
work_messages: [
|
|
264
|
+
'id',
|
|
265
|
+
'task_id',
|
|
266
|
+
'run_id',
|
|
267
|
+
'role',
|
|
268
|
+
'kind',
|
|
269
|
+
'content',
|
|
270
|
+
'metadata',
|
|
271
|
+
'message_index',
|
|
272
|
+
'created_at',
|
|
273
|
+
],
|
|
274
|
+
persona_memories: [
|
|
275
|
+
'id',
|
|
276
|
+
'user_id',
|
|
277
|
+
'persona_id',
|
|
278
|
+
'content',
|
|
279
|
+
'embedding',
|
|
280
|
+
'timestamp',
|
|
281
|
+
'context',
|
|
282
|
+
'importance_score',
|
|
283
|
+
'memory_type',
|
|
284
|
+
'access_count',
|
|
285
|
+
'last_accessed',
|
|
286
|
+
'decay_factor',
|
|
287
|
+
'consolidated_from',
|
|
288
|
+
],
|
|
289
|
+
persona_states: [
|
|
290
|
+
'persona_id',
|
|
291
|
+
'user_id',
|
|
292
|
+
'runtime_state',
|
|
293
|
+
'mutation_log',
|
|
294
|
+
'last_updated',
|
|
295
|
+
'version',
|
|
296
|
+
],
|
|
297
|
+
};
|
|
298
|
+
/**
|
|
299
|
+
* SQLite vector storage is application schema, not adapter-owned scratch
|
|
300
|
+
* state. Keep this statement immutable after release and add a new migration
|
|
301
|
+
* for every later schema change.
|
|
302
|
+
*/
|
|
303
|
+
export const PLATFORM_VECTOR_SCHEMA_SQL = `
|
|
304
|
+
CREATE TABLE IF NOT EXISTS platform_vector_entries (
|
|
305
|
+
namespace TEXT NOT NULL,
|
|
306
|
+
id TEXT NOT NULL,
|
|
307
|
+
owner_user_id TEXT NOT NULL,
|
|
308
|
+
resource_id TEXT NOT NULL,
|
|
309
|
+
model TEXT NOT NULL,
|
|
310
|
+
dimensions INTEGER NOT NULL CHECK(dimensions > 0),
|
|
311
|
+
embedding_version TEXT NOT NULL,
|
|
312
|
+
source_revision TEXT NOT NULL,
|
|
313
|
+
embedding BLOB NOT NULL,
|
|
314
|
+
created_at INTEGER NOT NULL,
|
|
315
|
+
updated_at INTEGER NOT NULL,
|
|
316
|
+
PRIMARY KEY (namespace, owner_user_id, id)
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
CREATE TABLE IF NOT EXISTS platform_vector_acl (
|
|
320
|
+
namespace TEXT NOT NULL,
|
|
321
|
+
owner_user_id TEXT NOT NULL,
|
|
322
|
+
vector_id TEXT NOT NULL,
|
|
323
|
+
principal_type TEXT NOT NULL CHECK(principal_type IN ('user', 'group')),
|
|
324
|
+
principal_id TEXT NOT NULL,
|
|
325
|
+
PRIMARY KEY (
|
|
326
|
+
namespace,
|
|
327
|
+
owner_user_id,
|
|
328
|
+
vector_id,
|
|
329
|
+
principal_type,
|
|
330
|
+
principal_id
|
|
331
|
+
),
|
|
332
|
+
FOREIGN KEY (namespace, owner_user_id, vector_id)
|
|
333
|
+
REFERENCES platform_vector_entries(namespace, owner_user_id, id)
|
|
334
|
+
ON DELETE CASCADE
|
|
335
|
+
);
|
|
336
|
+
|
|
337
|
+
CREATE TABLE IF NOT EXISTS platform_vector_attributes (
|
|
338
|
+
namespace TEXT NOT NULL,
|
|
339
|
+
owner_user_id TEXT NOT NULL,
|
|
340
|
+
vector_id TEXT NOT NULL,
|
|
341
|
+
attribute_key TEXT NOT NULL,
|
|
342
|
+
attribute_value TEXT NOT NULL,
|
|
343
|
+
PRIMARY KEY (namespace, owner_user_id, vector_id, attribute_key),
|
|
344
|
+
FOREIGN KEY (namespace, owner_user_id, vector_id)
|
|
345
|
+
REFERENCES platform_vector_entries(namespace, owner_user_id, id)
|
|
346
|
+
ON DELETE CASCADE
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
CREATE INDEX IF NOT EXISTS idx_platform_vectors_scope
|
|
350
|
+
ON platform_vector_entries(
|
|
351
|
+
namespace,
|
|
352
|
+
model,
|
|
353
|
+
dimensions,
|
|
354
|
+
embedding_version,
|
|
355
|
+
owner_user_id
|
|
356
|
+
);
|
|
357
|
+
CREATE INDEX IF NOT EXISTS idx_platform_vectors_resource
|
|
358
|
+
ON platform_vector_entries(namespace, resource_id, owner_user_id);
|
|
359
|
+
CREATE INDEX IF NOT EXISTS idx_platform_vector_acl_principal
|
|
360
|
+
ON platform_vector_acl(
|
|
361
|
+
principal_type,
|
|
362
|
+
principal_id,
|
|
363
|
+
namespace,
|
|
364
|
+
owner_user_id,
|
|
365
|
+
vector_id
|
|
366
|
+
);
|
|
367
|
+
CREATE INDEX IF NOT EXISTS idx_platform_vector_attributes_lookup
|
|
368
|
+
ON platform_vector_attributes(
|
|
369
|
+
attribute_key,
|
|
370
|
+
attribute_value,
|
|
371
|
+
namespace,
|
|
372
|
+
owner_user_id,
|
|
373
|
+
vector_id
|
|
374
|
+
);
|
|
375
|
+
`;
|
|
376
|
+
/**
|
|
377
|
+
* Solo-mode durable jobs and the transactional event log. The event table is
|
|
378
|
+
* also the local outbox: every job transition appends to it in the same
|
|
379
|
+
* transaction, and consumers replay its monotonic global cursor.
|
|
380
|
+
*/
|
|
381
|
+
export const DURABLE_JOBS_EVENTS_SCHEMA_SQL = `
|
|
382
|
+
CREATE TABLE IF NOT EXISTS platform_jobs (
|
|
383
|
+
id TEXT PRIMARY KEY,
|
|
384
|
+
job_type TEXT NOT NULL,
|
|
385
|
+
actor_user_id TEXT NOT NULL,
|
|
386
|
+
state TEXT NOT NULL CHECK(
|
|
387
|
+
state IN ('queued', 'running', 'succeeded', 'cancelled', 'dead_letter')
|
|
388
|
+
),
|
|
389
|
+
payload_format TEXT NOT NULL CHECK(
|
|
390
|
+
payload_format IN ('encrypted', 'reference')
|
|
391
|
+
),
|
|
392
|
+
payload TEXT NOT NULL,
|
|
393
|
+
idempotency_scope TEXT NOT NULL,
|
|
394
|
+
idempotency_key_hash TEXT NOT NULL,
|
|
395
|
+
request_fingerprint TEXT NOT NULL,
|
|
396
|
+
priority INTEGER NOT NULL DEFAULT 0 CHECK(priority BETWEEN -100 AND 100),
|
|
397
|
+
attempt_count INTEGER NOT NULL DEFAULT 0 CHECK(attempt_count >= 0),
|
|
398
|
+
max_attempts INTEGER NOT NULL CHECK(max_attempts BETWEEN 1 AND 10),
|
|
399
|
+
available_at INTEGER NOT NULL,
|
|
400
|
+
lease_owner TEXT,
|
|
401
|
+
lease_token INTEGER NOT NULL DEFAULT 0 CHECK(lease_token >= 0),
|
|
402
|
+
lease_expires_at INTEGER,
|
|
403
|
+
cancellation_requested_at INTEGER,
|
|
404
|
+
cancellation_reason TEXT,
|
|
405
|
+
progress_current INTEGER NOT NULL DEFAULT 0 CHECK(progress_current >= 0),
|
|
406
|
+
progress_total INTEGER NOT NULL DEFAULT 100 CHECK(progress_total > 0),
|
|
407
|
+
progress_message TEXT,
|
|
408
|
+
result_reference TEXT,
|
|
409
|
+
error_code TEXT,
|
|
410
|
+
error_summary TEXT,
|
|
411
|
+
created_at INTEGER NOT NULL,
|
|
412
|
+
updated_at INTEGER NOT NULL,
|
|
413
|
+
started_at INTEGER,
|
|
414
|
+
finished_at INTEGER,
|
|
415
|
+
UNIQUE (actor_user_id, idempotency_scope, idempotency_key_hash),
|
|
416
|
+
CHECK(progress_current <= progress_total),
|
|
417
|
+
CHECK(
|
|
418
|
+
(state = 'running' AND lease_owner IS NOT NULL AND lease_expires_at IS NOT NULL)
|
|
419
|
+
OR
|
|
420
|
+
(state != 'running' AND lease_owner IS NULL AND lease_expires_at IS NULL)
|
|
421
|
+
)
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
CREATE TABLE IF NOT EXISTS platform_job_attempts (
|
|
425
|
+
job_id TEXT NOT NULL,
|
|
426
|
+
attempt_number INTEGER NOT NULL CHECK(attempt_number > 0),
|
|
427
|
+
lease_token INTEGER NOT NULL CHECK(lease_token > 0),
|
|
428
|
+
worker_id TEXT NOT NULL,
|
|
429
|
+
started_at INTEGER NOT NULL,
|
|
430
|
+
last_heartbeat_at INTEGER NOT NULL,
|
|
431
|
+
finished_at INTEGER,
|
|
432
|
+
outcome TEXT NOT NULL CHECK(
|
|
433
|
+
outcome IN (
|
|
434
|
+
'running',
|
|
435
|
+
'succeeded',
|
|
436
|
+
'retry_scheduled',
|
|
437
|
+
'cancelled',
|
|
438
|
+
'dead_letter',
|
|
439
|
+
'abandoned'
|
|
440
|
+
)
|
|
441
|
+
),
|
|
442
|
+
error_code TEXT,
|
|
443
|
+
error_summary TEXT,
|
|
444
|
+
PRIMARY KEY (job_id, attempt_number),
|
|
445
|
+
UNIQUE (job_id, lease_token),
|
|
446
|
+
FOREIGN KEY (job_id) REFERENCES platform_jobs(id) ON DELETE CASCADE
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
CREATE TABLE IF NOT EXISTS platform_event_stream_heads (
|
|
450
|
+
stream_id TEXT PRIMARY KEY,
|
|
451
|
+
last_sequence INTEGER NOT NULL CHECK(last_sequence >= 0)
|
|
452
|
+
);
|
|
453
|
+
|
|
454
|
+
CREATE TABLE IF NOT EXISTS platform_events (
|
|
455
|
+
global_cursor INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
456
|
+
event_id TEXT NOT NULL UNIQUE,
|
|
457
|
+
stream_id TEXT NOT NULL,
|
|
458
|
+
stream_sequence INTEGER NOT NULL CHECK(stream_sequence > 0),
|
|
459
|
+
event_type TEXT NOT NULL,
|
|
460
|
+
subject_id TEXT NOT NULL,
|
|
461
|
+
actor_user_id TEXT,
|
|
462
|
+
payload_format TEXT NOT NULL CHECK(
|
|
463
|
+
payload_format IN ('encrypted', 'reference')
|
|
464
|
+
),
|
|
465
|
+
payload TEXT NOT NULL,
|
|
466
|
+
occurred_at INTEGER NOT NULL,
|
|
467
|
+
UNIQUE (stream_id, stream_sequence),
|
|
468
|
+
FOREIGN KEY (stream_id) REFERENCES platform_event_stream_heads(stream_id)
|
|
469
|
+
ON DELETE CASCADE
|
|
470
|
+
);
|
|
471
|
+
|
|
472
|
+
CREATE INDEX IF NOT EXISTS idx_platform_jobs_claim
|
|
473
|
+
ON platform_jobs(state, available_at, lease_expires_at, priority, created_at);
|
|
474
|
+
CREATE INDEX IF NOT EXISTS idx_platform_jobs_actor_created
|
|
475
|
+
ON platform_jobs(actor_user_id, created_at DESC);
|
|
476
|
+
CREATE INDEX IF NOT EXISTS idx_platform_job_attempts_worker
|
|
477
|
+
ON platform_job_attempts(worker_id, outcome, last_heartbeat_at);
|
|
478
|
+
CREATE INDEX IF NOT EXISTS idx_platform_events_stream_cursor
|
|
479
|
+
ON platform_events(stream_id, global_cursor);
|
|
480
|
+
CREATE INDEX IF NOT EXISTS idx_platform_events_occurred
|
|
481
|
+
ON platform_events(occurred_at, global_cursor);
|
|
482
|
+
`;
|
|
483
|
+
const PLATFORM_VECTOR_REQUIRED_SCHEMA = {
|
|
484
|
+
platform_vector_entries: [
|
|
485
|
+
'namespace',
|
|
486
|
+
'id',
|
|
487
|
+
'owner_user_id',
|
|
488
|
+
'resource_id',
|
|
489
|
+
'model',
|
|
490
|
+
'dimensions',
|
|
491
|
+
'embedding_version',
|
|
492
|
+
'source_revision',
|
|
493
|
+
'embedding',
|
|
494
|
+
'created_at',
|
|
495
|
+
'updated_at',
|
|
496
|
+
],
|
|
497
|
+
platform_vector_acl: [
|
|
498
|
+
'namespace',
|
|
499
|
+
'owner_user_id',
|
|
500
|
+
'vector_id',
|
|
501
|
+
'principal_type',
|
|
502
|
+
'principal_id',
|
|
503
|
+
],
|
|
504
|
+
platform_vector_attributes: [
|
|
505
|
+
'namespace',
|
|
506
|
+
'owner_user_id',
|
|
507
|
+
'vector_id',
|
|
508
|
+
'attribute_key',
|
|
509
|
+
'attribute_value',
|
|
510
|
+
],
|
|
511
|
+
};
|
|
512
|
+
const DURABLE_JOBS_EVENTS_REQUIRED_SCHEMA = {
|
|
513
|
+
platform_jobs: [
|
|
514
|
+
'id',
|
|
515
|
+
'job_type',
|
|
516
|
+
'actor_user_id',
|
|
517
|
+
'state',
|
|
518
|
+
'payload_format',
|
|
519
|
+
'payload',
|
|
520
|
+
'idempotency_scope',
|
|
521
|
+
'idempotency_key_hash',
|
|
522
|
+
'request_fingerprint',
|
|
523
|
+
'priority',
|
|
524
|
+
'attempt_count',
|
|
525
|
+
'max_attempts',
|
|
526
|
+
'available_at',
|
|
527
|
+
'lease_owner',
|
|
528
|
+
'lease_token',
|
|
529
|
+
'lease_expires_at',
|
|
530
|
+
'cancellation_requested_at',
|
|
531
|
+
'cancellation_reason',
|
|
532
|
+
'progress_current',
|
|
533
|
+
'progress_total',
|
|
534
|
+
'progress_message',
|
|
535
|
+
'result_reference',
|
|
536
|
+
'error_code',
|
|
537
|
+
'error_summary',
|
|
538
|
+
'created_at',
|
|
539
|
+
'updated_at',
|
|
540
|
+
'started_at',
|
|
541
|
+
'finished_at',
|
|
542
|
+
],
|
|
543
|
+
platform_job_attempts: [
|
|
544
|
+
'job_id',
|
|
545
|
+
'attempt_number',
|
|
546
|
+
'lease_token',
|
|
547
|
+
'worker_id',
|
|
548
|
+
'started_at',
|
|
549
|
+
'last_heartbeat_at',
|
|
550
|
+
'finished_at',
|
|
551
|
+
'outcome',
|
|
552
|
+
'error_code',
|
|
553
|
+
'error_summary',
|
|
554
|
+
],
|
|
555
|
+
platform_event_stream_heads: ['stream_id', 'last_sequence'],
|
|
556
|
+
platform_events: [
|
|
557
|
+
'global_cursor',
|
|
558
|
+
'event_id',
|
|
559
|
+
'stream_id',
|
|
560
|
+
'stream_sequence',
|
|
561
|
+
'event_type',
|
|
562
|
+
'subject_id',
|
|
563
|
+
'actor_user_id',
|
|
564
|
+
'payload_format',
|
|
565
|
+
'payload',
|
|
566
|
+
'occurred_at',
|
|
567
|
+
],
|
|
568
|
+
};
|
|
569
|
+
const IDENTITY_EMAIL_LOOKUP_REQUIRED_SCHEMA = {
|
|
570
|
+
users: ['email_lookup'],
|
|
571
|
+
};
|
|
572
|
+
const BLOB_REFERENCE_REQUIRED_SCHEMA = {
|
|
573
|
+
platform_blob_references: [
|
|
574
|
+
'blob_id',
|
|
575
|
+
'owner_user_id',
|
|
576
|
+
'resource_type',
|
|
577
|
+
'resource_id',
|
|
578
|
+
'purpose',
|
|
579
|
+
'created_at',
|
|
580
|
+
],
|
|
581
|
+
};
|
|
582
|
+
const BLOB_QUOTA_REQUIRED_SCHEMA = {
|
|
583
|
+
platform_blob_quota_usage: [
|
|
584
|
+
'owner_user_id',
|
|
585
|
+
'stored_bytes',
|
|
586
|
+
'reserved_bytes',
|
|
587
|
+
'updated_at',
|
|
588
|
+
],
|
|
589
|
+
platform_blob_quota_reservations: [
|
|
590
|
+
'id',
|
|
591
|
+
'owner_user_id',
|
|
592
|
+
'purpose',
|
|
593
|
+
'reserved_bytes',
|
|
594
|
+
'consumed_bytes',
|
|
595
|
+
'expires_at',
|
|
596
|
+
'created_at',
|
|
597
|
+
'updated_at',
|
|
598
|
+
],
|
|
599
|
+
platform_blob_quota_objects: [
|
|
600
|
+
'blob_id',
|
|
601
|
+
'owner_user_id',
|
|
602
|
+
'purpose',
|
|
603
|
+
'stored_bytes',
|
|
604
|
+
'created_at',
|
|
605
|
+
],
|
|
606
|
+
};
|
|
607
|
+
const VOICE_PROFILE_NAME_LOOKUP_REQUIRED_SCHEMA = {
|
|
608
|
+
voice_profiles: ['name_lookup'],
|
|
609
|
+
};
|
|
610
|
+
const PLUGIN_DEFINITION_REQUIRED_SCHEMA = {
|
|
611
|
+
plugin_definitions: [
|
|
612
|
+
'plugin_id',
|
|
613
|
+
'definition_json',
|
|
614
|
+
'definition_fingerprint',
|
|
615
|
+
'approved_by_user_id',
|
|
616
|
+
'approved_at',
|
|
617
|
+
'created_at',
|
|
618
|
+
'updated_at',
|
|
619
|
+
],
|
|
620
|
+
};
|
|
621
|
+
const WORK_PREVIEW_UPSTREAM_REQUIRED_SCHEMA = {
|
|
622
|
+
work_tasks: ['preview_upstream_host', 'preview_upstream_port'],
|
|
623
|
+
};
|
|
624
|
+
const DURABLE_EVENT_IDEMPOTENCY_REQUIRED_SCHEMA = {
|
|
625
|
+
platform_events: ['request_fingerprint'],
|
|
626
|
+
};
|
|
627
|
+
const RESOURCE_DELETION_LIFECYCLE_REQUIRED_SCHEMA = {
|
|
628
|
+
platform_resource_deletion_tombstones: [
|
|
629
|
+
'resource_type',
|
|
630
|
+
'resource_id',
|
|
631
|
+
'owner_user_id',
|
|
632
|
+
'deletion_incarnation',
|
|
633
|
+
'deletion_token',
|
|
634
|
+
'deleted_at',
|
|
635
|
+
'completed_at',
|
|
636
|
+
],
|
|
637
|
+
};
|
|
638
|
+
export const IDENTITY_EMAIL_LOOKUP_SCHEMA_SQL = `
|
|
639
|
+
ALTER TABLE users ADD COLUMN email_lookup TEXT;
|
|
640
|
+
CREATE UNIQUE INDEX idx_users_email_lookup
|
|
641
|
+
ON users(email_lookup)
|
|
642
|
+
WHERE email_lookup IS NOT NULL;
|
|
643
|
+
`;
|
|
644
|
+
export const VOICE_PROFILE_NAME_LOOKUP_SCHEMA_SQL = `
|
|
645
|
+
ALTER TABLE voice_profiles ADD COLUMN name_lookup TEXT;
|
|
646
|
+
CREATE UNIQUE INDEX idx_voice_profiles_name_lookup
|
|
647
|
+
ON voice_profiles(user_id, plugin_id, model, name_lookup)
|
|
648
|
+
WHERE name_lookup IS NOT NULL;
|
|
649
|
+
`;
|
|
650
|
+
export const PLUGIN_DEFINITION_SCHEMA_SQL = `
|
|
651
|
+
CREATE TABLE IF NOT EXISTS plugin_definitions (
|
|
652
|
+
plugin_id TEXT PRIMARY KEY,
|
|
653
|
+
definition_json TEXT NOT NULL,
|
|
654
|
+
definition_fingerprint TEXT NOT NULL,
|
|
655
|
+
approved_by_user_id TEXT,
|
|
656
|
+
approved_at INTEGER,
|
|
657
|
+
created_at INTEGER NOT NULL,
|
|
658
|
+
updated_at INTEGER NOT NULL,
|
|
659
|
+
CHECK (
|
|
660
|
+
(approved_by_user_id IS NULL AND approved_at IS NULL)
|
|
661
|
+
OR
|
|
662
|
+
(approved_by_user_id IS NOT NULL AND approved_at IS NOT NULL)
|
|
663
|
+
)
|
|
664
|
+
);
|
|
665
|
+
|
|
666
|
+
CREATE INDEX IF NOT EXISTS idx_plugin_definitions_updated
|
|
667
|
+
ON plugin_definitions(updated_at DESC, plugin_id);
|
|
668
|
+
`;
|
|
669
|
+
export const IDENTITY_ACCOUNT_RETIREMENT_SCHEMA_SQL = `
|
|
670
|
+
CREATE TABLE users__retiring_v9 (
|
|
671
|
+
id TEXT PRIMARY KEY,
|
|
672
|
+
username TEXT UNIQUE NOT NULL,
|
|
673
|
+
email TEXT UNIQUE,
|
|
674
|
+
email_lookup TEXT,
|
|
675
|
+
password_hash TEXT NOT NULL,
|
|
676
|
+
role TEXT NOT NULL DEFAULT 'user' CHECK(role IN ('admin', 'user')),
|
|
677
|
+
account_status TEXT NOT NULL DEFAULT 'active'
|
|
678
|
+
CHECK(account_status IN ('pending', 'active', 'retiring')),
|
|
679
|
+
approved_at INTEGER,
|
|
680
|
+
approved_by TEXT,
|
|
681
|
+
avatar TEXT,
|
|
682
|
+
created_at INTEGER NOT NULL,
|
|
683
|
+
updated_at INTEGER NOT NULL
|
|
684
|
+
);
|
|
685
|
+
`;
|
|
686
|
+
export const WORK_PREVIEW_UPSTREAM_SCHEMA_SQL = `
|
|
687
|
+
ALTER TABLE work_tasks ADD COLUMN preview_upstream_host TEXT
|
|
688
|
+
CHECK (
|
|
689
|
+
preview_upstream_host IS NULL
|
|
690
|
+
OR length(preview_upstream_host) BETWEEN 1 AND 253
|
|
691
|
+
);
|
|
692
|
+
ALTER TABLE work_tasks ADD COLUMN preview_upstream_port INTEGER
|
|
693
|
+
CHECK (
|
|
694
|
+
preview_upstream_port IS NULL
|
|
695
|
+
OR preview_upstream_port BETWEEN 1 AND 65535
|
|
696
|
+
);
|
|
697
|
+
`;
|
|
698
|
+
export const DURABLE_EVENT_IDEMPOTENCY_SCHEMA_SQL = `
|
|
699
|
+
ALTER TABLE platform_events ADD COLUMN request_fingerprint TEXT NOT NULL
|
|
700
|
+
DEFAULT '0000000000000000000000000000000000000000000000000000000000000000'
|
|
701
|
+
CHECK (
|
|
702
|
+
length(request_fingerprint) = 64
|
|
703
|
+
AND request_fingerprint NOT GLOB '*[^0-9a-f]*'
|
|
704
|
+
);
|
|
705
|
+
`;
|
|
706
|
+
export const DURABLE_EVENT_REPLAY_INDEX_SCHEMA_SQL = `
|
|
707
|
+
CREATE INDEX IF NOT EXISTS idx_platform_events_stream_subject_cursor
|
|
708
|
+
ON platform_events(stream_id, subject_id, global_cursor);
|
|
709
|
+
`;
|
|
710
|
+
export const RESOURCE_DELETION_LIFECYCLE_SCHEMA_SQL = `
|
|
711
|
+
CREATE TABLE IF NOT EXISTS platform_resource_deletion_tombstones (
|
|
712
|
+
resource_type TEXT NOT NULL
|
|
713
|
+
CHECK (resource_type IN ('document', 'generated-media', 'persona')),
|
|
714
|
+
resource_id TEXT NOT NULL CHECK (length(resource_id) BETWEEN 1 AND 256),
|
|
715
|
+
owner_user_id TEXT NOT NULL CHECK (length(owner_user_id) BETWEEN 1 AND 256),
|
|
716
|
+
deletion_incarnation INTEGER NOT NULL CHECK (deletion_incarnation > 0),
|
|
717
|
+
deletion_token TEXT NOT NULL UNIQUE
|
|
718
|
+
CHECK (
|
|
719
|
+
length(deletion_token) = 64
|
|
720
|
+
AND deletion_token NOT GLOB '*[^0-9a-f]*'
|
|
721
|
+
),
|
|
722
|
+
deleted_at INTEGER NOT NULL CHECK (deleted_at >= 0),
|
|
723
|
+
completed_at INTEGER CHECK (
|
|
724
|
+
completed_at IS NULL OR completed_at >= deleted_at
|
|
725
|
+
),
|
|
726
|
+
PRIMARY KEY (resource_type, resource_id)
|
|
727
|
+
);
|
|
728
|
+
|
|
729
|
+
CREATE INDEX IF NOT EXISTS idx_platform_resource_tombstones_owner
|
|
730
|
+
ON platform_resource_deletion_tombstones(
|
|
731
|
+
owner_user_id,
|
|
732
|
+
deleted_at,
|
|
733
|
+
resource_type,
|
|
734
|
+
resource_id
|
|
735
|
+
);
|
|
736
|
+
`;
|
|
737
|
+
const REQUIRED_SCHEMA = {
|
|
738
|
+
...LEGACY_REQUIRED_SCHEMA,
|
|
739
|
+
users: [
|
|
740
|
+
...LEGACY_REQUIRED_SCHEMA.users,
|
|
741
|
+
...IDENTITY_EMAIL_LOOKUP_REQUIRED_SCHEMA.users,
|
|
742
|
+
],
|
|
743
|
+
voice_profiles: [
|
|
744
|
+
...LEGACY_REQUIRED_SCHEMA.voice_profiles,
|
|
745
|
+
...VOICE_PROFILE_NAME_LOOKUP_REQUIRED_SCHEMA.voice_profiles,
|
|
746
|
+
],
|
|
747
|
+
...PLATFORM_VECTOR_REQUIRED_SCHEMA,
|
|
748
|
+
...DURABLE_JOBS_EVENTS_REQUIRED_SCHEMA,
|
|
749
|
+
...BLOB_REFERENCE_REQUIRED_SCHEMA,
|
|
750
|
+
...PLUGIN_DEFINITION_REQUIRED_SCHEMA,
|
|
751
|
+
};
|
|
752
|
+
const LEGACY_ADDITIVE_COLUMNS = {
|
|
753
|
+
users: ['avatar', 'account_status', 'approved_at', 'approved_by'],
|
|
754
|
+
personas: ['embedding_model', 'memory_settings', 'mutation_settings'],
|
|
755
|
+
sessions: [
|
|
756
|
+
'persona_id',
|
|
757
|
+
'provider_type',
|
|
758
|
+
'provider_id',
|
|
759
|
+
'archived',
|
|
760
|
+
'settings',
|
|
761
|
+
'folder_id',
|
|
762
|
+
'pinned',
|
|
763
|
+
],
|
|
764
|
+
session_messages: [
|
|
765
|
+
'thinking',
|
|
766
|
+
'model',
|
|
767
|
+
'provider_metadata',
|
|
768
|
+
'images',
|
|
769
|
+
'statistics',
|
|
770
|
+
'artifacts',
|
|
771
|
+
'parent_id',
|
|
772
|
+
'branch_index',
|
|
773
|
+
'is_active',
|
|
774
|
+
'rating',
|
|
775
|
+
],
|
|
776
|
+
documents: ['file_type', 'size', 'session_id', 'collection_id'],
|
|
777
|
+
plugin_credentials: ['routing_auth_fingerprint'],
|
|
778
|
+
plugin_definition_approvals: ['source_path'],
|
|
779
|
+
generated_images: ['kind', 'plugin_id', 'mime_type', 'metadata'],
|
|
780
|
+
voice_profiles: ['routing_fingerprint'],
|
|
781
|
+
work_tasks: ['provider_type', 'provider_id', 'host_path', 'policy_id'],
|
|
782
|
+
work_runs: ['provider_type', 'provider_id'],
|
|
783
|
+
persona_memories: [
|
|
784
|
+
'memory_type',
|
|
785
|
+
'access_count',
|
|
786
|
+
'last_accessed',
|
|
787
|
+
'decay_factor',
|
|
788
|
+
'consolidated_from',
|
|
789
|
+
],
|
|
790
|
+
};
|
|
791
|
+
const LEGACY_BOOTSTRAP_CORE_TABLES = [
|
|
792
|
+
'users',
|
|
793
|
+
'sessions',
|
|
794
|
+
'session_messages',
|
|
795
|
+
'documents',
|
|
796
|
+
'document_chunks',
|
|
797
|
+
'user_preferences',
|
|
798
|
+
'system_settings',
|
|
799
|
+
'personas',
|
|
800
|
+
];
|
|
801
|
+
const addColumnIfMissing = (database, table, column, definition) => {
|
|
802
|
+
const columns = database
|
|
803
|
+
.prepare(`PRAGMA table_info(${table})`)
|
|
804
|
+
.all();
|
|
805
|
+
if (!columns.some(item => item.name === column)) {
|
|
806
|
+
database.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
const ensurePersonaPersistence = (database) => {
|
|
810
|
+
database.exec(`
|
|
811
|
+
CREATE TABLE IF NOT EXISTS persona_memories (
|
|
812
|
+
id TEXT PRIMARY KEY,
|
|
813
|
+
user_id TEXT NOT NULL,
|
|
814
|
+
persona_id TEXT NOT NULL,
|
|
815
|
+
content TEXT NOT NULL,
|
|
816
|
+
embedding BLOB,
|
|
817
|
+
timestamp INTEGER NOT NULL,
|
|
818
|
+
context TEXT,
|
|
819
|
+
importance_score REAL DEFAULT 0.5,
|
|
820
|
+
memory_type TEXT DEFAULT 'general',
|
|
821
|
+
access_count INTEGER DEFAULT 0,
|
|
822
|
+
last_accessed INTEGER,
|
|
823
|
+
decay_factor REAL DEFAULT 1.0,
|
|
824
|
+
consolidated_from TEXT,
|
|
825
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
826
|
+
FOREIGN KEY (persona_id) REFERENCES personas(id) ON DELETE CASCADE
|
|
827
|
+
);
|
|
828
|
+
|
|
829
|
+
CREATE TABLE IF NOT EXISTS persona_states (
|
|
830
|
+
persona_id TEXT PRIMARY KEY,
|
|
831
|
+
user_id TEXT NOT NULL,
|
|
832
|
+
runtime_state TEXT NOT NULL,
|
|
833
|
+
mutation_log TEXT NOT NULL,
|
|
834
|
+
last_updated INTEGER NOT NULL,
|
|
835
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
836
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
837
|
+
FOREIGN KEY (persona_id) REFERENCES personas(id) ON DELETE CASCADE
|
|
838
|
+
);
|
|
839
|
+
`);
|
|
840
|
+
addColumnIfMissing(database, 'persona_memories', 'memory_type', "TEXT DEFAULT 'general'");
|
|
841
|
+
addColumnIfMissing(database, 'persona_memories', 'access_count', 'INTEGER DEFAULT 0');
|
|
842
|
+
addColumnIfMissing(database, 'persona_memories', 'last_accessed', 'INTEGER DEFAULT NULL');
|
|
843
|
+
addColumnIfMissing(database, 'persona_memories', 'decay_factor', 'REAL DEFAULT 1.0');
|
|
844
|
+
addColumnIfMissing(database, 'persona_memories', 'consolidated_from', 'TEXT DEFAULT NULL');
|
|
845
|
+
database.exec(`
|
|
846
|
+
CREATE INDEX IF NOT EXISTS idx_persona_memories_user_persona
|
|
847
|
+
ON persona_memories(user_id, persona_id);
|
|
848
|
+
CREATE INDEX IF NOT EXISTS idx_persona_memories_timestamp
|
|
849
|
+
ON persona_memories(timestamp);
|
|
850
|
+
CREATE INDEX IF NOT EXISTS idx_persona_memories_importance
|
|
851
|
+
ON persona_memories(importance_score);
|
|
852
|
+
CREATE INDEX IF NOT EXISTS idx_persona_memories_type
|
|
853
|
+
ON persona_memories(memory_type);
|
|
854
|
+
CREATE INDEX IF NOT EXISTS idx_persona_memories_last_accessed
|
|
855
|
+
ON persona_memories(last_accessed);
|
|
856
|
+
CREATE INDEX IF NOT EXISTS idx_persona_states_user
|
|
857
|
+
ON persona_states(user_id);
|
|
858
|
+
CREATE INDEX IF NOT EXISTS idx_persona_states_updated
|
|
859
|
+
ON persona_states(last_updated);
|
|
860
|
+
`);
|
|
861
|
+
};
|
|
862
|
+
const REQUIRED_PRIMARY_KEYS = {
|
|
863
|
+
[MIGRATION_TABLE]: ['version'],
|
|
864
|
+
users: ['id'],
|
|
865
|
+
personas: ['id'],
|
|
866
|
+
sessions: ['id'],
|
|
867
|
+
session_messages: ['id'],
|
|
868
|
+
plugin_credentials: ['id'],
|
|
869
|
+
work_tasks: ['id'],
|
|
870
|
+
work_runs: ['id'],
|
|
871
|
+
work_messages: ['id'],
|
|
872
|
+
persona_memories: ['id'],
|
|
873
|
+
persona_states: ['persona_id'],
|
|
874
|
+
platform_vector_entries: ['namespace', 'owner_user_id', 'id'],
|
|
875
|
+
platform_vector_acl: [
|
|
876
|
+
'namespace',
|
|
877
|
+
'owner_user_id',
|
|
878
|
+
'vector_id',
|
|
879
|
+
'principal_type',
|
|
880
|
+
'principal_id',
|
|
881
|
+
],
|
|
882
|
+
platform_vector_attributes: [
|
|
883
|
+
'namespace',
|
|
884
|
+
'owner_user_id',
|
|
885
|
+
'vector_id',
|
|
886
|
+
'attribute_key',
|
|
887
|
+
],
|
|
888
|
+
platform_jobs: ['id'],
|
|
889
|
+
platform_job_attempts: ['job_id', 'attempt_number'],
|
|
890
|
+
platform_event_stream_heads: ['stream_id'],
|
|
891
|
+
platform_events: ['global_cursor'],
|
|
892
|
+
platform_blob_references: ['blob_id'],
|
|
893
|
+
platform_blob_quota_usage: ['owner_user_id'],
|
|
894
|
+
platform_blob_quota_reservations: ['id'],
|
|
895
|
+
platform_blob_quota_objects: ['blob_id'],
|
|
896
|
+
plugin_definitions: ['plugin_id'],
|
|
897
|
+
platform_resource_deletion_tombstones: ['resource_type', 'resource_id'],
|
|
898
|
+
};
|
|
899
|
+
const REQUIRED_UNIQUE_KEYS = {
|
|
900
|
+
[MIGRATION_TABLE]: [['name']],
|
|
901
|
+
users: [['username'], ['email']],
|
|
902
|
+
plugin_credentials: [['user_id', 'plugin_id']],
|
|
903
|
+
work_tasks: [['volume_name'], ['container_name']],
|
|
904
|
+
work_messages: [['task_id', 'message_index']],
|
|
905
|
+
platform_jobs: [
|
|
906
|
+
['actor_user_id', 'idempotency_scope', 'idempotency_key_hash'],
|
|
907
|
+
],
|
|
908
|
+
platform_job_attempts: [['job_id', 'lease_token']],
|
|
909
|
+
platform_events: [['event_id'], ['stream_id', 'stream_sequence']],
|
|
910
|
+
platform_blob_references: [['resource_type', 'resource_id', 'purpose']],
|
|
911
|
+
platform_resource_deletion_tombstones: [['deletion_token']],
|
|
912
|
+
};
|
|
913
|
+
const REQUIRED_FOREIGN_KEYS = [
|
|
914
|
+
{
|
|
915
|
+
table: 'sessions',
|
|
916
|
+
columns: ['user_id'],
|
|
917
|
+
referencedTable: 'users',
|
|
918
|
+
referencedColumns: ['id'],
|
|
919
|
+
onDelete: 'CASCADE',
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
table: 'session_messages',
|
|
923
|
+
columns: ['session_id'],
|
|
924
|
+
referencedTable: 'sessions',
|
|
925
|
+
referencedColumns: ['id'],
|
|
926
|
+
onDelete: 'CASCADE',
|
|
927
|
+
},
|
|
928
|
+
{
|
|
929
|
+
table: 'plugin_credentials',
|
|
930
|
+
columns: ['user_id'],
|
|
931
|
+
referencedTable: 'users',
|
|
932
|
+
referencedColumns: ['id'],
|
|
933
|
+
onDelete: 'CASCADE',
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
table: 'work_tasks',
|
|
937
|
+
columns: ['user_id'],
|
|
938
|
+
referencedTable: 'users',
|
|
939
|
+
referencedColumns: ['id'],
|
|
940
|
+
onDelete: 'CASCADE',
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
table: 'work_runs',
|
|
944
|
+
columns: ['task_id'],
|
|
945
|
+
referencedTable: 'work_tasks',
|
|
946
|
+
referencedColumns: ['id'],
|
|
947
|
+
onDelete: 'CASCADE',
|
|
948
|
+
},
|
|
949
|
+
{
|
|
950
|
+
table: 'work_messages',
|
|
951
|
+
columns: ['task_id'],
|
|
952
|
+
referencedTable: 'work_tasks',
|
|
953
|
+
referencedColumns: ['id'],
|
|
954
|
+
onDelete: 'CASCADE',
|
|
955
|
+
},
|
|
956
|
+
{
|
|
957
|
+
table: 'work_messages',
|
|
958
|
+
columns: ['run_id'],
|
|
959
|
+
referencedTable: 'work_runs',
|
|
960
|
+
referencedColumns: ['id'],
|
|
961
|
+
onDelete: 'SET NULL',
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
table: 'persona_memories',
|
|
965
|
+
columns: ['user_id'],
|
|
966
|
+
referencedTable: 'users',
|
|
967
|
+
referencedColumns: ['id'],
|
|
968
|
+
onDelete: 'CASCADE',
|
|
969
|
+
},
|
|
970
|
+
{
|
|
971
|
+
table: 'persona_memories',
|
|
972
|
+
columns: ['persona_id'],
|
|
973
|
+
referencedTable: 'personas',
|
|
974
|
+
referencedColumns: ['id'],
|
|
975
|
+
onDelete: 'CASCADE',
|
|
976
|
+
},
|
|
977
|
+
{
|
|
978
|
+
table: 'persona_states',
|
|
979
|
+
columns: ['persona_id'],
|
|
980
|
+
referencedTable: 'personas',
|
|
981
|
+
referencedColumns: ['id'],
|
|
982
|
+
onDelete: 'CASCADE',
|
|
983
|
+
},
|
|
984
|
+
{
|
|
985
|
+
table: 'platform_vector_acl',
|
|
986
|
+
columns: ['namespace', 'owner_user_id', 'vector_id'],
|
|
987
|
+
referencedTable: 'platform_vector_entries',
|
|
988
|
+
referencedColumns: ['namespace', 'owner_user_id', 'id'],
|
|
989
|
+
onDelete: 'CASCADE',
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
table: 'platform_vector_attributes',
|
|
993
|
+
columns: ['namespace', 'owner_user_id', 'vector_id'],
|
|
994
|
+
referencedTable: 'platform_vector_entries',
|
|
995
|
+
referencedColumns: ['namespace', 'owner_user_id', 'id'],
|
|
996
|
+
onDelete: 'CASCADE',
|
|
997
|
+
},
|
|
998
|
+
{
|
|
999
|
+
table: 'platform_job_attempts',
|
|
1000
|
+
columns: ['job_id'],
|
|
1001
|
+
referencedTable: 'platform_jobs',
|
|
1002
|
+
referencedColumns: ['id'],
|
|
1003
|
+
onDelete: 'CASCADE',
|
|
1004
|
+
},
|
|
1005
|
+
{
|
|
1006
|
+
table: 'platform_events',
|
|
1007
|
+
columns: ['stream_id'],
|
|
1008
|
+
referencedTable: 'platform_event_stream_heads',
|
|
1009
|
+
referencedColumns: ['stream_id'],
|
|
1010
|
+
onDelete: 'CASCADE',
|
|
1011
|
+
},
|
|
1012
|
+
];
|
|
1013
|
+
const REQUIRED_INDEXES = [
|
|
1014
|
+
{
|
|
1015
|
+
name: 'idx_users_email_lookup',
|
|
1016
|
+
table: 'users',
|
|
1017
|
+
columns: ['email_lookup'],
|
|
1018
|
+
unique: true,
|
|
1019
|
+
sqlFragment: 'WHERE email_lookup IS NOT NULL',
|
|
1020
|
+
},
|
|
1021
|
+
{
|
|
1022
|
+
name: 'idx_voice_profiles_name_lookup',
|
|
1023
|
+
table: 'voice_profiles',
|
|
1024
|
+
columns: ['user_id', 'plugin_id', 'model', 'name_lookup'],
|
|
1025
|
+
unique: true,
|
|
1026
|
+
sqlFragment: 'WHERE name_lookup IS NOT NULL',
|
|
1027
|
+
},
|
|
1028
|
+
{
|
|
1029
|
+
name: 'idx_plugin_definitions_updated',
|
|
1030
|
+
table: 'plugin_definitions',
|
|
1031
|
+
columns: ['updated_at', 'plugin_id'],
|
|
1032
|
+
},
|
|
1033
|
+
{
|
|
1034
|
+
name: 'idx_sessions_user_id',
|
|
1035
|
+
table: 'sessions',
|
|
1036
|
+
columns: ['user_id'],
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
name: 'idx_session_messages_session_id',
|
|
1040
|
+
table: 'session_messages',
|
|
1041
|
+
columns: ['session_id'],
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
name: 'idx_plugin_credentials_user_id',
|
|
1045
|
+
table: 'plugin_credentials',
|
|
1046
|
+
columns: ['user_id'],
|
|
1047
|
+
},
|
|
1048
|
+
{
|
|
1049
|
+
name: 'idx_work_runs_one_active',
|
|
1050
|
+
table: 'work_runs',
|
|
1051
|
+
columns: ['task_id'],
|
|
1052
|
+
unique: true,
|
|
1053
|
+
sqlFragment: "WHERE status IN ('queued', 'preparing', 'running')",
|
|
1054
|
+
},
|
|
1055
|
+
{
|
|
1056
|
+
name: 'idx_platform_vectors_scope',
|
|
1057
|
+
table: 'platform_vector_entries',
|
|
1058
|
+
columns: [
|
|
1059
|
+
'namespace',
|
|
1060
|
+
'model',
|
|
1061
|
+
'dimensions',
|
|
1062
|
+
'embedding_version',
|
|
1063
|
+
'owner_user_id',
|
|
1064
|
+
],
|
|
1065
|
+
},
|
|
1066
|
+
{
|
|
1067
|
+
name: 'idx_platform_vectors_resource',
|
|
1068
|
+
table: 'platform_vector_entries',
|
|
1069
|
+
columns: ['namespace', 'resource_id', 'owner_user_id'],
|
|
1070
|
+
},
|
|
1071
|
+
{
|
|
1072
|
+
name: 'idx_platform_vector_acl_principal',
|
|
1073
|
+
table: 'platform_vector_acl',
|
|
1074
|
+
columns: [
|
|
1075
|
+
'principal_type',
|
|
1076
|
+
'principal_id',
|
|
1077
|
+
'namespace',
|
|
1078
|
+
'owner_user_id',
|
|
1079
|
+
'vector_id',
|
|
1080
|
+
],
|
|
1081
|
+
},
|
|
1082
|
+
{
|
|
1083
|
+
name: 'idx_platform_vector_attributes_lookup',
|
|
1084
|
+
table: 'platform_vector_attributes',
|
|
1085
|
+
columns: [
|
|
1086
|
+
'attribute_key',
|
|
1087
|
+
'attribute_value',
|
|
1088
|
+
'namespace',
|
|
1089
|
+
'owner_user_id',
|
|
1090
|
+
'vector_id',
|
|
1091
|
+
],
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
name: 'idx_platform_jobs_claim',
|
|
1095
|
+
table: 'platform_jobs',
|
|
1096
|
+
columns: [
|
|
1097
|
+
'state',
|
|
1098
|
+
'available_at',
|
|
1099
|
+
'lease_expires_at',
|
|
1100
|
+
'priority',
|
|
1101
|
+
'created_at',
|
|
1102
|
+
],
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
name: 'idx_platform_jobs_actor_created',
|
|
1106
|
+
table: 'platform_jobs',
|
|
1107
|
+
columns: ['actor_user_id', 'created_at'],
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
name: 'idx_platform_job_attempts_worker',
|
|
1111
|
+
table: 'platform_job_attempts',
|
|
1112
|
+
columns: ['worker_id', 'outcome', 'last_heartbeat_at'],
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
name: 'idx_platform_events_stream_cursor',
|
|
1116
|
+
table: 'platform_events',
|
|
1117
|
+
columns: ['stream_id', 'global_cursor'],
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
name: 'idx_platform_events_stream_subject_cursor',
|
|
1121
|
+
table: 'platform_events',
|
|
1122
|
+
columns: ['stream_id', 'subject_id', 'global_cursor'],
|
|
1123
|
+
},
|
|
1124
|
+
{
|
|
1125
|
+
name: 'idx_platform_events_occurred',
|
|
1126
|
+
table: 'platform_events',
|
|
1127
|
+
columns: ['occurred_at', 'global_cursor'],
|
|
1128
|
+
},
|
|
1129
|
+
{
|
|
1130
|
+
name: 'idx_platform_blob_references_owner',
|
|
1131
|
+
table: 'platform_blob_references',
|
|
1132
|
+
columns: ['owner_user_id', 'purpose', 'created_at'],
|
|
1133
|
+
},
|
|
1134
|
+
{
|
|
1135
|
+
name: 'idx_platform_blob_references_resource',
|
|
1136
|
+
table: 'platform_blob_references',
|
|
1137
|
+
columns: ['resource_type', 'resource_id'],
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
name: 'idx_platform_blob_quota_reservations_expiry',
|
|
1141
|
+
table: 'platform_blob_quota_reservations',
|
|
1142
|
+
columns: ['expires_at', 'id'],
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
name: 'idx_platform_blob_quota_reservations_owner',
|
|
1146
|
+
table: 'platform_blob_quota_reservations',
|
|
1147
|
+
columns: ['owner_user_id', 'expires_at'],
|
|
1148
|
+
},
|
|
1149
|
+
{
|
|
1150
|
+
name: 'idx_platform_blob_quota_objects_owner',
|
|
1151
|
+
table: 'platform_blob_quota_objects',
|
|
1152
|
+
columns: ['owner_user_id', 'purpose', 'created_at'],
|
|
1153
|
+
},
|
|
1154
|
+
{
|
|
1155
|
+
name: 'idx_platform_resource_tombstones_owner',
|
|
1156
|
+
table: 'platform_resource_deletion_tombstones',
|
|
1157
|
+
columns: ['owner_user_id', 'deleted_at', 'resource_type', 'resource_id'],
|
|
1158
|
+
},
|
|
1159
|
+
];
|
|
1160
|
+
const REQUIRED_TABLE_SQL_FRAGMENTS = {
|
|
1161
|
+
platform_vector_entries: ['CHECK(dimensions > 0)'],
|
|
1162
|
+
platform_vector_acl: ["CHECK(principal_type IN ('user', 'group'))"],
|
|
1163
|
+
platform_jobs: [
|
|
1164
|
+
"state IN ('queued', 'running', 'succeeded', 'cancelled', 'dead_letter')",
|
|
1165
|
+
"payload_format IN ('encrypted', 'reference')",
|
|
1166
|
+
'UNIQUE (actor_user_id, idempotency_scope, idempotency_key_hash)',
|
|
1167
|
+
"state = 'running' AND lease_owner IS NOT NULL",
|
|
1168
|
+
],
|
|
1169
|
+
platform_job_attempts: [
|
|
1170
|
+
"outcome IN ('running', 'succeeded', 'retry_scheduled', 'cancelled', 'dead_letter', 'abandoned')",
|
|
1171
|
+
],
|
|
1172
|
+
platform_events: [
|
|
1173
|
+
"payload_format IN ('encrypted', 'reference')",
|
|
1174
|
+
'UNIQUE (stream_id, stream_sequence)',
|
|
1175
|
+
],
|
|
1176
|
+
platform_blob_quota_usage: [
|
|
1177
|
+
'CHECK(stored_bytes >= 0)',
|
|
1178
|
+
'CHECK(reserved_bytes >= 0)',
|
|
1179
|
+
],
|
|
1180
|
+
platform_blob_quota_reservations: [
|
|
1181
|
+
'CHECK(reserved_bytes >= 0)',
|
|
1182
|
+
'CHECK(consumed_bytes >= 0)',
|
|
1183
|
+
],
|
|
1184
|
+
platform_blob_quota_objects: ['CHECK(stored_bytes >= 0)'],
|
|
1185
|
+
plugin_definitions: ['approved_by_user_id IS NULL AND approved_at IS NULL'],
|
|
1186
|
+
platform_resource_deletion_tombstones: [
|
|
1187
|
+
"resource_type IN ('document', 'generated-media', 'persona')",
|
|
1188
|
+
'CHECK(deletion_incarnation > 0)',
|
|
1189
|
+
],
|
|
1190
|
+
};
|
|
1191
|
+
const quoteIdentifier = (identifier) => `"${identifier.replace(/"/g, '""')}"`;
|
|
1192
|
+
const normalizeSql = (sql) => sql
|
|
1193
|
+
.toLowerCase()
|
|
1194
|
+
.replace(/["`]/g, '')
|
|
1195
|
+
.replace(/\[/g, '')
|
|
1196
|
+
.replace(/\]/g, '')
|
|
1197
|
+
.replace(/\s+/g, ' ')
|
|
1198
|
+
.replace(/\s*([(),>])\s*/g, '$1')
|
|
1199
|
+
.trim();
|
|
1200
|
+
const normalizeSchemaObjectSql = (sql) => sql
|
|
1201
|
+
.trim()
|
|
1202
|
+
.replace(/^CREATE\s+(TABLE|INDEX)\s+IF\s+NOT\s+EXISTS\s+/, 'CREATE $1 ')
|
|
1203
|
+
.replace(/\s+/g, ' ')
|
|
1204
|
+
.replace(/\s*([(),>])\s*/g, '$1');
|
|
1205
|
+
const CANONICAL_DURABLE_EVENT_REPLAY_INDEX_SQL = normalizeSchemaObjectSql(DURABLE_EVENT_REPLAY_INDEX_SCHEMA_SQL.trim().replace(/;$/, ''));
|
|
1206
|
+
const collectDurableEventReplayIndexIdentityMismatches = (database) => {
|
|
1207
|
+
const observed = database
|
|
1208
|
+
.prepare(`SELECT type, tbl_name, sql
|
|
1209
|
+
FROM sqlite_master
|
|
1210
|
+
WHERE name = 'idx_platform_events_stream_subject_cursor'`)
|
|
1211
|
+
.get();
|
|
1212
|
+
if (!observed) {
|
|
1213
|
+
return ['idx_platform_events_stream_subject_cursor is missing'];
|
|
1214
|
+
}
|
|
1215
|
+
if (observed.type !== 'index' ||
|
|
1216
|
+
observed.tbl_name !== 'platform_events' ||
|
|
1217
|
+
observed.sql === null ||
|
|
1218
|
+
normalizeSchemaObjectSql(observed.sql) !==
|
|
1219
|
+
CANONICAL_DURABLE_EVENT_REPLAY_INDEX_SQL) {
|
|
1220
|
+
return [
|
|
1221
|
+
'idx_platform_events_stream_subject_cursor does not match its canonical definition',
|
|
1222
|
+
];
|
|
1223
|
+
}
|
|
1224
|
+
return [];
|
|
1225
|
+
};
|
|
1226
|
+
const CANONICAL_PLATFORM_VECTOR_SCHEMA_OBJECTS = PLATFORM_VECTOR_SCHEMA_SQL.split(';')
|
|
1227
|
+
.map(statement => statement.trim())
|
|
1228
|
+
.filter(Boolean)
|
|
1229
|
+
.map(statement => {
|
|
1230
|
+
const declaration = /^CREATE\s+(TABLE|INDEX)\s+IF\s+NOT\s+EXISTS\s+([A-Za-z0-9_]+)/i.exec(statement);
|
|
1231
|
+
if (!declaration) {
|
|
1232
|
+
throw new Error('Invalid canonical platform vector schema statement');
|
|
1233
|
+
}
|
|
1234
|
+
const type = declaration[1]?.toLowerCase();
|
|
1235
|
+
const name = declaration[2];
|
|
1236
|
+
const indexTarget = type === 'index'
|
|
1237
|
+
? /\bON\s+([A-Za-z0-9_]+)/i.exec(statement)?.[1]
|
|
1238
|
+
: undefined;
|
|
1239
|
+
if (type === 'index' && !indexTarget) {
|
|
1240
|
+
throw new Error('Invalid canonical platform vector index statement');
|
|
1241
|
+
}
|
|
1242
|
+
return Object.freeze({
|
|
1243
|
+
type,
|
|
1244
|
+
name,
|
|
1245
|
+
table: indexTarget ?? name,
|
|
1246
|
+
sql: normalizeSchemaObjectSql(statement),
|
|
1247
|
+
});
|
|
1248
|
+
});
|
|
1249
|
+
/**
|
|
1250
|
+
* Compare migration v2's complete declared schema identity, not only its
|
|
1251
|
+
* columns. This covers column definitions, keys, foreign keys, checks, and
|
|
1252
|
+
* every explicit index while rejecting additional indexes or triggers on the
|
|
1253
|
+
* migration-owned tables.
|
|
1254
|
+
*/
|
|
1255
|
+
const collectPlatformVectorSchemaIdentityMismatches = (database) => {
|
|
1256
|
+
const expected = new Map(CANONICAL_PLATFORM_VECTOR_SCHEMA_OBJECTS.map(item => [item.name, item]));
|
|
1257
|
+
const ownedTables = new Set(CANONICAL_PLATFORM_VECTOR_SCHEMA_OBJECTS.filter(item => item.type === 'table').map(item => item.name));
|
|
1258
|
+
const actual = database
|
|
1259
|
+
.prepare(`SELECT type, name, tbl_name, sql
|
|
1260
|
+
FROM sqlite_master
|
|
1261
|
+
WHERE sql IS NOT NULL
|
|
1262
|
+
ORDER BY type, name`)
|
|
1263
|
+
.all().filter(item => expected.has(item.name) ||
|
|
1264
|
+
(ownedTables.has(item.tbl_name) &&
|
|
1265
|
+
(item.type === 'index' || item.type === 'trigger')));
|
|
1266
|
+
const actualByName = new Map(actual.map(item => [item.name, item]));
|
|
1267
|
+
const mismatches = [];
|
|
1268
|
+
for (const item of expected.values()) {
|
|
1269
|
+
const observed = actualByName.get(item.name);
|
|
1270
|
+
if (!observed) {
|
|
1271
|
+
mismatches.push(`${item.name} is missing`);
|
|
1272
|
+
continue;
|
|
1273
|
+
}
|
|
1274
|
+
if (observed.type !== item.type ||
|
|
1275
|
+
observed.tbl_name !== item.table ||
|
|
1276
|
+
normalizeSchemaObjectSql(observed.sql) !== item.sql) {
|
|
1277
|
+
mismatches.push(`${item.name} does not match its canonical definition`);
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
for (const item of actual) {
|
|
1281
|
+
if (!expected.has(item.name)) {
|
|
1282
|
+
mismatches.push(`${item.name} is not part of migration v2`);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
return mismatches;
|
|
1286
|
+
};
|
|
1287
|
+
const sameColumns = (actual, expected) => actual.length === expected.length &&
|
|
1288
|
+
actual.every((column, index) => column === expected[index]);
|
|
1289
|
+
const tableExists = (database, table) => Boolean(database
|
|
1290
|
+
.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
1291
|
+
.get(table));
|
|
1292
|
+
const indexColumns = (database, indexName) => database
|
|
1293
|
+
.prepare(`PRAGMA index_info(${quoteIdentifier(indexName)})`)
|
|
1294
|
+
.all()
|
|
1295
|
+
.sort((left, right) => left.seqno - right.seqno)
|
|
1296
|
+
.map(row => row.name);
|
|
1297
|
+
const collectMissingColumns = (database, requiredSchema) => {
|
|
1298
|
+
const missing = [];
|
|
1299
|
+
for (const [table, requiredColumns] of Object.entries(requiredSchema)) {
|
|
1300
|
+
if (!tableExists(database, table)) {
|
|
1301
|
+
missing.push(`${table} (table)`);
|
|
1302
|
+
continue;
|
|
1303
|
+
}
|
|
1304
|
+
const columns = new Set(database.prepare(`PRAGMA table_info(${table})`).all().map(column => column.name));
|
|
1305
|
+
for (const column of requiredColumns) {
|
|
1306
|
+
if (!columns.has(column))
|
|
1307
|
+
missing.push(`${table}.${column}`);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
return missing;
|
|
1311
|
+
};
|
|
1312
|
+
const collectMissingStructuralInvariants = (database, includeRequiredIndexes = true) => {
|
|
1313
|
+
const missing = [];
|
|
1314
|
+
for (const [table, expectedColumns] of Object.entries(REQUIRED_PRIMARY_KEYS)) {
|
|
1315
|
+
if (!tableExists(database, table))
|
|
1316
|
+
continue;
|
|
1317
|
+
const actualColumns = database
|
|
1318
|
+
.prepare(`PRAGMA table_info(${quoteIdentifier(table)})`)
|
|
1319
|
+
.all()
|
|
1320
|
+
.filter(column => column.pk > 0)
|
|
1321
|
+
.sort((left, right) => left.pk - right.pk)
|
|
1322
|
+
.map(column => column.name);
|
|
1323
|
+
if (!sameColumns(actualColumns, expectedColumns)) {
|
|
1324
|
+
missing.push(`${table} primary key (${expectedColumns.join(', ')})`);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
for (const [table, expectedKeys] of Object.entries(REQUIRED_UNIQUE_KEYS)) {
|
|
1328
|
+
if (!tableExists(database, table))
|
|
1329
|
+
continue;
|
|
1330
|
+
const indexes = database
|
|
1331
|
+
.prepare(`PRAGMA index_list(${quoteIdentifier(table)})`)
|
|
1332
|
+
.all();
|
|
1333
|
+
const uniqueColumns = indexes
|
|
1334
|
+
.filter(index => index.unique === 1)
|
|
1335
|
+
.map(index => indexColumns(database, index.name));
|
|
1336
|
+
for (const expectedColumns of expectedKeys) {
|
|
1337
|
+
if (!uniqueColumns.some(columns => sameColumns(columns, expectedColumns))) {
|
|
1338
|
+
missing.push(`${table} unique (${expectedColumns.join(', ')})`);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
for (const required of REQUIRED_FOREIGN_KEYS) {
|
|
1343
|
+
if (!tableExists(database, required.table))
|
|
1344
|
+
continue;
|
|
1345
|
+
const rows = database
|
|
1346
|
+
.prepare(`PRAGMA foreign_key_list(${quoteIdentifier(required.table)})`)
|
|
1347
|
+
.all();
|
|
1348
|
+
const grouped = new Map();
|
|
1349
|
+
for (const row of rows) {
|
|
1350
|
+
const group = grouped.get(row.id) ?? [];
|
|
1351
|
+
group.push(row);
|
|
1352
|
+
grouped.set(row.id, group);
|
|
1353
|
+
}
|
|
1354
|
+
const found = [...grouped.values()].some(group => {
|
|
1355
|
+
const ordered = [...group].sort((left, right) => left.seq - right.seq);
|
|
1356
|
+
return (ordered[0]?.table === required.referencedTable &&
|
|
1357
|
+
ordered[0]?.on_delete.toUpperCase() === required.onDelete &&
|
|
1358
|
+
sameColumns(ordered.map(row => row.from), required.columns) &&
|
|
1359
|
+
sameColumns(ordered.map(row => row.to), required.referencedColumns));
|
|
1360
|
+
});
|
|
1361
|
+
if (!found) {
|
|
1362
|
+
missing.push(`${required.table} foreign key (${required.columns.join(', ')}) -> ` +
|
|
1363
|
+
`${required.referencedTable} (${required.referencedColumns.join(', ')}) ` +
|
|
1364
|
+
`on delete ${required.onDelete}`);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
for (const required of includeRequiredIndexes ? REQUIRED_INDEXES : []) {
|
|
1368
|
+
if (!tableExists(database, required.table))
|
|
1369
|
+
continue;
|
|
1370
|
+
const row = database
|
|
1371
|
+
.prepare("SELECT tbl_name, sql FROM sqlite_master WHERE type = 'index' AND name = ?")
|
|
1372
|
+
.get(required.name);
|
|
1373
|
+
const indexList = database
|
|
1374
|
+
.prepare(`PRAGMA index_list(${quoteIdentifier(required.table)})`)
|
|
1375
|
+
.all();
|
|
1376
|
+
const listEntry = indexList.find(index => index.name === required.name);
|
|
1377
|
+
if (!row ||
|
|
1378
|
+
row.tbl_name !== required.table ||
|
|
1379
|
+
!listEntry ||
|
|
1380
|
+
!sameColumns(indexColumns(database, required.name), required.columns) ||
|
|
1381
|
+
(required.unique === true && listEntry.unique !== 1) ||
|
|
1382
|
+
(required.sqlFragment !== undefined &&
|
|
1383
|
+
!normalizeSql(row.sql ?? '').includes(normalizeSql(required.sqlFragment)))) {
|
|
1384
|
+
missing.push(`index ${required.name} (${required.columns.join(', ')})`);
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
for (const [table, fragments] of Object.entries(REQUIRED_TABLE_SQL_FRAGMENTS)) {
|
|
1388
|
+
if (!tableExists(database, table))
|
|
1389
|
+
continue;
|
|
1390
|
+
const row = database
|
|
1391
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
1392
|
+
.get(table);
|
|
1393
|
+
const normalized = normalizeSql(row?.sql ?? '');
|
|
1394
|
+
for (const fragment of fragments) {
|
|
1395
|
+
if (!normalized.includes(normalizeSql(fragment))) {
|
|
1396
|
+
missing.push(`${table} constraint ${fragment}`);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
return missing;
|
|
1401
|
+
};
|
|
1402
|
+
const collectMissingSchema = (database) => [
|
|
1403
|
+
...collectMissingColumns(database, REQUIRED_SCHEMA),
|
|
1404
|
+
...collectMissingStructuralInvariants(database),
|
|
1405
|
+
...collectMissingIdentityAccountRetirementSchema(database),
|
|
1406
|
+
...collectMissingWorkPreviewUpstreamSchema(database),
|
|
1407
|
+
...collectMissingDurableEventIdempotencySchema(database),
|
|
1408
|
+
...collectMissingResourceDeletionLifecycleSchema(database),
|
|
1409
|
+
];
|
|
1410
|
+
const collectMissingMigrationLedgerSchema = (database) => [
|
|
1411
|
+
...collectMissingColumns(database, {
|
|
1412
|
+
[MIGRATION_TABLE]: ['version', 'name', 'checksum', 'applied_at'],
|
|
1413
|
+
}),
|
|
1414
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes(MIGRATION_TABLE)),
|
|
1415
|
+
];
|
|
1416
|
+
const collectMissingLegacySchema = (database) => [
|
|
1417
|
+
...collectMissingColumns(database, LEGACY_REQUIRED_SCHEMA),
|
|
1418
|
+
...collectMissingStructuralInvariants(database).filter(item => !item.includes('platform_') &&
|
|
1419
|
+
!item.includes('idx_users_email_lookup') &&
|
|
1420
|
+
!item.includes('idx_voice_profiles_name_lookup')),
|
|
1421
|
+
];
|
|
1422
|
+
const collectMissingIdentityEmailLookupSchema = (database) => [
|
|
1423
|
+
...collectMissingColumns(database, IDENTITY_EMAIL_LOOKUP_REQUIRED_SCHEMA),
|
|
1424
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('idx_users_email_lookup')),
|
|
1425
|
+
];
|
|
1426
|
+
const collectMissingPlatformVectorSchema = (database) => [
|
|
1427
|
+
...collectMissingColumns(database, PLATFORM_VECTOR_REQUIRED_SCHEMA),
|
|
1428
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('platform_vector')),
|
|
1429
|
+
];
|
|
1430
|
+
const collectMissingDurableJobsEventsSchema = (database) => [
|
|
1431
|
+
...collectMissingColumns(database, DURABLE_JOBS_EVENTS_REQUIRED_SCHEMA),
|
|
1432
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('platform_job') ||
|
|
1433
|
+
(item.includes('platform_event') &&
|
|
1434
|
+
!item.includes('idx_platform_events_stream_subject_cursor')) ||
|
|
1435
|
+
item.includes('durable job')),
|
|
1436
|
+
];
|
|
1437
|
+
const collectMissingDurableEventReplayIndexSchema = (database) => collectMissingStructuralInvariants(database).filter(item => item.includes('idx_platform_events_stream_subject_cursor'));
|
|
1438
|
+
const collectMissingBlobReferenceSchema = (database) => [
|
|
1439
|
+
...collectMissingColumns(database, BLOB_REFERENCE_REQUIRED_SCHEMA),
|
|
1440
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('platform_blob_reference')),
|
|
1441
|
+
];
|
|
1442
|
+
const collectMissingBlobQuotaSchema = (database) => [
|
|
1443
|
+
...collectMissingColumns(database, BLOB_QUOTA_REQUIRED_SCHEMA),
|
|
1444
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('platform_blob_quota')),
|
|
1445
|
+
];
|
|
1446
|
+
const collectMissingVoiceProfileNameLookupSchema = (database) => [
|
|
1447
|
+
...collectMissingColumns(database, VOICE_PROFILE_NAME_LOOKUP_REQUIRED_SCHEMA),
|
|
1448
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('idx_voice_profiles_name_lookup')),
|
|
1449
|
+
];
|
|
1450
|
+
const collectMissingPluginDefinitionSchema = (database) => [
|
|
1451
|
+
...collectMissingColumns(database, PLUGIN_DEFINITION_REQUIRED_SCHEMA),
|
|
1452
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('plugin_definition')),
|
|
1453
|
+
];
|
|
1454
|
+
const collectMissingWorkPreviewUpstreamSchema = (database) => collectMissingColumns(database, WORK_PREVIEW_UPSTREAM_REQUIRED_SCHEMA);
|
|
1455
|
+
const collectMissingDurableEventIdempotencySchema = (database) => collectMissingColumns(database, DURABLE_EVENT_IDEMPOTENCY_REQUIRED_SCHEMA);
|
|
1456
|
+
const collectMissingResourceDeletionLifecycleSchema = (database) => [
|
|
1457
|
+
...collectMissingColumns(database, RESOURCE_DELETION_LIFECYCLE_REQUIRED_SCHEMA),
|
|
1458
|
+
...collectMissingStructuralInvariants(database).filter(item => item.includes('platform_resource_deletion_tombstones')),
|
|
1459
|
+
];
|
|
1460
|
+
const collectMissingIdentityAccountRetirementSchema = (database) => {
|
|
1461
|
+
const row = database
|
|
1462
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'users'")
|
|
1463
|
+
.get();
|
|
1464
|
+
const normalized = normalizeSql(row?.sql ?? '');
|
|
1465
|
+
return normalized.includes(normalizeSql("account_status IN ('pending', 'active', 'retiring')"))
|
|
1466
|
+
? []
|
|
1467
|
+
: ['users account_status retiring constraint'];
|
|
1468
|
+
};
|
|
1469
|
+
function collectMissingSchemaAtVersion(database, version) {
|
|
1470
|
+
if (version <= 0)
|
|
1471
|
+
return collectMissingLegacyBootstrapSchema(database);
|
|
1472
|
+
return [
|
|
1473
|
+
...collectMissingLegacySchema(database),
|
|
1474
|
+
...(version >= 2 ? collectMissingPlatformVectorSchema(database) : []),
|
|
1475
|
+
...(version >= 3 ? collectMissingDurableJobsEventsSchema(database) : []),
|
|
1476
|
+
...(version >= 4 ? collectMissingIdentityEmailLookupSchema(database) : []),
|
|
1477
|
+
...(version >= 5 ? collectMissingBlobReferenceSchema(database) : []),
|
|
1478
|
+
...(version >= 6
|
|
1479
|
+
? collectMissingVoiceProfileNameLookupSchema(database)
|
|
1480
|
+
: []),
|
|
1481
|
+
...(version >= 7 ? collectMissingPluginDefinitionSchema(database) : []),
|
|
1482
|
+
...(version >= 8 ? collectMissingBlobQuotaSchema(database) : []),
|
|
1483
|
+
...(version >= 9
|
|
1484
|
+
? collectMissingIdentityAccountRetirementSchema(database)
|
|
1485
|
+
: []),
|
|
1486
|
+
...(version >= 10 ? collectMissingWorkPreviewUpstreamSchema(database) : []),
|
|
1487
|
+
...(version >= 11
|
|
1488
|
+
? collectMissingDurableEventIdempotencySchema(database)
|
|
1489
|
+
: []),
|
|
1490
|
+
...(version >= 12
|
|
1491
|
+
? collectMissingResourceDeletionLifecycleSchema(database)
|
|
1492
|
+
: []),
|
|
1493
|
+
...(version >= 13
|
|
1494
|
+
? collectMissingDurableEventReplayIndexSchema(database)
|
|
1495
|
+
: []),
|
|
1496
|
+
];
|
|
1497
|
+
}
|
|
1498
|
+
const collectMissingLegacyBootstrapSchema = (database) => {
|
|
1499
|
+
const knownTables = Object.keys(LEGACY_REQUIRED_SCHEMA).filter(table => tableExists(database, table));
|
|
1500
|
+
if (knownTables.length === 0)
|
|
1501
|
+
return [];
|
|
1502
|
+
const missing = [];
|
|
1503
|
+
for (const table of LEGACY_BOOTSTRAP_CORE_TABLES) {
|
|
1504
|
+
if (!tableExists(database, table))
|
|
1505
|
+
missing.push(`${table} (table)`);
|
|
1506
|
+
}
|
|
1507
|
+
const existingHistoricalSchema = Object.fromEntries(knownTables.map(table => {
|
|
1508
|
+
const additive = new Set(LEGACY_ADDITIVE_COLUMNS[table] ?? []);
|
|
1509
|
+
return [
|
|
1510
|
+
table,
|
|
1511
|
+
LEGACY_REQUIRED_SCHEMA[table].filter(column => !additive.has(column)),
|
|
1512
|
+
];
|
|
1513
|
+
}));
|
|
1514
|
+
missing.push(...collectMissingColumns(database, existingHistoricalSchema),
|
|
1515
|
+
// Inline bootstrap safely recreates named indexes. Keys, foreign keys,
|
|
1516
|
+
// uniqueness, and table constraints cannot be repaired additively and
|
|
1517
|
+
// therefore must already be trustworthy.
|
|
1518
|
+
...collectMissingStructuralInvariants(database, false).filter(item => !item.includes(MIGRATION_TABLE)));
|
|
1519
|
+
return [...new Set(missing)];
|
|
1520
|
+
};
|
|
1521
|
+
const validateCurrentSchema = (database) => {
|
|
1522
|
+
const missing = collectMissingSchema(database);
|
|
1523
|
+
if (missing.length > 0) {
|
|
1524
|
+
throw new Error(`SQLite schema is incomplete; missing ${missing.slice(0, 20).join(', ')}${missing.length > 20 ? ` and ${missing.length - 20} more` : ''}`);
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
// Released ledger checksums are immutable protocol constants. In particular,
|
|
1528
|
+
// v1 must never change when the current required schema grows.
|
|
1529
|
+
const BASELINE_MIGRATION_CHECKSUM = '6027d48757e31a6d2a65819c46a5b641bfd9a8bde50628757e2d682ec3e320bf';
|
|
1530
|
+
const PLATFORM_VECTOR_MIGRATION_CHECKSUM = '633f4d535c207fb212764f4fddf43536678a3f02e8ccad52628b7223d17b00d5';
|
|
1531
|
+
const LEGACY_PLATFORM_VECTOR_MIGRATION_CHECKSUM = 'VECTOR_CHECKSUM_TO_FREEZE';
|
|
1532
|
+
const DURABLE_JOBS_EVENTS_MIGRATION_CHECKSUM = 'dbc2cfa903c0ab173acc2e29f9aa576b7ba744816fb819492271c39a4fbd23de';
|
|
1533
|
+
const IDENTITY_EMAIL_LOOKUP_MIGRATION_CHECKSUM = 'abac261ef3848667aa3ad5dbb47c123b119cadbc0738c167c9b9d35b057a43a0';
|
|
1534
|
+
const BLOB_REFERENCE_MIGRATION_CHECKSUM = '84a2c0cf783c81f46e90c73ae2e62ca80b89669e672767f94af7ea5d37098b79';
|
|
1535
|
+
const VOICE_PROFILE_NAME_LOOKUP_MIGRATION_CHECKSUM = '6162d4feb454f812ea1ddf88c472943f1fc07da5933c29986d4b8b27d6156df6';
|
|
1536
|
+
const PLUGIN_DEFINITION_MIGRATION_CHECKSUM = '7092b4bb02ad71be4ef7d6106ed5bab6d5b76e9ec8d98f36f7a8a6c3a70c84c6';
|
|
1537
|
+
const BLOB_QUOTA_MIGRATION_CHECKSUM = 'c6dd6ff729b92dc935aacd5ea236bbbf6f8f455999abd3ab8f687457ec0ca998';
|
|
1538
|
+
const IDENTITY_ACCOUNT_RETIREMENT_MIGRATION_CHECKSUM = '72c57042dd74cba8b1b22395bfe7942e62e269a0041706711094565fb6860657';
|
|
1539
|
+
const WORK_PREVIEW_UPSTREAM_MIGRATION_CHECKSUM = 'aa2023e736da5a2b63ab2e39c378a3c43fc6f40be9318eec1397dff83c4a9358';
|
|
1540
|
+
const DURABLE_EVENT_IDEMPOTENCY_MIGRATION_CHECKSUM = 'fe9aee7dc21dc4ca6a5bdcd0fcd5788104501f68bc2c72e83faf9b6ce6514d44';
|
|
1541
|
+
const RESOURCE_DELETION_LIFECYCLE_MIGRATION_CHECKSUM = 'a72e862afe109daf68b7ec8e445ef359bc3550a5ac8973d135cf7a18eb5bf1cc';
|
|
1542
|
+
const DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM = '7d6b769ceadd08791c77ac5c5a1d7bd61a63d87cac87da56ae847c4067cacdad';
|
|
1543
|
+
const LEGACY_DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM = 'DURABLE_EVENT_REPLAY_INDEX_CHECKSUM_TO_FREEZE';
|
|
1544
|
+
const MIGRATIONS = [
|
|
1545
|
+
{
|
|
1546
|
+
version: 1,
|
|
1547
|
+
name: 'adopt-current-schema',
|
|
1548
|
+
checksum: BASELINE_MIGRATION_CHECKSUM,
|
|
1549
|
+
apply(database) {
|
|
1550
|
+
ensurePersonaPersistence(database);
|
|
1551
|
+
const missing = collectMissingLegacySchema(database);
|
|
1552
|
+
if (missing.length > 0) {
|
|
1553
|
+
throw new Error(`SQLite schema is incomplete; missing ${missing.join(', ')}`);
|
|
1554
|
+
}
|
|
1555
|
+
},
|
|
1556
|
+
},
|
|
1557
|
+
{
|
|
1558
|
+
version: 2,
|
|
1559
|
+
name: 'platform-vector-storage',
|
|
1560
|
+
checksum: PLATFORM_VECTOR_MIGRATION_CHECKSUM,
|
|
1561
|
+
apply(database) {
|
|
1562
|
+
database.exec(PLATFORM_VECTOR_SCHEMA_SQL);
|
|
1563
|
+
const missing = collectMissingPlatformVectorSchema(database);
|
|
1564
|
+
if (missing.length > 0) {
|
|
1565
|
+
throw new Error(`SQLite vector schema is incomplete; missing ${missing.join(', ')}`);
|
|
1566
|
+
}
|
|
1567
|
+
},
|
|
1568
|
+
},
|
|
1569
|
+
{
|
|
1570
|
+
version: 3,
|
|
1571
|
+
name: 'durable-jobs-events',
|
|
1572
|
+
checksum: DURABLE_JOBS_EVENTS_MIGRATION_CHECKSUM,
|
|
1573
|
+
apply(database) {
|
|
1574
|
+
database.exec(DURABLE_JOBS_EVENTS_SCHEMA_SQL);
|
|
1575
|
+
const missing = collectMissingDurableJobsEventsSchema(database);
|
|
1576
|
+
if (missing.length > 0) {
|
|
1577
|
+
throw new Error(`SQLite durable jobs schema is incomplete; missing ${missing.join(', ')}`);
|
|
1578
|
+
}
|
|
1579
|
+
},
|
|
1580
|
+
},
|
|
1581
|
+
{
|
|
1582
|
+
version: 4,
|
|
1583
|
+
name: 'identity-email-lookup',
|
|
1584
|
+
checksum: IDENTITY_EMAIL_LOOKUP_MIGRATION_CHECKSUM,
|
|
1585
|
+
apply(database) {
|
|
1586
|
+
addColumnIfMissing(database, 'users', 'email_lookup', 'TEXT');
|
|
1587
|
+
database.exec(`
|
|
1588
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email_lookup
|
|
1589
|
+
ON users(email_lookup)
|
|
1590
|
+
WHERE email_lookup IS NOT NULL;
|
|
1591
|
+
`);
|
|
1592
|
+
const missing = collectMissingIdentityEmailLookupSchema(database);
|
|
1593
|
+
if (missing.length > 0) {
|
|
1594
|
+
throw new Error(`SQLite identity email lookup schema is incomplete; missing ${missing.join(', ')}`);
|
|
1595
|
+
}
|
|
1596
|
+
},
|
|
1597
|
+
},
|
|
1598
|
+
{
|
|
1599
|
+
version: 5,
|
|
1600
|
+
name: 'blob-references',
|
|
1601
|
+
checksum: BLOB_REFERENCE_MIGRATION_CHECKSUM,
|
|
1602
|
+
apply(database) {
|
|
1603
|
+
database.exec(SQLITE_BLOB_REFERENCE_SCHEMA_SQL);
|
|
1604
|
+
const missing = collectMissingBlobReferenceSchema(database);
|
|
1605
|
+
if (missing.length > 0) {
|
|
1606
|
+
throw new Error(`SQLite blob reference schema is incomplete; missing ${missing.join(', ')}`);
|
|
1607
|
+
}
|
|
1608
|
+
},
|
|
1609
|
+
},
|
|
1610
|
+
{
|
|
1611
|
+
version: 6,
|
|
1612
|
+
name: 'voice-profile-name-lookup',
|
|
1613
|
+
checksum: VOICE_PROFILE_NAME_LOOKUP_MIGRATION_CHECKSUM,
|
|
1614
|
+
apply(database) {
|
|
1615
|
+
// Existing names are encrypted with per-record authenticated data, so
|
|
1616
|
+
// the adapter backfills their keyed lookup after migrations complete.
|
|
1617
|
+
addColumnIfMissing(database, 'voice_profiles', 'name_lookup', 'TEXT');
|
|
1618
|
+
database.exec(`
|
|
1619
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_voice_profiles_name_lookup
|
|
1620
|
+
ON voice_profiles(user_id, plugin_id, model, name_lookup)
|
|
1621
|
+
WHERE name_lookup IS NOT NULL;
|
|
1622
|
+
`);
|
|
1623
|
+
const missing = collectMissingVoiceProfileNameLookupSchema(database);
|
|
1624
|
+
if (missing.length > 0) {
|
|
1625
|
+
throw new Error(`SQLite voice profile lookup schema is incomplete; missing ${missing.join(', ')}`);
|
|
1626
|
+
}
|
|
1627
|
+
},
|
|
1628
|
+
},
|
|
1629
|
+
{
|
|
1630
|
+
version: 7,
|
|
1631
|
+
name: 'shared-plugin-definitions',
|
|
1632
|
+
checksum: PLUGIN_DEFINITION_MIGRATION_CHECKSUM,
|
|
1633
|
+
apply(database) {
|
|
1634
|
+
database.exec(PLUGIN_DEFINITION_SCHEMA_SQL);
|
|
1635
|
+
const missing = collectMissingPluginDefinitionSchema(database);
|
|
1636
|
+
if (missing.length > 0) {
|
|
1637
|
+
throw new Error(`SQLite plugin definition schema is incomplete; missing ${missing.join(', ')}`);
|
|
1638
|
+
}
|
|
1639
|
+
},
|
|
1640
|
+
},
|
|
1641
|
+
{
|
|
1642
|
+
version: 8,
|
|
1643
|
+
name: 'blob-quotas',
|
|
1644
|
+
checksum: BLOB_QUOTA_MIGRATION_CHECKSUM,
|
|
1645
|
+
apply(database) {
|
|
1646
|
+
database.exec(SQLITE_BLOB_QUOTA_SCHEMA_SQL);
|
|
1647
|
+
const missing = collectMissingBlobQuotaSchema(database);
|
|
1648
|
+
if (missing.length > 0) {
|
|
1649
|
+
throw new Error(`SQLite blob quota schema is incomplete; missing ${missing.join(', ')}`);
|
|
1650
|
+
}
|
|
1651
|
+
},
|
|
1652
|
+
},
|
|
1653
|
+
{
|
|
1654
|
+
version: 9,
|
|
1655
|
+
name: 'identity-account-retirement',
|
|
1656
|
+
checksum: IDENTITY_ACCOUNT_RETIREMENT_MIGRATION_CHECKSUM,
|
|
1657
|
+
requiresForeignKeysDisabled: true,
|
|
1658
|
+
apply(database) {
|
|
1659
|
+
database.exec(IDENTITY_ACCOUNT_RETIREMENT_SCHEMA_SQL);
|
|
1660
|
+
database.exec(`
|
|
1661
|
+
INSERT INTO users__retiring_v9 (
|
|
1662
|
+
id, username, email, email_lookup, password_hash, role,
|
|
1663
|
+
account_status, approved_at, approved_by, avatar, created_at,
|
|
1664
|
+
updated_at
|
|
1665
|
+
)
|
|
1666
|
+
SELECT id, username, email, email_lookup, password_hash, role,
|
|
1667
|
+
account_status, approved_at, approved_by, avatar, created_at,
|
|
1668
|
+
updated_at
|
|
1669
|
+
FROM users;
|
|
1670
|
+
DROP TABLE users;
|
|
1671
|
+
ALTER TABLE users__retiring_v9 RENAME TO users;
|
|
1672
|
+
CREATE UNIQUE INDEX idx_users_email_lookup
|
|
1673
|
+
ON users(email_lookup)
|
|
1674
|
+
WHERE email_lookup IS NOT NULL;
|
|
1675
|
+
`);
|
|
1676
|
+
const missing = collectMissingIdentityAccountRetirementSchema(database);
|
|
1677
|
+
if (missing.length > 0) {
|
|
1678
|
+
throw new Error(`SQLite account retirement schema is incomplete; missing ${missing.join(', ')}`);
|
|
1679
|
+
}
|
|
1680
|
+
},
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
version: 10,
|
|
1684
|
+
name: 'work-preview-upstream',
|
|
1685
|
+
checksum: WORK_PREVIEW_UPSTREAM_MIGRATION_CHECKSUM,
|
|
1686
|
+
apply(database) {
|
|
1687
|
+
addColumnIfMissing(database, 'work_tasks', 'preview_upstream_host', `TEXT CHECK (
|
|
1688
|
+
preview_upstream_host IS NULL
|
|
1689
|
+
OR length(preview_upstream_host) BETWEEN 1 AND 253
|
|
1690
|
+
)`);
|
|
1691
|
+
addColumnIfMissing(database, 'work_tasks', 'preview_upstream_port', `INTEGER CHECK (
|
|
1692
|
+
preview_upstream_port IS NULL
|
|
1693
|
+
OR preview_upstream_port BETWEEN 1 AND 65535
|
|
1694
|
+
)`);
|
|
1695
|
+
const missing = collectMissingWorkPreviewUpstreamSchema(database);
|
|
1696
|
+
if (missing.length > 0) {
|
|
1697
|
+
throw new Error(`SQLite Work preview upstream schema is incomplete; missing ${missing.join(', ')}`);
|
|
1698
|
+
}
|
|
1699
|
+
},
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
version: 11,
|
|
1703
|
+
name: 'durable-event-idempotency',
|
|
1704
|
+
checksum: DURABLE_EVENT_IDEMPOTENCY_MIGRATION_CHECKSUM,
|
|
1705
|
+
apply(database) {
|
|
1706
|
+
addColumnIfMissing(database, 'platform_events', 'request_fingerprint', `TEXT NOT NULL
|
|
1707
|
+
DEFAULT '0000000000000000000000000000000000000000000000000000000000000000'
|
|
1708
|
+
CHECK (
|
|
1709
|
+
length(request_fingerprint) = 64
|
|
1710
|
+
AND request_fingerprint NOT GLOB '*[^0-9a-f]*'
|
|
1711
|
+
)`);
|
|
1712
|
+
const missing = collectMissingDurableEventIdempotencySchema(database);
|
|
1713
|
+
if (missing.length > 0) {
|
|
1714
|
+
throw new Error(`SQLite durable event idempotency schema is incomplete; missing ${missing.join(', ')}`);
|
|
1715
|
+
}
|
|
1716
|
+
},
|
|
1717
|
+
},
|
|
1718
|
+
{
|
|
1719
|
+
version: 12,
|
|
1720
|
+
name: 'resource-deletion-lifecycle',
|
|
1721
|
+
checksum: RESOURCE_DELETION_LIFECYCLE_MIGRATION_CHECKSUM,
|
|
1722
|
+
apply(database) {
|
|
1723
|
+
database.exec(RESOURCE_DELETION_LIFECYCLE_SCHEMA_SQL);
|
|
1724
|
+
const missing = collectMissingResourceDeletionLifecycleSchema(database);
|
|
1725
|
+
if (missing.length > 0) {
|
|
1726
|
+
throw new Error(`SQLite resource deletion lifecycle schema is incomplete; missing ${missing.join(', ')}`);
|
|
1727
|
+
}
|
|
1728
|
+
},
|
|
1729
|
+
},
|
|
1730
|
+
{
|
|
1731
|
+
version: 13,
|
|
1732
|
+
name: 'durable-event-replay-index',
|
|
1733
|
+
checksum: DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM,
|
|
1734
|
+
apply(database) {
|
|
1735
|
+
database.exec(DURABLE_EVENT_REPLAY_INDEX_SCHEMA_SQL);
|
|
1736
|
+
const missing = collectMissingDurableEventReplayIndexSchema(database);
|
|
1737
|
+
if (missing.length > 0) {
|
|
1738
|
+
throw new Error(`SQLite durable event replay index is incomplete; missing ${missing.join(', ')}`);
|
|
1739
|
+
}
|
|
1740
|
+
},
|
|
1741
|
+
},
|
|
1742
|
+
];
|
|
1743
|
+
/**
|
|
1744
|
+
* Whether a pending migration needs foreign-key enforcement suspended before
|
|
1745
|
+
* its surrounding transaction begins. SQLite ignores `PRAGMA foreign_keys`
|
|
1746
|
+
* changes while a transaction is active, so bootstrap must establish this
|
|
1747
|
+
* connection state before opening its atomic schema transaction.
|
|
1748
|
+
*/
|
|
1749
|
+
export const sqliteMigrationsRequireForeignKeysDisabledAfter = (currentVersion) => MIGRATIONS.some(migration => migration.version > currentVersion &&
|
|
1750
|
+
migration.requiresForeignKeysDisabled === true);
|
|
1751
|
+
/** Public, read-only migration identities for adapters and conformance tests. */
|
|
1752
|
+
export const SQLITE_MIGRATION_CONTRACT = Object.freeze(MIGRATIONS.map(migration => Object.freeze({
|
|
1753
|
+
version: migration.version,
|
|
1754
|
+
name: migration.name,
|
|
1755
|
+
checksum: migration.checksum,
|
|
1756
|
+
})));
|
|
1757
|
+
const targetVersion = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
|
|
1758
|
+
const minimumSupportedVersion = 1;
|
|
1759
|
+
const readAppliedMigrations = (database) => database
|
|
1760
|
+
.prepare(`SELECT version, name, checksum
|
|
1761
|
+
FROM ${MIGRATION_TABLE}
|
|
1762
|
+
ORDER BY version ASC`)
|
|
1763
|
+
.all();
|
|
1764
|
+
const validateAppliedMigrations = (applied, options = {}) => {
|
|
1765
|
+
const currentVersion = applied[applied.length - 1]?.version ?? 0;
|
|
1766
|
+
let legacyPlatformVectorChecksumRepairRequired = false;
|
|
1767
|
+
let legacyDurableEventReplayIndexChecksumRepairRequired = false;
|
|
1768
|
+
if (currentVersion > targetVersion) {
|
|
1769
|
+
throw new Error(`Database schema version ${currentVersion} is newer than supported version ${targetVersion}`);
|
|
1770
|
+
}
|
|
1771
|
+
for (const [index, row] of applied.entries()) {
|
|
1772
|
+
if (row.version !== index + 1) {
|
|
1773
|
+
throw new Error(`Database migration sequence has a gap before version ${row.version}`);
|
|
1774
|
+
}
|
|
1775
|
+
const expected = MIGRATIONS.find(item => item.version === row.version);
|
|
1776
|
+
if (!expected) {
|
|
1777
|
+
throw new Error(`Unknown database migration version ${row.version}`);
|
|
1778
|
+
}
|
|
1779
|
+
if (row.name !== expected.name) {
|
|
1780
|
+
throw new Error(`Database migration ${row.version} name mismatch: expected ${expected.name}`);
|
|
1781
|
+
}
|
|
1782
|
+
if (row.checksum !== expected.checksum) {
|
|
1783
|
+
if (options.allowLegacyPlatformVectorChecksum === true &&
|
|
1784
|
+
row.version === 2 &&
|
|
1785
|
+
row.name === 'platform-vector-storage' &&
|
|
1786
|
+
row.checksum === LEGACY_PLATFORM_VECTOR_MIGRATION_CHECKSUM) {
|
|
1787
|
+
legacyPlatformVectorChecksumRepairRequired = true;
|
|
1788
|
+
continue;
|
|
1789
|
+
}
|
|
1790
|
+
if (options.allowLegacyDurableEventReplayIndexChecksum === true &&
|
|
1791
|
+
row.version === 13 &&
|
|
1792
|
+
row.name === 'durable-event-replay-index' &&
|
|
1793
|
+
row.checksum === LEGACY_DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM) {
|
|
1794
|
+
legacyDurableEventReplayIndexChecksumRepairRequired = true;
|
|
1795
|
+
continue;
|
|
1796
|
+
}
|
|
1797
|
+
throw new Error(`Database migration ${row.version} checksum mismatch for ${row.name}`);
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
return {
|
|
1801
|
+
currentVersion,
|
|
1802
|
+
legacyPlatformVectorChecksumRepairRequired,
|
|
1803
|
+
legacyDurableEventReplayIndexChecksumRepairRequired,
|
|
1804
|
+
};
|
|
1805
|
+
};
|
|
1806
|
+
const validateAppliedMigrationsForLiveRepair = (database, applied) => {
|
|
1807
|
+
const validation = validateAppliedMigrations(applied, {
|
|
1808
|
+
allowLegacyPlatformVectorChecksum: true,
|
|
1809
|
+
allowLegacyDurableEventReplayIndexChecksum: true,
|
|
1810
|
+
});
|
|
1811
|
+
if (validation.legacyPlatformVectorChecksumRepairRequired) {
|
|
1812
|
+
const mismatches = collectPlatformVectorSchemaIdentityMismatches(database);
|
|
1813
|
+
if (mismatches.length > 0) {
|
|
1814
|
+
throw new Error('Database migration 2 legacy checksum cannot be repaired because ' +
|
|
1815
|
+
`the platform vector schema is not canonical: ${mismatches.join(', ')}`);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
if (validation.legacyDurableEventReplayIndexChecksumRepairRequired) {
|
|
1819
|
+
const mismatches = collectDurableEventReplayIndexIdentityMismatches(database);
|
|
1820
|
+
if (mismatches.length > 0) {
|
|
1821
|
+
throw new Error('Database migration 13 legacy checksum cannot be repaired because ' +
|
|
1822
|
+
`the durable event replay index is not canonical: ${mismatches.join(', ')}`);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
return validation;
|
|
1826
|
+
};
|
|
1827
|
+
/**
|
|
1828
|
+
* Fail closed unless checksummed migration v2 installed the complete vector
|
|
1829
|
+
* schema. Storage adapters must never create application tables themselves.
|
|
1830
|
+
*/
|
|
1831
|
+
export function assertPlatformVectorMigrationReady(database) {
|
|
1832
|
+
if (!tableExists(database, MIGRATION_TABLE)) {
|
|
1833
|
+
throw new Error('The SQLite migration ledger is missing');
|
|
1834
|
+
}
|
|
1835
|
+
const { currentVersion } = validateAppliedMigrations(readAppliedMigrations(database));
|
|
1836
|
+
if (currentVersion < 2) {
|
|
1837
|
+
throw new Error('Platform vector storage requires SQLite migration version 2');
|
|
1838
|
+
}
|
|
1839
|
+
const missing = collectMissingPlatformVectorSchema(database);
|
|
1840
|
+
if (missing.length > 0) {
|
|
1841
|
+
throw new Error(`SQLite vector schema is incomplete; missing ${missing.join(', ')}`);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
/** Fail closed unless checksummed migration v3 installed durable job state. */
|
|
1845
|
+
export function assertDurableJobMigrationReady(database) {
|
|
1846
|
+
if (!tableExists(database, MIGRATION_TABLE)) {
|
|
1847
|
+
throw new Error('The SQLite migration ledger is missing');
|
|
1848
|
+
}
|
|
1849
|
+
const { currentVersion } = validateAppliedMigrations(readAppliedMigrations(database));
|
|
1850
|
+
if (currentVersion < 11) {
|
|
1851
|
+
throw new Error('Durable jobs require SQLite migration version 11');
|
|
1852
|
+
}
|
|
1853
|
+
const missing = [
|
|
1854
|
+
...collectMissingDurableJobsEventsSchema(database),
|
|
1855
|
+
...collectMissingDurableEventIdempotencySchema(database),
|
|
1856
|
+
];
|
|
1857
|
+
if (missing.length > 0) {
|
|
1858
|
+
throw new Error(`SQLite durable jobs schema is incomplete; missing ${missing.join(', ')}`);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Inspect an open SQLite database without changing it. Recovery and health
|
|
1863
|
+
* checks use the same contract and checksums as the startup coordinator.
|
|
1864
|
+
*/
|
|
1865
|
+
export function inspectSQLiteSchema(database) {
|
|
1866
|
+
const missingSchema = collectMissingSchema(database);
|
|
1867
|
+
const ledgerPresent = Boolean(database
|
|
1868
|
+
.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
1869
|
+
.get(MIGRATION_TABLE));
|
|
1870
|
+
if (!ledgerPresent) {
|
|
1871
|
+
const missingBootstrap = collectMissingLegacyBootstrapSchema(database);
|
|
1872
|
+
const canBootstrap = missingBootstrap.length === 0;
|
|
1873
|
+
return {
|
|
1874
|
+
dialect: 'sqlite',
|
|
1875
|
+
status: canBootstrap ? 'uninitialized' : 'incompatible',
|
|
1876
|
+
compatible: false,
|
|
1877
|
+
ledgerPresent: false,
|
|
1878
|
+
currentVersion: 0,
|
|
1879
|
+
targetVersion,
|
|
1880
|
+
minimumSupportedVersion,
|
|
1881
|
+
missing: missingSchema,
|
|
1882
|
+
appliedMigrations: [],
|
|
1883
|
+
reason: canBootstrap
|
|
1884
|
+
? 'Migration ledger has not been adopted'
|
|
1885
|
+
: `SQLite ledgerless schema is incompatible; missing ${missingBootstrap.join(', ')}`,
|
|
1886
|
+
};
|
|
1887
|
+
}
|
|
1888
|
+
const missingLedger = collectMissingMigrationLedgerSchema(database);
|
|
1889
|
+
const missing = [...missingLedger, ...missingSchema];
|
|
1890
|
+
if (missingLedger.length > 0) {
|
|
1891
|
+
return {
|
|
1892
|
+
dialect: 'sqlite',
|
|
1893
|
+
status: 'incompatible',
|
|
1894
|
+
compatible: false,
|
|
1895
|
+
ledgerPresent: true,
|
|
1896
|
+
currentVersion: 0,
|
|
1897
|
+
targetVersion,
|
|
1898
|
+
minimumSupportedVersion,
|
|
1899
|
+
missing,
|
|
1900
|
+
appliedMigrations: [],
|
|
1901
|
+
reason: `SQLite migration ledger is incompatible; missing ${missingLedger.join(', ')}`,
|
|
1902
|
+
};
|
|
1903
|
+
}
|
|
1904
|
+
let applied;
|
|
1905
|
+
try {
|
|
1906
|
+
applied = readAppliedMigrations(database);
|
|
1907
|
+
}
|
|
1908
|
+
catch (error) {
|
|
1909
|
+
return {
|
|
1910
|
+
dialect: 'sqlite',
|
|
1911
|
+
status: 'incompatible',
|
|
1912
|
+
compatible: false,
|
|
1913
|
+
ledgerPresent: true,
|
|
1914
|
+
currentVersion: 0,
|
|
1915
|
+
targetVersion,
|
|
1916
|
+
minimumSupportedVersion,
|
|
1917
|
+
missing,
|
|
1918
|
+
appliedMigrations: [],
|
|
1919
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1922
|
+
const appliedMigrations = applied.map(row => {
|
|
1923
|
+
const expected = MIGRATIONS.find(item => item.version === row.version);
|
|
1924
|
+
return {
|
|
1925
|
+
...row,
|
|
1926
|
+
checksumMatches: expected?.name === row.name && expected.checksum === row.checksum,
|
|
1927
|
+
};
|
|
1928
|
+
});
|
|
1929
|
+
const currentVersion = applied[applied.length - 1]?.version ?? 0;
|
|
1930
|
+
let reason;
|
|
1931
|
+
let canMigrate = false;
|
|
1932
|
+
if (currentVersion > targetVersion) {
|
|
1933
|
+
reason = `Database schema version ${currentVersion} is newer than supported version ${targetVersion}`;
|
|
1934
|
+
}
|
|
1935
|
+
else {
|
|
1936
|
+
const invalid = appliedMigrations.find((row, index) => row.version !== index + 1 || !row.checksumMatches);
|
|
1937
|
+
if (invalid) {
|
|
1938
|
+
try {
|
|
1939
|
+
const validation = validateAppliedMigrationsForLiveRepair(database, applied);
|
|
1940
|
+
const requiredAtCurrentVersion = collectMissingSchemaAtVersion(database, validation.currentVersion);
|
|
1941
|
+
if ((validation.legacyPlatformVectorChecksumRepairRequired ||
|
|
1942
|
+
validation.legacyDurableEventReplayIndexChecksumRepairRequired) &&
|
|
1943
|
+
requiredAtCurrentVersion.length === 0) {
|
|
1944
|
+
reason = `Database migration ${invalid.version} uses a recognized historical checksum and requires canonical repair`;
|
|
1945
|
+
canMigrate = true;
|
|
1946
|
+
}
|
|
1947
|
+
else {
|
|
1948
|
+
reason = `Database migration ${invalid.version} ledger entry does not match the application migration`;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
catch {
|
|
1952
|
+
reason = `Database migration ${invalid.version} ledger entry does not match the application migration`;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
else if (currentVersion < targetVersion) {
|
|
1956
|
+
const requiredAtCurrentVersion = collectMissingSchemaAtVersion(database, currentVersion);
|
|
1957
|
+
if (requiredAtCurrentVersion.length === 0) {
|
|
1958
|
+
reason = `Database schema version ${currentVersion} requires migration to version ${targetVersion}`;
|
|
1959
|
+
canMigrate = true;
|
|
1960
|
+
}
|
|
1961
|
+
else {
|
|
1962
|
+
reason =
|
|
1963
|
+
`SQLite schema is incompatible at migration version ${currentVersion}; ` +
|
|
1964
|
+
`missing ${requiredAtCurrentVersion.join(', ')}`;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
else if (missing.length > 0) {
|
|
1968
|
+
reason = `SQLite schema is incomplete; missing ${missing.join(', ')}`;
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
const compatible = reason === undefined;
|
|
1972
|
+
return {
|
|
1973
|
+
dialect: 'sqlite',
|
|
1974
|
+
status: compatible
|
|
1975
|
+
? 'compatible'
|
|
1976
|
+
: canMigrate
|
|
1977
|
+
? 'migrating'
|
|
1978
|
+
: 'incompatible',
|
|
1979
|
+
compatible,
|
|
1980
|
+
ledgerPresent: true,
|
|
1981
|
+
currentVersion,
|
|
1982
|
+
targetVersion,
|
|
1983
|
+
minimumSupportedVersion,
|
|
1984
|
+
missing,
|
|
1985
|
+
appliedMigrations,
|
|
1986
|
+
...(reason ? { reason } : {}),
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
let compatibilityState = {
|
|
1990
|
+
dialect: 'sqlite',
|
|
1991
|
+
status: 'uninitialized',
|
|
1992
|
+
currentVersion: 0,
|
|
1993
|
+
targetVersion,
|
|
1994
|
+
minimumSupportedVersion,
|
|
1995
|
+
};
|
|
1996
|
+
export const getSchemaCompatibilityState = () => ({
|
|
1997
|
+
...compatibilityState,
|
|
1998
|
+
});
|
|
1999
|
+
const updateIncompatible = (currentVersion, error) => {
|
|
2000
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
2001
|
+
compatibilityState = {
|
|
2002
|
+
dialect: 'sqlite',
|
|
2003
|
+
status: 'incompatible',
|
|
2004
|
+
currentVersion,
|
|
2005
|
+
targetVersion,
|
|
2006
|
+
minimumSupportedVersion,
|
|
2007
|
+
reason,
|
|
2008
|
+
};
|
|
2009
|
+
return getSchemaCompatibilityState();
|
|
2010
|
+
};
|
|
2011
|
+
export const recordSQLiteSchemaFailure = (error) => updateIncompatible(compatibilityState.currentVersion, error);
|
|
2012
|
+
/**
|
|
2013
|
+
* Validate an existing migration ledger without changing the database. This
|
|
2014
|
+
* must run before historical inline initialization so an unsupported or
|
|
2015
|
+
* tampered database cannot be partially upgraded before startup fails.
|
|
2016
|
+
*/
|
|
2017
|
+
export function preflightSQLiteMigrationLedger(database) {
|
|
2018
|
+
if (!tableExists(database, MIGRATION_TABLE)) {
|
|
2019
|
+
compatibilityState = {
|
|
2020
|
+
dialect: 'sqlite',
|
|
2021
|
+
status: 'uninitialized',
|
|
2022
|
+
currentVersion: 0,
|
|
2023
|
+
targetVersion,
|
|
2024
|
+
minimumSupportedVersion,
|
|
2025
|
+
};
|
|
2026
|
+
return getSchemaCompatibilityState();
|
|
2027
|
+
}
|
|
2028
|
+
const missingLedger = collectMissingMigrationLedgerSchema(database);
|
|
2029
|
+
if (missingLedger.length > 0) {
|
|
2030
|
+
const error = new Error(`SQLite migration ledger is incompatible; missing ${missingLedger.join(', ')}`);
|
|
2031
|
+
updateIncompatible(0, error);
|
|
2032
|
+
throw error;
|
|
2033
|
+
}
|
|
2034
|
+
const applied = readAppliedMigrations(database);
|
|
2035
|
+
const observedVersion = applied[applied.length - 1]?.version ?? 0;
|
|
2036
|
+
try {
|
|
2037
|
+
const { currentVersion, legacyPlatformVectorChecksumRepairRequired, legacyDurableEventReplayIndexChecksumRepairRequired, } = validateAppliedMigrationsForLiveRepair(database, applied);
|
|
2038
|
+
const missing = collectMissingSchemaAtVersion(database, currentVersion);
|
|
2039
|
+
if (missing.length > 0) {
|
|
2040
|
+
throw new Error(`SQLite schema is incompatible at migration version ${currentVersion}; ` +
|
|
2041
|
+
`missing ${missing.slice(0, 20).join(', ')}${missing.length > 20 ? ` and ${missing.length - 20} more` : ''}`);
|
|
2042
|
+
}
|
|
2043
|
+
compatibilityState = {
|
|
2044
|
+
dialect: 'sqlite',
|
|
2045
|
+
status: currentVersion === targetVersion &&
|
|
2046
|
+
!legacyPlatformVectorChecksumRepairRequired &&
|
|
2047
|
+
!legacyDurableEventReplayIndexChecksumRepairRequired
|
|
2048
|
+
? 'compatible'
|
|
2049
|
+
: 'migrating',
|
|
2050
|
+
currentVersion,
|
|
2051
|
+
targetVersion,
|
|
2052
|
+
minimumSupportedVersion,
|
|
2053
|
+
};
|
|
2054
|
+
return getSchemaCompatibilityState();
|
|
2055
|
+
}
|
|
2056
|
+
catch (error) {
|
|
2057
|
+
updateIncompatible(observedVersion, error);
|
|
2058
|
+
throw error;
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Read-only compatibility check for the pre-ledger bootstrap boundary. It
|
|
2063
|
+
* accepts a fresh database and supported additive legacy shapes, but rejects
|
|
2064
|
+
* structural damage that the atomic inline migration cannot safely repair.
|
|
2065
|
+
*/
|
|
2066
|
+
export function preflightSQLiteBootstrapSchema(database) {
|
|
2067
|
+
if (tableExists(database, MIGRATION_TABLE)) {
|
|
2068
|
+
return preflightSQLiteMigrationLedger(database);
|
|
2069
|
+
}
|
|
2070
|
+
const missing = collectMissingLegacyBootstrapSchema(database);
|
|
2071
|
+
if (missing.length > 0) {
|
|
2072
|
+
const error = new Error(`SQLite ledgerless schema is incompatible; missing ${missing
|
|
2073
|
+
.slice(0, 20)
|
|
2074
|
+
.join(', ')}${missing.length > 20 ? ` and ${missing.length - 20} more` : ''}`);
|
|
2075
|
+
updateIncompatible(0, error);
|
|
2076
|
+
throw error;
|
|
2077
|
+
}
|
|
2078
|
+
compatibilityState = {
|
|
2079
|
+
dialect: 'sqlite',
|
|
2080
|
+
status: 'uninitialized',
|
|
2081
|
+
currentVersion: 0,
|
|
2082
|
+
targetVersion,
|
|
2083
|
+
minimumSupportedVersion,
|
|
2084
|
+
};
|
|
2085
|
+
return getSchemaCompatibilityState();
|
|
2086
|
+
}
|
|
2087
|
+
/**
|
|
2088
|
+
* Adopt the legacy inline schema into a numbered, checksummed migration ledger.
|
|
2089
|
+
* Every subsequent startup verifies both the ledger and the required schema.
|
|
2090
|
+
*/
|
|
2091
|
+
export function runSQLiteMigrationCoordinator(database) {
|
|
2092
|
+
let currentVersion = 0;
|
|
2093
|
+
compatibilityState = {
|
|
2094
|
+
dialect: 'sqlite',
|
|
2095
|
+
status: 'migrating',
|
|
2096
|
+
currentVersion,
|
|
2097
|
+
targetVersion,
|
|
2098
|
+
minimumSupportedVersion,
|
|
2099
|
+
};
|
|
2100
|
+
try {
|
|
2101
|
+
database.exec(`
|
|
2102
|
+
CREATE TABLE IF NOT EXISTS ${MIGRATION_TABLE} (
|
|
2103
|
+
version INTEGER PRIMARY KEY,
|
|
2104
|
+
name TEXT NOT NULL UNIQUE,
|
|
2105
|
+
checksum TEXT NOT NULL,
|
|
2106
|
+
applied_at INTEGER NOT NULL
|
|
2107
|
+
)
|
|
2108
|
+
`);
|
|
2109
|
+
const applied = readAppliedMigrations(database);
|
|
2110
|
+
currentVersion = applied[applied.length - 1]?.version ?? 0;
|
|
2111
|
+
const validation = validateAppliedMigrationsForLiveRepair(database, applied);
|
|
2112
|
+
currentVersion = validation.currentVersion;
|
|
2113
|
+
const missingAtCurrentVersion = collectMissingSchemaAtVersion(database, currentVersion);
|
|
2114
|
+
if (missingAtCurrentVersion.length > 0) {
|
|
2115
|
+
throw new Error(`SQLite schema is incompatible at migration version ${currentVersion}; ` +
|
|
2116
|
+
`missing ${missingAtCurrentVersion.slice(0, 20).join(', ')}${missingAtCurrentVersion.length > 20
|
|
2117
|
+
? ` and ${missingAtCurrentVersion.length - 20} more`
|
|
2118
|
+
: ''}`);
|
|
2119
|
+
}
|
|
2120
|
+
if (database.inTransaction &&
|
|
2121
|
+
database.pragma('foreign_keys', { simple: true }) === 1 &&
|
|
2122
|
+
sqliteMigrationsRequireForeignKeysDisabledAfter(currentVersion)) {
|
|
2123
|
+
throw new Error('SQLite migration requires foreign keys to be disabled before its transaction begins');
|
|
2124
|
+
}
|
|
2125
|
+
if (validation.legacyPlatformVectorChecksumRepairRequired ||
|
|
2126
|
+
validation.legacyDurableEventReplayIndexChecksumRepairRequired) {
|
|
2127
|
+
database.transaction(() => {
|
|
2128
|
+
const repairValidation = validateAppliedMigrationsForLiveRepair(database, readAppliedMigrations(database));
|
|
2129
|
+
if (repairValidation.currentVersion !== currentVersion ||
|
|
2130
|
+
repairValidation.legacyPlatformVectorChecksumRepairRequired !==
|
|
2131
|
+
validation.legacyPlatformVectorChecksumRepairRequired ||
|
|
2132
|
+
repairValidation.legacyDurableEventReplayIndexChecksumRepairRequired !==
|
|
2133
|
+
validation.legacyDurableEventReplayIndexChecksumRepairRequired) {
|
|
2134
|
+
throw new Error('Database migration ledger changed during legacy checksum repair');
|
|
2135
|
+
}
|
|
2136
|
+
const repairMissing = collectMissingSchemaAtVersion(database, repairValidation.currentVersion);
|
|
2137
|
+
if (repairMissing.length > 0) {
|
|
2138
|
+
throw new Error(`SQLite schema is incompatible at migration version ${repairValidation.currentVersion}; ` +
|
|
2139
|
+
`missing ${repairMissing.slice(0, 20).join(', ')}${repairMissing.length > 20
|
|
2140
|
+
? ` and ${repairMissing.length - 20} more`
|
|
2141
|
+
: ''}`);
|
|
2142
|
+
}
|
|
2143
|
+
if (repairValidation.legacyPlatformVectorChecksumRepairRequired) {
|
|
2144
|
+
const result = database
|
|
2145
|
+
.prepare(`UPDATE ${MIGRATION_TABLE}
|
|
2146
|
+
SET checksum = ?
|
|
2147
|
+
WHERE version = 2
|
|
2148
|
+
AND name = 'platform-vector-storage'
|
|
2149
|
+
AND checksum = ?`)
|
|
2150
|
+
.run(PLATFORM_VECTOR_MIGRATION_CHECKSUM, LEGACY_PLATFORM_VECTOR_MIGRATION_CHECKSUM);
|
|
2151
|
+
if (result.changes !== 1) {
|
|
2152
|
+
throw new Error('Database migration 2 changed during legacy checksum repair');
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
if (repairValidation.legacyDurableEventReplayIndexChecksumRepairRequired) {
|
|
2156
|
+
const result = database
|
|
2157
|
+
.prepare(`UPDATE ${MIGRATION_TABLE}
|
|
2158
|
+
SET checksum = ?
|
|
2159
|
+
WHERE version = 13
|
|
2160
|
+
AND name = 'durable-event-replay-index'
|
|
2161
|
+
AND checksum = ?`)
|
|
2162
|
+
.run(DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM, LEGACY_DURABLE_EVENT_REPLAY_INDEX_MIGRATION_CHECKSUM);
|
|
2163
|
+
if (result.changes !== 1) {
|
|
2164
|
+
throw new Error('Database migration 13 changed during legacy checksum repair');
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
const repairedValidation = validateAppliedMigrations(readAppliedMigrations(database));
|
|
2168
|
+
if (repairedValidation.currentVersion !== currentVersion) {
|
|
2169
|
+
throw new Error('Database migration ledger changed during legacy checksum repair');
|
|
2170
|
+
}
|
|
2171
|
+
})();
|
|
2172
|
+
}
|
|
2173
|
+
compatibilityState = {
|
|
2174
|
+
...compatibilityState,
|
|
2175
|
+
currentVersion,
|
|
2176
|
+
};
|
|
2177
|
+
for (const migration of MIGRATIONS) {
|
|
2178
|
+
if (migration.version <= currentVersion)
|
|
2179
|
+
continue;
|
|
2180
|
+
if (migration.version !== currentVersion + 1) {
|
|
2181
|
+
throw new Error(`Database migration sequence has a gap after version ${currentVersion}`);
|
|
2182
|
+
}
|
|
2183
|
+
const applyMigration = () => {
|
|
2184
|
+
migration.apply(database);
|
|
2185
|
+
database
|
|
2186
|
+
.prepare(`INSERT INTO ${MIGRATION_TABLE}
|
|
2187
|
+
(version, name, checksum, applied_at)
|
|
2188
|
+
VALUES (?, ?, ?, ?)`)
|
|
2189
|
+
.run(migration.version, migration.name, migration.checksum, Date.now());
|
|
2190
|
+
};
|
|
2191
|
+
if (migration.requiresForeignKeysDisabled) {
|
|
2192
|
+
const foreignKeysEnabled = database.pragma('foreign_keys', {
|
|
2193
|
+
simple: true,
|
|
2194
|
+
});
|
|
2195
|
+
database.pragma('foreign_keys = OFF');
|
|
2196
|
+
if (database.pragma('foreign_keys', { simple: true }) !== 0) {
|
|
2197
|
+
throw new Error('SQLite migration requires foreign keys to be disabled before its transaction begins');
|
|
2198
|
+
}
|
|
2199
|
+
try {
|
|
2200
|
+
database.transaction(() => {
|
|
2201
|
+
applyMigration();
|
|
2202
|
+
const violations = database.pragma('foreign_key_check');
|
|
2203
|
+
if (violations.length > 0) {
|
|
2204
|
+
throw new Error('SQLite account retirement migration left foreign-key violations');
|
|
2205
|
+
}
|
|
2206
|
+
})();
|
|
2207
|
+
}
|
|
2208
|
+
finally {
|
|
2209
|
+
database.pragma(`foreign_keys = ${foreignKeysEnabled === 1 ? 'ON' : 'OFF'}`);
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
else {
|
|
2213
|
+
database.transaction(applyMigration)();
|
|
2214
|
+
}
|
|
2215
|
+
currentVersion = migration.version;
|
|
2216
|
+
}
|
|
2217
|
+
validateCurrentSchema(database);
|
|
2218
|
+
compatibilityState = {
|
|
2219
|
+
dialect: 'sqlite',
|
|
2220
|
+
status: 'compatible',
|
|
2221
|
+
currentVersion,
|
|
2222
|
+
targetVersion,
|
|
2223
|
+
minimumSupportedVersion,
|
|
2224
|
+
};
|
|
2225
|
+
return getSchemaCompatibilityState();
|
|
2226
|
+
}
|
|
2227
|
+
catch (error) {
|
|
2228
|
+
updateIncompatible(currentVersion, error);
|
|
2229
|
+
throw error;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
//# sourceMappingURL=sqliteMigrations.js.map
|