@codemation/host 0.6.0 → 0.8.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 +483 -0
- package/dist/{ApiPaths-CLTHphYZ.js → ApiPaths-Dv1dcHu_.js} +4 -4
- package/dist/ApiPaths-Dv1dcHu_.js.map +1 -0
- package/dist/{AppConfigFactory-YnveXE9k.d.ts → AppConfigFactory-BT0y0LVC.d.ts} +8490 -5548
- package/dist/{AppConfigFactory-C6q-CSKb.js → AppConfigFactory-Cx4qQvRk.js} +112 -52
- package/dist/AppConfigFactory-Cx4qQvRk.js.map +1 -0
- package/dist/{AppContainerFactory-qaqc-R1D.js → AppContainerFactory-DRTjG7nG.js} +7298 -1732
- package/dist/AppContainerFactory-DRTjG7nG.js.map +1 -0
- package/dist/{CodemationAppContext-DRu1Dpri.d.ts → CodemationAppContext-CGFYVcSb.d.ts} +14 -4
- package/dist/{CodemationAuthoring.types-DZl-sJaM.js → CodemationAuthoring.types-BteaR3Dc.js} +19 -6
- package/dist/CodemationAuthoring.types-BteaR3Dc.js.map +1 -0
- package/dist/{CodemationAuthoring.types-fBRppnmi.d.ts → CodemationAuthoring.types-DiKKogum.d.ts} +30 -5
- package/dist/{CodemationConfigNormalizer-DVko3cVN.d.ts → CodemationConfigNormalizer-48f-T66P.d.ts} +3 -3
- package/dist/{CodemationConsumerConfigLoader-BeAUS144.js → CodemationConsumerConfigLoader-By-6tuGc.js} +81 -10
- package/dist/CodemationConsumerConfigLoader-By-6tuGc.js.map +1 -0
- package/dist/{CodemationConsumerConfigLoader-DJWr86f-.d.ts → CodemationConsumerConfigLoader-_PIYqwVx.d.ts} +18 -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-DGc-jfa2.d.ts → CodemationPluginListMerger-DP7djJ9S.d.ts} +151 -19
- 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-DrMIDSw8.d.ts → CredentialContractsRegistry-Bq2bq28t.d.ts} +2 -2
- package/dist/{CredentialServices-UfvHB-rN.d.ts → CredentialServices-BLloBztI.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-c7t3KnV_.d.ts +17 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js +221 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js.map +1 -0
- package/dist/{ItemsInputNormalizer-C-KHg9Mo.d.ts → ItemsInputNormalizer-_RwIfRIQ.d.ts} +89 -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-Dv04tJ-6.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-DbaNomrH.d.ts → TelemetryContracts-BtDx84Cp.d.ts} +13 -4
- package/dist/{WorkflowPolicyUiPresentationFactory-DQEY-h_S.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-CzK2KFuz.d.ts → WorkflowViewContracts-B7aFQcIw.d.ts} +10 -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-BbBk26m0.d.ts → index-DilAYwnH.d.ts} +49 -3
- package/dist/index.d.ts +141 -21
- package/dist/index.js +109 -14
- package/dist/index.js.map +1 -0
- package/dist/mapping.d.ts +2 -2
- package/dist/mapping.js +1 -1
- package/dist/nextServer.d.ts +42 -113
- 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-B71RGvSj.d.ts +30 -0
- package/dist/{persistenceServer-CmsIKnO9.js → persistenceServer-C-hH4z6l.js} +2 -2
- package/dist/{persistenceServer-CmsIKnO9.js.map → persistenceServer-C-hH4z6l.js.map} +1 -1
- package/dist/persistenceServer.d.ts +8 -8
- package/dist/persistenceServer.js +3 -3
- package/dist/{server-MUNGsBYK.d.ts → server-09PKasWR.d.ts} +21 -6
- package/dist/{server-CJFfY67o.js → server-vtRCPgRJ.js} +7 -6
- package/dist/{server-CJFfY67o.js.map → server-vtRCPgRJ.js.map} +1 -1
- package/dist/server.d.ts +14 -14
- package/dist/server.js +13 -11
- package/package.json +47 -58
- 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/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 +55 -17
- package/prisma/schema.sqlite.prisma +55 -17
- package/prisma-generated/prisma-postgresql-client/edge.js +33 -5
- package/prisma-generated/prisma-postgresql-client/index-browser.js +29 -1
- package/prisma-generated/prisma-postgresql-client/index.d.ts +8933 -5716
- package/prisma-generated/prisma-postgresql-client/index.js +33 -5
- package/prisma-generated/prisma-postgresql-client/package.json +1 -1
- package/prisma-generated/prisma-postgresql-client/schema.prisma +38 -0
- package/prisma-generated/prisma-sqlite-client/edge.js +33 -5
- package/prisma-generated/prisma-sqlite-client/index-browser.js +29 -1
- package/prisma-generated/prisma-sqlite-client/index.d.ts +8925 -5713
- package/prisma-generated/prisma-sqlite-client/index.js +33 -5
- package/prisma-generated/prisma-sqlite-client/package.json +1 -1
- package/prisma-generated/prisma-sqlite-client/schema.prisma +38 -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 +6 -0
- package/src/application/contracts/WorkflowWebsocketMessage.ts +3 -1
- package/src/application/mapping/WorkflowDefinitionMapper.ts +40 -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 +295 -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/HeadlessApiRuntime.ts +47 -0
- 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 +9 -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/PrismaMigrationDeployer.ts +21 -13
- package/src/infrastructure/persistence/PrismaTelemetryArtifactStore.ts +43 -8
- package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +26 -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 +60 -5
- package/src/presentation/config/CodemationConfig.ts +9 -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/HeadlessHttpServerFactory.ts +56 -0
- 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 +59 -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/presentation/websocket/WorkflowWebsocketServerFactory.ts +16 -0
- 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-C6q-CSKb.js.map +0 -1
- package/dist/AppContainerFactory-qaqc-R1D.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-Cb2pLmDd.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-vtJAGDat.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,63 @@ 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
|
-
|
|
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", () =>
|
|
397
|
+
this.registerCoreInfrastructure(container, inputs),
|
|
398
|
+
);
|
|
399
|
+
BootTimer.measure("appContainer.registerRepositoriesAndBuses", () => this.registerRepositoriesAndBuses(container));
|
|
400
|
+
BootTimer.measure("appContainer.registerApplicationServicesAndRoutes", () =>
|
|
401
|
+
this.registerApplicationServicesAndRoutes(container, inputs.appConfig),
|
|
402
|
+
);
|
|
403
|
+
BootTimer.measure("appContainer.registerOperationalInfrastructure", () =>
|
|
404
|
+
this.registerOperationalInfrastructure(container),
|
|
405
|
+
);
|
|
406
|
+
BootTimer.measure("appContainer.registerManagedAuthInfrastructure", () =>
|
|
407
|
+
this.registerManagedAuthInfrastructure(container, inputs.appConfig),
|
|
408
|
+
);
|
|
409
|
+
BootTimer.measure("appContainer.registerPairingInfrastructure", () =>
|
|
410
|
+
this.registerPairingInfrastructure(container, inputs.appConfig),
|
|
411
|
+
);
|
|
412
|
+
BootTimer.measure("appContainer.registerConfiguredRegistrations", () =>
|
|
413
|
+
this.registerConfiguredRegistrations(container, inputs.appConfig),
|
|
414
|
+
);
|
|
415
|
+
const credentialTypes = BootTimer.measure("appContainer.collectCredentialTypes", () =>
|
|
416
|
+
this.collectCredentialTypes(inputs.appConfig),
|
|
417
|
+
);
|
|
418
|
+
BootTimer.measure("appContainer.registerMcpCatalog", () => this.registerMcpCatalog(container));
|
|
419
|
+
await BootTimer.measureAsync("appContainer.applyPlugins", () =>
|
|
420
|
+
this.applyPlugins(container, inputs.appConfig, credentialTypes),
|
|
421
|
+
);
|
|
422
|
+
BootTimer.measure("appContainer.mergeConfigMcpServers", () =>
|
|
423
|
+
this.mergeConfigMcpServers(container, inputs.appConfig),
|
|
368
424
|
);
|
|
425
|
+
const ownership = await BootTimer.measureAsync("appContainer.registerRuntimeInfrastructure", () =>
|
|
426
|
+
this.registerRuntimeInfrastructure(container, inputs.appConfig),
|
|
427
|
+
);
|
|
428
|
+
BootTimer.measure("appContainer.registerWorkflowAuditWriter", () =>
|
|
429
|
+
this.registerWorkflowAuditWriter(container, inputs.appConfig),
|
|
430
|
+
);
|
|
431
|
+
BootTimer.measure("appContainer.registerCollectionsInfrastructure", () =>
|
|
432
|
+
this.registerCollectionsInfrastructure(container, inputs.appConfig),
|
|
433
|
+
);
|
|
434
|
+
BootTimer.measure("appContainer.registerCredentialTypes", () =>
|
|
435
|
+
this.registerCredentialTypes(container, credentialTypes),
|
|
436
|
+
);
|
|
437
|
+
BootTimer.measure("appContainer.registerControlPlaneCatalogFetcher", () =>
|
|
438
|
+
this.registerControlPlaneCatalogFetcher(container),
|
|
439
|
+
);
|
|
440
|
+
BootTimer.measure("appContainer.synchronizeLiveWorkflowRepository", () =>
|
|
441
|
+
this.synchronizeLiveWorkflowRepository(container, inputs.appConfig.workflows),
|
|
442
|
+
);
|
|
443
|
+
BootTimer.measure("appContainer.registerWorkflowDefinitions", () =>
|
|
444
|
+
new CodemationTsyringeTypeInfoRegistrar(container).registerWorkflowDefinitions(inputs.appConfig.workflows ?? []),
|
|
445
|
+
);
|
|
446
|
+
container.resolve(BootRuntimeSnapshotHolder).set(this.createRuntimeSummary(inputs.appConfig));
|
|
447
|
+
const lifecycle = new AppContainerLifecycle(container, ownership.ownedPrismaClient);
|
|
448
|
+
container.registerInstance(AppContainerLifecycle, lifecycle);
|
|
449
|
+
await BootTimer.measureAsync("appContainer.lifecycleStart", () => lifecycle.start());
|
|
369
450
|
return container;
|
|
370
451
|
}
|
|
371
452
|
|
|
@@ -391,11 +472,28 @@ export class AppContainerFactory {
|
|
|
391
472
|
return credentialTypes;
|
|
392
473
|
}
|
|
393
474
|
|
|
475
|
+
private registerMcpCatalog(container: Container): void {
|
|
476
|
+
container.registerSingleton(McpServerCatalog, McpServerCatalog);
|
|
477
|
+
container.registerSingleton(DefaultMcpClientFactory, DefaultMcpClientFactory);
|
|
478
|
+
container.registerSingleton(McpConnectionPool, McpConnectionPool);
|
|
479
|
+
container.registerSingleton(AgentMcpIntegrationImpl, AgentMcpIntegrationImpl);
|
|
480
|
+
// Register the host-side AgentMcpIntegration, overriding the NoOp registered by EngineRuntimeRegistrar.
|
|
481
|
+
container.register(CoreTokens.AgentMcpIntegration, {
|
|
482
|
+
useFactory: instanceCachingFactory((c) => c.resolve(AgentMcpIntegrationImpl)),
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
private mergeConfigMcpServers(container: Container, appConfig: AppConfig): void {
|
|
487
|
+
const catalog = container.resolve(McpServerCatalog);
|
|
488
|
+
catalog.merge("config", appConfig.mcpServers ?? []);
|
|
489
|
+
}
|
|
490
|
+
|
|
394
491
|
private async applyPlugins(
|
|
395
492
|
container: Container,
|
|
396
493
|
appConfig: AppConfig,
|
|
397
494
|
credentialTypes: Array<CredentialType<any, any, unknown>>,
|
|
398
495
|
): Promise<void> {
|
|
496
|
+
const catalog = container.resolve(McpServerCatalog);
|
|
399
497
|
await this.pluginRegistrar.apply({
|
|
400
498
|
plugins: appConfig.plugins,
|
|
401
499
|
container,
|
|
@@ -411,6 +509,7 @@ export class AppContainerFactory {
|
|
|
411
509
|
// during plugin.register() are accepted silently — Phase 6 store wiring will
|
|
412
510
|
// pick them up once collection infrastructure can reload from a mutable registry.
|
|
413
511
|
},
|
|
512
|
+
mergeMcpServers: (declarations) => catalog.merge("plugin", declarations),
|
|
414
513
|
loggerFactory: container.resolve(ApplicationTokens.LoggerFactory),
|
|
415
514
|
});
|
|
416
515
|
}
|
|
@@ -420,9 +519,27 @@ export class AppContainerFactory {
|
|
|
420
519
|
credentialTypes: ReadonlyArray<CredentialType<any, any, unknown>>,
|
|
421
520
|
): void {
|
|
422
521
|
const registry = container.resolve(CredentialTypeRegistryImpl);
|
|
423
|
-
|
|
424
|
-
|
|
522
|
+
registry.merge("plugin", credentialTypes);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private registerControlPlaneCatalogFetcher(container: Container): void {
|
|
526
|
+
// Only register the fetcher when paired with a control plane.
|
|
527
|
+
// PairedFetch is only registered inside registerPairingInfrastructure,
|
|
528
|
+
// which skips registration when pairing env vars are absent.
|
|
529
|
+
if (!container.isRegistered(PairedFetch, true)) {
|
|
530
|
+
return;
|
|
425
531
|
}
|
|
532
|
+
|
|
533
|
+
container.registerSingleton(ControlPlaneCatalogFetcher, ControlPlaneCatalogFetcher);
|
|
534
|
+
|
|
535
|
+
const fetcher = container.resolve(ControlPlaneCatalogFetcher);
|
|
536
|
+
const credentialTypeRegistry = container.resolve(CredentialTypeRegistryImpl);
|
|
537
|
+
const mcpServerCatalog = container.resolve(McpServerCatalog);
|
|
538
|
+
|
|
539
|
+
fetcher.onRefresh = () => {
|
|
540
|
+
credentialTypeRegistry.mergeDefinitions("controlPlane", fetcher.credentialTypeOverrides ?? []);
|
|
541
|
+
mcpServerCatalog.merge("controlPlane", fetcher.mcpServers ?? []);
|
|
542
|
+
};
|
|
426
543
|
}
|
|
427
544
|
|
|
428
545
|
private registerConfiguredRegistrations(container: Container, appConfig: AppConfig): void {
|
|
@@ -499,9 +616,7 @@ export class AppContainerFactory {
|
|
|
499
616
|
CoreTokens.PersistedWorkflowTokenRegistry,
|
|
500
617
|
container.resolve(PersistedWorkflowTokenRegistry),
|
|
501
618
|
);
|
|
502
|
-
container.
|
|
503
|
-
useFactory: instanceCachingFactory(() => new CredentialTypeRegistryImpl()),
|
|
504
|
-
});
|
|
619
|
+
container.registerSingleton(CredentialTypeRegistryImpl, CredentialTypeRegistryImpl);
|
|
505
620
|
container.register(CoreTokens.CredentialTypeRegistry, {
|
|
506
621
|
useFactory: instanceCachingFactory((dependencyContainer) =>
|
|
507
622
|
dependencyContainer.resolve(CredentialTypeRegistryImpl),
|
|
@@ -516,9 +631,11 @@ export class AppContainerFactory {
|
|
|
516
631
|
});
|
|
517
632
|
container.register(CoreTokens.LiveWorkflowRepository, {
|
|
518
633
|
useFactory: instanceCachingFactory(
|
|
519
|
-
() =>
|
|
634
|
+
(dependencyContainer) =>
|
|
520
635
|
new LiveWorkflowRepository(
|
|
521
|
-
new AIAgentConnectionWorkflowExpander(new ConnectionCredentialNodeConfigFactory())
|
|
636
|
+
new AIAgentConnectionWorkflowExpander(new ConnectionCredentialNodeConfigFactory(), (id) =>
|
|
637
|
+
dependencyContainer.resolve(McpServerCatalog).get(id),
|
|
638
|
+
),
|
|
522
639
|
),
|
|
523
640
|
),
|
|
524
641
|
});
|
|
@@ -563,6 +680,7 @@ export class AppContainerFactory {
|
|
|
563
680
|
});
|
|
564
681
|
container.registerInstance(LogLevelPolicyFactory, logLevelPolicyFactory);
|
|
565
682
|
container.registerSingleton(ServerLoggerFactory, ServerLoggerFactory);
|
|
683
|
+
container.registerInstance(ApplicationTokens.ProcessRunner, new ExecaProcessRunner());
|
|
566
684
|
container.register(ApplicationTokens.LoggerFactory, {
|
|
567
685
|
useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(ServerLoggerFactory)),
|
|
568
686
|
});
|
|
@@ -576,10 +694,14 @@ export class AppContainerFactory {
|
|
|
576
694
|
if (inputs.sharedWorkflowWebsocketServer) {
|
|
577
695
|
return inputs.sharedWorkflowWebsocketServer;
|
|
578
696
|
}
|
|
697
|
+
const authenticator = dependencyContainer.isRegistered(ApplicationTokens.WebsocketAuthenticator, true)
|
|
698
|
+
? dependencyContainer.resolve(ApplicationTokens.WebsocketAuthenticator)
|
|
699
|
+
: null;
|
|
579
700
|
return new WorkflowWebsocketServer(
|
|
580
701
|
dependencyContainer.resolve(ApplicationTokens.WebSocketPort),
|
|
581
702
|
dependencyContainer.resolve(ApplicationTokens.WebSocketBindHost),
|
|
582
703
|
dependencyContainer.resolve(ServerLoggerFactory).create("codemation-websocket.server"),
|
|
704
|
+
authenticator,
|
|
583
705
|
);
|
|
584
706
|
}),
|
|
585
707
|
});
|
|
@@ -605,7 +727,19 @@ export class AppContainerFactory {
|
|
|
605
727
|
container.register(CoreTokens.CredentialSessionService, { useToken: CredentialSessionServiceImpl });
|
|
606
728
|
}
|
|
607
729
|
container.registerSingleton(OAuth2ProviderRegistry, OAuth2ProviderRegistry);
|
|
608
|
-
container.registerSingleton(
|
|
730
|
+
container.registerSingleton(OAuth2RedirectUriResolver, OAuth2RedirectUriResolver);
|
|
731
|
+
if (container.isRegistered(PairedFetch, true)) {
|
|
732
|
+
container.register(ApplicationTokens.OAuthFlowExecutor, {
|
|
733
|
+
useFactory: instanceCachingFactory((c) => c.resolve(ManagedOAuthFlowExecutor)),
|
|
734
|
+
});
|
|
735
|
+
container.registerSingleton(ManagedOAuthFlowExecutor, ManagedOAuthFlowExecutor);
|
|
736
|
+
} else {
|
|
737
|
+
container.register(ApplicationTokens.OAuthFlowExecutor, {
|
|
738
|
+
useFactory: instanceCachingFactory((c) => c.resolve(LocalOAuthFlowExecutor)),
|
|
739
|
+
});
|
|
740
|
+
container.registerSingleton(LocalOAuthFlowExecutor, LocalOAuthFlowExecutor);
|
|
741
|
+
}
|
|
742
|
+
container.registerSingleton(CredentialOAuth2MaterialReader, CredentialOAuth2MaterialReader);
|
|
609
743
|
container.registerSingleton(CodemationFrontendAuthSnapshotFactory, CodemationFrontendAuthSnapshotFactory);
|
|
610
744
|
container.registerSingleton(FrontendAppConfigFactory, FrontendAppConfigFactory);
|
|
611
745
|
container.registerSingleton(PublicFrontendBootstrapFactory, PublicFrontendBootstrapFactory);
|
|
@@ -723,6 +857,7 @@ export class AppContainerFactory {
|
|
|
723
857
|
container.registerSingleton(InMemoryTelemetryArtifactStore, InMemoryTelemetryArtifactStore);
|
|
724
858
|
container.registerSingleton(InMemoryTelemetryMetricPointStore, InMemoryTelemetryMetricPointStore);
|
|
725
859
|
container.registerSingleton(PrismaRunTraceContextRepository, PrismaRunTraceContextRepository);
|
|
860
|
+
container.registerSingleton(PrismaWorkflowSnapshotRepository, PrismaWorkflowSnapshotRepository);
|
|
726
861
|
container.registerSingleton(PrismaTelemetrySpanStore, PrismaTelemetrySpanStore);
|
|
727
862
|
container.registerSingleton(PrismaTelemetryArtifactStore, PrismaTelemetryArtifactStore);
|
|
728
863
|
container.registerSingleton(PrismaTelemetryMetricPointStore, PrismaTelemetryMetricPointStore);
|
|
@@ -770,7 +905,7 @@ export class AppContainerFactory {
|
|
|
770
905
|
});
|
|
771
906
|
}
|
|
772
907
|
|
|
773
|
-
private registerApplicationServicesAndRoutes(container: Container): void {
|
|
908
|
+
private registerApplicationServicesAndRoutes(container: Container, appConfig: AppConfig): void {
|
|
774
909
|
container.registerSingleton(DevBootstrapSummaryAssembler, DevBootstrapSummaryAssembler);
|
|
775
910
|
container.registerSingleton(DevBootstrapSummaryHttpRouteHandler, DevBootstrapSummaryHttpRouteHandler);
|
|
776
911
|
container.registerSingleton(AuthHttpRouteHandler, AuthHttpRouteHandler);
|
|
@@ -808,21 +943,126 @@ export class AppContainerFactory {
|
|
|
808
943
|
container.registerSingleton(TestRunnerService, TestRunnerService);
|
|
809
944
|
container.registerSingleton(TestSuiteHttpRouteHandler, TestSuiteHttpRouteHandler);
|
|
810
945
|
container.registerSingleton(CollectionHttpRouteHandler, CollectionHttpRouteHandler);
|
|
946
|
+
const isManagedMode = appConfig.auth?.kind === "managed";
|
|
811
947
|
for (const registrar of AppContainerFactory.honoRouteRegistrars) {
|
|
948
|
+
// In managed mode, skip the Better Auth route registrar so /api/auth/* returns 404
|
|
949
|
+
if (isManagedMode && registrar === AuthHonoApiRouteRegistrar) {
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
812
952
|
container.registerSingleton(ApplicationTokens.HonoApiRouteRegistrar, registrar);
|
|
813
953
|
}
|
|
814
954
|
container.registerSingleton(CodemationHonoApiApp, CodemationHonoApiApp);
|
|
815
955
|
}
|
|
816
956
|
|
|
957
|
+
private registerManagedAuthInfrastructure(container: Container, appConfig: AppConfig): void {
|
|
958
|
+
if (appConfig.auth?.kind !== "managed") {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
new ManagedModeBootGuard().assertRequiredEnv(appConfig.env);
|
|
963
|
+
const managedAuthConfig = new ManagedAuthConfigFactory().create(appConfig.env);
|
|
964
|
+
const workspaceId = appConfig.env["WORKSPACE_ID"] ?? "";
|
|
965
|
+
|
|
966
|
+
const jwksCache = new JwksCache({ jwksUrl: managedAuthConfig.jwksUrl }, (url) => fetch(url), {
|
|
967
|
+
now: () => Date.now(),
|
|
968
|
+
});
|
|
969
|
+
// Shared verifier: both ManagedAuthMiddleware (HTTP) and ManagedWebsocketAuthenticator (WS)
|
|
970
|
+
// use the same JwksCache instance so JWKS key rotation propagates to both transports.
|
|
971
|
+
const jwtVerifier = new ManagedJwtVerifier(
|
|
972
|
+
{
|
|
973
|
+
expectedIssuer: managedAuthConfig.issuer,
|
|
974
|
+
expectedAudience: workspaceId,
|
|
975
|
+
jwksCache: { jwksUrl: managedAuthConfig.jwksUrl },
|
|
976
|
+
},
|
|
977
|
+
jwksCache,
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
const managedAuthMiddleware = new ManagedAuthMiddleware(jwtVerifier);
|
|
981
|
+
container.register(ApplicationTokens.SessionVerifier, { useValue: managedAuthMiddleware });
|
|
982
|
+
|
|
983
|
+
const websocketAuthenticator = new ManagedWebsocketAuthenticator(jwtVerifier);
|
|
984
|
+
container.registerInstance(ApplicationTokens.WebsocketAuthenticator, websocketAuthenticator);
|
|
985
|
+
|
|
986
|
+
const corsMiddleware = new ManagedCorsMiddleware(managedAuthConfig.cpWebOrigin);
|
|
987
|
+
container.registerInstance(ApplicationTokens.ManagedCorsMiddleware, corsMiddleware);
|
|
988
|
+
|
|
989
|
+
container.registerSingleton(ApplicationTokens.HonoApiRouteRegistrar, ManagedMeHonoApiRouteRegistrar);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
private registerPairingInfrastructure(container: Container, appConfig: AppConfig): void {
|
|
993
|
+
const isManagedMode = appConfig.auth?.kind === "managed";
|
|
994
|
+
let pairingConfig;
|
|
995
|
+
try {
|
|
996
|
+
pairingConfig = new PairingConfigFactory().create(appConfig.env);
|
|
997
|
+
} catch (err) {
|
|
998
|
+
if (isManagedMode) {
|
|
999
|
+
// In managed mode the secret is required — let the error surface.
|
|
1000
|
+
throw err;
|
|
1001
|
+
}
|
|
1002
|
+
// In non-managed mode an invalid-but-present WORKSPACE_PAIRING_SECRET is a misconfiguration
|
|
1003
|
+
// warning, not a fatal error. Log and continue without pairing.
|
|
1004
|
+
const logger = container.resolve(ServerLoggerFactory).create("codemation.pairing");
|
|
1005
|
+
logger.warn(
|
|
1006
|
+
`WORKSPACE_PAIRING_SECRET is set but invalid — pairing disabled. ${err instanceof Error ? err.message : String(err)}`,
|
|
1007
|
+
);
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (!pairingConfig) {
|
|
1011
|
+
// Pairing is optional in non-production environments (local dev without CP integration).
|
|
1012
|
+
// Emit a startup warning so operators know the workspace-mcp HMAC channel is inactive.
|
|
1013
|
+
const missingVars: string[] = [];
|
|
1014
|
+
if (!appConfig.env["WORKSPACE_ID"]) missingVars.push("WORKSPACE_ID");
|
|
1015
|
+
if (!appConfig.env["WORKSPACE_PAIRING_SECRET"]) missingVars.push("WORKSPACE_PAIRING_SECRET");
|
|
1016
|
+
if (!appConfig.env["CONTROL_PLANE_URL"]) missingVars.push("CONTROL_PLANE_URL");
|
|
1017
|
+
if (missingVars.length > 0) {
|
|
1018
|
+
const logger = container.resolve(ServerLoggerFactory).create("codemation.pairing");
|
|
1019
|
+
logger.warn(
|
|
1020
|
+
`Pairing not configured — missing env vars: ${missingVars.join(", ")}. ` +
|
|
1021
|
+
"Internal /internal/* routes are inactive. Set these vars for managed-mode integration.",
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
container.registerInstance(PairingConfigToken, pairingConfig);
|
|
1027
|
+
container.registerSingleton(HmacRequestSigner, HmacRequestSigner);
|
|
1028
|
+
container.registerSingleton(PairedFetch, PairedFetch);
|
|
1029
|
+
container.registerSingleton(IncomingHmacVerifier, IncomingHmacVerifier);
|
|
1030
|
+
container.registerSingleton(InternalHmacAuthMiddleware, InternalHmacAuthMiddleware);
|
|
1031
|
+
container.registerSingleton(BrokerClient, BrokerClient);
|
|
1032
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalPingRegistrar);
|
|
1033
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalCredentialsPushRegistrar);
|
|
1034
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalCredentialsListRegistrar);
|
|
1035
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowsListRegistrar);
|
|
1036
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowDetailRegistrar);
|
|
1037
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowActivationRegistrar);
|
|
1038
|
+
container.registerSingleton(ApplicationTokens.InternalHonoApiRouteRegistrar, InternalWorkflowTestRunRegistrar);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
817
1041
|
private registerOperationalInfrastructure(container: Container): void {
|
|
818
1042
|
container.register(ApplicationTokens.WorkflowWebsocketPublisher, {
|
|
819
1043
|
useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(WorkflowWebsocketServer)),
|
|
820
1044
|
});
|
|
821
1045
|
container.registerSingleton(WorkflowRunEventWebsocketRelay, WorkflowRunEventWebsocketRelay);
|
|
1046
|
+
container.registerSingleton(TelemetrySpanWebsocketRelay, TelemetrySpanWebsocketRelay);
|
|
1047
|
+
container.register(ApplicationTokens.TelemetrySpanPublisher, {
|
|
1048
|
+
useFactory: instanceCachingFactory((dependencyContainer) =>
|
|
1049
|
+
dependencyContainer.resolve(TelemetrySpanWebsocketRelay),
|
|
1050
|
+
),
|
|
1051
|
+
});
|
|
822
1052
|
container.registerSingleton(RunEventBusTelemetryReporter, RunEventBusTelemetryReporter);
|
|
823
1053
|
container.registerSingleton(WorkflowRunRetentionPruneScheduler, WorkflowRunRetentionPruneScheduler);
|
|
824
1054
|
}
|
|
825
1055
|
|
|
1056
|
+
private registerWorkflowAuditWriter(container: Container, appConfig: AppConfig): void {
|
|
1057
|
+
if (appConfig.persistence.kind === "none") {
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
container.registerSingleton(PrismaWorkflowAuditLogRepository, PrismaWorkflowAuditLogRepository);
|
|
1061
|
+
container.register(ApplicationTokens.WorkflowAuditEmitter, { useToken: PrismaWorkflowAuditLogRepository });
|
|
1062
|
+
container.registerSingleton(WorkflowAuditLogWriter, WorkflowAuditLogWriter);
|
|
1063
|
+
container.registerSingleton(WorkflowAuditLogPruneScheduler, WorkflowAuditLogPruneScheduler);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
826
1066
|
private async registerRuntimeInfrastructure(container: Container, appConfig: AppConfig): Promise<PrismaOwnership> {
|
|
827
1067
|
const queuePrefix = appConfig.scheduler.queuePrefix ?? appConfig.eventing.queuePrefix ?? "codemation";
|
|
828
1068
|
const eventBus =
|
|
@@ -830,7 +1070,7 @@ export class AppContainerFactory {
|
|
|
830
1070
|
? new RedisRunEventBus(this.requireRedisUrl(appConfig.eventing.redisUrl), queuePrefix)
|
|
831
1071
|
: new InMemoryRunEventBus();
|
|
832
1072
|
container.registerInstance(CoreTokens.RunEventBus, eventBus);
|
|
833
|
-
const binaryStorage = this.createBinaryStorage(appConfig
|
|
1073
|
+
const binaryStorage = await this.createBinaryStorage(appConfig);
|
|
834
1074
|
container.registerInstance(CoreTokens.RunDataFactory, new InMemoryRunDataFactory());
|
|
835
1075
|
container.registerInstance(CoreTokens.BinaryStorage, binaryStorage);
|
|
836
1076
|
container.registerInstance(ApplicationTokens.Clock, new SystemClock());
|
|
@@ -1005,11 +1245,37 @@ export class AppContainerFactory {
|
|
|
1005
1245
|
};
|
|
1006
1246
|
}
|
|
1007
1247
|
|
|
1008
|
-
private createBinaryStorage(
|
|
1009
|
-
|
|
1248
|
+
private async createBinaryStorage(
|
|
1249
|
+
appConfig: AppConfig,
|
|
1250
|
+
): Promise<InMemoryBinaryStorage | LocalFilesystemBinaryStorage | S3BinaryStorage> {
|
|
1251
|
+
const kind = appConfig.env.BINARY_STORAGE_KIND ?? "local";
|
|
1252
|
+
|
|
1253
|
+
if (kind === "s3") {
|
|
1254
|
+
const parseResult = S3BinaryStorageConfigSchema.safeParse({
|
|
1255
|
+
endpoint: appConfig.env.BINARY_STORAGE_S3_ENDPOINT,
|
|
1256
|
+
region: appConfig.env.BINARY_STORAGE_S3_REGION,
|
|
1257
|
+
bucket: appConfig.env.BINARY_STORAGE_S3_BUCKET,
|
|
1258
|
+
accessKeyId: appConfig.env.BINARY_STORAGE_S3_ACCESS_KEY_ID,
|
|
1259
|
+
secretAccessKey: appConfig.env.BINARY_STORAGE_S3_SECRET_ACCESS_KEY,
|
|
1260
|
+
});
|
|
1261
|
+
if (!parseResult.success) {
|
|
1262
|
+
throw new Error(
|
|
1263
|
+
`BINARY_STORAGE_KIND=s3 requires all BINARY_STORAGE_S3_* env vars. Validation errors: ${parseResult.error.message}`,
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
const storage = new S3BinaryStorage(parseResult.data);
|
|
1267
|
+
await storage.checkConnectivity();
|
|
1268
|
+
return storage;
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
if (kind !== "local") {
|
|
1272
|
+
throw new Error(`Unknown BINARY_STORAGE_KIND: "${kind}". Expected "local" or "s3".`);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
if (!appConfig.repoRoot) {
|
|
1010
1276
|
return new InMemoryBinaryStorage();
|
|
1011
1277
|
}
|
|
1012
|
-
return new LocalFilesystemBinaryStorage(`${repoRoot}/.codemation/binary`);
|
|
1278
|
+
return new LocalFilesystemBinaryStorage(`${appConfig.repoRoot}/.codemation/binary`);
|
|
1013
1279
|
}
|
|
1014
1280
|
|
|
1015
1281
|
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
|
}
|