@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,488 @@
1
1
  # @codemation/host
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#150](https://github.com/MadeRelevant/codemation/pull/150) [`8ac207a`](https://github.com/MadeRelevant/codemation/commit/8ac207ab263542e46fad0b9e1ea584fbb71a747c) Thanks [@cblokland90](https://github.com/cblokland90)! - Add workspace-host Docker image packaging and managed template peerDeps fix.
8
+ - Move @codemation/\* from dependencies to peerDependencies in the managed template (avoids n8n-style dual-instance singleton trap at runtime; framework packages resolve from the base image)
9
+ - Add codemationVersion: "1.0.0" field to managed template codemation.config.ts and DefineCodemationAppOptions (reserved compatibility-date slot, no enforcement yet)
10
+ - Add packages/host/src/bin/server.ts standalone entry point for workspace pod runtime
11
+ - Add packaging/workspace-host/Dockerfile for the codemation-workspace-host:1.0.0 base image
12
+
13
+ ### Patch Changes
14
+
15
+ - [#153](https://github.com/MadeRelevant/codemation/pull/153) [`a70e182`](https://github.com/MadeRelevant/codemation/commit/a70e182a852026e4f6d8f317fe9862417dc23ce6) Thanks [@cblokland90](https://github.com/cblokland90)! - Move UI-only packages (monaco-editor, react, @xyflow/react, dagre, lucide-react, rc-tree, etc.) from `dependencies` to `devDependencies` in @codemation/host. No runtime source in `packages/host/src` imports these packages — they were vestigial from before the UI was extracted to @codemation/next-host. Moving them ensures pnpm filtered installs (e.g. `--filter @codemation/host...`) no longer pull in ~1.5 GB of UI dependencies, which is required for the workspace-host container image to stay small.
16
+
17
+ - [#156](https://github.com/MadeRelevant/codemation/pull/156) [`5315e23`](https://github.com/MadeRelevant/codemation/commit/5315e2361492560601ac2c97491aa58c49346fd4) Thanks [@cblokland90](https://github.com/cblokland90)! - fix(host): only throw on invalid WORKSPACE_PAIRING_SECRET in managed mode
18
+
19
+ Previously, setting WORKSPACE_PAIRING_SECRET to an invalid value (not a 32-byte base64 string) would crash the host at boot time even when running in non-managed mode (the default). Framework consumers who accidentally set this env var or left a misconfigured value would see an opaque boot error unrelated to their actual configuration.
20
+
21
+ After this fix, the invalid-secret error is only propagated in `auth.kind: "managed"` mode. In all other modes, the error is caught, a warning is logged, and the host boots normally without pairing infrastructure wired up. Managed-mode consumers continue to see the full error at startup.
22
+
23
+ - [#152](https://github.com/MadeRelevant/codemation/pull/152) [`ac860a5`](https://github.com/MadeRelevant/codemation/commit/ac860a5af1df3e5766581e644fef8cc0d1b24eba) Thanks [@cblokland90](https://github.com/cblokland90)! - Fix ControlPlaneCatalogFetcher calling wrong URL path (sprint-mvp/01).
24
+
25
+ The fetcher was calling `/api/catalog/*` (session-gated in the CP) instead of
26
+ `/internal/catalog/*` (HMAC-gated). The CP's `/api/*` router returned 401 for
27
+ every HMAC-signed request because it requires a Better Auth session cookie, not a
28
+ workspace pairing signature.
29
+
30
+ This caused every provisioned workspace to log steady `HTTP 401 Unauthorized`
31
+ errors from `ControlPlaneCatalogFetcher`, blocking OAuth credential-type and MCP
32
+ server catalog fetches.
33
+
34
+ - [#157](https://github.com/MadeRelevant/codemation/pull/157) [`3025b86`](https://github.com/MadeRelevant/codemation/commit/3025b8685b0d7ad60c506b5a0f21967e681a25ea) Thanks [@cblokland90](https://github.com/cblokland90)! - Shrink workspace-host Docker image by decoupling CLI from next-host at runtime.
35
+
36
+ `@codemation/cli`: demote `@codemation/next-host` from `dependencies` to `devDependencies`. The CLI's
37
+ non-headless serve path resolves the next-host package at runtime via `require.resolve()`; the
38
+ headless path (used by workspace-host pods) never touches it. Consumers that install `@codemation/cli`
39
+ from the registry and need the UI shell must add `@codemation/next-host` as a direct dependency.
40
+
41
+ `@codemation/core-nodes`: demote `lucide-react` from `dependencies` to `devDependencies`. The package
42
+ only references lucide icon names as strings (e.g. `"lucide:bot"`); it never imports the react library
43
+ at runtime. This removes ~46 MB from runtime installs of `@codemation/core-nodes`.
44
+
45
+ `@codemation/host`: promote `execa` and `dotenv` from `devDependencies` to `dependencies`. Both are
46
+ required at Dockerfile build time by `scripts/generate-prisma-clients.mjs` (imports `execaSync` from
47
+ `execa`) and `prisma.config.ts` (imports `dotenv/config`). These files run during `prisma:generate`
48
+ which executes in the production builder stage with `--prod` install (no devDeps available).
49
+
50
+ - Updated dependencies [[`e0933eb`](https://github.com/MadeRelevant/codemation/commit/e0933ebc51806a9593f94758860c591b8346a7a5), [`3025b86`](https://github.com/MadeRelevant/codemation/commit/3025b8685b0d7ad60c506b5a0f21967e681a25ea)]:
51
+ - @codemation/core@0.11.1
52
+ - @codemation/core-nodes@0.8.1
53
+ - @codemation/eventbus-redis@0.0.39
54
+
55
+ ## 0.7.0
56
+
57
+ ### Minor Changes
58
+
59
+ - 8285ec0: Add framework-side OAuth broker delegation (Story 4): HMAC-verified `POST /internal/credentials/push` and `GET /internal/credentials` endpoints on the installation's internal HTTP API; `BrokerClient` for calling the control-plane refresh endpoint via `PairedFetch`; `RemoteOAuthRefreshDelegate` with single-flight deduplication for refreshing expired access tokens through the broker.
60
+ - 8285ec0: Add `ControlPlaneCatalogFetcher` — polls the three control-plane catalog endpoints (`/api/catalog/oauth-apps`, `/api/catalog/mcp-servers`, `/api/catalog/credential-types`) on a configurable interval, caches last-known-good responses per endpoint independently, and exposes `oauthApps`, `mcpServers`, and `credentialTypeOverrides` getters. No-ops when pairing config is absent.
61
+ - 8285ec0: Add credential dialog Create-then-Connect flow for OAuth2 credential types.
62
+
63
+ New endpoints `POST /api/credentials/oauth/start` and `GET /api/credentials/oauth/callback` drive the `OAuthFlowExecutor` directly from the credential dialog. The frontend starts the consent flow via a popup opened against the consent URL returned by `/start`; the `/callback` page exchanges the code, persists the tokens, and posts a message to close the popup.
64
+
65
+ The `OAuthFlowExecutor` interface gains a `lookupInstanceId(stateToken)` method (additive; no breaking change to callers). `CredentialDialog` footer shows Connect / Reconnect for OAuth2 instances in edit mode.
66
+
67
+ - 8285ec0: `CredentialTypeRegistry` now accepts named sources with priority shadowing (parity with `McpServerCatalog`). Sources are ordered `plugin` < `config` < `controlPlane`; higher-priority sources shadow lower ones, lower-priority duplicates are ignored, and both cases log a warn.
68
+
69
+ `applyControlPlaneOverrides` is removed. Control-plane payload now flows through `mergeDefinitions("controlPlane", …)` and can add new types — not just override existing ones. Plugins/config use `merge(source, types)` for full credential types.
70
+
71
+ `McpRegistryFetcher` is removed; `ControlPlaneCatalogFetcher` is the single control-plane catalog poller and now merges credential-type definitions in addition to MCP server declarations and OAuth app catalog entries.
72
+
73
+ - 8285ec0: Declare Gmail MCP server via plugin source (standalone framework). Add mcpServers to DefinePluginOptions and thread it through createPlugin. Add gmail MCP server declaration to core-nodes-gmail plugin. Break host↔gmail cycle by removing gmail from host devDependencies.
74
+ - 8285ec0: feat(host/audit): workflow audit retention + tier-gated emission (Sprint 14 Story 06)
75
+ - WorkflowAuditLogPruneScheduler: deletes WorkflowAuditLog rows older than 90 days (CODEMATION_AUDIT_WORKFLOW_RETENTION_SECONDS override)
76
+ - TelemetryRetentionTimestampFactory: hard-coded defaults (span 7d, artifact 3d, metric 30d) so telemetry retention works out-of-box with no env vars required
77
+
78
+ - 8285ec0: Runtime DI parity: hoist TypeInfo registrar into AppContainerFactory so CLI runs get the same DI graph as the HTTP host. Add codemation run workflow CLI command that dispatches StartWorkflowRunCommand and polls until terminal status.
79
+ - 8285ec0: Add internal workflow introspection endpoints (`GET /internal/workflows` and `GET /internal/workflows/:workflowId`) protected by HMAC pairing-secret middleware. These allow the concierge agent to enumerate workflow summaries and fetch individual workflow DAGs (nodes + edges) via the paired-fetch channel.
80
+ - 8285ec0: Add `POST /internal/workflows/:id/test-run` HMAC-protected endpoint. Runs a workflow once synchronously without requiring it to be active, letting the coding agent verify a workflow before activating it. Body: `{ input?: unknown }`. Returns `{ ok, runId?, output?, error?, durationMs }` with a 30-second timeout.
81
+ - 8285ec0: feat(host/audit): RunEvent-driven WorkflowAuditLog persistence (Sprint 13 Story B)
82
+
83
+ Adds a workspace-local audit trail that captures run-events as queryable rows.
84
+ - `WorkflowAuditLog` Prisma model with indexes on `(actor_user_id, occurred_at)` and `(workflow_id, occurred_at)`
85
+ - `WorkflowAuditLogWriter` subscribes to `RunEventBus` and persists `nodeCompleted`, `nodeFailed`, `runSaved` (terminal), and `connectionInvocationStarted` events
86
+ - `PrismaWorkflowAuditLogRepository` implements `IWorkflowAuditEmitter` using the workspace Prisma client
87
+ - Emission is best-effort: errors are logged and swallowed so workflow execution is never blocked
88
+ - Only active when `persistence.kind !== "none"`
89
+
90
+ - 8285ec0: Add WebSocket JWT authentication for managed mode.
91
+
92
+ In `auth.kind: "managed"` mode the workspace WebSocket server now requires a CP-signed JWT
93
+ passed as `?token=<jwt>` in the upgrade URL. Connections with a missing, expired, wrong-audience,
94
+ or otherwise invalid token are closed immediately with code 4401 ("unauthorized"). Self-hosted
95
+ mode behavior is unchanged.
96
+
97
+ New exports: `WebsocketAuthenticator` interface (types), `ManagedWebsocketAuthenticator` class.
98
+ The `JwksCache` instance is shared between the HTTP JWT verifier and the WS authenticator so
99
+ key rotation propagates to both transports without a restart.
100
+
101
+ - 8285ec0: Add LocalOAuthFlowExecutor for framework (OSS/standalone) mode. Reads clientId from the credential instance's publicConfig and clientSecret from its secret material; builds PKCE-protected consent URLs; exchanges auth codes and refresh tokens directly against the provider's token endpoint. Also patches OAuthFlowExecutor.refresh to accept typeId and instanceId alongside the material, since looking up the tokenUrl and app credentials requires the instance.
102
+ - 8285ec0: Add `GET /api/me` endpoint in managed-auth mode (Story A). Returns `{ userId, workspaceId }` from the bearer JWT principal. Only mounted when `auth.kind === "managed"`.
103
+ - 8285ec0: Add ManagedOAuthFlowExecutor for managed (paired) mode. Delegates the OAuth dance to the control plane over HMAC-signed calls, keeping client secrets off the host. AppContainerFactory now selects ManagedOAuthFlowExecutor when pairing is configured and LocalOAuthFlowExecutor otherwise.
104
+ - 8285ec0: Add McpConnectionPool — lazy, keyed MCP client pool for managed HTTP connections.
105
+
106
+ Pools `experimental_createMCPClient` connections keyed by `(credentialInstanceId, serverId)`.
107
+ Reads bearer tokens fresh from the OAuth2-via-broker credential session at open time.
108
+ Caches `tools/list` results per entry and applies `toolDescriptionOverrides` from the catalog declaration.
109
+ Supports `closeForCredential` (revocation) and `closeAll` (host shutdown).
110
+
111
+ - 8285ec0: Remove the MCP credential bypass on AI agents. `AIAgent.mcpServers` is now a plain
112
+ `ReadonlyArray<string>` of server ids — the inline `{ credential }` field is gone. Each
113
+ declared server surfaces a standard credential slot on the agent node (key
114
+ `mcp:<serverId>`, label and accepted types from the MCP catalog) and binds through the
115
+ same `CredentialBinding` table as every other slot. At execute time the host resolves the
116
+ binding via `getBinding({ workflowId, agentNodeId, slotKey: mcp:<serverId> })`, then opens
117
+ the MCP pool with the resolved credential instance — no more reading the credential id
118
+ out of the workflow config.
119
+
120
+ Breaking — config shape change. Replace:
121
+
122
+ ```ts
123
+ mcpServers: {
124
+ gmail: {
125
+ credential: "<instanceId>";
126
+ }
127
+ }
128
+ ```
129
+
130
+ with:
131
+
132
+ ```ts
133
+ mcpServers: ["gmail"];
134
+ ```
135
+
136
+ Then bind the credential through the canvas credential dropdown before activating the
137
+ workflow, the same way trigger credentials are bound. The `McpServerBindings` /
138
+ `McpServerExplicitBinding` types are removed from `@codemation/core`;
139
+ `AgentMcpIntegration.prepareMcpTools` now takes `{ workflowId, agentNodeId, serverIds }`.
140
+
141
+ - 8285ec0: Replace `McpServerDeclaration.credentialKind` / `credentialTypeId` / `oauthAppKey` with `acceptedCredentialTypes?: ReadonlyArray<string>`, matching the `CredentialRequirement.acceptedTypes` shape. Absent or empty array means no credential required. Gmail MCP declaration now uses `["oauth.google.gmail"]`, the same type as the Gmail trigger node.
142
+ - 8285ec0: Add `McpServerDeclaration` type and `McpServerCatalog` service (Story 7).
143
+ - `@codemation/core` exports `McpServerDeclaration` and `McpServerTransport` from `packages/core/src/contracts/mcpTypes.ts`.
144
+ - `CodemationPlugin` gains an optional `mcpServers?: ReadonlyArray<McpServerDeclaration>` field.
145
+ - `CodemationConfig` gains an optional `mcpServers?: ReadonlyArray<McpServerDeclaration>` field (also threaded through `AppConfig` and `DefineCodemationAppOptions`).
146
+ - `McpServerCatalog` in `packages/host/src/mcp/` merges declarations from three sources (`plugin`, `config`, `controlPlane`) with deterministic precedence and validation (id regex, stdio gate, credential requirements).
147
+ - `CodemationPluginDiscovery.isPluginConfig` now recognises `mcpServers`-only plugins.
148
+ - Plugin registrar and app container factory wire catalog merge on startup.
149
+
150
+ - 8285ec0: Add `McpRegistryFetcher` — installation-side polling service that fetches `GET /internal/registry/mcp-servers` from the control plane via the paired HMAC channel on startup and on a configurable interval (default 5 minutes), merging results into `McpServerCatalog` as source `"controlPlane"` (Story 13).
151
+ - 8285ec0: Wire `ControlPlaneCatalogFetcher` into app bootstrap so credential-type overrides fetched from the control plane take highest precedence in `CredentialTypeRegistryImpl` (control plane > consumer config > framework default). Add `applyControlPlaneOverrides` to `CredentialTypeRegistryImpl` — full replacement per typeId, preserving runtime callbacks.
152
+ - 0082ab5: Adds an `inspectorSummary` hook on node configs (and `defineNode({ inspectorSummary })` for plugin-author nodes). Returns 2–6 short label/value pairs that describe what the node will do at design time — model + prompt for an agent, method + URL for an HTTP call, schedule + timezone for a cron, etc. Surfaced in the workflow editor's node-properties panel as a new "Configuration" section that renders before any run telemetry exists. Hidden when no rows are produced; node configs that don't implement the hook contribute nothing. Built-in nodes will fill these in across follow-up PRs.
153
+ - 8285ec0: Remove legacy OAuth connect code path. `OAuth2ConnectService` and its `getAuthRedirect` / `handleCallback` methods are deleted; the `/api/oauth2/auth` route and the duplicate `/api/credentials/oauth/callback` route are removed. The canonical flow is now exclusively `OAuthFlowExecutor` (`LocalOAuthFlowExecutor` / `ManagedOAuthFlowExecutor`) via `POST /api/credentials/oauth/start` and `GET /api/oauth2/callback`. Redirect-URI resolution is extracted to a dedicated `OAuth2RedirectUriResolver`. `ApiPaths.oauth2Auth()` and `ApiPaths.credentialOAuthCallback()` are removed; the client now requires the server-canonical redirect URI from `ApiPaths.oauth2RedirectUri()` before starting the flow.
154
+ - 8285ec0: Add `CredentialOAuth2MaterialReader` — a host service that reads stored OAuth2 material and proactively refreshes the access token via `OAuthFlowExecutor.refresh` when it's past expiry (or within a 60-second lead window). Re-encrypts and saves the refreshed material back so subsequent reads find a fresh token.
155
+
156
+ Wired into `McpConnectionPool` immediately: MCP HTTP transport had no SDK-level 401-and-refresh path (the Gmail trigger doesn't hit this because `googleapis.OAuth2Client` refreshes internally — that was the exception, not the rule). Before this change, the MCP pool happily sent expired tokens and the workflow failed with `401 — Request had invalid authentication credentials` about an hour after the user connected.
157
+
158
+ Concurrent reads share a single in-flight refresh per `instanceId` so the refresh token isn't exchanged twice in parallel. If the refresh call itself fails (e.g. revoked refresh token), the reader logs a warn and returns the stale material — the caller's downstream 401 is what surfaces the actual reconnect-required condition.
159
+
160
+ - 8285ec0: Add `OAuth2ViaBrokerCredentialTypeFactory` — framework credential type (`host.oauth2-via-broker`) that reads the current access token from the local credential store (populated by the broker push endpoint) and injects `Authorization: Bearer <token>` on requests. Satisfies Story 8: zero credential-type code per new SaaS integration.
161
+ - 8285ec0: Introduce a cross-platform `ProcessRunner` seam (interface + execa-backed `ExecaProcessRunner`) exported from `@codemation/host/server`, registered in `AppContainerFactory` under `ApplicationTokens.ProcessRunner`. Migrate every CLI site that previously spawned bare external commands (`pnpm exec next dev` and the packaged Next UI in `DevCommand`, `pnpm exec next start` in `ServeWebCommand`, `pnpm --filter … dev` in `WorkspacePluginDevProcessCoordinator`, `pnpm exec prisma migrate deploy` in `PrismaMigrateDeployInvoker`) so Windows finds `pnpm.cmd` / `pnpm.ps1` shims via execa's PATH resolution instead of erroring with ENOENT. Replace the bash-only `realpath "$(command -v pnpm)"` lookup in `packages/host/scripts/generate-prisma-clients.mjs` with an `execaSync("pnpm", ["root", "-g"])` probe. Fix the root `dev:framework` script's single-quoted command tokens (broken on Windows `cmd.exe`) by switching to escaped double quotes so it works on cmd, PowerShell, bash and zsh.
162
+ - 8285ec0: Remove deprecated broker-era MCP fields: `NeedsReconsentEvent.oauthAppKey`, shorthand `McpServerBindings` string array form, and `AgentMcpIntegrationImpl.autoResolveCredential`. Explicit binding (`{ serverId: { credential: "<instanceId>" } }`) is now the only supported form — eliminating ambiguity when multiple credential instances of the same type exist.
163
+ - 8285ec0: Remove the `host.oauth2-via-broker` credential type and all related broker-upsert machinery. The broker is now an implementation detail of `ManagedOAuthFlowExecutor`; the credential type catalog only contains mode-agnostic types.
164
+ - 8285ec0: Remove `RemoteOAuthRefreshDelegate` and its DI registration. The only refresh path is now `OAuthFlowExecutor`. `McpConnectionPool` uses a local inline type instead of importing from `OAuth2ViaBrokerCredentialTypeFactory`.
165
+ - 8285ec0: feat(host/binary): S3BinaryStorage implementation + boot connectivity check (Sprint 15 Story 03)
166
+
167
+ Adds `S3BinaryStorage` — a Scaleway-compatible S3 implementation of `BinaryStorage` using
168
+ `@aws-sdk/client-s3` + `@aws-sdk/lib-storage` (multipart for large payloads). Key scheme:
169
+ `<workspaceId>/<runId>/<binaryId>`.
170
+
171
+ Runtime selection is controlled by `BINARY_STORAGE_KIND` env var (`"local"` default | `"s3"`).
172
+ When `"s3"`, all `BINARY_STORAGE_S3_*` vars are required and validated at boot. A `HeadBucket`
173
+ connectivity check fails loudly on startup if the bucket is unreachable.
174
+
175
+ Extends `BinaryStorage` interface (core) with `deleteMany(keys)` and `listByPrefix(prefix)` for
176
+ bulk-delete (1000-key S3 batching) and workspace-prefix enumeration (GDPR erasure). All existing
177
+ implementations (`InMemoryBinaryStorage`, `LocalFilesystemBinaryStorage`, `UnavailableBinaryStorage`)
178
+ updated with correct implementations.
179
+
180
+ - 8285ec0: fix(security): engine activation budget + retry ceiling + SSRF allowlist + HKDF cipher + pairing entropy (Sprint 14 Story 09)
181
+
182
+ **Engine / retry fixes (already implemented in Sprint 13/14 — tests added here):**
183
+ - `RunContinuationService` uses `EngineExecutionLimitsPolicy.defaultMaxNodeActivations` (100,000) as the fallback, not `Number.MAX_SAFE_INTEGER`.
184
+ - `InProcessRetryRunner` enforces a hard ceiling of 10 retry attempts via `HARD_MAX_RETRY_ATTEMPTS`; workflow-declared values above this are clamped with a warning log.
185
+
186
+ **SSRF allowlist (`@codemation/core-nodes`):**
187
+ - New `SsrfGuard` class DNS-resolves the target host before any outbound HTTP call and throws `SSRFBlockedError` if any resolved address falls in RFC-1918 (10/8, 172.16/12, 192.168/16), link-local (169.254/16), or loopback (127/8, ::1) ranges.
188
+ - `HttpRequestExecutor` now accepts `SsrfGuard` as an injected collaborator (4th constructor arg). All composition roots updated.
189
+ - `HttpRequestSpec.allowPrivateNetworkTargets` opt-in flag allows trusted workflows to bypass SSRF protection.
190
+ - New `SSRFBlockedError` class with `resolvedIp` field for structured error handling.
191
+
192
+ **HKDF cipher key derivation (`@codemation/host`) — BACKWARDS-INCOMPATIBLE:**
193
+ - `CredentialSecretCipher` switches from raw SHA-256 to HKDF-SHA-256 for AES key derivation.
194
+ - HKDF salt: `"codemation/credential-cipher/v1"`, info: `"aes-256-gcm-key"`.
195
+ - Input (`CODEMATION_CREDENTIALS_MASTER_KEY`) must now be a base64-encoded 32-byte value.
196
+ - New `schemaVersion: 2` for all new encryptions. Existing `schemaVersion: 1` records can still be decrypted (v1 SHA-256 read-path retained for migration).
197
+ - **Migration**: Re-bind affected credentials in the UI (which re-encrypts with the new HKDF key).
198
+ - See migration guide below.
199
+
200
+ **Pairing secret entropy validation (`@codemation/host`):**
201
+ - `PairingConfigFactory` now throws at boot when `WORKSPACE_PAIRING_SECRET` is present but does not decode to exactly 32 bytes from base64.
202
+ - Error message includes `openssl rand -base64 32` hint for generating a valid secret.
203
+
204
+ ***
205
+
206
+ ### Migration guide — CODEMATION_CREDENTIALS_MASTER_KEY
207
+
208
+ **Who is affected:** Any deployment that has `CODEMATION_CREDENTIALS_MASTER_KEY` set and has encrypted credentials stored in the database.
209
+
210
+ **What changed:** The key derivation function changed from `SHA-256(rawString)` to `HKDF-SHA-256(base64Decode(rawString), salt, info)`. The input key must now be exactly 32 bytes when base64-decoded.
211
+
212
+ **Migration steps:**
213
+ 1. Generate a new 32-byte key: `openssl rand -base64 32`
214
+ 2. Set `CODEMATION_CREDENTIALS_MASTER_KEY` to this new value.
215
+ 3. Re-bind each credential in the Codemation UI (open the credential, re-enter secrets, save). This re-encrypts with the new HKDF-derived key at `schemaVersion: 2`.
216
+ 4. Credentials not yet re-bound will throw `CredentialKeyRotatedError` when accessed — the existing key-rotation error handling applies.
217
+
218
+ **Rollback:** Keep the old key value in a safe location. To roll back, restore the old `CODEMATION_CREDENTIALS_MASTER_KEY` value — the v1 SHA-256 decrypt path is retained in this release.
219
+
220
+ - 8285ec0: Add `@codemation/managed-auth` package and `auth.kind: "managed"` support in `@codemation/host`.
221
+
222
+ `@codemation/managed-auth` is a new publishable package containing the JWKS cache and EdDSA JWT verifier used by managed-mode workspaces. It has no dependency on `@codemation/host` or `@codemation/core` and is intentionally self-contained so the closed-source workspace-mcp can install it from the public registry.
223
+
224
+ `@codemation/host` gains `auth.kind: "managed"` — a new auth mode where Better Auth is not mounted, the workspace verifies CP-signed JWT bearers, and a single-origin CORS allowlist is enforced via `CP_WEB_ORIGIN`. Boot-time guard ensures all required env vars are present before startup.
225
+
226
+ - 8285ec0: feat(story-11): Wire MCP catalog into agent — explicit and shorthand binding, scope validation, pool integration, telemetry, and runtime 403 detection
227
+ - `@codemation/core`: `AgentMcpIntegration` interface + token, `McpServerBindings` types, `NeedsReconsentEvent`, `AgentBindError`, `NoOpAgentMcpIntegration` fallback, `CodemationTelemetryAttributeNames.mcpServerId/mcpToolName`
228
+ - `@codemation/core-nodes`: `AIAgentConfig` + `AIAgent` extended with `mcpServers` and `pinnedMcpTools`; `DeferredMetaToolStrategy.ownsToolName` covers MCP tools; `AIAgentNode` injects `AgentMcpIntegration` and strips AI SDK auto-execute from strategy tools
229
+ - `@codemation/host`: `AgentMcpIntegrationImpl` — resolves bindings, validates scopes, opens pool, wraps tool execute with telemetry spans and 403/permission error detection
230
+
231
+ - 8285ec0: Add `managed` scaffold template and workflow auto-discovery config fields
232
+ - New `create-codemation` template `managed` — pre-configured for managed mode with PostgreSQL, CP-JWT auth, and workflow auto-discovery from `./src/workflows`.
233
+ - `defineCodemationApp` now accepts `workflowsDir` (maps to `workflowDiscovery.directories`), `database.urlEnv`, `execution.modeEnv`, and `execution.redisUrlEnv` for env-resolved config values.
234
+ - `CodemationConfigNormalizer` enforces managed-mode invariants: PostgreSQL required, at least one workflow source required.
235
+ - New `WorkflowDirectoryDiscoverer` class for walking a directory and collecting exported workflows with test-file exclusion.
236
+ - `WorkflowModulePathFinder` now excludes `*.test.*` and `*.spec.*` files from discovery.
237
+
238
+ - 8285ec0: Add workspace pairing primitives to `packages/host/src/pairing/`: `HmacRequestSigner`, `PairedFetch` (outgoing signed requests to the control plane), `IncomingHmacVerifier` (verify signed requests from the control plane), `InternalHmacAuthMiddleware`, and `InternalPingRegistrar`. These enable HMAC-SHA256 authenticated channels between a workspace installation and the control plane per the protocol defined in `docs/pairing-protocol.md`. Also extends `CodemationHonoApiApp` to mount optional `/internal/*` routes via the new `InternalHonoApiRouteRegistrar` token.
239
+ - 51b728d: Stream telemetry spans over WebSocket transport, eliminating HTTP polling.
240
+
241
+ **Backend (@codemation/host):**
242
+ - Added `TelemetrySpanPublisher` interface + `NoOpTelemetrySpanPublisher` default.
243
+ - Added `telemetryEvent` variant to `WorkflowWebsocketMessage` carrying `TelemetrySpanUpsert`.
244
+ - New `TelemetrySpanWebsocketRelay` class publishes each span upsert to a per-run room (`run:<runId>`) after it is committed to persistent storage.
245
+ - `OtelExecutionTelemetryFactory` injects `TelemetrySpanPublisher` (defaults to no-op when unregistered).
246
+ - `StoredTelemetrySpanScope.upsert()` calls the publisher after the span store write so reconnect HTTP catch-up and WS pushes are consistent.
247
+
248
+ **Frontend (@codemation/next-host):**
249
+ - `useWorkflowRealtimeInfrastructure` handles `kind: "telemetryEvent"` messages via `applyTelemetrySpanEvent`, which merges spans into the `telemetry-run-trace` query cache by `spanId` (deduped, sorted by `startTime`).
250
+ - New `retainRunSubscription` API manages per-run WS room subscribe/unsubscribe with reference counting.
251
+ - Auto-unsubscribe from run rooms when the tab is hidden for ≥ 5 minutes (Page Visibility API); re-subscribes on tab return.
252
+ - `useTelemetryRunTraceQuery` drops HTTP polling (`refetchInterval: false`); refetches once on WS reconnect for catch-up.
253
+ - `resolveTelemetryTraceRefetchIntervalMs` is now a no-op (always returns `false`) — retained for call-site compatibility.
254
+
255
+ ### Patch Changes
256
+
257
+ - 8285ec0: Add activation-time OAuth scope validation: workflows with bound OAuth credentials are now rejected at activation if the granted scopes do not cover the required scopes for the credential type.
258
+ - 8285ec0: Add a `statusLabel` field to `ConnectionInvocationRecord` / `ConnectionInvocationAppendArgs` so connection invocations can carry a short human-readable description of what they are doing (e.g. `"calling search_messages"`). The engine-side `NodeRunStateWriter` persists it; the canvas-side mirror picks it up via the standard patch projection.
259
+
260
+ Wire per-MCP-tool-call lifecycle invocations through `AgentMcpIntegration`. `prepareMcpTools` now accepts an optional `appendMcpInvocation` callback (plus the agent activation / iteration / item / parent-invocation context). When the host-side `AgentMcpIntegrationImpl` wraps a tool's `execute`, it emits a `running` record with `statusLabel: "calling <toolName>"` and a matching `completed` or `failed` record; the existing telemetry span and 403 `NeedsReconsentEvent` paths are preserved. `@codemation/canvas-core` exposes a `CurrentStatusLabelSelector` and `WorkflowCanvasNodeData.currentStatusLabel`; `@codemation/canvas` renders the latest non-empty label as a sub-line under the node card. The two capabilities work together: MCP tool calls under an agent now stream the same invocation events the LLM and node-backed tool paths already emit, and the canvas surfaces the running label per-node.
261
+
262
+ - 8285ec0: Fix workflow detail screen hydration mismatch caused by overlay siblings (tabs, run button, error banner, realtime badge) being rendered conditionally on controller state that diverges between SSR and a warm React Query client cache. Overlay siblings are now gated behind the same `hasMounted` flag as the canvas root.
263
+
264
+ Render AIAgent MCP-server attachments in the canvas. `WorkflowDefinitionMapper` (the server-side mapper that feeds `/api/workflows/:id`) now passes an `McpServerResolver` backed by the host's `McpServerCatalog` to `AgentConnectionNodeCollector.collect`, so virtual connection nodes for declared `mcpServers` are emitted alongside the LLM and tool children. The MCP descriptor itself carries `icon: "lucide:plug"` and `lucide:plug` is added to the curated `WorkflowCanvasLucideIconRegistry` so MCP servers render with a distinct icon on the synchronous zero-HTTP path.
265
+
266
+ - 8285ec0: Add optional `subjectName?: string` to `ConnectionInvocationRecord` and `ConnectionInvocationAppendArgs` — a stable identifier for the thing an invocation acts on that persists across status transitions. The MCP integration's `wrapToolExecutes` sets it to the tool name on every transition (running / completed / failed), so the inspector's tool-call timeline entries can render `"Tool call · <toolName>"` for MCP servers (which expose many tools through a single connection node) instead of an opaque `"Tool call"`.
267
+
268
+ For node-backed agent tools, the parent connection node id already encodes the tool name — `subjectName` stays unset there and the inspector renders the existing `"Tool call"` title unchanged.
269
+
270
+ `statusLabel` (the running-only sentence rendered on the canvas card sub-line) is unchanged; `subjectName` is the persistent structural sibling used by the inspector.
271
+
272
+ - 8285ec0: Coverage Phase 2: testkits (LoggerTestKit, McpTestKit, CoreNodesTestContextFactory,
273
+ TelemetryTestKit, GmailTestKit, AppConfigFixturesFactory, HookTestkit), per-package
274
+ vitest coverage thresholds, and new tests on previously zero-coverage critical paths
275
+ (mergeNode, switchNode, waitNode, connectionCredentialNode, canvas-lib pure, hook smoke).
276
+ No production code changes.
277
+ - e4d3e1a: perf(host): reject workflow runs immediately when required credential slots are unbound
278
+
279
+ `StartWorkflowRunCommandHandler` now calls
280
+ `CredentialBindingService.assertRequiredCredentialsBound` before queuing any
281
+ node activations. The check does a single DB query (all bindings for the
282
+ workflow) and walks every slot including deeply-nested ones in AI agent nodes
283
+ (language model, node-backed tools, nested agents) via
284
+ `WorkflowCredentialNodeResolver.listSlots`. If any required slot has no
285
+ binding the request fails with a 400 before the run record is created, so the
286
+ user sees a clear error message instead of waiting for the run to start and
287
+ then fail several seconds later.
288
+
289
+ - 8285ec0: Fix `/collections` 500 on consumer dev startup: `no such table: collections_<name>`. The CLI sets `CODEMATION_SKIP_STARTUP_MIGRATIONS=true` because it runs Prisma migrations ahead of the runtime, but the same env var was also gating consumer-defined collection-schema sync inside `FrontendRuntime.start` (and `WorkerRuntime.start`). Only the runtime knows about collections declared in `codemation.config.ts`, so the CLI can never run that sync on the runtime's behalf. The two gates are now separate: Prisma migrations remain skip-able via the env var, but collection sync always runs at runtime startup when collections are declared and persistence is configured.
290
+ - 8285ec0: fix(host/http): generic 500 error envelope + ManagedMeHonoApi error boundary (Sprint 14 Story 08)
291
+ - `ServerHttpErrorResponseFactory.fromUnknown` now returns `{ error: "Internal server error" }` for unexpected errors instead of leaking `error.message` to the client (Prisma messages, stack fragments, internal state).
292
+ - `ManagedMeHonoApiRouteRegistrar.register` wraps `sessionVerifier.verify()` in try/catch; a thrown JWT verification error now returns 401 instead of propagating as an unhandled 500.
293
+ - Tests updated: `telemetryHttpRouteHandler.test.ts` reflects generic envelope; new test in `ManagedMeHonoApiRouteRegistrar.test.ts` asserts 401 on `verify()` throw; new `ServerHttpErrorResponseFactory.test.ts` asserts generic message does not contain internal details.
294
+
295
+ - 8285ec0: test(host/persistence): cascade-on-delete integration tests (Sprint 13 Story C)
296
+
297
+ Adds `cascadeOnDelete.integration.test.ts` covering all 8 `onDelete: Cascade`
298
+ relationships declared in `schema.postgresql.prisma`. Each test creates a parent
299
+ row and N child rows, deletes the parent, and asserts the child count drops to 0.
300
+
301
+ Relationships tested:
302
+ - `RunWorkItem → Run`
303
+ - `ExecutionInstance → Run`
304
+ - `RunSlotProjection → Run`
305
+ - `TestAssertion → Run`
306
+ - `TestAssertion → TestSuiteRun`
307
+ - `UserInvite → User`
308
+ - `Account → User`
309
+ - `Session → User`
310
+
311
+ Gaps noted (no cascade declared in schema, no schema changes made):
312
+ - `Credential*` tables (CredentialSecretMaterial, CredentialOAuth2Material, etc.)
313
+ share `instanceId` with `CredentialInstance` but have no `@relation onDelete:
314
+ Cascade`. GDPR right-to-erasure risk.
315
+ - No `Workspace` model exists in `schema.postgresql.prisma`.
316
+
317
+ - 8285ec0: test(host): increase unit test coverage to ≥90% (Sprint 14 Story 13)
318
+
319
+ Adds 30+ new unit test files and extensions covering previously untested logic in
320
+ `@codemation/host`. New test suites include:
321
+ - `InMemoryCredentialStore` — full CRUD + OAuth2 state/material lifecycle
322
+ - `CredentialSessionServiceImpl` — getSession, createSessionForInstance, evict\*
323
+ - `SetPinnedNodeInputCommandHandler` — 404/403/decode/null-items paths
324
+ - `ReplaceMutableRunWorkflowSnapshotCommandHandler` — 400/404/403/success
325
+ - `ReplayWorkflowNodeCommandHandler` — 404/403/workflow-not-found/decode/mode
326
+ - `GetWorkflowRunDetailQueryHandler` — undefined detail, empty rollups, cost join
327
+ - `WorkflowRunRetentionPruneScheduler` (extended) — both-disabled early return, listRuns fallback, binary storage key fallback, artifact storage key deletion
328
+ - `WorkflowAuditLogPruneScheduler` — disabled, custom retention, delete path
329
+ - `ManagedCorsMiddleware` — preflight allow/deny, non-preflight with/without CORS headers
330
+ - `InMemoryDomainEventBus` — publish routing, metadata error, empty handlers
331
+ - `WorkflowRunRepository` wrapper — load/save/listRuns/deleteRun with URL decoding
332
+ - `ApiPaths` — all static path methods
333
+ - `CodemationConfigNormalizer` — register callback, managed-mode constraints, DefinedCollection unwrapping
334
+ - `LocalFilesystemBinaryStorage` — write/read/stat/delete/deleteMany/listByPrefix/path-escape
335
+ - `StoredTelemetrySpanScope` (extended) — addSpanEvent, attachArtifact no-op path, asNodeTelemetry view
336
+ - `TelemetryQueryService` (extended) — empty-spans early returns, cachedInputTokens/reasoningTokens branches
337
+
338
+ Coverage exclusions added for infrastructure-only files that require live
339
+ connections (SQLite, S3, module loader, internal HMAC wiring).
340
+
341
+ - 8285ec0: test(host): push @codemation/host coverage to ≥90% lines (Sprint 16 Story 01)
342
+ - 8285ec0: Surface unbound credential errors to workflow run dialog by fixing the swallowed catch block in CredentialBindingService.assertRequiredCredentialsBound.
343
+ - 8285ec0: fix(credentials): MCP server credential slots now appear in the properties panel
344
+
345
+ `WorkflowCredentialNodeResolver` was calling `AgentConnectionNodeCollector.collect()` without the `mcpServerResolver` argument in both `addRecursiveAgentSlots` and `findRecursiveConnectionNode`, so MCP attachment nodes (e.g. Gmail) were never included in the credential slot list. The early-return guard in `findRecursiveConnectionNode` also rejected MCP node IDs because it only checked for LLM and tool connection node ID patterns. Injecting `McpServerCatalog` into the resolver and passing it as the resolver to all three `collect()` call sites fixes both paths.
346
+
347
+ - 8285ec0: feat(host): warn at startup when pairing env vars are absent (Sprint 14 Story 05)
348
+
349
+ When WORKSPACE_ID, WORKSPACE_PAIRING_SECRET, or CONTROL_PLANE_URL are not set
350
+ at boot, the host now logs a named warning (codemation.pairing) listing the
351
+ missing variable names instead of silently skipping pairing registration.
352
+ This makes misconfigured managed-mode deployments immediately visible in logs.
353
+
354
+ - 8285ec0: feat(host/storage): artifact-to-object-storage + Run snapshot dedup (Sprint 14 Story 07)
355
+ - TelemetryArtifact payloads > 64 KB are now offloaded to BinaryStorage (payloadStorageKey column)
356
+ instead of stored inline in Postgres TEXT columns. Expired artifacts with storage keys have their
357
+ BinaryStorage blobs deleted during prune.
358
+ - Run snapshot deduplication: new WorkflowSnapshot table keyed by (workflowId, snapshotHash).
359
+ PrismaWorkflowRunRepository.createRun/save call findOrCreate to share identical snapshot JSON
360
+ across runs instead of storing redundant copies per run.
361
+ - Schema migrations added for both PostgreSQL and SQLite (with backfill of existing rows).
362
+
363
+ - 8285ec0: feat(host/security): HMAC verifier + credential cipher trust-boundary tests and `CredentialKeyRotatedError` for key rotation (Sprint 13 Story E framework-side).
364
+ - New `CredentialKeyRotatedError` thrown by `CredentialSecretCipher.decrypt` when the stored `encryptionKeyId` does not match the active master key — explicit fail-loud on key rotation.
365
+ - `CredentialSecretCipher` updated: decrypt now checks key id before attempting decryption, with missing-env → key-id-mismatch → auth-tag-failure ordering.
366
+ - `IncomingHmacVerifier` now throws explicitly when `pairingSecret` is empty (prevents silent signature-mismatch on misconfiguration).
367
+ - 8 unit tests for `IncomingHmacVerifier` (valid/wrong-workspace/tampered-body/tampered-header/skewed-timestamp/missing-secret-throws/replay/nonce-per-instance).
368
+ - 4 integration tests for `InternalHmacAuthMiddleware` hitting `/internal/ping` (valid 200/tampered 401/wrong-workspace 401/replay 401).
369
+ - 7 unit tests for `CredentialSecretCipher` (round-trip/tamper/missing-env-encrypt/missing-env-decrypt/IV-randomness/keyId-format/key-rotation-throws-CredentialKeyRotatedError).
370
+ - Fix pre-existing TS error: `ManagedAuthTestJwks` `KeyLike` → `CryptoKey` (jose v6 dropped the alias).
371
+ - New `docs/security-boundary.md` documenting HMAC trust boundary, in-memory nonce cache semantics, and cipher key rotation contract.
372
+
373
+ - 8285ec0: Allow SQLite in managed mode. The Sprint 3 Story 6 normalizer rule that
374
+ forced PostgreSQL when `auth.kind === "managed"` is removed for now —
375
+ the provisioner doesn't inject `DATABASE_URL` into spawned workspaces,
376
+ so the constraint blocked local provisioning. The managed scaffold
377
+ template now defaults to a per-workspace SQLite file.
378
+ - 8285ec0: `McpConnectionPool` now reads OAuth material directly from the credential store + cipher instead of casting the credential session to an invented `McpOAuth2Session` shape. The previous path called `CredentialSessionServiceImpl.createSessionForInstance<McpOAuth2Session>(...)`, which was an unsafe generic cast — credential types' actual session shapes (e.g. `GmailSession`) don't implement `applyToRequest`, so the call threw `TypeError: session.applyToRequest is not a function` at runtime even though it type-checked.
379
+
380
+ The pool now resolves an instance's OAuth2 material via `credentialStore.getOAuth2Material(instanceId)` + `credentialSecretCipher.decrypt(...)` and builds the `authorization: Bearer <accessToken>` header from `material.accessToken` — bypassing the session entirely. Bound MCP credential types are already gated by `McpServerDeclaration.acceptedCredentialTypes` (OAuth2-shape verified at the catalog level), so the material is always available when binding succeeds.
381
+
382
+ `CredentialSessionServiceImpl.createSessionForInstance` is removed — it was only kept to feed this dead path. `McpOAuth2Session` (the fictional local type) is deleted.
383
+
384
+ - 8285ec0: MCP credential slots now live on the MCP connection node, matching ChatModel and Tool
385
+ connection nodes. Each declared `mcpServers` entry materializes an MCP connection node
386
+ and the credential slot is attached to that node with slot key `"credential"` (label
387
+ and accepted types derived from the MCP catalog declaration). The standard credential
388
+ slot traversal picks them up via `AgentConnectionNodeCollector` — no special-case path.
389
+
390
+ Removed the agent-owned `mcp:<serverId>` slot key. Removed the `mcpSlotKey(serverId)`
391
+ helper from `@codemation/core` (and its re-export from the type-only `contracts`
392
+ subpath). At runtime, `AgentMcpIntegration.prepareMcpTools` now resolves the binding at
393
+ `(workflowId, ConnectionNodeIdFactory.mcpConnectionNodeId(agentNodeId, serverId), "credential")`.
394
+
395
+ Gmail MCP `requiredScopes` trimmed to `["https://www.googleapis.com/auth/gmail.modify"]`
396
+ — `gmail.modify` is a superset of `gmail.readonly` + `gmail.send` for messages, threads,
397
+ drafts, and labels, so the previous list was redundant.
398
+
399
+ - 8285ec0: fix: validate edge output ports against declared node ports at load time
400
+
401
+ Adds `WorkflowEdgePortValidator` to `@codemation/core`. The validator checks that every edge's `from.output` port is declared by the source node's `declaredOutputPorts`; nodes without declared ports are treated as unconstrained (legacy behaviour).
402
+
403
+ The validator is wired into `WorkflowDefinitionExportsResolver` in `@codemation/host`, which is the common chokepoint for both the `CodemationConsumerConfigLoader` and `CodemationConsumerAppResolver` load paths. On violation, all errors are reported at once so an agent can self-correct in a single pass.
404
+
405
+ `WorkflowElkPortInfoResolver` in `@codemation/canvas-core` is tightened to render _exactly_ the declared ports (plus the synthetic `error` port when applicable) when a node has `declaredOutputPorts`, preventing phantom handles from rogue edges on the canvas. Legacy nodes without declared ports continue to infer ports from edges as before.
406
+
407
+ Root cause: an LLM agent created an `If` workflow node (declares `["true", "false"]`) with a rogue edge using `output: "main"`, which the canvas unioned into the port list, producing a phantom third handle.
408
+
409
+ - 8285ec0: Reduce the number of worker processes/threads spawned by the test suite so it doesn't throttle other processes on the developer's machine. Root `turbo.json` concurrency drops 12 → 4 (cross-package parallelism) and every vitest config in `tooling/vitest/*` and `packages/host/*.config.ts` drops `maxWorkers` 2 → 1 with `fileParallelism: false`. Worst-case worker count was 12 × 2 = 24 simultaneous, now 4 × 1 = 4. CI throughput will be lower but local `pnpm test` no longer pegs the box.
410
+ - 8285ec0: Add integration test coverage for managed-auth pipeline (Sprint 13 Story F).
411
+ - `managedAuth.integration.test.ts`: 5 new `/api/me` end-to-end cases (happy path, anonymous, tampered, expired, wrong audience) using a real signed JWT.
412
+ - `managedAuthSqlite.integration.test.ts`: boot regression guard for `auth.kind: "managed"` + sqlite combination (commit 35b8732c fix).
413
+ - `ManagedAuthTestJwks` testkit: reusable test EdDSA keypair + JWKS server helper.
414
+
415
+ - 8285ec0: fix(credentials): require ownership for ?withSecrets=1 (Sprint 14 Story 03)
416
+
417
+ `CredentialHttpRouteHandler.getCredentialInstance` now enforces workspace
418
+ ownership when `?withSecrets=1` is requested. In managed-auth mode a principal
419
+ with a `workspaceId` that differs from the installation's `pairingConfig.workspaceId`
420
+ receives 403 Forbidden. Local-auth mode (no pairingConfig) is unchanged.
421
+
422
+ - 8285ec0: fix(security): fail-closed on null principal for ?withSecrets=1 (Sprint 14.5 fix pass)
423
+
424
+ `CredentialHttpRouteHandler.getCredentialInstance` now returns 403 when the session verifier returns null (unauthenticated request) and `?withSecrets=1` is present, closing the silent pass-through gap that existed in local-auth mode.
425
+
426
+ - 8285ec0: fix(sprint-14.5/storage+ssrf): S3 403-not-as-404 + KIND unknown throw + CGN SSRF block + audit prune interval env (Sprint 14 fix pass)
427
+ - `S3BinaryStorage.isNotFoundError`: remove `statusCode === 403` from not-found check; propagate 403 (misconfiguration) instead of silently treating it as missing.
428
+ - `AppContainerFactory.createBinaryStorage`: throw `Error` for unknown `BINARY_STORAGE_KIND` values (e.g. `"gcs"`) instead of silently falling back to local storage.
429
+ - `WorkflowAuditLogPruneScheduler`: read interval from `CODEMATION_AUDIT_PRUNE_INTERVAL_MS` (dedicated env); fall back to `CODEMATION_RUN_PRUNE_INTERVAL_MS` then static default.
430
+ - `SsrfGuard.isPrivateIPv4`: add `100.64.0.0/10` (Carrier-Grade NAT, RFC 6598) to blocked ranges.
431
+
432
+ - 8285ec0: Remove the `development` export condition from `@codemation/canvas`, `@codemation/core`, and `@codemation/host` package.json exports. Module resolution now consistently uses the built `dist/` regardless of `NODE_ENV`.
433
+
434
+ **Why:** the `development` condition is auto-applied by bundlers (Next.js dev mode, Vite dev, etc.) and was making every cross-repo monorepo consumer fall through to TypeScript source. For the framework's own `@codemation/next-host`, this was fine — turbo's `dev` already runs `tsdown --watch` on these packages so dist is always fresh in dev. For external consumers (notably the managed control plane), it caused multi-hundred-file recursive source compiles on every cold page load.
435
+
436
+ **Impact:** zero behavior change for normal users (they consume published `dist/`). Framework monorepo devs editing canvas/core/host source still see live updates as long as `tsdown --watch` is running for the package — which is what `pnpm dev` (turbo) orchestrates by default. If you're running an app in isolation without the package's watch task, you now need to start it explicitly.
437
+
438
+ - 8285ec0: Make the unit-test suite pass on Windows.
439
+ - `PrismaMigrationDeployer`: read `CODEMATION_PRISMA_CLI_PATH`, `CODEMATION_PRISMA_CONFIG_PATH`, `CODEMATION_HOST_PACKAGE_ROOT` from the `env` argument passed to `deploy(...)`/`deployPersistence(...)` instead of `process.env` at call time. Tests can now pass their CLI path through the deployer's existing `env` parameter rather than mutating shared `process.env`, removing the cross-file env-race that flaked SQLite deployer tests under thread-pool parallelism.
440
+ - `NodeInspectorTelemetryPresenter` + `DashboardCostAmountFormatter`: pin currency formatting to `en-US` with `currencyDisplay: "narrowSymbol"` so Node ICU versions produce `"$0.000039"` rather than `"US$0.000039"`.
441
+ - `DashboardAiUsageSummaryCard`: pin token-count formatting to `en-US` so the dashboard renders `"1,840"` regardless of system locale.
442
+
443
+ Companion test changes (not user-visible): test fixtures pass the test-only env via the deployer's `env` argument, several CLI tests wrap expected paths in `path.resolve(...)` so Windows backslash output matches, `PrismaMigrationDeployer` recovery test moved to its own file (libsql native state from earlier tests in the same file leaked into the recovery flow on Windows), and `vitest.unit.config.ts` switched to the forks pool for libsql native-module isolation across files.
444
+
445
+ - Updated dependencies [8285ec0]
446
+ - Updated dependencies [8285ec0]
447
+ - Updated dependencies [8285ec0]
448
+ - Updated dependencies [8285ec0]
449
+ - Updated dependencies [8285ec0]
450
+ - Updated dependencies [8285ec0]
451
+ - Updated dependencies [8285ec0]
452
+ - Updated dependencies [8285ec0]
453
+ - Updated dependencies [8285ec0]
454
+ - Updated dependencies [8285ec0]
455
+ - Updated dependencies [8285ec0]
456
+ - Updated dependencies [e4d3e1a]
457
+ - Updated dependencies [7b50018]
458
+ - Updated dependencies [8285ec0]
459
+ - Updated dependencies [8285ec0]
460
+ - Updated dependencies [8285ec0]
461
+ - Updated dependencies [8285ec0]
462
+ - Updated dependencies [8285ec0]
463
+ - Updated dependencies [8285ec0]
464
+ - Updated dependencies [e4d3e1a]
465
+ - Updated dependencies [0082ab5]
466
+ - Updated dependencies [8285ec0]
467
+ - Updated dependencies [8285ec0]
468
+ - Updated dependencies [8285ec0]
469
+ - Updated dependencies [8285ec0]
470
+ - Updated dependencies [8285ec0]
471
+ - Updated dependencies [8285ec0]
472
+ - Updated dependencies [8285ec0]
473
+ - Updated dependencies [8285ec0]
474
+ - Updated dependencies [8285ec0]
475
+ - Updated dependencies [8285ec0]
476
+ - Updated dependencies [8285ec0]
477
+ - Updated dependencies [8285ec0]
478
+ - Updated dependencies [8285ec0]
479
+ - Updated dependencies [8285ec0]
480
+ - Updated dependencies [f344d6d]
481
+ - @codemation/core-nodes@0.8.0
482
+ - @codemation/core@0.11.0
483
+ - @codemation/eventbus-redis@0.0.38
484
+ - @codemation/managed-auth@0.1.0
485
+
3
486
  ## 0.6.0
4
487
 
5
488
  ### Minor Changes
@@ -130,15 +130,15 @@ var ApiPaths = class {
130
130
  static credentialBindings() {
131
131
  return `${this.apiBasePath}/credential-bindings`;
132
132
  }
133
- static oauth2Auth(instanceId) {
134
- return `${this.oauth2BasePath}/auth?instanceId=${encodeURIComponent(instanceId)}`;
135
- }
136
133
  static oauth2RedirectUri() {
137
134
  return `${this.oauth2BasePath}/redirect-uri`;
138
135
  }
139
136
  static oauth2Disconnect(instanceId) {
140
137
  return `${this.oauth2BasePath}/disconnect?instanceId=${encodeURIComponent(instanceId)}`;
141
138
  }
139
+ static credentialOAuthStart() {
140
+ return `${this.credentialsBasePath}/oauth/start`;
141
+ }
142
142
  static workflowWebsocket() {
143
143
  return `${this.workflowsBasePath}/ws`;
144
144
  }
@@ -235,4 +235,4 @@ var ApiPaths = class {
235
235
 
236
236
  //#endregion
237
237
  export { InAppCallbackUrlPolicy as n, ApiPaths as t };
238
- //# sourceMappingURL=ApiPaths-CLTHphYZ.js.map
238
+ //# sourceMappingURL=ApiPaths-Dv1dcHu_.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApiPaths-Dv1dcHu_.js","names":[],"sources":["../src/infrastructure/auth/InAppCallbackUrlPolicy.ts","../src/presentation/http/ApiPaths.ts"],"sourcesContent":["/**\n * Restricts post-login navigation targets to same-origin relative paths (no open redirects).\n */\nexport class InAppCallbackUrlPolicy {\n private static readonly fallbackPath = \"/\";\n\n resolveSafeRelativeCallbackUrl(raw: string | undefined | null): string {\n if (raw === undefined || raw === null) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n if (this.containsAsciiControl(raw)) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n const trimmed = raw.trim();\n if (trimmed.length === 0) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n if (!trimmed.startsWith(\"/\")) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n if (trimmed.startsWith(\"//\")) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n if (trimmed.includes(\"\\\\\")) {\n return InAppCallbackUrlPolicy.fallbackPath;\n }\n return trimmed;\n }\n\n private containsAsciiControl(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const code = value.charCodeAt(index);\n if (code <= 0x1f || code === 0x7f) {\n return true;\n }\n }\n return false;\n }\n}\n","export class ApiPaths {\n private static readonly apiBasePath = \"/api\";\n\n private static readonly workflowsBasePath = `${this.apiBasePath}/workflows`;\n\n private static readonly runsBasePath = `${this.apiBasePath}/runs`;\n\n private static readonly credentialsBasePath = `${this.apiBasePath}/credentials`;\n\n private static readonly oauth2BasePath = `${this.apiBasePath}/oauth2`;\n\n private static readonly webhooksBasePath = `${this.apiBasePath}/webhooks`;\n\n private static readonly usersBasePath = `${this.apiBasePath}/users`;\n\n private static readonly telemetryBasePath = `${this.apiBasePath}/telemetry`;\n\n private static readonly whitelabelBasePath = `${this.apiBasePath}/whitelabel`;\n\n private static readonly bootstrapBasePath = `${this.apiBasePath}/bootstrap`;\n\n private static readonly authBasePath = `${this.apiBasePath}/auth`;\n\n private static readonly collectionsBasePath = `${this.apiBasePath}/collections`;\n\n static collections(): string {\n return this.collectionsBasePath;\n }\n\n static collection(name: string): string {\n return `${this.collectionsBasePath}/${encodeURIComponent(name)}`;\n }\n\n static collectionRows(name: string): string {\n return `${this.collection(name)}/rows`;\n }\n\n static collectionRow(name: string, id: string): string {\n return `${this.collectionRows(name)}/${encodeURIComponent(id)}`;\n }\n\n static syncCollections(): string {\n return `${this.collectionsBasePath}/sync`;\n }\n\n static workflows(): string {\n return this.workflowsBasePath;\n }\n\n static workflow(workflowId: string): string {\n return `${this.workflowsBasePath}/${encodeURIComponent(workflowId)}`;\n }\n\n static workflowActivation(workflowId: string): string {\n return `${this.workflow(workflowId)}/activation`;\n }\n\n static workflowRuns(workflowId: string): string {\n return `${this.workflow(workflowId)}/runs`;\n }\n\n static workflowTestSuiteRuns(workflowId: string): string {\n return `${this.workflow(workflowId)}/test-suite-runs`;\n }\n\n /**\n * `GET` returns per-assertion-metric trends across the workflow's recent suite runs. With\n * no `names` arg, every distinct assertion name is returned (so the multi-select can populate);\n * with `names`, only the requested subset is returned (order preserved).\n */\n static workflowAssertionMetricTrends(workflowId: string, names?: ReadonlyArray<string>): string {\n const base = `${this.workflow(workflowId)}/assertion-metric-trends`;\n if (!names || names.length === 0) {\n return base;\n }\n return `${base}?names=${names.map((n) => encodeURIComponent(n)).join(\",\")}`;\n }\n\n static testSuiteRun(testSuiteRunId: string): string {\n return `${this.apiBasePath}/test-suite-runs/${encodeURIComponent(testSuiteRunId)}`;\n }\n\n static testSuiteRunAssertions(testSuiteRunId: string): string {\n return `${this.testSuiteRun(testSuiteRunId)}/assertions`;\n }\n\n static testSuiteRunChildRuns(testSuiteRunId: string): string {\n return `${this.testSuiteRun(testSuiteRunId)}/runs`;\n }\n\n static runAssertions(runId: string): string {\n return `${this.runState(runId)}/assertions`;\n }\n\n static workflowCredentialHealth(workflowId: string): string {\n return `${this.workflow(workflowId)}/credential-health`;\n }\n\n static workflowDebuggerOverlay(workflowId: string): string {\n return `${this.workflow(workflowId)}/debugger-overlay`;\n }\n\n static workflowDebuggerOverlayCopyRun(workflowId: string): string {\n return `${this.workflowDebuggerOverlay(workflowId)}/copy-run`;\n }\n\n static workflowDebuggerOverlayBinaryUpload(workflowId: string): string {\n return `${this.workflowDebuggerOverlay(workflowId)}/binary/upload`;\n }\n\n static workflowOverlayBinaryContent(workflowId: string, binaryId: string): string {\n return `${this.workflow(workflowId)}/debugger-overlay/binary/${encodeURIComponent(binaryId)}/content`;\n }\n\n static runs(): string {\n return this.runsBasePath;\n }\n\n static run(): string {\n return this.runs();\n }\n\n static credentialTypes(): string {\n return `${this.credentialsBasePath}/types`;\n }\n\n static credentialsEnvStatus(): string {\n return `${this.credentialsBasePath}/env-status`;\n }\n\n static credentialInstances(): string {\n return `${this.credentialsBasePath}/instances`;\n }\n\n static credentialInstance(instanceId: string, withSecrets?: boolean): string {\n const base = `${this.credentialInstances()}/${encodeURIComponent(instanceId)}`;\n return withSecrets ? `${base}?withSecrets=1` : base;\n }\n\n static credentialInstanceTest(instanceId: string): string {\n return `${this.credentialInstance(instanceId)}/test`;\n }\n\n static credentialBindings(): string {\n return `${this.apiBasePath}/credential-bindings`;\n }\n\n static oauth2RedirectUri(): string {\n return `${this.oauth2BasePath}/redirect-uri`;\n }\n\n static oauth2Disconnect(instanceId: string): string {\n return `${this.oauth2BasePath}/disconnect?instanceId=${encodeURIComponent(instanceId)}`;\n }\n\n static credentialOAuthStart(): string {\n return `${this.credentialsBasePath}/oauth/start`;\n }\n\n static workflowWebsocket(): string {\n return `${this.workflowsBasePath}/ws`;\n }\n\n /** Dev gateway: stable browser WebSocket for build lifecycle (CLI → gateway → browser). */\n static devGatewaySocket(): string {\n return `${this.apiBasePath}/dev/socket`;\n }\n\n /** Dev gateway: HTTP notify endpoint used by the Codemation CLI during consumer rebuilds. */\n static devGatewayNotify(): string {\n return `${this.apiBasePath}/dev/notify`;\n }\n\n static webhooks(): string {\n return this.webhooksBasePath;\n }\n\n static users(): string {\n return this.usersBasePath;\n }\n\n static telemetryDashboardSummary(): string {\n return `${this.telemetryBasePath}/dashboard/summary`;\n }\n\n static telemetryDashboardTimeseries(): string {\n return `${this.telemetryBasePath}/dashboard/timeseries`;\n }\n\n static telemetryDashboardDimensions(): string {\n return `${this.telemetryBasePath}/dashboard/dimensions`;\n }\n\n static telemetryDashboardRuns(): string {\n return `${this.telemetryBasePath}/dashboard/runs`;\n }\n\n static telemetryRunTrace(runId: string): string {\n return `${this.telemetryBasePath}/runs/${runId}/trace`;\n }\n\n static authSession(): string {\n return `${this.authBasePath}/session`;\n }\n\n static authLogin(): string {\n return `${this.authBasePath}/login`;\n }\n\n static authLogout(): string {\n return `${this.authBasePath}/logout`;\n }\n\n static authOAuthStart(providerId: string, callbackUrl?: string): string {\n const base = `${this.authBasePath}/oauth/${encodeURIComponent(providerId)}/start`;\n if (!callbackUrl) {\n return base;\n }\n return `${base}?callbackUrl=${encodeURIComponent(callbackUrl)}`;\n }\n\n static authOAuthCallback(providerId: string): string {\n return `${this.authBasePath}/oauth/${encodeURIComponent(providerId)}/callback`;\n }\n\n static userInviteVerify(): string {\n return `${this.usersBasePath}/invites/verify`;\n }\n\n static userInviteAccept(): string {\n return `${this.usersBasePath}/invites/accept`;\n }\n\n static userInvites(): string {\n return `${this.usersBasePath}/invites`;\n }\n\n static userInviteRegenerate(userId: string): string {\n return `${this.usersBasePath}/${encodeURIComponent(userId)}/invites/regenerate`;\n }\n\n static userStatus(userId: string): string {\n return `${this.usersBasePath}/${encodeURIComponent(userId)}/status`;\n }\n\n static runState(runId: string): string {\n return `${this.runsBasePath}/${encodeURIComponent(runId)}`;\n }\n\n static runDetail(runId: string): string {\n return `${this.runState(runId)}/detail`;\n }\n\n static runWorkflowSnapshot(runId: string): string {\n return `${this.runState(runId)}/workflow-snapshot`;\n }\n\n static runNodePin(runId: string, nodeId: string): string {\n return `${this.runState(runId)}/nodes/${encodeURIComponent(nodeId)}/pin`;\n }\n\n static runNode(runId: string, nodeId: string): string {\n return `${this.runState(runId)}/nodes/${encodeURIComponent(nodeId)}/run`;\n }\n\n static runBinaryContent(runId: string, binaryId: string): string {\n return `${this.runState(runId)}/binary/${encodeURIComponent(binaryId)}/content`;\n }\n\n /** Anonymous: consumer logo from `codemation.config.ts` whitelabel.logoPath. */\n static whitelabelLogo(): string {\n return `${this.whitelabelBasePath}/logo`;\n }\n\n static frontendBootstrap(): string {\n return `${this.bootstrapBasePath}/frontend`;\n }\n\n static internalAuthBootstrap(): string {\n return `${this.bootstrapBasePath}/auth/internal`;\n }\n}\n"],"mappings":"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"}