@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.
Files changed (226) hide show
  1. package/CHANGELOG.md +483 -0
  2. package/dist/{ApiPaths-CLTHphYZ.js → ApiPaths-Dv1dcHu_.js} +4 -4
  3. package/dist/ApiPaths-Dv1dcHu_.js.map +1 -0
  4. package/dist/{AppConfigFactory-YnveXE9k.d.ts → AppConfigFactory-BT0y0LVC.d.ts} +8490 -5548
  5. package/dist/{AppConfigFactory-C6q-CSKb.js → AppConfigFactory-Cx4qQvRk.js} +112 -52
  6. package/dist/AppConfigFactory-Cx4qQvRk.js.map +1 -0
  7. package/dist/{AppContainerFactory-qaqc-R1D.js → AppContainerFactory-DRTjG7nG.js} +7298 -1732
  8. package/dist/AppContainerFactory-DRTjG7nG.js.map +1 -0
  9. package/dist/{CodemationAppContext-DRu1Dpri.d.ts → CodemationAppContext-CGFYVcSb.d.ts} +14 -4
  10. package/dist/{CodemationAuthoring.types-DZl-sJaM.js → CodemationAuthoring.types-BteaR3Dc.js} +19 -6
  11. package/dist/CodemationAuthoring.types-BteaR3Dc.js.map +1 -0
  12. package/dist/{CodemationAuthoring.types-fBRppnmi.d.ts → CodemationAuthoring.types-DiKKogum.d.ts} +30 -5
  13. package/dist/{CodemationConfigNormalizer-DVko3cVN.d.ts → CodemationConfigNormalizer-48f-T66P.d.ts} +3 -3
  14. package/dist/{CodemationConsumerConfigLoader-BeAUS144.js → CodemationConsumerConfigLoader-By-6tuGc.js} +81 -10
  15. package/dist/CodemationConsumerConfigLoader-By-6tuGc.js.map +1 -0
  16. package/dist/{CodemationConsumerConfigLoader-DJWr86f-.d.ts → CodemationConsumerConfigLoader-_PIYqwVx.d.ts} +18 -2
  17. package/dist/{CodemationPluginListMerger-B-W5Fa_X.js → CodemationPluginListMerger-D1B1IEbt.js} +1 -1
  18. package/dist/{CodemationPluginListMerger-B-W5Fa_X.js.map → CodemationPluginListMerger-D1B1IEbt.js.map} +1 -1
  19. package/dist/{CodemationPluginListMerger-DGc-jfa2.d.ts → CodemationPluginListMerger-DP7djJ9S.d.ts} +151 -19
  20. package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js +97 -0
  21. package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js.map +1 -0
  22. package/dist/{CodemationWhitelabelConfig-CWbcyQqn.d.ts → CodemationWhitelabelConfig-Ca2mCUeC.d.ts} +2 -2
  23. package/dist/{CollectionContracts.types-DdpHft0i.d.ts → CollectionContracts.types-DDyFYT_D.d.ts} +1 -1
  24. package/dist/{CredentialContractsRegistry-DrMIDSw8.d.ts → CredentialContractsRegistry-Bq2bq28t.d.ts} +2 -2
  25. package/dist/{CredentialServices-UfvHB-rN.d.ts → CredentialServices-BLloBztI.d.ts} +65 -20
  26. package/dist/{CredentialServices-CgxwguAv.js → CredentialServices-Dk8yypeL.js} +310 -51
  27. package/dist/CredentialServices-Dk8yypeL.js.map +1 -0
  28. package/dist/InternalHonoApiRouteRegistrar-c7t3KnV_.d.ts +17 -0
  29. package/dist/InternalPingRegistrar-DY3kSfxP.js +221 -0
  30. package/dist/InternalPingRegistrar-DY3kSfxP.js.map +1 -0
  31. package/dist/{ItemsInputNormalizer-C-KHg9Mo.d.ts → ItemsInputNormalizer-_RwIfRIQ.d.ts} +89 -25
  32. package/dist/{LogLevelPolicyFactory-CampWO0l.d.ts → LogLevelPolicyFactory-ewCHLDLn.d.ts} +2 -2
  33. package/dist/{PublicFrontendBootstrap-DzBgwOnG.d.ts → PublicFrontendBootstrap-Cev3qK46.d.ts} +9 -2
  34. package/dist/PublicFrontendBootstrapFactory-Dv04tJ-6.d.ts +82 -0
  35. package/dist/{PublicFrontendBootstrapJsonCodec-Cl_DLRh0.d.ts → PublicFrontendBootstrapJsonCodec-CXG9Dxft.d.ts} +3 -3
  36. package/dist/{PublicFrontendBootstrapJsonCodec-DzqvA0uo.js → PublicFrontendBootstrapJsonCodec-CegIF_ne.js} +7 -2
  37. package/dist/PublicFrontendBootstrapJsonCodec-CegIF_ne.js.map +1 -0
  38. package/dist/ServerLoggerFactory-Ckk52S3w.js +223 -0
  39. package/dist/ServerLoggerFactory-Ckk52S3w.js.map +1 -0
  40. package/dist/{TelemetryContracts-DbaNomrH.d.ts → TelemetryContracts-BtDx84Cp.d.ts} +13 -4
  41. package/dist/{WorkflowPolicyUiPresentationFactory-DQEY-h_S.d.ts → WorkflowPolicyUiPresentationFactory-6MyjCvBO.d.ts} +2 -2
  42. package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js} +1 -1
  43. package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js.map → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js.map} +1 -1
  44. package/dist/{WorkflowViewContracts-CzK2KFuz.d.ts → WorkflowViewContracts-B7aFQcIw.d.ts} +10 -1
  45. package/dist/authoring.d.ts +5 -5
  46. package/dist/authoring.js +1 -1
  47. package/dist/client.d.ts +4 -4
  48. package/dist/client.js +2 -2
  49. package/dist/consumer.d.ts +6 -6
  50. package/dist/consumer.js +2 -2
  51. package/dist/credentials.d.ts +6 -6
  52. package/dist/credentials.js +1 -1
  53. package/dist/devServerSidecar.d.ts +2 -2
  54. package/dist/devServerSidecar.js +1 -94
  55. package/dist/devServerSidecar.js.map +1 -1
  56. package/dist/dto.d.ts +6 -6
  57. package/dist/{index-BbBk26m0.d.ts → index-DilAYwnH.d.ts} +49 -3
  58. package/dist/index.d.ts +141 -21
  59. package/dist/index.js +109 -14
  60. package/dist/index.js.map +1 -0
  61. package/dist/mapping.d.ts +2 -2
  62. package/dist/mapping.js +1 -1
  63. package/dist/nextServer.d.ts +42 -113
  64. package/dist/nextServer.js +9 -7
  65. package/dist/pairing.d.ts +93 -0
  66. package/dist/pairing.js +5 -0
  67. package/dist/pairing.types-snfZ_OzB.d.ts +19 -0
  68. package/dist/persistenceServer-B71RGvSj.d.ts +30 -0
  69. package/dist/{persistenceServer-CmsIKnO9.js → persistenceServer-C-hH4z6l.js} +2 -2
  70. package/dist/{persistenceServer-CmsIKnO9.js.map → persistenceServer-C-hH4z6l.js.map} +1 -1
  71. package/dist/persistenceServer.d.ts +8 -8
  72. package/dist/persistenceServer.js +3 -3
  73. package/dist/{server-MUNGsBYK.d.ts → server-09PKasWR.d.ts} +21 -6
  74. package/dist/{server-CJFfY67o.js → server-vtRCPgRJ.js} +7 -6
  75. package/dist/{server-CJFfY67o.js.map → server-vtRCPgRJ.js.map} +1 -1
  76. package/dist/server.d.ts +14 -14
  77. package/dist/server.js +13 -11
  78. package/package.json +47 -58
  79. package/prisma/migrations/20260519000000_workflow_audit_log/migration.sql +23 -0
  80. package/prisma/migrations/20260519100000_storage_growth_fixes/migration.sql +61 -0
  81. package/prisma/migrations.sqlite/20260519000000_workflow_audit_log/migration.sql +21 -0
  82. package/prisma/migrations.sqlite/20260519100000_storage_growth_fixes/migration.sql +29 -0
  83. package/prisma/schema.postgresql.prisma +55 -17
  84. package/prisma/schema.sqlite.prisma +55 -17
  85. package/prisma-generated/prisma-postgresql-client/edge.js +33 -5
  86. package/prisma-generated/prisma-postgresql-client/index-browser.js +29 -1
  87. package/prisma-generated/prisma-postgresql-client/index.d.ts +8933 -5716
  88. package/prisma-generated/prisma-postgresql-client/index.js +33 -5
  89. package/prisma-generated/prisma-postgresql-client/package.json +1 -1
  90. package/prisma-generated/prisma-postgresql-client/schema.prisma +38 -0
  91. package/prisma-generated/prisma-sqlite-client/edge.js +33 -5
  92. package/prisma-generated/prisma-sqlite-client/index-browser.js +29 -1
  93. package/prisma-generated/prisma-sqlite-client/index.d.ts +8925 -5713
  94. package/prisma-generated/prisma-sqlite-client/index.js +33 -5
  95. package/prisma-generated/prisma-sqlite-client/package.json +1 -1
  96. package/prisma-generated/prisma-sqlite-client/schema.prisma +38 -0
  97. package/scripts/check-collections.mjs +18 -0
  98. package/scripts/generate-prisma-clients.mjs +20 -11
  99. package/src/application/WorkflowAuditLogPruneScheduler.ts +96 -0
  100. package/src/application/auth/AuthenticatedPrincipal.ts +4 -0
  101. package/src/application/commands/StartWorkflowRunCommandHandler.ts +4 -0
  102. package/src/application/contracts/WorkflowViewContracts.ts +6 -0
  103. package/src/application/contracts/WorkflowWebsocketMessage.ts +3 -1
  104. package/src/application/mapping/WorkflowDefinitionMapper.ts +40 -1
  105. package/src/application/runs/WorkflowRunRetentionPruneScheduler.ts +7 -1
  106. package/src/application/telemetry/OtelExecutionTelemetry.types.ts +5 -0
  107. package/src/application/telemetry/OtelExecutionTelemetryFactory.ts +4 -0
  108. package/src/application/telemetry/StoredTelemetrySpanScope.ts +6 -2
  109. package/src/application/telemetry/TelemetryRetentionTimestampFactory.ts +27 -17
  110. package/src/application/telemetry/TelemetrySpanPublisher.ts +11 -0
  111. package/src/application/websocket/TelemetrySpanWebsocketRelay.ts +31 -0
  112. package/src/applicationTokens.ts +20 -1
  113. package/src/audit/IAuditEmitter.ts +32 -0
  114. package/src/audit/PrismaWorkflowAuditLogRepository.ts +34 -0
  115. package/src/audit/WorkflowAuditLogWriter.ts +125 -0
  116. package/src/auth/managed/ManagedAuthConfig.ts +29 -0
  117. package/src/auth/managed/ManagedAuthMiddleware.ts +52 -0
  118. package/src/auth/managed/ManagedCorsMiddleware.ts +43 -0
  119. package/src/auth/managed/ManagedModeBootGuard.ts +27 -0
  120. package/src/auth/managed/index.ts +5 -0
  121. package/src/bootstrap/AppContainerFactory.ts +295 -29
  122. package/src/bootstrap/AppContainerLifecycle.ts +31 -0
  123. package/src/bootstrap/perf/BootTimer.ts +168 -0
  124. package/src/bootstrap/runtime/AppConfigFactory.ts +21 -65
  125. package/src/bootstrap/runtime/FrontendRuntime.ts +4 -1
  126. package/src/bootstrap/runtime/HeadlessApiRuntime.ts +47 -0
  127. package/src/bootstrap/runtime/WorkerRuntime.ts +2 -1
  128. package/src/credentials/BrokerClient.ts +49 -0
  129. package/src/credentials/BrokerRefreshError.ts +12 -0
  130. package/src/credentials/BrokerRefreshInvalidGrantError.ts +13 -0
  131. package/src/credentials/ControlPlaneCatalogFetcher.ts +261 -0
  132. package/src/credentials/CredentialOAuth2MaterialReader.ts +136 -0
  133. package/src/credentials/InternalCredentialsListRegistrar.ts +48 -0
  134. package/src/credentials/InternalCredentialsPushRegistrar.ts +125 -0
  135. package/src/credentials/LocalOAuthFlowExecutor.ts +316 -0
  136. package/src/credentials/ManagedOAuthFlowExecutor.ts +94 -0
  137. package/src/credentials/ManagedOAuthRefreshInvalidGrantError.ts +13 -0
  138. package/src/credentials/catalogTypes.ts +4 -0
  139. package/src/credentials/refresh/CredentialDisconnectedError.ts +11 -0
  140. package/src/domain/credentials/CredentialBindingService.ts +54 -2
  141. package/src/domain/credentials/CredentialKeyRotatedError.ts +22 -0
  142. package/src/domain/credentials/CredentialSecretCipher.ts +68 -6
  143. package/src/domain/credentials/CredentialTypeRegistryImpl.ts +117 -10
  144. package/src/domain/credentials/OAuth2RedirectUriResolver.ts +79 -0
  145. package/src/domain/credentials/WorkflowCredentialNodeResolver.ts +14 -5
  146. package/src/domain/telemetry/TelemetryContracts.ts +7 -1
  147. package/src/domain/workflows/WorkflowActivationPreflight.ts +24 -1
  148. package/src/domain/workflows/WorkflowActivationPreflightRules.ts +40 -1
  149. package/src/index.ts +9 -0
  150. package/src/infrastructure/binary/LocalFilesystemBinaryStorageRegistry.ts +29 -1
  151. package/src/infrastructure/binary/S3BinaryStorage.ts +169 -0
  152. package/src/infrastructure/binary/S3BinaryStorageConfig.ts +17 -0
  153. package/src/infrastructure/config/CodemationPluginRegistrar.ts +3 -1
  154. package/src/infrastructure/persistence/CodemationDatabaseUrlParser.ts +41 -0
  155. package/src/infrastructure/persistence/InMemoryTelemetryArtifactStore.ts +8 -3
  156. package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +21 -13
  157. package/src/infrastructure/persistence/PrismaTelemetryArtifactStore.ts +43 -8
  158. package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +26 -3
  159. package/src/infrastructure/persistence/PrismaWorkflowSnapshotRepository.ts +48 -0
  160. package/src/mcp/AgentMcpIntegrationImpl.ts +344 -0
  161. package/src/mcp/McpClientFactory.ts +29 -0
  162. package/src/mcp/McpConnectionPool.ts +184 -0
  163. package/src/mcp/McpConnectionPool.types.ts +12 -0
  164. package/src/mcp/McpServerCatalog.ts +104 -0
  165. package/src/mcp/index.ts +5 -0
  166. package/src/pairing/HmacRequestSigner.ts +32 -0
  167. package/src/pairing/IncomingHmacVerifier.ts +82 -0
  168. package/src/pairing/InternalHmacAuthMiddleware.ts +33 -0
  169. package/src/pairing/InternalPingRegistrar.ts +25 -0
  170. package/src/pairing/PairedFetch.ts +33 -0
  171. package/src/pairing/PairingConfigFactory.ts +35 -0
  172. package/src/pairing/PairingConfigToken.ts +6 -0
  173. package/src/pairing/index.ts +14 -0
  174. package/src/pairing/pairing.types.ts +18 -0
  175. package/src/pairing.ts +17 -0
  176. package/src/persistenceServer.ts +1 -0
  177. package/src/presentation/config/AppConfig.ts +7 -1
  178. package/src/presentation/config/CodemationAuthConfig.ts +1 -1
  179. package/src/presentation/config/CodemationAuthoring.types.ts +60 -5
  180. package/src/presentation/config/CodemationConfig.ts +9 -0
  181. package/src/presentation/config/CodemationConfigNormalizer.ts +39 -1
  182. package/src/presentation/config/CodemationPlugin.ts +2 -1
  183. package/src/presentation/frontend/CodemationFrontendAuthSnapshot.ts +5 -0
  184. package/src/presentation/frontend/CodemationFrontendAuthSnapshotFactory.ts +7 -1
  185. package/src/presentation/frontend/PublicFrontendBootstrap.ts +2 -0
  186. package/src/presentation/frontend/PublicFrontendBootstrapFactory.ts +5 -1
  187. package/src/presentation/frontend/PublicFrontendBootstrapJsonCodec.ts +4 -1
  188. package/src/presentation/http/ApiPaths.ts +4 -4
  189. package/src/presentation/http/HeadlessHttpServerFactory.ts +56 -0
  190. package/src/presentation/http/ServerHttpErrorResponseFactory.ts +39 -2
  191. package/src/presentation/http/hono/CodemationHonoApiAppFactory.ts +33 -8
  192. package/src/presentation/http/hono/InternalHonoApiRouteRegistrar.ts +12 -0
  193. package/src/presentation/http/hono/registrars/ManagedMeHonoApiRouteRegistrar.ts +35 -0
  194. package/src/presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar.ts +2 -2
  195. package/src/presentation/http/routeHandlers/CredentialHttpRouteHandler.ts +28 -0
  196. package/src/presentation/http/routeHandlers/OAuth2HttpRouteHandlerFactory.ts +98 -41
  197. package/src/presentation/server/CodemationConsumerConfigLoader.ts +59 -7
  198. package/src/presentation/server/CodemationPluginDiscovery.ts +5 -0
  199. package/src/presentation/server/WorkflowDefinitionExportsResolver.ts +18 -0
  200. package/src/presentation/server/WorkflowModulePathFinder.ts +12 -1
  201. package/src/presentation/websocket/ManagedWebsocketAuthenticator.ts +50 -0
  202. package/src/presentation/websocket/WebsocketAuthenticator.types.ts +12 -0
  203. package/src/presentation/websocket/WorkflowWebsocketServer.ts +24 -3
  204. package/src/presentation/websocket/WorkflowWebsocketServerFactory.ts +16 -0
  205. package/src/process/ExecaProcessRunner.ts +41 -0
  206. package/src/process/ProcessRunner.types.ts +39 -0
  207. package/src/server.ts +2 -0
  208. package/src/workflows/InternalWorkflowActivationRegistrar.ts +42 -0
  209. package/src/workflows/InternalWorkflowDetailRegistrar.ts +33 -0
  210. package/src/workflows/InternalWorkflowTestRunRegistrar.ts +91 -0
  211. package/src/workflows/InternalWorkflowsListRegistrar.ts +28 -0
  212. package/src/workflows/discovery/WorkflowDirectoryDiscoverer.ts +79 -0
  213. package/tsconfig.json +2 -0
  214. package/vitest.shared.ts +5 -0
  215. package/dist/ApiPaths-CLTHphYZ.js.map +0 -1
  216. package/dist/AppConfigFactory-C6q-CSKb.js.map +0 -1
  217. package/dist/AppContainerFactory-qaqc-R1D.js.map +0 -1
  218. package/dist/CodemationAuthoring.types-DZl-sJaM.js.map +0 -1
  219. package/dist/CodemationConsumerConfigLoader-BeAUS144.js.map +0 -1
  220. package/dist/CredentialServices-CgxwguAv.js.map +0 -1
  221. package/dist/PublicFrontendBootstrapFactory-Cb2pLmDd.d.ts +0 -45
  222. package/dist/PublicFrontendBootstrapJsonCodec-DzqvA0uo.js.map +0 -1
  223. package/dist/ServerLoggerFactory-BKSIh9Xv.js +0 -98
  224. package/dist/ServerLoggerFactory-BKSIh9Xv.js.map +0 -1
  225. package/dist/persistenceServer-vtJAGDat.d.ts +0 -9
  226. package/src/domain/credentials/OAuth2ConnectServiceFactory.ts +0 -411
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Workspace-local audit emitter contract.
3
+ * Mirror of the CP-side IAuditEmitter shape; kept separate to avoid cross-repo coupling.
4
+ */
5
+ export interface WorkflowAuditActor {
6
+ readonly userId: string;
7
+ readonly sessionId?: string;
8
+ }
9
+
10
+ export interface WorkflowAuditResource {
11
+ readonly type: string;
12
+ readonly id: string;
13
+ }
14
+
15
+ export interface WorkflowAuditEntry {
16
+ readonly id: string;
17
+ readonly occurredAt: string;
18
+ readonly actor: WorkflowAuditActor;
19
+ readonly action: string;
20
+ readonly resource: WorkflowAuditResource;
21
+ readonly outcome: "success" | "failure";
22
+ readonly errorCode?: string;
23
+ readonly correlationId?: string;
24
+ /** Denormalised on every row for query convenience. */
25
+ readonly workflowId: string;
26
+ readonly runId?: string;
27
+ readonly nodeId?: string;
28
+ }
29
+
30
+ export interface IWorkflowAuditEmitter {
31
+ emit(entry: WorkflowAuditEntry): Promise<void>;
32
+ }
@@ -0,0 +1,34 @@
1
+ import { inject, injectable } from "@codemation/core";
2
+ import {
3
+ PrismaDatabaseClientToken,
4
+ type PrismaDatabaseClient,
5
+ } from "../infrastructure/persistence/PrismaDatabaseClient";
6
+ import type { IWorkflowAuditEmitter, WorkflowAuditEntry } from "./IAuditEmitter";
7
+
8
+ @injectable()
9
+ export class PrismaWorkflowAuditLogRepository implements IWorkflowAuditEmitter {
10
+ constructor(
11
+ @inject(PrismaDatabaseClientToken)
12
+ private readonly prisma: PrismaDatabaseClient,
13
+ ) {}
14
+
15
+ async emit(entry: WorkflowAuditEntry): Promise<void> {
16
+ await this.prisma.workflowAuditLog.create({
17
+ data: {
18
+ id: entry.id,
19
+ occurredAt: new Date(entry.occurredAt),
20
+ actorUserId: entry.actor.userId,
21
+ actorSessionId: entry.actor.sessionId ?? null,
22
+ action: entry.action,
23
+ resourceType: entry.resource.type,
24
+ resourceId: entry.resource.id,
25
+ outcome: entry.outcome,
26
+ errorCode: entry.errorCode ?? null,
27
+ correlationId: entry.correlationId ?? null,
28
+ workflowId: entry.workflowId,
29
+ runId: entry.runId ?? null,
30
+ nodeId: entry.nodeId ?? null,
31
+ },
32
+ });
33
+ }
34
+ }
@@ -0,0 +1,125 @@
1
+ import type { RunEvent, RunEventBus, RunEventSubscription } from "@codemation/core";
2
+ import { CoreTokens, inject, injectable } from "@codemation/core";
3
+ import { ApplicationTokens } from "../applicationTokens";
4
+ import type { Logger, LoggerFactory } from "../application/logging/Logger";
5
+ import type { IWorkflowAuditEmitter } from "./IAuditEmitter";
6
+
7
+ /**
8
+ * RunEventBus subscriber that persists workspace run-events as WorkflowAuditLog rows.
9
+ * Best-effort: errors are logged and swallowed so workflow execution is never blocked.
10
+ * Actor is recorded as "system" in V1 — the run event bus carries no user context.
11
+ */
12
+ @injectable()
13
+ export class WorkflowAuditLogWriter {
14
+ private subscription: RunEventSubscription | null = null;
15
+ private readonly logger: Logger;
16
+
17
+ constructor(
18
+ @inject(CoreTokens.RunEventBus)
19
+ private readonly runEventBus: RunEventBus,
20
+ @inject(ApplicationTokens.WorkflowAuditEmitter)
21
+ private readonly auditEmitter: IWorkflowAuditEmitter,
22
+ @inject(ApplicationTokens.LoggerFactory)
23
+ loggerFactory: LoggerFactory,
24
+ ) {
25
+ this.logger = loggerFactory.create("codemation.audit.workflow");
26
+ }
27
+
28
+ async start(): Promise<void> {
29
+ if (this.subscription) {
30
+ return;
31
+ }
32
+ this.subscription = await this.runEventBus.subscribe(async (event) => {
33
+ try {
34
+ await this.handleEvent(event);
35
+ } catch (err) {
36
+ // Audit must remain best-effort so workflow execution does not fail on observer persistence races.
37
+ this.logger.error(
38
+ "WorkflowAuditLogWriter: failed to persist audit entry",
39
+ err instanceof Error ? err : undefined,
40
+ );
41
+ }
42
+ });
43
+ }
44
+
45
+ async stop(): Promise<void> {
46
+ if (!this.subscription) {
47
+ return;
48
+ }
49
+ await this.subscription.close();
50
+ this.subscription = null;
51
+ }
52
+
53
+ private async handleEvent(event: RunEvent): Promise<void> {
54
+ switch (event.kind) {
55
+ case "nodeCompleted":
56
+ await this.auditEmitter.emit({
57
+ id: globalThis.crypto.randomUUID(),
58
+ occurredAt: event.at,
59
+ actor: { userId: "system" },
60
+ action: "workflow.node.completed",
61
+ resource: { type: "node", id: event.snapshot.nodeId },
62
+ outcome: "success",
63
+ workflowId: event.workflowId,
64
+ runId: event.runId,
65
+ nodeId: event.snapshot.nodeId,
66
+ });
67
+ return;
68
+ case "nodeFailed":
69
+ await this.auditEmitter.emit({
70
+ id: globalThis.crypto.randomUUID(),
71
+ occurredAt: event.at,
72
+ actor: { userId: "system" },
73
+ action: "workflow.node.failed",
74
+ resource: { type: "node", id: event.snapshot.nodeId },
75
+ outcome: "failure",
76
+ errorCode: event.snapshot.error?.name,
77
+ workflowId: event.workflowId,
78
+ runId: event.runId,
79
+ nodeId: event.snapshot.nodeId,
80
+ });
81
+ return;
82
+ case "runSaved":
83
+ if (event.state.status === "completed") {
84
+ await this.auditEmitter.emit({
85
+ id: globalThis.crypto.randomUUID(),
86
+ occurredAt: event.at,
87
+ actor: { userId: "system" },
88
+ action: "workflow.run.completed",
89
+ resource: { type: "run", id: event.runId },
90
+ outcome: "success",
91
+ workflowId: event.workflowId,
92
+ runId: event.runId,
93
+ });
94
+ } else if (event.state.status === "failed") {
95
+ await this.auditEmitter.emit({
96
+ id: globalThis.crypto.randomUUID(),
97
+ occurredAt: event.at,
98
+ actor: { userId: "system" },
99
+ action: "workflow.run.failed",
100
+ resource: { type: "run", id: event.runId },
101
+ outcome: "failure",
102
+ workflowId: event.workflowId,
103
+ runId: event.runId,
104
+ });
105
+ }
106
+ return;
107
+ case "connectionInvocationStarted":
108
+ await this.auditEmitter.emit({
109
+ id: globalThis.crypto.randomUUID(),
110
+ occurredAt: event.at,
111
+ actor: { userId: "system" },
112
+ action: "workflow.credential.used",
113
+ resource: { type: "credential", id: event.record.connectionNodeId },
114
+ outcome: "success",
115
+ workflowId: event.workflowId,
116
+ runId: event.runId,
117
+ });
118
+ return;
119
+ default:
120
+ // runCreated, nodeQueued, nodeStarted, connectionInvocationCompleted/Failed, testSuite*, testCase*
121
+ // are not audit-relevant at this fidelity level.
122
+ return;
123
+ }
124
+ }
125
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Env-derived configuration for managed auth mode.
3
+ *
4
+ * Required env vars when auth.kind === "managed":
5
+ * CONTROL_PLANE_JWKS_URL — JWKS endpoint URL for the control plane
6
+ * CONTROL_PLANE_ISSUER — expected JWT `iss` claim value
7
+ * CP_WEB_ORIGIN — single-origin CORS allowlist for the CP browser UI
8
+ */
9
+ export interface ManagedAuthConfig {
10
+ readonly jwksUrl: string;
11
+ readonly issuer: string;
12
+ readonly cpWebOrigin: string;
13
+ }
14
+
15
+ export class ManagedAuthConfigFactory {
16
+ create(env: Readonly<NodeJS.ProcessEnv>): ManagedAuthConfig {
17
+ const jwksUrl = env["CONTROL_PLANE_JWKS_URL"];
18
+ const issuer = env["CONTROL_PLANE_ISSUER"];
19
+ const cpWebOrigin = env["CP_WEB_ORIGIN"];
20
+
21
+ if (!jwksUrl || !issuer || !cpWebOrigin) {
22
+ throw new Error(
23
+ "ManagedAuthConfigFactory: CONTROL_PLANE_JWKS_URL, CONTROL_PLANE_ISSUER, and CP_WEB_ORIGIN are required in managed auth mode.",
24
+ );
25
+ }
26
+
27
+ return { jwksUrl, issuer, cpWebOrigin };
28
+ }
29
+ }
@@ -0,0 +1,52 @@
1
+ import { injectable } from "@codemation/core";
2
+ import type { AuthenticatedPrincipal } from "../../application/auth/AuthenticatedPrincipal";
3
+ import type { SessionVerifier } from "../../application/auth/SessionVerifier";
4
+ import type { ManagedJwtVerifier } from "@codemation/managed-auth";
5
+
6
+ /**
7
+ * Session verifier for `auth.kind: "managed"`.
8
+ *
9
+ * Reads `Authorization: Bearer <token>`, delegates to `ManagedJwtVerifier`,
10
+ * and maps the verified principal to `AuthenticatedPrincipal`.
11
+ *
12
+ * Returns null (unauthorized) when the header is missing or the token fails
13
+ * verification — the API middleware converts this to 401.
14
+ */
15
+ @injectable()
16
+ export class ManagedAuthMiddleware implements SessionVerifier {
17
+ constructor(private readonly verifier: ManagedJwtVerifier) {}
18
+
19
+ async verify(request: Request): Promise<AuthenticatedPrincipal | null> {
20
+ const authorization = request.headers.get("authorization");
21
+ if (!authorization) {
22
+ return null;
23
+ }
24
+
25
+ const token = this.extractBearerToken(authorization);
26
+ if (!token) {
27
+ return null;
28
+ }
29
+
30
+ const result = await this.verifier.verify(token);
31
+ if ("failure" in result) {
32
+ return null;
33
+ }
34
+
35
+ return {
36
+ id: result.userId,
37
+ email: null,
38
+ name: null,
39
+ source: "managed-jwt",
40
+ workspaceId: result.workspaceId,
41
+ };
42
+ }
43
+
44
+ private extractBearerToken(authorization: string): string | null {
45
+ const lower = authorization.trimStart();
46
+ if (!lower.toLowerCase().startsWith("bearer ")) {
47
+ return null;
48
+ }
49
+ const token = authorization.slice(7).trim();
50
+ return token.length > 0 ? token : null;
51
+ }
52
+ }
@@ -0,0 +1,43 @@
1
+ import { injectable } from "@codemation/core";
2
+ import type { MiddlewareHandler } from "hono";
3
+
4
+ /**
5
+ * CORS allowlist middleware for managed mode.
6
+ *
7
+ * Only the single `CP_WEB_ORIGIN` value (provisioner-injected) is permitted.
8
+ * All other origins are refused on preflight with a 403.
9
+ */
10
+ @injectable()
11
+ export class ManagedCorsMiddleware {
12
+ constructor(private readonly allowedOrigin: string) {}
13
+
14
+ handle(): MiddlewareHandler {
15
+ return async (c, next) => {
16
+ const origin = c.req.header("origin");
17
+
18
+ // Respond to CORS preflight
19
+ if (c.req.method === "OPTIONS") {
20
+ if (origin === this.allowedOrigin) {
21
+ c.header("access-control-allow-origin", origin);
22
+ c.header("access-control-allow-methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS");
23
+ c.header("access-control-allow-headers", "content-type, authorization");
24
+ c.header("access-control-allow-credentials", "true");
25
+ c.header("vary", "Origin");
26
+ return c.body(null, 204);
27
+ }
28
+ return c.body(null, 403);
29
+ }
30
+
31
+ // For actual requests, set CORS headers after the handler runs
32
+ if (origin === this.allowedOrigin) {
33
+ await next();
34
+ c.header("access-control-allow-origin", origin);
35
+ c.header("access-control-allow-credentials", "true");
36
+ c.header("vary", "Origin");
37
+ return;
38
+ }
39
+
40
+ await next();
41
+ };
42
+ }
43
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Boot-time guard for `auth.kind: "managed"`.
3
+ *
4
+ * Validates that all required environment variables are present before the
5
+ * container boots. Throws a descriptive error listing every missing variable
6
+ * so operators can fix the config in one shot.
7
+ */
8
+ export class ManagedModeBootGuard {
9
+ private static readonly requiredVars: ReadonlyArray<string> = [
10
+ "WORKSPACE_ID",
11
+ "WORKSPACE_PAIRING_SECRET",
12
+ "CONTROL_PLANE_URL",
13
+ "CONTROL_PLANE_JWKS_URL",
14
+ "CONTROL_PLANE_ISSUER",
15
+ "CP_WEB_ORIGIN",
16
+ ];
17
+
18
+ assertRequiredEnv(env: Readonly<NodeJS.ProcessEnv>): void {
19
+ const missing = ManagedModeBootGuard.requiredVars.filter((name) => !env[name]);
20
+ if (missing.length > 0) {
21
+ throw new Error(
22
+ `auth.kind "managed" requires the following environment variables which are not set: ${missing.join(", ")}.\n` +
23
+ "Set all of them before starting in managed mode.",
24
+ );
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,5 @@
1
+ export type { ManagedAuthConfig } from "./ManagedAuthConfig";
2
+ export { ManagedAuthConfigFactory } from "./ManagedAuthConfig";
3
+ export { ManagedAuthMiddleware } from "./ManagedAuthMiddleware";
4
+ export { ManagedCorsMiddleware } from "./ManagedCorsMiddleware";
5
+ export { ManagedModeBootGuard } from "./ManagedModeBootGuard";