@codemation/host 0.5.1 → 0.7.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/CHANGELOG.md +465 -0
- package/LICENSE +1 -37
- package/dist/{ApiPaths-CLTHphYZ.js → ApiPaths-Dv1dcHu_.js} +4 -4
- package/dist/ApiPaths-Dv1dcHu_.js.map +1 -0
- package/dist/{AppConfigFactory-CvpFScwB.js → AppConfigFactory-Cx4qQvRk.js} +114 -53
- package/dist/AppConfigFactory-Cx4qQvRk.js.map +1 -0
- package/dist/{AppConfigFactory-LK76niPc.d.ts → AppConfigFactory-DnLoQ9Li.d.ts} +8527 -5549
- package/dist/{AppContainerFactory-BlLrm6_h.js → AppContainerFactory-DqKYCRNP.js} +7656 -2090
- package/dist/AppContainerFactory-DqKYCRNP.js.map +1 -0
- package/dist/{CodemationAppContext-CvWi5gey.d.ts → CodemationAppContext-CKVv9W9q.d.ts} +8 -4
- package/dist/{CodemationAuthoring.types-BuKNTDC1.d.ts → CodemationAuthoring.types-DA3G3s6d.d.ts} +25 -5
- package/dist/{CodemationAuthoring.types-DZl-sJaM.js → CodemationAuthoring.types-NGkBcmmT.js} +18 -6
- package/dist/CodemationAuthoring.types-NGkBcmmT.js.map +1 -0
- package/dist/{CodemationConfigNormalizer-CYdR0PR5.d.ts → CodemationConfigNormalizer-BAKjetJ6.d.ts} +3 -3
- package/dist/{CodemationConsumerConfigLoader-BeAUS144.js → CodemationConsumerConfigLoader-GYpBBvqE.js} +79 -10
- package/dist/CodemationConsumerConfigLoader-GYpBBvqE.js.map +1 -0
- package/dist/{CodemationConsumerConfigLoader-C3nAj9Bj.d.ts → CodemationConsumerConfigLoader-nxOqvv46.d.ts} +17 -2
- package/dist/{CodemationPluginListMerger-B-W5Fa_X.js → CodemationPluginListMerger-D1B1IEbt.js} +1 -1
- package/dist/{CodemationPluginListMerger-B-W5Fa_X.js.map → CodemationPluginListMerger-D1B1IEbt.js.map} +1 -1
- package/dist/{CodemationPluginListMerger-D-gwVwtw.d.ts → CodemationPluginListMerger-DKLAHT2b.d.ts} +123 -16
- package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js +97 -0
- package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js.map +1 -0
- package/dist/{CodemationWhitelabelConfig-CWbcyQqn.d.ts → CodemationWhitelabelConfig-Ca2mCUeC.d.ts} +2 -2
- package/dist/{CollectionContracts.types-DdpHft0i.d.ts → CollectionContracts.types-DDyFYT_D.d.ts} +1 -1
- package/dist/{CredentialContractsRegistry-D7mcPed2.d.ts → CredentialContractsRegistry-Bq2bq28t.d.ts} +2 -2
- package/dist/{CredentialServices-DdCEP2xt.d.ts → CredentialServices-Be2I60Th.d.ts} +65 -20
- package/dist/{CredentialServices-CgxwguAv.js → CredentialServices-Dk8yypeL.js} +310 -51
- package/dist/CredentialServices-Dk8yypeL.js.map +1 -0
- package/dist/InternalHonoApiRouteRegistrar-Ce1yxpnO.d.ts +17 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js +221 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js.map +1 -0
- package/dist/{ItemsInputNormalizer-D1WppVMU.d.ts → ItemsInputNormalizer-_RwIfRIQ.d.ts} +108 -25
- package/dist/{LogLevelPolicyFactory-CampWO0l.d.ts → LogLevelPolicyFactory-ewCHLDLn.d.ts} +2 -2
- package/dist/{PublicFrontendBootstrap-DzBgwOnG.d.ts → PublicFrontendBootstrap-Cev3qK46.d.ts} +9 -2
- package/dist/PublicFrontendBootstrapFactory-CY2FS-5g.d.ts +82 -0
- package/dist/{PublicFrontendBootstrapJsonCodec-Cl_DLRh0.d.ts → PublicFrontendBootstrapJsonCodec-CXG9Dxft.d.ts} +3 -3
- package/dist/{PublicFrontendBootstrapJsonCodec-DzqvA0uo.js → PublicFrontendBootstrapJsonCodec-CegIF_ne.js} +7 -2
- package/dist/PublicFrontendBootstrapJsonCodec-CegIF_ne.js.map +1 -0
- package/dist/ServerLoggerFactory-Ckk52S3w.js +223 -0
- package/dist/ServerLoggerFactory-Ckk52S3w.js.map +1 -0
- package/dist/{TelemetryContracts-BsOD_Y17.d.ts → TelemetryContracts-BtDx84Cp.d.ts} +13 -4
- package/dist/{WorkflowPolicyUiPresentationFactory-DNE5oAI6.d.ts → WorkflowPolicyUiPresentationFactory-6MyjCvBO.d.ts} +2 -2
- package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js} +1 -1
- package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js.map → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js.map} +1 -1
- package/dist/{WorkflowViewContracts-0ZgsHQdp.d.ts → WorkflowViewContracts-B7aFQcIw.d.ts} +15 -1
- package/dist/authoring.d.ts +5 -5
- package/dist/authoring.js +1 -1
- package/dist/client.d.ts +4 -4
- package/dist/client.js +2 -2
- package/dist/consumer.d.ts +6 -6
- package/dist/consumer.js +2 -2
- package/dist/credentials.d.ts +6 -6
- package/dist/credentials.js +1 -1
- package/dist/devServerSidecar.d.ts +2 -2
- package/dist/devServerSidecar.js +1 -94
- package/dist/devServerSidecar.js.map +1 -1
- package/dist/dto.d.ts +6 -6
- package/dist/{index-BlGs9e9Q.d.ts → index-DilAYwnH.d.ts} +49 -3
- package/dist/index.d.ts +110 -21
- package/dist/index.js +15 -13
- package/dist/mapping.d.ts +2 -2
- package/dist/mapping.js +1 -1
- package/dist/nextServer.d.ts +43 -88
- package/dist/nextServer.js +9 -7
- package/dist/pairing.d.ts +93 -0
- package/dist/pairing.js +5 -0
- package/dist/pairing.types-snfZ_OzB.d.ts +19 -0
- package/dist/{persistenceServer-CpNFYa_q.js → persistenceServer-C-hH4z6l.js} +2 -2
- package/dist/{persistenceServer-CpNFYa_q.js.map → persistenceServer-C-hH4z6l.js.map} +1 -1
- package/dist/persistenceServer-CeTHtC6E.d.ts +30 -0
- package/dist/persistenceServer.d.ts +8 -8
- package/dist/persistenceServer.js +3 -3
- package/dist/{server-CQWdkT7t.d.ts → server-C4bS62rg.d.ts} +21 -6
- package/dist/{server-BK43OKxW.js → server-Y7kxwtCK.js} +7 -6
- package/dist/{server-BK43OKxW.js.map → server-Y7kxwtCK.js.map} +1 -1
- package/dist/server.d.ts +14 -14
- package/dist/server.js +13 -11
- package/package.json +29 -42
- package/prisma/migrations/20260507120000_execution_instance_child_run_id/migration.sql +5 -0
- package/prisma/migrations/20260519000000_workflow_audit_log/migration.sql +23 -0
- package/prisma/migrations/20260519100000_storage_growth_fixes/migration.sql +61 -0
- package/prisma/migrations.sqlite/20260507120000_execution_instance_child_run_id/migration.sql +5 -0
- package/prisma/migrations.sqlite/20260519000000_workflow_audit_log/migration.sql +21 -0
- package/prisma/migrations.sqlite/20260519100000_storage_growth_fixes/migration.sql +29 -0
- package/prisma/schema.postgresql.prisma +56 -17
- package/prisma/schema.sqlite.prisma +56 -17
- package/prisma-generated/prisma-postgresql-client/edge.js +35 -6
- package/prisma-generated/prisma-postgresql-client/index-browser.js +31 -2
- package/prisma-generated/prisma-postgresql-client/index.d.ts +8971 -5718
- package/prisma-generated/prisma-postgresql-client/index.js +35 -6
- package/prisma-generated/prisma-postgresql-client/package.json +1 -1
- package/prisma-generated/prisma-postgresql-client/schema.prisma +39 -0
- package/prisma-generated/prisma-sqlite-client/edge.js +35 -6
- package/prisma-generated/prisma-sqlite-client/index-browser.js +31 -2
- package/prisma-generated/prisma-sqlite-client/index.d.ts +8963 -5715
- package/prisma-generated/prisma-sqlite-client/index.js +35 -6
- package/prisma-generated/prisma-sqlite-client/package.json +1 -1
- package/prisma-generated/prisma-sqlite-client/schema.prisma +39 -0
- package/scripts/check-collections.mjs +18 -0
- package/scripts/generate-prisma-clients.mjs +20 -11
- package/src/application/WorkflowAuditLogPruneScheduler.ts +96 -0
- package/src/application/auth/AuthenticatedPrincipal.ts +4 -0
- package/src/application/commands/StartWorkflowRunCommandHandler.ts +4 -0
- package/src/application/contracts/WorkflowViewContracts.ts +11 -0
- package/src/application/contracts/WorkflowWebsocketMessage.ts +3 -1
- package/src/application/mapping/WorkflowDefinitionMapper.ts +44 -1
- package/src/application/runs/WorkflowRunRetentionPruneScheduler.ts +7 -1
- package/src/application/telemetry/OtelExecutionTelemetry.types.ts +5 -0
- package/src/application/telemetry/OtelExecutionTelemetryFactory.ts +4 -0
- package/src/application/telemetry/StoredTelemetrySpanScope.ts +6 -2
- package/src/application/telemetry/TelemetryRetentionTimestampFactory.ts +27 -17
- package/src/application/telemetry/TelemetrySpanPublisher.ts +11 -0
- package/src/application/websocket/TelemetrySpanWebsocketRelay.ts +31 -0
- package/src/applicationTokens.ts +20 -1
- package/src/audit/IAuditEmitter.ts +32 -0
- package/src/audit/PrismaWorkflowAuditLogRepository.ts +34 -0
- package/src/audit/WorkflowAuditLogWriter.ts +125 -0
- package/src/auth/managed/ManagedAuthConfig.ts +29 -0
- package/src/auth/managed/ManagedAuthMiddleware.ts +52 -0
- package/src/auth/managed/ManagedCorsMiddleware.ts +43 -0
- package/src/auth/managed/ManagedModeBootGuard.ts +27 -0
- package/src/auth/managed/index.ts +5 -0
- package/src/bootstrap/AppContainerFactory.ts +277 -29
- package/src/bootstrap/AppContainerLifecycle.ts +31 -0
- package/src/bootstrap/perf/BootTimer.ts +168 -0
- package/src/bootstrap/runtime/AppConfigFactory.ts +21 -65
- package/src/bootstrap/runtime/FrontendRuntime.ts +4 -1
- package/src/bootstrap/runtime/WorkerRuntime.ts +2 -1
- package/src/credentials/BrokerClient.ts +49 -0
- package/src/credentials/BrokerRefreshError.ts +12 -0
- package/src/credentials/BrokerRefreshInvalidGrantError.ts +13 -0
- package/src/credentials/ControlPlaneCatalogFetcher.ts +261 -0
- package/src/credentials/CredentialOAuth2MaterialReader.ts +136 -0
- package/src/credentials/InternalCredentialsListRegistrar.ts +48 -0
- package/src/credentials/InternalCredentialsPushRegistrar.ts +125 -0
- package/src/credentials/LocalOAuthFlowExecutor.ts +316 -0
- package/src/credentials/ManagedOAuthFlowExecutor.ts +94 -0
- package/src/credentials/ManagedOAuthRefreshInvalidGrantError.ts +13 -0
- package/src/credentials/catalogTypes.ts +4 -0
- package/src/credentials/refresh/CredentialDisconnectedError.ts +11 -0
- package/src/domain/credentials/CredentialBindingService.ts +54 -2
- package/src/domain/credentials/CredentialKeyRotatedError.ts +22 -0
- package/src/domain/credentials/CredentialSecretCipher.ts +68 -6
- package/src/domain/credentials/CredentialTypeRegistryImpl.ts +117 -10
- package/src/domain/credentials/OAuth2RedirectUriResolver.ts +79 -0
- package/src/domain/credentials/WorkflowCredentialNodeResolver.ts +14 -5
- package/src/domain/telemetry/TelemetryContracts.ts +7 -1
- package/src/domain/workflows/WorkflowActivationPreflight.ts +24 -1
- package/src/domain/workflows/WorkflowActivationPreflightRules.ts +40 -1
- package/src/index.ts +6 -0
- package/src/infrastructure/binary/LocalFilesystemBinaryStorageRegistry.ts +29 -1
- package/src/infrastructure/binary/S3BinaryStorage.ts +169 -0
- package/src/infrastructure/binary/S3BinaryStorageConfig.ts +17 -0
- package/src/infrastructure/config/CodemationPluginRegistrar.ts +3 -1
- package/src/infrastructure/persistence/CodemationDatabaseUrlParser.ts +41 -0
- package/src/infrastructure/persistence/InMemoryTelemetryArtifactStore.ts +8 -3
- package/src/infrastructure/persistence/InMemoryWorkflowRunRepository.ts +1 -0
- package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +21 -13
- package/src/infrastructure/persistence/PrismaTelemetryArtifactStore.ts +43 -8
- package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +33 -3
- package/src/infrastructure/persistence/PrismaWorkflowSnapshotRepository.ts +48 -0
- package/src/mcp/AgentMcpIntegrationImpl.ts +344 -0
- package/src/mcp/McpClientFactory.ts +29 -0
- package/src/mcp/McpConnectionPool.ts +184 -0
- package/src/mcp/McpConnectionPool.types.ts +12 -0
- package/src/mcp/McpServerCatalog.ts +104 -0
- package/src/mcp/index.ts +5 -0
- package/src/pairing/HmacRequestSigner.ts +32 -0
- package/src/pairing/IncomingHmacVerifier.ts +82 -0
- package/src/pairing/InternalHmacAuthMiddleware.ts +33 -0
- package/src/pairing/InternalPingRegistrar.ts +25 -0
- package/src/pairing/PairedFetch.ts +33 -0
- package/src/pairing/PairingConfigFactory.ts +35 -0
- package/src/pairing/PairingConfigToken.ts +6 -0
- package/src/pairing/index.ts +14 -0
- package/src/pairing/pairing.types.ts +18 -0
- package/src/pairing.ts +17 -0
- package/src/persistenceServer.ts +1 -0
- package/src/presentation/config/AppConfig.ts +7 -1
- package/src/presentation/config/CodemationAuthConfig.ts +1 -1
- package/src/presentation/config/CodemationAuthoring.types.ts +54 -5
- package/src/presentation/config/CodemationConfig.ts +3 -0
- package/src/presentation/config/CodemationConfigNormalizer.ts +39 -1
- package/src/presentation/config/CodemationPlugin.ts +2 -1
- package/src/presentation/frontend/CodemationFrontendAuthSnapshot.ts +5 -0
- package/src/presentation/frontend/CodemationFrontendAuthSnapshotFactory.ts +7 -1
- package/src/presentation/frontend/PublicFrontendBootstrap.ts +2 -0
- package/src/presentation/frontend/PublicFrontendBootstrapFactory.ts +5 -1
- package/src/presentation/frontend/PublicFrontendBootstrapJsonCodec.ts +4 -1
- package/src/presentation/http/ApiPaths.ts +4 -4
- package/src/presentation/http/ServerHttpErrorResponseFactory.ts +39 -2
- package/src/presentation/http/hono/CodemationHonoApiAppFactory.ts +33 -8
- package/src/presentation/http/hono/InternalHonoApiRouteRegistrar.ts +12 -0
- package/src/presentation/http/hono/registrars/ManagedMeHonoApiRouteRegistrar.ts +35 -0
- package/src/presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar.ts +2 -2
- package/src/presentation/http/routeHandlers/CredentialHttpRouteHandler.ts +28 -0
- package/src/presentation/http/routeHandlers/OAuth2HttpRouteHandlerFactory.ts +98 -41
- package/src/presentation/server/CodemationConsumerConfigLoader.ts +54 -7
- package/src/presentation/server/CodemationPluginDiscovery.ts +5 -0
- package/src/presentation/server/WorkflowDefinitionExportsResolver.ts +18 -0
- package/src/presentation/server/WorkflowModulePathFinder.ts +12 -1
- package/src/presentation/websocket/ManagedWebsocketAuthenticator.ts +50 -0
- package/src/presentation/websocket/WebsocketAuthenticator.types.ts +12 -0
- package/src/presentation/websocket/WorkflowWebsocketServer.ts +24 -3
- package/src/process/ExecaProcessRunner.ts +41 -0
- package/src/process/ProcessRunner.types.ts +39 -0
- package/src/server.ts +2 -0
- package/src/workflows/InternalWorkflowActivationRegistrar.ts +42 -0
- package/src/workflows/InternalWorkflowDetailRegistrar.ts +33 -0
- package/src/workflows/InternalWorkflowTestRunRegistrar.ts +91 -0
- package/src/workflows/InternalWorkflowsListRegistrar.ts +28 -0
- package/src/workflows/discovery/WorkflowDirectoryDiscoverer.ts +79 -0
- package/tsconfig.json +2 -0
- package/vitest.shared.ts +5 -0
- package/dist/ApiPaths-CLTHphYZ.js.map +0 -1
- package/dist/AppConfigFactory-CvpFScwB.js.map +0 -1
- package/dist/AppContainerFactory-BlLrm6_h.js.map +0 -1
- package/dist/CodemationAuthoring.types-DZl-sJaM.js.map +0 -1
- package/dist/CodemationConsumerConfigLoader-BeAUS144.js.map +0 -1
- package/dist/CredentialServices-CgxwguAv.js.map +0 -1
- package/dist/PublicFrontendBootstrapFactory-BMWqNM9a.d.ts +0 -45
- package/dist/PublicFrontendBootstrapJsonCodec-DzqvA0uo.js.map +0 -1
- package/dist/ServerLoggerFactory-BKSIh9Xv.js +0 -98
- package/dist/ServerLoggerFactory-BKSIh9Xv.js.map +0 -1
- package/dist/persistenceServer-CIVt3UOX.d.ts +0 -9
- package/src/domain/credentials/OAuth2ConnectServiceFactory.ts +0 -411
|
@@ -89,6 +89,8 @@ import { OpenAiApiKeyCredentialHealthTester } from "../infrastructure/credential
|
|
|
89
89
|
import { OpenAiApiKeyCredentialTypeFactory } from "../infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory";
|
|
90
90
|
import { CodemationPluginRegistrar } from "../infrastructure/config/CodemationPluginRegistrar";
|
|
91
91
|
import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
|
|
92
|
+
import { TelemetrySpanWebsocketRelay } from "../application/websocket/TelemetrySpanWebsocketRelay";
|
|
93
|
+
import { NoOpTelemetrySpanPublisher } from "../application/telemetry/TelemetrySpanPublisher";
|
|
92
94
|
import { FrameworkCostCatalogEntries } from "../application/cost/FrameworkCostCatalogEntries";
|
|
93
95
|
import { CompositeTelemetryExporter } from "../application/telemetry/CompositeTelemetryExporter";
|
|
94
96
|
import { LazyExecutionTelemetryFactory } from "../application/telemetry/LazyExecutionTelemetryFactory";
|
|
@@ -96,6 +98,8 @@ import { NoOpTelemetryExporter } from "../application/telemetry/NoOpTelemetryExp
|
|
|
96
98
|
import { OtelExecutionTelemetryFactory } from "../application/telemetry/OtelExecutionTelemetryFactory";
|
|
97
99
|
import { OtelIdentityFactory } from "../application/telemetry/OtelIdentityFactory";
|
|
98
100
|
import { RunEventBusTelemetryReporter } from "../application/telemetry/RunEventBusTelemetryReporter";
|
|
101
|
+
import { WorkflowAuditLogWriter } from "../audit/WorkflowAuditLogWriter";
|
|
102
|
+
import { PrismaWorkflowAuditLogRepository } from "../audit/PrismaWorkflowAuditLogRepository";
|
|
99
103
|
import { TelemetryEnricherChain } from "../application/telemetry/TelemetryEnricherChain";
|
|
100
104
|
import { TelemetryPrivacyPolicy } from "../application/telemetry/TelemetryPrivacyPolicy";
|
|
101
105
|
import { TelemetryQueryService } from "../application/telemetry/TelemetryQueryService";
|
|
@@ -113,8 +117,8 @@ import {
|
|
|
113
117
|
CredentialTestService,
|
|
114
118
|
CredentialTypeRegistryImpl,
|
|
115
119
|
} from "../domain/credentials/CredentialServices";
|
|
116
|
-
import { OAuth2ConnectService } from "../domain/credentials/OAuth2ConnectServiceFactory";
|
|
117
120
|
import { OAuth2ProviderRegistry } from "../domain/credentials/OAuth2ProviderRegistry";
|
|
121
|
+
import { OAuth2RedirectUriResolver } from "../domain/credentials/OAuth2RedirectUriResolver";
|
|
118
122
|
import { WorkflowCredentialNodeResolver } from "../domain/credentials/WorkflowCredentialNodeResolver";
|
|
119
123
|
import { UserAccountService } from "../domain/users/UserAccountServiceRegistry";
|
|
120
124
|
import { UserAccountSessionPolicy } from "../domain/users/UserAccountSessionPolicy";
|
|
@@ -228,19 +232,25 @@ import { PrismaTestSuiteRunRepository } from "../infrastructure/persistence/Pris
|
|
|
228
232
|
import { PrismaWorkflowActivationRepository } from "../infrastructure/persistence/PrismaWorkflowActivationRepository";
|
|
229
233
|
import { PrismaWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/PrismaWorkflowDebuggerOverlayRepository";
|
|
230
234
|
import { PrismaWorkflowRunRepository } from "../infrastructure/persistence/PrismaWorkflowRunRepository";
|
|
235
|
+
import { PrismaWorkflowSnapshotRepository } from "../infrastructure/persistence/PrismaWorkflowSnapshotRepository";
|
|
231
236
|
import { RuntimeWorkflowActivationPolicy } from "../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
|
|
232
237
|
import { WorkflowDefinitionRepositoryAdapter } from "../infrastructure/persistence/WorkflowDefinitionRepositoryAdapter";
|
|
233
238
|
import { WorkflowRunRepository as SqlWorkflowRunRepository } from "../infrastructure/persistence/WorkflowRunRepository";
|
|
234
239
|
import { LiveWorkflowRepository } from "../infrastructure/runtime/LiveWorkflowRepository";
|
|
235
240
|
import { LogLevelPolicyFactory, logLevelPolicyFactory } from "../infrastructure/logging/LogLevelPolicyFactory";
|
|
236
241
|
import { ServerLoggerFactory } from "../infrastructure/logging/ServerLoggerFactory";
|
|
242
|
+
import { ExecaProcessRunner } from "../process/ExecaProcessRunner";
|
|
237
243
|
import type { AppConfig } from "../presentation/config/AppConfig";
|
|
238
244
|
import { CodemationContainerRegistrationRegistrar } from "./CodemationContainerRegistrationRegistrar";
|
|
239
245
|
import { LocalFilesystemBinaryStorage } from "../infrastructure/binary/LocalFilesystemBinaryStorageRegistry";
|
|
246
|
+
import { S3BinaryStorage } from "../infrastructure/binary/S3BinaryStorage";
|
|
247
|
+
import { S3BinaryStorageConfigSchema } from "../infrastructure/binary/S3BinaryStorageConfig";
|
|
240
248
|
import { InMemoryBinaryStorage } from "@codemation/core/bootstrap";
|
|
241
249
|
import { RedisRunEventBus } from "@codemation/eventbus-redis";
|
|
242
250
|
import { AppContainerLifecycle } from "./AppContainerLifecycle";
|
|
251
|
+
import { BootTimer } from "./perf/BootTimer";
|
|
243
252
|
import { WorkflowRunRetentionPruneScheduler } from "../application/runs/WorkflowRunRetentionPruneScheduler";
|
|
253
|
+
import { WorkflowAuditLogPruneScheduler } from "../application/WorkflowAuditLogPruneScheduler";
|
|
244
254
|
import { DatabaseMigrations } from "./runtime/DatabaseMigrations";
|
|
245
255
|
import { FrontendRuntime } from "./runtime/FrontendRuntime";
|
|
246
256
|
import { WorkerRuntime } from "./runtime/WorkerRuntime";
|
|
@@ -261,6 +271,36 @@ import { ListCollectionRowsQueryHandler } from "../application/collections/ListC
|
|
|
261
271
|
import { ListCollectionsQueryHandler } from "../application/collections/ListCollectionsQueryHandler";
|
|
262
272
|
import { CollectionHttpRouteHandler } from "../presentation/http/routeHandlers/CollectionHttpRouteHandlerFactory";
|
|
263
273
|
import { CollectionHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/CollectionHonoApiRouteRegistrar";
|
|
274
|
+
import { ManagedMeHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/ManagedMeHonoApiRouteRegistrar";
|
|
275
|
+
import { PairingConfigFactory } from "../pairing/PairingConfigFactory";
|
|
276
|
+
import { PairingConfigToken } from "../pairing/PairingConfigToken";
|
|
277
|
+
import { HmacRequestSigner } from "../pairing/HmacRequestSigner";
|
|
278
|
+
import { PairedFetch } from "../pairing/PairedFetch";
|
|
279
|
+
import { IncomingHmacVerifier } from "../pairing/IncomingHmacVerifier";
|
|
280
|
+
import { InternalHmacAuthMiddleware } from "../pairing/InternalHmacAuthMiddleware";
|
|
281
|
+
import { InternalPingRegistrar } from "../pairing/InternalPingRegistrar";
|
|
282
|
+
import { LocalOAuthFlowExecutor } from "../credentials/LocalOAuthFlowExecutor";
|
|
283
|
+
import { CredentialOAuth2MaterialReader } from "../credentials/CredentialOAuth2MaterialReader";
|
|
284
|
+
import { ManagedOAuthFlowExecutor } from "../credentials/ManagedOAuthFlowExecutor";
|
|
285
|
+
import { BrokerClient } from "../credentials/BrokerClient";
|
|
286
|
+
import { InternalCredentialsPushRegistrar } from "../credentials/InternalCredentialsPushRegistrar";
|
|
287
|
+
import { InternalCredentialsListRegistrar } from "../credentials/InternalCredentialsListRegistrar";
|
|
288
|
+
import { InternalWorkflowsListRegistrar } from "../workflows/InternalWorkflowsListRegistrar";
|
|
289
|
+
import { InternalWorkflowDetailRegistrar } from "../workflows/InternalWorkflowDetailRegistrar";
|
|
290
|
+
import { InternalWorkflowActivationRegistrar } from "../workflows/InternalWorkflowActivationRegistrar";
|
|
291
|
+
import { InternalWorkflowTestRunRegistrar } from "../workflows/InternalWorkflowTestRunRegistrar";
|
|
292
|
+
import { McpServerCatalog } from "../mcp/McpServerCatalog";
|
|
293
|
+
import { McpConnectionPool } from "../mcp/McpConnectionPool";
|
|
294
|
+
import { DefaultMcpClientFactory } from "../mcp/McpClientFactory";
|
|
295
|
+
import { AgentMcpIntegrationImpl } from "../mcp/AgentMcpIntegrationImpl";
|
|
296
|
+
import { ManagedAuthConfigFactory } from "../auth/managed/ManagedAuthConfig";
|
|
297
|
+
import { ManagedAuthMiddleware } from "../auth/managed/ManagedAuthMiddleware";
|
|
298
|
+
import { ManagedCorsMiddleware } from "../auth/managed/ManagedCorsMiddleware";
|
|
299
|
+
import { ManagedModeBootGuard } from "../auth/managed/ManagedModeBootGuard";
|
|
300
|
+
import { ManagedWebsocketAuthenticator } from "../presentation/websocket/ManagedWebsocketAuthenticator";
|
|
301
|
+
import { JwksCache, ManagedJwtVerifier } from "@codemation/managed-auth";
|
|
302
|
+
import { CodemationTsyringeTypeInfoRegistrar } from "../presentation/server/CodemationTsyringeTypeInfoRegistrar";
|
|
303
|
+
import { ControlPlaneCatalogFetcher } from "../credentials/ControlPlaneCatalogFetcher";
|
|
264
304
|
|
|
265
305
|
type AppContainerInputs = Readonly<{
|
|
266
306
|
appConfig: AppConfig;
|
|
@@ -350,22 +390,61 @@ export class AppContainerFactory {
|
|
|
350
390
|
async create(inputs: AppContainerInputs): Promise<Container> {
|
|
351
391
|
const container = tsyringeContainer.createChildContainer();
|
|
352
392
|
container.registerInstance(ApplicationTokens.AppConfig, inputs.appConfig);
|
|
353
|
-
|
|
354
|
-
this.
|
|
355
|
-
|
|
356
|
-
this.
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
393
|
+
// Register the no-op publisher as a fallback so OtelExecutionTelemetryFactory can always
|
|
394
|
+
// resolve the token. registerOperationalInfrastructure overrides this with the WS relay.
|
|
395
|
+
container.registerInstance(ApplicationTokens.TelemetrySpanPublisher, NoOpTelemetrySpanPublisher);
|
|
396
|
+
BootTimer.measure("appContainer.registerCoreInfrastructure", () => this.registerCoreInfrastructure(container, inputs));
|
|
397
|
+
BootTimer.measure("appContainer.registerRepositoriesAndBuses", () => this.registerRepositoriesAndBuses(container));
|
|
398
|
+
BootTimer.measure("appContainer.registerApplicationServicesAndRoutes", () =>
|
|
399
|
+
this.registerApplicationServicesAndRoutes(container, inputs.appConfig),
|
|
400
|
+
);
|
|
401
|
+
BootTimer.measure("appContainer.registerOperationalInfrastructure", () =>
|
|
402
|
+
this.registerOperationalInfrastructure(container),
|
|
403
|
+
);
|
|
404
|
+
BootTimer.measure("appContainer.registerManagedAuthInfrastructure", () =>
|
|
405
|
+
this.registerManagedAuthInfrastructure(container, inputs.appConfig),
|
|
406
|
+
);
|
|
407
|
+
BootTimer.measure("appContainer.registerPairingInfrastructure", () =>
|
|
408
|
+
this.registerPairingInfrastructure(container, inputs.appConfig),
|
|
409
|
+
);
|
|
410
|
+
BootTimer.measure("appContainer.registerConfiguredRegistrations", () =>
|
|
411
|
+
this.registerConfiguredRegistrations(container, inputs.appConfig),
|
|
412
|
+
);
|
|
413
|
+
const credentialTypes = BootTimer.measure("appContainer.collectCredentialTypes", () =>
|
|
414
|
+
this.collectCredentialTypes(inputs.appConfig),
|
|
415
|
+
);
|
|
416
|
+
BootTimer.measure("appContainer.registerMcpCatalog", () => this.registerMcpCatalog(container));
|
|
417
|
+
await BootTimer.measureAsync("appContainer.applyPlugins", () =>
|
|
418
|
+
this.applyPlugins(container, inputs.appConfig, credentialTypes),
|
|
419
|
+
);
|
|
420
|
+
BootTimer.measure("appContainer.mergeConfigMcpServers", () =>
|
|
421
|
+
this.mergeConfigMcpServers(container, inputs.appConfig),
|
|
368
422
|
);
|
|
423
|
+
const ownership = await BootTimer.measureAsync("appContainer.registerRuntimeInfrastructure", () =>
|
|
424
|
+
this.registerRuntimeInfrastructure(container, inputs.appConfig),
|
|
425
|
+
);
|
|
426
|
+
BootTimer.measure("appContainer.registerWorkflowAuditWriter", () =>
|
|
427
|
+
this.registerWorkflowAuditWriter(container, inputs.appConfig),
|
|
428
|
+
);
|
|
429
|
+
BootTimer.measure("appContainer.registerCollectionsInfrastructure", () =>
|
|
430
|
+
this.registerCollectionsInfrastructure(container, inputs.appConfig),
|
|
431
|
+
);
|
|
432
|
+
BootTimer.measure("appContainer.registerCredentialTypes", () =>
|
|
433
|
+
this.registerCredentialTypes(container, credentialTypes),
|
|
434
|
+
);
|
|
435
|
+
BootTimer.measure("appContainer.registerControlPlaneCatalogFetcher", () =>
|
|
436
|
+
this.registerControlPlaneCatalogFetcher(container),
|
|
437
|
+
);
|
|
438
|
+
BootTimer.measure("appContainer.synchronizeLiveWorkflowRepository", () =>
|
|
439
|
+
this.synchronizeLiveWorkflowRepository(container, inputs.appConfig.workflows),
|
|
440
|
+
);
|
|
441
|
+
BootTimer.measure("appContainer.registerWorkflowDefinitions", () =>
|
|
442
|
+
new CodemationTsyringeTypeInfoRegistrar(container).registerWorkflowDefinitions(inputs.appConfig.workflows ?? []),
|
|
443
|
+
);
|
|
444
|
+
container.resolve(BootRuntimeSnapshotHolder).set(this.createRuntimeSummary(inputs.appConfig));
|
|
445
|
+
const lifecycle = new AppContainerLifecycle(container, ownership.ownedPrismaClient);
|
|
446
|
+
container.registerInstance(AppContainerLifecycle, lifecycle);
|
|
447
|
+
await BootTimer.measureAsync("appContainer.lifecycleStart", () => lifecycle.start());
|
|
369
448
|
return container;
|
|
370
449
|
}
|
|
371
450
|
|
|
@@ -391,11 +470,28 @@ export class AppContainerFactory {
|
|
|
391
470
|
return credentialTypes;
|
|
392
471
|
}
|
|
393
472
|
|
|
473
|
+
private registerMcpCatalog(container: Container): void {
|
|
474
|
+
container.registerSingleton(McpServerCatalog, McpServerCatalog);
|
|
475
|
+
container.registerSingleton(DefaultMcpClientFactory, DefaultMcpClientFactory);
|
|
476
|
+
container.registerSingleton(McpConnectionPool, McpConnectionPool);
|
|
477
|
+
container.registerSingleton(AgentMcpIntegrationImpl, AgentMcpIntegrationImpl);
|
|
478
|
+
// Register the host-side AgentMcpIntegration, overriding the NoOp registered by EngineRuntimeRegistrar.
|
|
479
|
+
container.register(CoreTokens.AgentMcpIntegration, {
|
|
480
|
+
useFactory: instanceCachingFactory((c) => c.resolve(AgentMcpIntegrationImpl)),
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
private mergeConfigMcpServers(container: Container, appConfig: AppConfig): void {
|
|
485
|
+
const catalog = container.resolve(McpServerCatalog);
|
|
486
|
+
catalog.merge("config", appConfig.mcpServers ?? []);
|
|
487
|
+
}
|
|
488
|
+
|
|
394
489
|
private async applyPlugins(
|
|
395
490
|
container: Container,
|
|
396
491
|
appConfig: AppConfig,
|
|
397
492
|
credentialTypes: Array<CredentialType<any, any, unknown>>,
|
|
398
493
|
): Promise<void> {
|
|
494
|
+
const catalog = container.resolve(McpServerCatalog);
|
|
399
495
|
await this.pluginRegistrar.apply({
|
|
400
496
|
plugins: appConfig.plugins,
|
|
401
497
|
container,
|
|
@@ -411,6 +507,7 @@ export class AppContainerFactory {
|
|
|
411
507
|
// during plugin.register() are accepted silently — Phase 6 store wiring will
|
|
412
508
|
// pick them up once collection infrastructure can reload from a mutable registry.
|
|
413
509
|
},
|
|
510
|
+
mergeMcpServers: (declarations) => catalog.merge("plugin", declarations),
|
|
414
511
|
loggerFactory: container.resolve(ApplicationTokens.LoggerFactory),
|
|
415
512
|
});
|
|
416
513
|
}
|
|
@@ -420,9 +517,27 @@ export class AppContainerFactory {
|
|
|
420
517
|
credentialTypes: ReadonlyArray<CredentialType<any, any, unknown>>,
|
|
421
518
|
): void {
|
|
422
519
|
const registry = container.resolve(CredentialTypeRegistryImpl);
|
|
423
|
-
|
|
424
|
-
|
|
520
|
+
registry.merge("plugin", credentialTypes);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
private registerControlPlaneCatalogFetcher(container: Container): void {
|
|
524
|
+
// Only register the fetcher when paired with a control plane.
|
|
525
|
+
// PairedFetch is only registered inside registerPairingInfrastructure,
|
|
526
|
+
// which skips registration when pairing env vars are absent.
|
|
527
|
+
if (!container.isRegistered(PairedFetch, true)) {
|
|
528
|
+
return;
|
|
425
529
|
}
|
|
530
|
+
|
|
531
|
+
container.registerSingleton(ControlPlaneCatalogFetcher, ControlPlaneCatalogFetcher);
|
|
532
|
+
|
|
533
|
+
const fetcher = container.resolve(ControlPlaneCatalogFetcher);
|
|
534
|
+
const credentialTypeRegistry = container.resolve(CredentialTypeRegistryImpl);
|
|
535
|
+
const mcpServerCatalog = container.resolve(McpServerCatalog);
|
|
536
|
+
|
|
537
|
+
fetcher.onRefresh = () => {
|
|
538
|
+
credentialTypeRegistry.mergeDefinitions("controlPlane", fetcher.credentialTypeOverrides ?? []);
|
|
539
|
+
mcpServerCatalog.merge("controlPlane", fetcher.mcpServers ?? []);
|
|
540
|
+
};
|
|
426
541
|
}
|
|
427
542
|
|
|
428
543
|
private registerConfiguredRegistrations(container: Container, appConfig: AppConfig): void {
|
|
@@ -499,9 +614,7 @@ export class AppContainerFactory {
|
|
|
499
614
|
CoreTokens.PersistedWorkflowTokenRegistry,
|
|
500
615
|
container.resolve(PersistedWorkflowTokenRegistry),
|
|
501
616
|
);
|
|
502
|
-
container.
|
|
503
|
-
useFactory: instanceCachingFactory(() => new CredentialTypeRegistryImpl()),
|
|
504
|
-
});
|
|
617
|
+
container.registerSingleton(CredentialTypeRegistryImpl, CredentialTypeRegistryImpl);
|
|
505
618
|
container.register(CoreTokens.CredentialTypeRegistry, {
|
|
506
619
|
useFactory: instanceCachingFactory((dependencyContainer) =>
|
|
507
620
|
dependencyContainer.resolve(CredentialTypeRegistryImpl),
|
|
@@ -516,9 +629,11 @@ export class AppContainerFactory {
|
|
|
516
629
|
});
|
|
517
630
|
container.register(CoreTokens.LiveWorkflowRepository, {
|
|
518
631
|
useFactory: instanceCachingFactory(
|
|
519
|
-
() =>
|
|
632
|
+
(dependencyContainer) =>
|
|
520
633
|
new LiveWorkflowRepository(
|
|
521
|
-
new AIAgentConnectionWorkflowExpander(new ConnectionCredentialNodeConfigFactory())
|
|
634
|
+
new AIAgentConnectionWorkflowExpander(new ConnectionCredentialNodeConfigFactory(), (id) =>
|
|
635
|
+
dependencyContainer.resolve(McpServerCatalog).get(id),
|
|
636
|
+
),
|
|
522
637
|
),
|
|
523
638
|
),
|
|
524
639
|
});
|
|
@@ -563,6 +678,7 @@ export class AppContainerFactory {
|
|
|
563
678
|
});
|
|
564
679
|
container.registerInstance(LogLevelPolicyFactory, logLevelPolicyFactory);
|
|
565
680
|
container.registerSingleton(ServerLoggerFactory, ServerLoggerFactory);
|
|
681
|
+
container.registerInstance(ApplicationTokens.ProcessRunner, new ExecaProcessRunner());
|
|
566
682
|
container.register(ApplicationTokens.LoggerFactory, {
|
|
567
683
|
useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(ServerLoggerFactory)),
|
|
568
684
|
});
|
|
@@ -576,10 +692,14 @@ export class AppContainerFactory {
|
|
|
576
692
|
if (inputs.sharedWorkflowWebsocketServer) {
|
|
577
693
|
return inputs.sharedWorkflowWebsocketServer;
|
|
578
694
|
}
|
|
695
|
+
const authenticator = dependencyContainer.isRegistered(ApplicationTokens.WebsocketAuthenticator, true)
|
|
696
|
+
? dependencyContainer.resolve(ApplicationTokens.WebsocketAuthenticator)
|
|
697
|
+
: null;
|
|
579
698
|
return new WorkflowWebsocketServer(
|
|
580
699
|
dependencyContainer.resolve(ApplicationTokens.WebSocketPort),
|
|
581
700
|
dependencyContainer.resolve(ApplicationTokens.WebSocketBindHost),
|
|
582
701
|
dependencyContainer.resolve(ServerLoggerFactory).create("codemation-websocket.server"),
|
|
702
|
+
authenticator,
|
|
583
703
|
);
|
|
584
704
|
}),
|
|
585
705
|
});
|
|
@@ -605,7 +725,19 @@ export class AppContainerFactory {
|
|
|
605
725
|
container.register(CoreTokens.CredentialSessionService, { useToken: CredentialSessionServiceImpl });
|
|
606
726
|
}
|
|
607
727
|
container.registerSingleton(OAuth2ProviderRegistry, OAuth2ProviderRegistry);
|
|
608
|
-
container.registerSingleton(
|
|
728
|
+
container.registerSingleton(OAuth2RedirectUriResolver, OAuth2RedirectUriResolver);
|
|
729
|
+
if (container.isRegistered(PairedFetch, true)) {
|
|
730
|
+
container.register(ApplicationTokens.OAuthFlowExecutor, {
|
|
731
|
+
useFactory: instanceCachingFactory((c) => c.resolve(ManagedOAuthFlowExecutor)),
|
|
732
|
+
});
|
|
733
|
+
container.registerSingleton(ManagedOAuthFlowExecutor, ManagedOAuthFlowExecutor);
|
|
734
|
+
} else {
|
|
735
|
+
container.register(ApplicationTokens.OAuthFlowExecutor, {
|
|
736
|
+
useFactory: instanceCachingFactory((c) => c.resolve(LocalOAuthFlowExecutor)),
|
|
737
|
+
});
|
|
738
|
+
container.registerSingleton(LocalOAuthFlowExecutor, LocalOAuthFlowExecutor);
|
|
739
|
+
}
|
|
740
|
+
container.registerSingleton(CredentialOAuth2MaterialReader, CredentialOAuth2MaterialReader);
|
|
609
741
|
container.registerSingleton(CodemationFrontendAuthSnapshotFactory, CodemationFrontendAuthSnapshotFactory);
|
|
610
742
|
container.registerSingleton(FrontendAppConfigFactory, FrontendAppConfigFactory);
|
|
611
743
|
container.registerSingleton(PublicFrontendBootstrapFactory, PublicFrontendBootstrapFactory);
|
|
@@ -723,6 +855,7 @@ export class AppContainerFactory {
|
|
|
723
855
|
container.registerSingleton(InMemoryTelemetryArtifactStore, InMemoryTelemetryArtifactStore);
|
|
724
856
|
container.registerSingleton(InMemoryTelemetryMetricPointStore, InMemoryTelemetryMetricPointStore);
|
|
725
857
|
container.registerSingleton(PrismaRunTraceContextRepository, PrismaRunTraceContextRepository);
|
|
858
|
+
container.registerSingleton(PrismaWorkflowSnapshotRepository, PrismaWorkflowSnapshotRepository);
|
|
726
859
|
container.registerSingleton(PrismaTelemetrySpanStore, PrismaTelemetrySpanStore);
|
|
727
860
|
container.registerSingleton(PrismaTelemetryArtifactStore, PrismaTelemetryArtifactStore);
|
|
728
861
|
container.registerSingleton(PrismaTelemetryMetricPointStore, PrismaTelemetryMetricPointStore);
|
|
@@ -770,7 +903,7 @@ export class AppContainerFactory {
|
|
|
770
903
|
});
|
|
771
904
|
}
|
|
772
905
|
|
|
773
|
-
private registerApplicationServicesAndRoutes(container: Container): void {
|
|
906
|
+
private registerApplicationServicesAndRoutes(container: Container, appConfig: AppConfig): void {
|
|
774
907
|
container.registerSingleton(DevBootstrapSummaryAssembler, DevBootstrapSummaryAssembler);
|
|
775
908
|
container.registerSingleton(DevBootstrapSummaryHttpRouteHandler, DevBootstrapSummaryHttpRouteHandler);
|
|
776
909
|
container.registerSingleton(AuthHttpRouteHandler, AuthHttpRouteHandler);
|
|
@@ -808,21 +941,110 @@ export class AppContainerFactory {
|
|
|
808
941
|
container.registerSingleton(TestRunnerService, TestRunnerService);
|
|
809
942
|
container.registerSingleton(TestSuiteHttpRouteHandler, TestSuiteHttpRouteHandler);
|
|
810
943
|
container.registerSingleton(CollectionHttpRouteHandler, CollectionHttpRouteHandler);
|
|
944
|
+
const isManagedMode = appConfig.auth?.kind === "managed";
|
|
811
945
|
for (const registrar of AppContainerFactory.honoRouteRegistrars) {
|
|
946
|
+
// In managed mode, skip the Better Auth route registrar so /api/auth/* returns 404
|
|
947
|
+
if (isManagedMode && registrar === AuthHonoApiRouteRegistrar) {
|
|
948
|
+
continue;
|
|
949
|
+
}
|
|
812
950
|
container.registerSingleton(ApplicationTokens.HonoApiRouteRegistrar, registrar);
|
|
813
951
|
}
|
|
814
952
|
container.registerSingleton(CodemationHonoApiApp, CodemationHonoApiApp);
|
|
815
953
|
}
|
|
816
954
|
|
|
955
|
+
private registerManagedAuthInfrastructure(container: Container, appConfig: AppConfig): void {
|
|
956
|
+
if (appConfig.auth?.kind !== "managed") {
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
new ManagedModeBootGuard().assertRequiredEnv(appConfig.env);
|
|
961
|
+
const managedAuthConfig = new ManagedAuthConfigFactory().create(appConfig.env);
|
|
962
|
+
const workspaceId = appConfig.env["WORKSPACE_ID"] ?? "";
|
|
963
|
+
|
|
964
|
+
const jwksCache = new JwksCache({ jwksUrl: managedAuthConfig.jwksUrl }, (url) => fetch(url), {
|
|
965
|
+
now: () => Date.now(),
|
|
966
|
+
});
|
|
967
|
+
// Shared verifier: both ManagedAuthMiddleware (HTTP) and ManagedWebsocketAuthenticator (WS)
|
|
968
|
+
// use the same JwksCache instance so JWKS key rotation propagates to both transports.
|
|
969
|
+
const jwtVerifier = new ManagedJwtVerifier(
|
|
970
|
+
{
|
|
971
|
+
expectedIssuer: managedAuthConfig.issuer,
|
|
972
|
+
expectedAudience: workspaceId,
|
|
973
|
+
jwksCache: { jwksUrl: managedAuthConfig.jwksUrl },
|
|
974
|
+
},
|
|
975
|
+
jwksCache,
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
const managedAuthMiddleware = new ManagedAuthMiddleware(jwtVerifier);
|
|
979
|
+
container.register(ApplicationTokens.SessionVerifier, { useValue: managedAuthMiddleware });
|
|
980
|
+
|
|
981
|
+
const websocketAuthenticator = new ManagedWebsocketAuthenticator(jwtVerifier);
|
|
982
|
+
container.registerInstance(ApplicationTokens.WebsocketAuthenticator, websocketAuthenticator);
|
|
983
|
+
|
|
984
|
+
const corsMiddleware = new ManagedCorsMiddleware(managedAuthConfig.cpWebOrigin);
|
|
985
|
+
container.registerInstance(ApplicationTokens.ManagedCorsMiddleware, corsMiddleware);
|
|
986
|
+
|
|
987
|
+
container.registerSingleton(ApplicationTokens.HonoApiRouteRegistrar, ManagedMeHonoApiRouteRegistrar);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
private registerPairingInfrastructure(container: Container, appConfig: AppConfig): void {
|
|
991
|
+
const pairingConfig = new PairingConfigFactory().create(appConfig.env);
|
|
992
|
+
if (!pairingConfig) {
|
|
993
|
+
// Pairing is optional in non-production environments (local dev without CP integration).
|
|
994
|
+
// Emit a startup warning so operators know the workspace-mcp HMAC channel is inactive.
|
|
995
|
+
const missingVars: string[] = [];
|
|
996
|
+
if (!appConfig.env["WORKSPACE_ID"]) missingVars.push("WORKSPACE_ID");
|
|
997
|
+
if (!appConfig.env["WORKSPACE_PAIRING_SECRET"]) missingVars.push("WORKSPACE_PAIRING_SECRET");
|
|
998
|
+
if (!appConfig.env["CONTROL_PLANE_URL"]) missingVars.push("CONTROL_PLANE_URL");
|
|
999
|
+
if (missingVars.length > 0) {
|
|
1000
|
+
const logger = container.resolve(ServerLoggerFactory).create("codemation.pairing");
|
|
1001
|
+
logger.warn(
|
|
1002
|
+
`Pairing not configured — missing env vars: ${missingVars.join(", ")}. ` +
|
|
1003
|
+
"Internal /internal/* routes are inactive. Set these vars for managed-mode integration.",
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
container.registerInstance(PairingConfigToken, pairingConfig);
|
|
1009
|
+
container.registerSingleton(HmacRequestSigner, HmacRequestSigner);
|
|
1010
|
+
container.registerSingleton(PairedFetch, PairedFetch);
|
|
1011
|
+
container.registerSingleton(IncomingHmacVerifier, IncomingHmacVerifier);
|
|
1012
|
+
container.registerSingleton(InternalHmacAuthMiddleware, InternalHmacAuthMiddleware);
|
|
1013
|
+
container.registerSingleton(BrokerClient, BrokerClient);
|
|
1014
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalPingRegistrar);
|
|
1015
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalCredentialsPushRegistrar);
|
|
1016
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalCredentialsListRegistrar);
|
|
1017
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowsListRegistrar);
|
|
1018
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowDetailRegistrar);
|
|
1019
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowActivationRegistrar);
|
|
1020
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowTestRunRegistrar);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
817
1023
|
private registerOperationalInfrastructure(container: Container): void {
|
|
818
1024
|
container.register(ApplicationTokens.WorkflowWebsocketPublisher, {
|
|
819
1025
|
useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(WorkflowWebsocketServer)),
|
|
820
1026
|
});
|
|
821
1027
|
container.registerSingleton(WorkflowRunEventWebsocketRelay, WorkflowRunEventWebsocketRelay);
|
|
1028
|
+
container.registerSingleton(TelemetrySpanWebsocketRelay, TelemetrySpanWebsocketRelay);
|
|
1029
|
+
container.register(ApplicationTokens.TelemetrySpanPublisher, {
|
|
1030
|
+
useFactory: instanceCachingFactory((dependencyContainer) =>
|
|
1031
|
+
dependencyContainer.resolve(TelemetrySpanWebsocketRelay),
|
|
1032
|
+
),
|
|
1033
|
+
});
|
|
822
1034
|
container.registerSingleton(RunEventBusTelemetryReporter, RunEventBusTelemetryReporter);
|
|
823
1035
|
container.registerSingleton(WorkflowRunRetentionPruneScheduler, WorkflowRunRetentionPruneScheduler);
|
|
824
1036
|
}
|
|
825
1037
|
|
|
1038
|
+
private registerWorkflowAuditWriter(container: Container, appConfig: AppConfig): void {
|
|
1039
|
+
if (appConfig.persistence.kind === "none") {
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
container.registerSingleton(PrismaWorkflowAuditLogRepository, PrismaWorkflowAuditLogRepository);
|
|
1043
|
+
container.register(ApplicationTokens.WorkflowAuditEmitter, { useToken: PrismaWorkflowAuditLogRepository });
|
|
1044
|
+
container.registerSingleton(WorkflowAuditLogWriter, WorkflowAuditLogWriter);
|
|
1045
|
+
container.registerSingleton(WorkflowAuditLogPruneScheduler, WorkflowAuditLogPruneScheduler);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
826
1048
|
private async registerRuntimeInfrastructure(container: Container, appConfig: AppConfig): Promise<PrismaOwnership> {
|
|
827
1049
|
const queuePrefix = appConfig.scheduler.queuePrefix ?? appConfig.eventing.queuePrefix ?? "codemation";
|
|
828
1050
|
const eventBus =
|
|
@@ -830,7 +1052,7 @@ export class AppContainerFactory {
|
|
|
830
1052
|
? new RedisRunEventBus(this.requireRedisUrl(appConfig.eventing.redisUrl), queuePrefix)
|
|
831
1053
|
: new InMemoryRunEventBus();
|
|
832
1054
|
container.registerInstance(CoreTokens.RunEventBus, eventBus);
|
|
833
|
-
const binaryStorage = this.createBinaryStorage(appConfig
|
|
1055
|
+
const binaryStorage = await this.createBinaryStorage(appConfig);
|
|
834
1056
|
container.registerInstance(CoreTokens.RunDataFactory, new InMemoryRunDataFactory());
|
|
835
1057
|
container.registerInstance(CoreTokens.BinaryStorage, binaryStorage);
|
|
836
1058
|
container.registerInstance(ApplicationTokens.Clock, new SystemClock());
|
|
@@ -1005,11 +1227,37 @@ export class AppContainerFactory {
|
|
|
1005
1227
|
};
|
|
1006
1228
|
}
|
|
1007
1229
|
|
|
1008
|
-
private createBinaryStorage(
|
|
1009
|
-
|
|
1230
|
+
private async createBinaryStorage(
|
|
1231
|
+
appConfig: AppConfig,
|
|
1232
|
+
): Promise<InMemoryBinaryStorage | LocalFilesystemBinaryStorage | S3BinaryStorage> {
|
|
1233
|
+
const kind = appConfig.env.BINARY_STORAGE_KIND ?? "local";
|
|
1234
|
+
|
|
1235
|
+
if (kind === "s3") {
|
|
1236
|
+
const parseResult = S3BinaryStorageConfigSchema.safeParse({
|
|
1237
|
+
endpoint: appConfig.env.BINARY_STORAGE_S3_ENDPOINT,
|
|
1238
|
+
region: appConfig.env.BINARY_STORAGE_S3_REGION,
|
|
1239
|
+
bucket: appConfig.env.BINARY_STORAGE_S3_BUCKET,
|
|
1240
|
+
accessKeyId: appConfig.env.BINARY_STORAGE_S3_ACCESS_KEY_ID,
|
|
1241
|
+
secretAccessKey: appConfig.env.BINARY_STORAGE_S3_SECRET_ACCESS_KEY,
|
|
1242
|
+
});
|
|
1243
|
+
if (!parseResult.success) {
|
|
1244
|
+
throw new Error(
|
|
1245
|
+
`BINARY_STORAGE_KIND=s3 requires all BINARY_STORAGE_S3_* env vars. Validation errors: ${parseResult.error.message}`,
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
const storage = new S3BinaryStorage(parseResult.data);
|
|
1249
|
+
await storage.checkConnectivity();
|
|
1250
|
+
return storage;
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
if (kind !== "local") {
|
|
1254
|
+
throw new Error(`Unknown BINARY_STORAGE_KIND: "${kind}". Expected "local" or "s3".`);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
if (!appConfig.repoRoot) {
|
|
1010
1258
|
return new InMemoryBinaryStorage();
|
|
1011
1259
|
}
|
|
1012
|
-
return new LocalFilesystemBinaryStorage(`${repoRoot}/.codemation/binary`);
|
|
1260
|
+
return new LocalFilesystemBinaryStorage(`${appConfig.repoRoot}/.codemation/binary`);
|
|
1013
1261
|
}
|
|
1014
1262
|
|
|
1015
1263
|
private createRuntimeSummary(appConfig: AppConfig): BootRuntimeSummary {
|
|
@@ -2,9 +2,13 @@ import type { Container } from "@codemation/core";
|
|
|
2
2
|
import { Engine } from "@codemation/core/bootstrap";
|
|
3
3
|
import { RunEventBusTelemetryReporter } from "../application/telemetry/RunEventBusTelemetryReporter";
|
|
4
4
|
import { WorkflowRunRetentionPruneScheduler } from "../application/runs/WorkflowRunRetentionPruneScheduler";
|
|
5
|
+
import { WorkflowAuditLogPruneScheduler } from "../application/WorkflowAuditLogPruneScheduler";
|
|
5
6
|
import type { PrismaDatabaseClient } from "../infrastructure/persistence/PrismaDatabaseClient";
|
|
6
7
|
import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
|
|
7
8
|
import { WorkflowWebsocketServer } from "../presentation/websocket/WorkflowWebsocketServer";
|
|
9
|
+
import { McpConnectionPool } from "../mcp/McpConnectionPool";
|
|
10
|
+
import { WorkflowAuditLogWriter } from "../audit/WorkflowAuditLogWriter";
|
|
11
|
+
import { ControlPlaneCatalogFetcher } from "../credentials/ControlPlaneCatalogFetcher";
|
|
8
12
|
|
|
9
13
|
export class AppContainerLifecycle {
|
|
10
14
|
constructor(
|
|
@@ -12,6 +16,21 @@ export class AppContainerLifecycle {
|
|
|
12
16
|
private readonly ownedPrismaClient: PrismaDatabaseClient | null,
|
|
13
17
|
) {}
|
|
14
18
|
|
|
19
|
+
async start(): Promise<void> {
|
|
20
|
+
if (this.container.isRegistered(ControlPlaneCatalogFetcher, true)) {
|
|
21
|
+
await this.container.resolve(ControlPlaneCatalogFetcher).start();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async startWorkerSubscribers(): Promise<void> {
|
|
26
|
+
if (this.container.isRegistered(WorkflowAuditLogWriter, true)) {
|
|
27
|
+
await this.container.resolve(WorkflowAuditLogWriter).start();
|
|
28
|
+
}
|
|
29
|
+
if (this.container.isRegistered(WorkflowAuditLogPruneScheduler, true)) {
|
|
30
|
+
this.container.resolve(WorkflowAuditLogPruneScheduler).start();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
15
34
|
async stop(args?: Readonly<{ stopWebsocketServer?: boolean }>): Promise<void> {
|
|
16
35
|
if (this.container.isRegistered(Engine, true)) {
|
|
17
36
|
await this.container.resolve(Engine).stop();
|
|
@@ -22,12 +41,24 @@ export class AppContainerLifecycle {
|
|
|
22
41
|
if (this.container.isRegistered(RunEventBusTelemetryReporter, true)) {
|
|
23
42
|
await this.container.resolve(RunEventBusTelemetryReporter).stop();
|
|
24
43
|
}
|
|
44
|
+
if (this.container.isRegistered(WorkflowAuditLogWriter, true)) {
|
|
45
|
+
await this.container.resolve(WorkflowAuditLogWriter).stop();
|
|
46
|
+
}
|
|
25
47
|
if (this.container.isRegistered(WorkflowRunRetentionPruneScheduler, true)) {
|
|
26
48
|
this.container.resolve(WorkflowRunRetentionPruneScheduler).stop();
|
|
27
49
|
}
|
|
50
|
+
if (this.container.isRegistered(WorkflowAuditLogPruneScheduler, true)) {
|
|
51
|
+
this.container.resolve(WorkflowAuditLogPruneScheduler).stop();
|
|
52
|
+
}
|
|
28
53
|
if (args?.stopWebsocketServer !== false && this.container.isRegistered(WorkflowWebsocketServer, true)) {
|
|
29
54
|
await this.container.resolve(WorkflowWebsocketServer).stop();
|
|
30
55
|
}
|
|
56
|
+
if (this.container.isRegistered(McpConnectionPool, true)) {
|
|
57
|
+
await this.container.resolve(McpConnectionPool).closeAll();
|
|
58
|
+
}
|
|
59
|
+
if (this.container.isRegistered(ControlPlaneCatalogFetcher, true)) {
|
|
60
|
+
await this.container.resolve(ControlPlaneCatalogFetcher).stop();
|
|
61
|
+
}
|
|
31
62
|
if (this.ownedPrismaClient) {
|
|
32
63
|
await this.ownedPrismaClient.$disconnect();
|
|
33
64
|
}
|