@codemation/host 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +465 -0
- package/LICENSE +1 -37
- package/dist/{ApiPaths-CLTHphYZ.js → ApiPaths-Dv1dcHu_.js} +4 -4
- package/dist/ApiPaths-Dv1dcHu_.js.map +1 -0
- package/dist/{AppConfigFactory-CvpFScwB.js → AppConfigFactory-Cx4qQvRk.js} +114 -53
- package/dist/AppConfigFactory-Cx4qQvRk.js.map +1 -0
- package/dist/{AppConfigFactory-LK76niPc.d.ts → AppConfigFactory-DnLoQ9Li.d.ts} +8527 -5549
- package/dist/{AppContainerFactory-BlLrm6_h.js → AppContainerFactory-DqKYCRNP.js} +7656 -2090
- package/dist/AppContainerFactory-DqKYCRNP.js.map +1 -0
- package/dist/{CodemationAppContext-CvWi5gey.d.ts → CodemationAppContext-CKVv9W9q.d.ts} +8 -4
- package/dist/{CodemationAuthoring.types-BuKNTDC1.d.ts → CodemationAuthoring.types-DA3G3s6d.d.ts} +25 -5
- package/dist/{CodemationAuthoring.types-DZl-sJaM.js → CodemationAuthoring.types-NGkBcmmT.js} +18 -6
- package/dist/CodemationAuthoring.types-NGkBcmmT.js.map +1 -0
- package/dist/{CodemationConfigNormalizer-CYdR0PR5.d.ts → CodemationConfigNormalizer-BAKjetJ6.d.ts} +3 -3
- package/dist/{CodemationConsumerConfigLoader-BeAUS144.js → CodemationConsumerConfigLoader-GYpBBvqE.js} +79 -10
- package/dist/CodemationConsumerConfigLoader-GYpBBvqE.js.map +1 -0
- package/dist/{CodemationConsumerConfigLoader-C3nAj9Bj.d.ts → CodemationConsumerConfigLoader-nxOqvv46.d.ts} +17 -2
- package/dist/{CodemationPluginListMerger-B-W5Fa_X.js → CodemationPluginListMerger-D1B1IEbt.js} +1 -1
- package/dist/{CodemationPluginListMerger-B-W5Fa_X.js.map → CodemationPluginListMerger-D1B1IEbt.js.map} +1 -1
- package/dist/{CodemationPluginListMerger-D-gwVwtw.d.ts → CodemationPluginListMerger-DKLAHT2b.d.ts} +123 -16
- package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js +97 -0
- package/dist/CodemationTsyringeTypeInfoRegistrar-Bj6FJYFz.js.map +1 -0
- package/dist/{CodemationWhitelabelConfig-CWbcyQqn.d.ts → CodemationWhitelabelConfig-Ca2mCUeC.d.ts} +2 -2
- package/dist/{CollectionContracts.types-DdpHft0i.d.ts → CollectionContracts.types-DDyFYT_D.d.ts} +1 -1
- package/dist/{CredentialContractsRegistry-D7mcPed2.d.ts → CredentialContractsRegistry-Bq2bq28t.d.ts} +2 -2
- package/dist/{CredentialServices-DdCEP2xt.d.ts → CredentialServices-Be2I60Th.d.ts} +65 -20
- package/dist/{CredentialServices-CgxwguAv.js → CredentialServices-Dk8yypeL.js} +310 -51
- package/dist/CredentialServices-Dk8yypeL.js.map +1 -0
- package/dist/InternalHonoApiRouteRegistrar-Ce1yxpnO.d.ts +17 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js +221 -0
- package/dist/InternalPingRegistrar-DY3kSfxP.js.map +1 -0
- package/dist/{ItemsInputNormalizer-D1WppVMU.d.ts → ItemsInputNormalizer-_RwIfRIQ.d.ts} +108 -25
- package/dist/{LogLevelPolicyFactory-CampWO0l.d.ts → LogLevelPolicyFactory-ewCHLDLn.d.ts} +2 -2
- package/dist/{PublicFrontendBootstrap-DzBgwOnG.d.ts → PublicFrontendBootstrap-Cev3qK46.d.ts} +9 -2
- package/dist/PublicFrontendBootstrapFactory-CY2FS-5g.d.ts +82 -0
- package/dist/{PublicFrontendBootstrapJsonCodec-Cl_DLRh0.d.ts → PublicFrontendBootstrapJsonCodec-CXG9Dxft.d.ts} +3 -3
- package/dist/{PublicFrontendBootstrapJsonCodec-DzqvA0uo.js → PublicFrontendBootstrapJsonCodec-CegIF_ne.js} +7 -2
- package/dist/PublicFrontendBootstrapJsonCodec-CegIF_ne.js.map +1 -0
- package/dist/ServerLoggerFactory-Ckk52S3w.js +223 -0
- package/dist/ServerLoggerFactory-Ckk52S3w.js.map +1 -0
- package/dist/{TelemetryContracts-BsOD_Y17.d.ts → TelemetryContracts-BtDx84Cp.d.ts} +13 -4
- package/dist/{WorkflowPolicyUiPresentationFactory-DNE5oAI6.d.ts → WorkflowPolicyUiPresentationFactory-6MyjCvBO.d.ts} +2 -2
- package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js} +1 -1
- package/dist/{WorkflowPolicyUiPresentationFactory-DhPqQ9aB.js.map → WorkflowPolicyUiPresentationFactory-Bb-ae_Zh.js.map} +1 -1
- package/dist/{WorkflowViewContracts-0ZgsHQdp.d.ts → WorkflowViewContracts-B7aFQcIw.d.ts} +15 -1
- package/dist/authoring.d.ts +5 -5
- package/dist/authoring.js +1 -1
- package/dist/client.d.ts +4 -4
- package/dist/client.js +2 -2
- package/dist/consumer.d.ts +6 -6
- package/dist/consumer.js +2 -2
- package/dist/credentials.d.ts +6 -6
- package/dist/credentials.js +1 -1
- package/dist/devServerSidecar.d.ts +2 -2
- package/dist/devServerSidecar.js +1 -94
- package/dist/devServerSidecar.js.map +1 -1
- package/dist/dto.d.ts +6 -6
- package/dist/{index-BlGs9e9Q.d.ts → index-DilAYwnH.d.ts} +49 -3
- package/dist/index.d.ts +110 -21
- package/dist/index.js +15 -13
- package/dist/mapping.d.ts +2 -2
- package/dist/mapping.js +1 -1
- package/dist/nextServer.d.ts +43 -88
- package/dist/nextServer.js +9 -7
- package/dist/pairing.d.ts +93 -0
- package/dist/pairing.js +5 -0
- package/dist/pairing.types-snfZ_OzB.d.ts +19 -0
- package/dist/{persistenceServer-CpNFYa_q.js → persistenceServer-C-hH4z6l.js} +2 -2
- package/dist/{persistenceServer-CpNFYa_q.js.map → persistenceServer-C-hH4z6l.js.map} +1 -1
- package/dist/persistenceServer-CeTHtC6E.d.ts +30 -0
- package/dist/persistenceServer.d.ts +8 -8
- package/dist/persistenceServer.js +3 -3
- package/dist/{server-CQWdkT7t.d.ts → server-C4bS62rg.d.ts} +21 -6
- package/dist/{server-BK43OKxW.js → server-Y7kxwtCK.js} +7 -6
- package/dist/{server-BK43OKxW.js.map → server-Y7kxwtCK.js.map} +1 -1
- package/dist/server.d.ts +14 -14
- package/dist/server.js +13 -11
- package/package.json +29 -42
- package/prisma/migrations/20260507120000_execution_instance_child_run_id/migration.sql +5 -0
- package/prisma/migrations/20260519000000_workflow_audit_log/migration.sql +23 -0
- package/prisma/migrations/20260519100000_storage_growth_fixes/migration.sql +61 -0
- package/prisma/migrations.sqlite/20260507120000_execution_instance_child_run_id/migration.sql +5 -0
- package/prisma/migrations.sqlite/20260519000000_workflow_audit_log/migration.sql +21 -0
- package/prisma/migrations.sqlite/20260519100000_storage_growth_fixes/migration.sql +29 -0
- package/prisma/schema.postgresql.prisma +56 -17
- package/prisma/schema.sqlite.prisma +56 -17
- package/prisma-generated/prisma-postgresql-client/edge.js +35 -6
- package/prisma-generated/prisma-postgresql-client/index-browser.js +31 -2
- package/prisma-generated/prisma-postgresql-client/index.d.ts +8971 -5718
- package/prisma-generated/prisma-postgresql-client/index.js +35 -6
- package/prisma-generated/prisma-postgresql-client/package.json +1 -1
- package/prisma-generated/prisma-postgresql-client/schema.prisma +39 -0
- package/prisma-generated/prisma-sqlite-client/edge.js +35 -6
- package/prisma-generated/prisma-sqlite-client/index-browser.js +31 -2
- package/prisma-generated/prisma-sqlite-client/index.d.ts +8963 -5715
- package/prisma-generated/prisma-sqlite-client/index.js +35 -6
- package/prisma-generated/prisma-sqlite-client/package.json +1 -1
- package/prisma-generated/prisma-sqlite-client/schema.prisma +39 -0
- package/scripts/check-collections.mjs +18 -0
- package/scripts/generate-prisma-clients.mjs +20 -11
- package/src/application/WorkflowAuditLogPruneScheduler.ts +96 -0
- package/src/application/auth/AuthenticatedPrincipal.ts +4 -0
- package/src/application/commands/StartWorkflowRunCommandHandler.ts +4 -0
- package/src/application/contracts/WorkflowViewContracts.ts +11 -0
- package/src/application/contracts/WorkflowWebsocketMessage.ts +3 -1
- package/src/application/mapping/WorkflowDefinitionMapper.ts +44 -1
- package/src/application/runs/WorkflowRunRetentionPruneScheduler.ts +7 -1
- package/src/application/telemetry/OtelExecutionTelemetry.types.ts +5 -0
- package/src/application/telemetry/OtelExecutionTelemetryFactory.ts +4 -0
- package/src/application/telemetry/StoredTelemetrySpanScope.ts +6 -2
- package/src/application/telemetry/TelemetryRetentionTimestampFactory.ts +27 -17
- package/src/application/telemetry/TelemetrySpanPublisher.ts +11 -0
- package/src/application/websocket/TelemetrySpanWebsocketRelay.ts +31 -0
- package/src/applicationTokens.ts +20 -1
- package/src/audit/IAuditEmitter.ts +32 -0
- package/src/audit/PrismaWorkflowAuditLogRepository.ts +34 -0
- package/src/audit/WorkflowAuditLogWriter.ts +125 -0
- package/src/auth/managed/ManagedAuthConfig.ts +29 -0
- package/src/auth/managed/ManagedAuthMiddleware.ts +52 -0
- package/src/auth/managed/ManagedCorsMiddleware.ts +43 -0
- package/src/auth/managed/ManagedModeBootGuard.ts +27 -0
- package/src/auth/managed/index.ts +5 -0
- package/src/bootstrap/AppContainerFactory.ts +277 -29
- package/src/bootstrap/AppContainerLifecycle.ts +31 -0
- package/src/bootstrap/perf/BootTimer.ts +168 -0
- package/src/bootstrap/runtime/AppConfigFactory.ts +21 -65
- package/src/bootstrap/runtime/FrontendRuntime.ts +4 -1
- package/src/bootstrap/runtime/WorkerRuntime.ts +2 -1
- package/src/credentials/BrokerClient.ts +49 -0
- package/src/credentials/BrokerRefreshError.ts +12 -0
- package/src/credentials/BrokerRefreshInvalidGrantError.ts +13 -0
- package/src/credentials/ControlPlaneCatalogFetcher.ts +261 -0
- package/src/credentials/CredentialOAuth2MaterialReader.ts +136 -0
- package/src/credentials/InternalCredentialsListRegistrar.ts +48 -0
- package/src/credentials/InternalCredentialsPushRegistrar.ts +125 -0
- package/src/credentials/LocalOAuthFlowExecutor.ts +316 -0
- package/src/credentials/ManagedOAuthFlowExecutor.ts +94 -0
- package/src/credentials/ManagedOAuthRefreshInvalidGrantError.ts +13 -0
- package/src/credentials/catalogTypes.ts +4 -0
- package/src/credentials/refresh/CredentialDisconnectedError.ts +11 -0
- package/src/domain/credentials/CredentialBindingService.ts +54 -2
- package/src/domain/credentials/CredentialKeyRotatedError.ts +22 -0
- package/src/domain/credentials/CredentialSecretCipher.ts +68 -6
- package/src/domain/credentials/CredentialTypeRegistryImpl.ts +117 -10
- package/src/domain/credentials/OAuth2RedirectUriResolver.ts +79 -0
- package/src/domain/credentials/WorkflowCredentialNodeResolver.ts +14 -5
- package/src/domain/telemetry/TelemetryContracts.ts +7 -1
- package/src/domain/workflows/WorkflowActivationPreflight.ts +24 -1
- package/src/domain/workflows/WorkflowActivationPreflightRules.ts +40 -1
- package/src/index.ts +6 -0
- package/src/infrastructure/binary/LocalFilesystemBinaryStorageRegistry.ts +29 -1
- package/src/infrastructure/binary/S3BinaryStorage.ts +169 -0
- package/src/infrastructure/binary/S3BinaryStorageConfig.ts +17 -0
- package/src/infrastructure/config/CodemationPluginRegistrar.ts +3 -1
- package/src/infrastructure/persistence/CodemationDatabaseUrlParser.ts +41 -0
- package/src/infrastructure/persistence/InMemoryTelemetryArtifactStore.ts +8 -3
- package/src/infrastructure/persistence/InMemoryWorkflowRunRepository.ts +1 -0
- package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +21 -13
- package/src/infrastructure/persistence/PrismaTelemetryArtifactStore.ts +43 -8
- package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +33 -3
- package/src/infrastructure/persistence/PrismaWorkflowSnapshotRepository.ts +48 -0
- package/src/mcp/AgentMcpIntegrationImpl.ts +344 -0
- package/src/mcp/McpClientFactory.ts +29 -0
- package/src/mcp/McpConnectionPool.ts +184 -0
- package/src/mcp/McpConnectionPool.types.ts +12 -0
- package/src/mcp/McpServerCatalog.ts +104 -0
- package/src/mcp/index.ts +5 -0
- package/src/pairing/HmacRequestSigner.ts +32 -0
- package/src/pairing/IncomingHmacVerifier.ts +82 -0
- package/src/pairing/InternalHmacAuthMiddleware.ts +33 -0
- package/src/pairing/InternalPingRegistrar.ts +25 -0
- package/src/pairing/PairedFetch.ts +33 -0
- package/src/pairing/PairingConfigFactory.ts +35 -0
- package/src/pairing/PairingConfigToken.ts +6 -0
- package/src/pairing/index.ts +14 -0
- package/src/pairing/pairing.types.ts +18 -0
- package/src/pairing.ts +17 -0
- package/src/persistenceServer.ts +1 -0
- package/src/presentation/config/AppConfig.ts +7 -1
- package/src/presentation/config/CodemationAuthConfig.ts +1 -1
- package/src/presentation/config/CodemationAuthoring.types.ts +54 -5
- package/src/presentation/config/CodemationConfig.ts +3 -0
- package/src/presentation/config/CodemationConfigNormalizer.ts +39 -1
- package/src/presentation/config/CodemationPlugin.ts +2 -1
- package/src/presentation/frontend/CodemationFrontendAuthSnapshot.ts +5 -0
- package/src/presentation/frontend/CodemationFrontendAuthSnapshotFactory.ts +7 -1
- package/src/presentation/frontend/PublicFrontendBootstrap.ts +2 -0
- package/src/presentation/frontend/PublicFrontendBootstrapFactory.ts +5 -1
- package/src/presentation/frontend/PublicFrontendBootstrapJsonCodec.ts +4 -1
- package/src/presentation/http/ApiPaths.ts +4 -4
- package/src/presentation/http/ServerHttpErrorResponseFactory.ts +39 -2
- package/src/presentation/http/hono/CodemationHonoApiAppFactory.ts +33 -8
- package/src/presentation/http/hono/InternalHonoApiRouteRegistrar.ts +12 -0
- package/src/presentation/http/hono/registrars/ManagedMeHonoApiRouteRegistrar.ts +35 -0
- package/src/presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar.ts +2 -2
- package/src/presentation/http/routeHandlers/CredentialHttpRouteHandler.ts +28 -0
- package/src/presentation/http/routeHandlers/OAuth2HttpRouteHandlerFactory.ts +98 -41
- package/src/presentation/server/CodemationConsumerConfigLoader.ts +54 -7
- package/src/presentation/server/CodemationPluginDiscovery.ts +5 -0
- package/src/presentation/server/WorkflowDefinitionExportsResolver.ts +18 -0
- package/src/presentation/server/WorkflowModulePathFinder.ts +12 -1
- package/src/presentation/websocket/ManagedWebsocketAuthenticator.ts +50 -0
- package/src/presentation/websocket/WebsocketAuthenticator.types.ts +12 -0
- package/src/presentation/websocket/WorkflowWebsocketServer.ts +24 -3
- package/src/process/ExecaProcessRunner.ts +41 -0
- package/src/process/ProcessRunner.types.ts +39 -0
- package/src/server.ts +2 -0
- package/src/workflows/InternalWorkflowActivationRegistrar.ts +42 -0
- package/src/workflows/InternalWorkflowDetailRegistrar.ts +33 -0
- package/src/workflows/InternalWorkflowTestRunRegistrar.ts +91 -0
- package/src/workflows/InternalWorkflowsListRegistrar.ts +28 -0
- package/src/workflows/discovery/WorkflowDirectoryDiscoverer.ts +79 -0
- package/tsconfig.json +2 -0
- package/vitest.shared.ts +5 -0
- package/dist/ApiPaths-CLTHphYZ.js.map +0 -1
- package/dist/AppConfigFactory-CvpFScwB.js.map +0 -1
- package/dist/AppContainerFactory-BlLrm6_h.js.map +0 -1
- package/dist/CodemationAuthoring.types-DZl-sJaM.js.map +0 -1
- package/dist/CodemationConsumerConfigLoader-BeAUS144.js.map +0 -1
- package/dist/CredentialServices-CgxwguAv.js.map +0 -1
- package/dist/PublicFrontendBootstrapFactory-BMWqNM9a.d.ts +0 -45
- package/dist/PublicFrontendBootstrapJsonCodec-DzqvA0uo.js.map +0 -1
- package/dist/ServerLoggerFactory-BKSIh9Xv.js +0 -98
- package/dist/ServerLoggerFactory-BKSIh9Xv.js.map +0 -1
- package/dist/persistenceServer-CIVt3UOX.d.ts +0 -9
- package/src/domain/credentials/OAuth2ConnectServiceFactory.ts +0 -411
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,470 @@
|
|
|
1
1
|
# @codemation/host
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 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.
|
|
8
|
+
- 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.
|
|
9
|
+
- 8285ec0: Add credential dialog Create-then-Connect flow for OAuth2 credential types.
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
- 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.
|
|
16
|
+
|
|
17
|
+
`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.
|
|
18
|
+
|
|
19
|
+
`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.
|
|
20
|
+
|
|
21
|
+
- 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.
|
|
22
|
+
- 8285ec0: feat(host/audit): workflow audit retention + tier-gated emission (Sprint 14 Story 06)
|
|
23
|
+
- WorkflowAuditLogPruneScheduler: deletes WorkflowAuditLog rows older than 90 days (CODEMATION_AUDIT_WORKFLOW_RETENTION_SECONDS override)
|
|
24
|
+
- TelemetryRetentionTimestampFactory: hard-coded defaults (span 7d, artifact 3d, metric 30d) so telemetry retention works out-of-box with no env vars required
|
|
25
|
+
|
|
26
|
+
- 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.
|
|
27
|
+
- 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.
|
|
28
|
+
- 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.
|
|
29
|
+
- 8285ec0: feat(host/audit): RunEvent-driven WorkflowAuditLog persistence (Sprint 13 Story B)
|
|
30
|
+
|
|
31
|
+
Adds a workspace-local audit trail that captures run-events as queryable rows.
|
|
32
|
+
- `WorkflowAuditLog` Prisma model with indexes on `(actor_user_id, occurred_at)` and `(workflow_id, occurred_at)`
|
|
33
|
+
- `WorkflowAuditLogWriter` subscribes to `RunEventBus` and persists `nodeCompleted`, `nodeFailed`, `runSaved` (terminal), and `connectionInvocationStarted` events
|
|
34
|
+
- `PrismaWorkflowAuditLogRepository` implements `IWorkflowAuditEmitter` using the workspace Prisma client
|
|
35
|
+
- Emission is best-effort: errors are logged and swallowed so workflow execution is never blocked
|
|
36
|
+
- Only active when `persistence.kind !== "none"`
|
|
37
|
+
|
|
38
|
+
- 8285ec0: Add WebSocket JWT authentication for managed mode.
|
|
39
|
+
|
|
40
|
+
In `auth.kind: "managed"` mode the workspace WebSocket server now requires a CP-signed JWT
|
|
41
|
+
passed as `?token=<jwt>` in the upgrade URL. Connections with a missing, expired, wrong-audience,
|
|
42
|
+
or otherwise invalid token are closed immediately with code 4401 ("unauthorized"). Self-hosted
|
|
43
|
+
mode behavior is unchanged.
|
|
44
|
+
|
|
45
|
+
New exports: `WebsocketAuthenticator` interface (types), `ManagedWebsocketAuthenticator` class.
|
|
46
|
+
The `JwksCache` instance is shared between the HTTP JWT verifier and the WS authenticator so
|
|
47
|
+
key rotation propagates to both transports without a restart.
|
|
48
|
+
|
|
49
|
+
- 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.
|
|
50
|
+
- 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"`.
|
|
51
|
+
- 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.
|
|
52
|
+
- 8285ec0: Add McpConnectionPool — lazy, keyed MCP client pool for managed HTTP connections.
|
|
53
|
+
|
|
54
|
+
Pools `experimental_createMCPClient` connections keyed by `(credentialInstanceId, serverId)`.
|
|
55
|
+
Reads bearer tokens fresh from the OAuth2-via-broker credential session at open time.
|
|
56
|
+
Caches `tools/list` results per entry and applies `toolDescriptionOverrides` from the catalog declaration.
|
|
57
|
+
Supports `closeForCredential` (revocation) and `closeAll` (host shutdown).
|
|
58
|
+
|
|
59
|
+
- 8285ec0: Remove the MCP credential bypass on AI agents. `AIAgent.mcpServers` is now a plain
|
|
60
|
+
`ReadonlyArray<string>` of server ids — the inline `{ credential }` field is gone. Each
|
|
61
|
+
declared server surfaces a standard credential slot on the agent node (key
|
|
62
|
+
`mcp:<serverId>`, label and accepted types from the MCP catalog) and binds through the
|
|
63
|
+
same `CredentialBinding` table as every other slot. At execute time the host resolves the
|
|
64
|
+
binding via `getBinding({ workflowId, agentNodeId, slotKey: mcp:<serverId> })`, then opens
|
|
65
|
+
the MCP pool with the resolved credential instance — no more reading the credential id
|
|
66
|
+
out of the workflow config.
|
|
67
|
+
|
|
68
|
+
Breaking — config shape change. Replace:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
mcpServers: {
|
|
72
|
+
gmail: {
|
|
73
|
+
credential: "<instanceId>";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
with:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
mcpServers: ["gmail"];
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then bind the credential through the canvas credential dropdown before activating the
|
|
85
|
+
workflow, the same way trigger credentials are bound. The `McpServerBindings` /
|
|
86
|
+
`McpServerExplicitBinding` types are removed from `@codemation/core`;
|
|
87
|
+
`AgentMcpIntegration.prepareMcpTools` now takes `{ workflowId, agentNodeId, serverIds }`.
|
|
88
|
+
|
|
89
|
+
- 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.
|
|
90
|
+
- 8285ec0: Add `McpServerDeclaration` type and `McpServerCatalog` service (Story 7).
|
|
91
|
+
- `@codemation/core` exports `McpServerDeclaration` and `McpServerTransport` from `packages/core/src/contracts/mcpTypes.ts`.
|
|
92
|
+
- `CodemationPlugin` gains an optional `mcpServers?: ReadonlyArray<McpServerDeclaration>` field.
|
|
93
|
+
- `CodemationConfig` gains an optional `mcpServers?: ReadonlyArray<McpServerDeclaration>` field (also threaded through `AppConfig` and `DefineCodemationAppOptions`).
|
|
94
|
+
- `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).
|
|
95
|
+
- `CodemationPluginDiscovery.isPluginConfig` now recognises `mcpServers`-only plugins.
|
|
96
|
+
- Plugin registrar and app container factory wire catalog merge on startup.
|
|
97
|
+
|
|
98
|
+
- 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).
|
|
99
|
+
- 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.
|
|
100
|
+
- 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.
|
|
101
|
+
- 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.
|
|
102
|
+
- 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.
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
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.
|
|
107
|
+
|
|
108
|
+
- 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.
|
|
109
|
+
- 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.
|
|
110
|
+
- 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.
|
|
111
|
+
- 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.
|
|
112
|
+
- 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`.
|
|
113
|
+
- 8285ec0: feat(host/binary): S3BinaryStorage implementation + boot connectivity check (Sprint 15 Story 03)
|
|
114
|
+
|
|
115
|
+
Adds `S3BinaryStorage` — a Scaleway-compatible S3 implementation of `BinaryStorage` using
|
|
116
|
+
`@aws-sdk/client-s3` + `@aws-sdk/lib-storage` (multipart for large payloads). Key scheme:
|
|
117
|
+
`<workspaceId>/<runId>/<binaryId>`.
|
|
118
|
+
|
|
119
|
+
Runtime selection is controlled by `BINARY_STORAGE_KIND` env var (`"local"` default | `"s3"`).
|
|
120
|
+
When `"s3"`, all `BINARY_STORAGE_S3_*` vars are required and validated at boot. A `HeadBucket`
|
|
121
|
+
connectivity check fails loudly on startup if the bucket is unreachable.
|
|
122
|
+
|
|
123
|
+
Extends `BinaryStorage` interface (core) with `deleteMany(keys)` and `listByPrefix(prefix)` for
|
|
124
|
+
bulk-delete (1000-key S3 batching) and workspace-prefix enumeration (GDPR erasure). All existing
|
|
125
|
+
implementations (`InMemoryBinaryStorage`, `LocalFilesystemBinaryStorage`, `UnavailableBinaryStorage`)
|
|
126
|
+
updated with correct implementations.
|
|
127
|
+
|
|
128
|
+
- 8285ec0: fix(security): engine activation budget + retry ceiling + SSRF allowlist + HKDF cipher + pairing entropy (Sprint 14 Story 09)
|
|
129
|
+
|
|
130
|
+
**Engine / retry fixes (already implemented in Sprint 13/14 — tests added here):**
|
|
131
|
+
- `RunContinuationService` uses `EngineExecutionLimitsPolicy.defaultMaxNodeActivations` (100,000) as the fallback, not `Number.MAX_SAFE_INTEGER`.
|
|
132
|
+
- `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.
|
|
133
|
+
|
|
134
|
+
**SSRF allowlist (`@codemation/core-nodes`):**
|
|
135
|
+
- 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.
|
|
136
|
+
- `HttpRequestExecutor` now accepts `SsrfGuard` as an injected collaborator (4th constructor arg). All composition roots updated.
|
|
137
|
+
- `HttpRequestSpec.allowPrivateNetworkTargets` opt-in flag allows trusted workflows to bypass SSRF protection.
|
|
138
|
+
- New `SSRFBlockedError` class with `resolvedIp` field for structured error handling.
|
|
139
|
+
|
|
140
|
+
**HKDF cipher key derivation (`@codemation/host`) — BACKWARDS-INCOMPATIBLE:**
|
|
141
|
+
- `CredentialSecretCipher` switches from raw SHA-256 to HKDF-SHA-256 for AES key derivation.
|
|
142
|
+
- HKDF salt: `"codemation/credential-cipher/v1"`, info: `"aes-256-gcm-key"`.
|
|
143
|
+
- Input (`CODEMATION_CREDENTIALS_MASTER_KEY`) must now be a base64-encoded 32-byte value.
|
|
144
|
+
- New `schemaVersion: 2` for all new encryptions. Existing `schemaVersion: 1` records can still be decrypted (v1 SHA-256 read-path retained for migration).
|
|
145
|
+
- **Migration**: Re-bind affected credentials in the UI (which re-encrypts with the new HKDF key).
|
|
146
|
+
- See migration guide below.
|
|
147
|
+
|
|
148
|
+
**Pairing secret entropy validation (`@codemation/host`):**
|
|
149
|
+
- `PairingConfigFactory` now throws at boot when `WORKSPACE_PAIRING_SECRET` is present but does not decode to exactly 32 bytes from base64.
|
|
150
|
+
- Error message includes `openssl rand -base64 32` hint for generating a valid secret.
|
|
151
|
+
|
|
152
|
+
***
|
|
153
|
+
|
|
154
|
+
### Migration guide — CODEMATION_CREDENTIALS_MASTER_KEY
|
|
155
|
+
|
|
156
|
+
**Who is affected:** Any deployment that has `CODEMATION_CREDENTIALS_MASTER_KEY` set and has encrypted credentials stored in the database.
|
|
157
|
+
|
|
158
|
+
**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.
|
|
159
|
+
|
|
160
|
+
**Migration steps:**
|
|
161
|
+
1. Generate a new 32-byte key: `openssl rand -base64 32`
|
|
162
|
+
2. Set `CODEMATION_CREDENTIALS_MASTER_KEY` to this new value.
|
|
163
|
+
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`.
|
|
164
|
+
4. Credentials not yet re-bound will throw `CredentialKeyRotatedError` when accessed — the existing key-rotation error handling applies.
|
|
165
|
+
|
|
166
|
+
**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.
|
|
167
|
+
|
|
168
|
+
- 8285ec0: Add `@codemation/managed-auth` package and `auth.kind: "managed"` support in `@codemation/host`.
|
|
169
|
+
|
|
170
|
+
`@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.
|
|
171
|
+
|
|
172
|
+
`@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.
|
|
173
|
+
|
|
174
|
+
- 8285ec0: feat(story-11): Wire MCP catalog into agent — explicit and shorthand binding, scope validation, pool integration, telemetry, and runtime 403 detection
|
|
175
|
+
- `@codemation/core`: `AgentMcpIntegration` interface + token, `McpServerBindings` types, `NeedsReconsentEvent`, `AgentBindError`, `NoOpAgentMcpIntegration` fallback, `CodemationTelemetryAttributeNames.mcpServerId/mcpToolName`
|
|
176
|
+
- `@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
|
|
177
|
+
- `@codemation/host`: `AgentMcpIntegrationImpl` — resolves bindings, validates scopes, opens pool, wraps tool execute with telemetry spans and 403/permission error detection
|
|
178
|
+
|
|
179
|
+
- 8285ec0: Add `managed` scaffold template and workflow auto-discovery config fields
|
|
180
|
+
- New `create-codemation` template `managed` — pre-configured for managed mode with PostgreSQL, CP-JWT auth, and workflow auto-discovery from `./src/workflows`.
|
|
181
|
+
- `defineCodemationApp` now accepts `workflowsDir` (maps to `workflowDiscovery.directories`), `database.urlEnv`, `execution.modeEnv`, and `execution.redisUrlEnv` for env-resolved config values.
|
|
182
|
+
- `CodemationConfigNormalizer` enforces managed-mode invariants: PostgreSQL required, at least one workflow source required.
|
|
183
|
+
- New `WorkflowDirectoryDiscoverer` class for walking a directory and collecting exported workflows with test-file exclusion.
|
|
184
|
+
- `WorkflowModulePathFinder` now excludes `*.test.*` and `*.spec.*` files from discovery.
|
|
185
|
+
|
|
186
|
+
- 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.
|
|
187
|
+
- 51b728d: Stream telemetry spans over WebSocket transport, eliminating HTTP polling.
|
|
188
|
+
|
|
189
|
+
**Backend (@codemation/host):**
|
|
190
|
+
- Added `TelemetrySpanPublisher` interface + `NoOpTelemetrySpanPublisher` default.
|
|
191
|
+
- Added `telemetryEvent` variant to `WorkflowWebsocketMessage` carrying `TelemetrySpanUpsert`.
|
|
192
|
+
- New `TelemetrySpanWebsocketRelay` class publishes each span upsert to a per-run room (`run:<runId>`) after it is committed to persistent storage.
|
|
193
|
+
- `OtelExecutionTelemetryFactory` injects `TelemetrySpanPublisher` (defaults to no-op when unregistered).
|
|
194
|
+
- `StoredTelemetrySpanScope.upsert()` calls the publisher after the span store write so reconnect HTTP catch-up and WS pushes are consistent.
|
|
195
|
+
|
|
196
|
+
**Frontend (@codemation/next-host):**
|
|
197
|
+
- `useWorkflowRealtimeInfrastructure` handles `kind: "telemetryEvent"` messages via `applyTelemetrySpanEvent`, which merges spans into the `telemetry-run-trace` query cache by `spanId` (deduped, sorted by `startTime`).
|
|
198
|
+
- New `retainRunSubscription` API manages per-run WS room subscribe/unsubscribe with reference counting.
|
|
199
|
+
- Auto-unsubscribe from run rooms when the tab is hidden for ≥ 5 minutes (Page Visibility API); re-subscribes on tab return.
|
|
200
|
+
- `useTelemetryRunTraceQuery` drops HTTP polling (`refetchInterval: false`); refetches once on WS reconnect for catch-up.
|
|
201
|
+
- `resolveTelemetryTraceRefetchIntervalMs` is now a no-op (always returns `false`) — retained for call-site compatibility.
|
|
202
|
+
|
|
203
|
+
### Patch Changes
|
|
204
|
+
|
|
205
|
+
- 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.
|
|
206
|
+
- 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.
|
|
207
|
+
|
|
208
|
+
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.
|
|
209
|
+
|
|
210
|
+
- 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.
|
|
211
|
+
|
|
212
|
+
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.
|
|
213
|
+
|
|
214
|
+
- 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"`.
|
|
215
|
+
|
|
216
|
+
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.
|
|
217
|
+
|
|
218
|
+
`statusLabel` (the running-only sentence rendered on the canvas card sub-line) is unchanged; `subjectName` is the persistent structural sibling used by the inspector.
|
|
219
|
+
|
|
220
|
+
- 8285ec0: Coverage Phase 2: testkits (LoggerTestKit, McpTestKit, CoreNodesTestContextFactory,
|
|
221
|
+
TelemetryTestKit, GmailTestKit, AppConfigFixturesFactory, HookTestkit), per-package
|
|
222
|
+
vitest coverage thresholds, and new tests on previously zero-coverage critical paths
|
|
223
|
+
(mergeNode, switchNode, waitNode, connectionCredentialNode, canvas-lib pure, hook smoke).
|
|
224
|
+
No production code changes.
|
|
225
|
+
- e4d3e1a: perf(host): reject workflow runs immediately when required credential slots are unbound
|
|
226
|
+
|
|
227
|
+
`StartWorkflowRunCommandHandler` now calls
|
|
228
|
+
`CredentialBindingService.assertRequiredCredentialsBound` before queuing any
|
|
229
|
+
node activations. The check does a single DB query (all bindings for the
|
|
230
|
+
workflow) and walks every slot including deeply-nested ones in AI agent nodes
|
|
231
|
+
(language model, node-backed tools, nested agents) via
|
|
232
|
+
`WorkflowCredentialNodeResolver.listSlots`. If any required slot has no
|
|
233
|
+
binding the request fails with a 400 before the run record is created, so the
|
|
234
|
+
user sees a clear error message instead of waiting for the run to start and
|
|
235
|
+
then fail several seconds later.
|
|
236
|
+
|
|
237
|
+
- 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.
|
|
238
|
+
- 8285ec0: fix(host/http): generic 500 error envelope + ManagedMeHonoApi error boundary (Sprint 14 Story 08)
|
|
239
|
+
- `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).
|
|
240
|
+
- `ManagedMeHonoApiRouteRegistrar.register` wraps `sessionVerifier.verify()` in try/catch; a thrown JWT verification error now returns 401 instead of propagating as an unhandled 500.
|
|
241
|
+
- 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.
|
|
242
|
+
|
|
243
|
+
- 8285ec0: test(host/persistence): cascade-on-delete integration tests (Sprint 13 Story C)
|
|
244
|
+
|
|
245
|
+
Adds `cascadeOnDelete.integration.test.ts` covering all 8 `onDelete: Cascade`
|
|
246
|
+
relationships declared in `schema.postgresql.prisma`. Each test creates a parent
|
|
247
|
+
row and N child rows, deletes the parent, and asserts the child count drops to 0.
|
|
248
|
+
|
|
249
|
+
Relationships tested:
|
|
250
|
+
- `RunWorkItem → Run`
|
|
251
|
+
- `ExecutionInstance → Run`
|
|
252
|
+
- `RunSlotProjection → Run`
|
|
253
|
+
- `TestAssertion → Run`
|
|
254
|
+
- `TestAssertion → TestSuiteRun`
|
|
255
|
+
- `UserInvite → User`
|
|
256
|
+
- `Account → User`
|
|
257
|
+
- `Session → User`
|
|
258
|
+
|
|
259
|
+
Gaps noted (no cascade declared in schema, no schema changes made):
|
|
260
|
+
- `Credential*` tables (CredentialSecretMaterial, CredentialOAuth2Material, etc.)
|
|
261
|
+
share `instanceId` with `CredentialInstance` but have no `@relation onDelete:
|
|
262
|
+
Cascade`. GDPR right-to-erasure risk.
|
|
263
|
+
- No `Workspace` model exists in `schema.postgresql.prisma`.
|
|
264
|
+
|
|
265
|
+
- 8285ec0: test(host): increase unit test coverage to ≥90% (Sprint 14 Story 13)
|
|
266
|
+
|
|
267
|
+
Adds 30+ new unit test files and extensions covering previously untested logic in
|
|
268
|
+
`@codemation/host`. New test suites include:
|
|
269
|
+
- `InMemoryCredentialStore` — full CRUD + OAuth2 state/material lifecycle
|
|
270
|
+
- `CredentialSessionServiceImpl` — getSession, createSessionForInstance, evict\*
|
|
271
|
+
- `SetPinnedNodeInputCommandHandler` — 404/403/decode/null-items paths
|
|
272
|
+
- `ReplaceMutableRunWorkflowSnapshotCommandHandler` — 400/404/403/success
|
|
273
|
+
- `ReplayWorkflowNodeCommandHandler` — 404/403/workflow-not-found/decode/mode
|
|
274
|
+
- `GetWorkflowRunDetailQueryHandler` — undefined detail, empty rollups, cost join
|
|
275
|
+
- `WorkflowRunRetentionPruneScheduler` (extended) — both-disabled early return, listRuns fallback, binary storage key fallback, artifact storage key deletion
|
|
276
|
+
- `WorkflowAuditLogPruneScheduler` — disabled, custom retention, delete path
|
|
277
|
+
- `ManagedCorsMiddleware` — preflight allow/deny, non-preflight with/without CORS headers
|
|
278
|
+
- `InMemoryDomainEventBus` — publish routing, metadata error, empty handlers
|
|
279
|
+
- `WorkflowRunRepository` wrapper — load/save/listRuns/deleteRun with URL decoding
|
|
280
|
+
- `ApiPaths` — all static path methods
|
|
281
|
+
- `CodemationConfigNormalizer` — register callback, managed-mode constraints, DefinedCollection unwrapping
|
|
282
|
+
- `LocalFilesystemBinaryStorage` — write/read/stat/delete/deleteMany/listByPrefix/path-escape
|
|
283
|
+
- `StoredTelemetrySpanScope` (extended) — addSpanEvent, attachArtifact no-op path, asNodeTelemetry view
|
|
284
|
+
- `TelemetryQueryService` (extended) — empty-spans early returns, cachedInputTokens/reasoningTokens branches
|
|
285
|
+
|
|
286
|
+
Coverage exclusions added for infrastructure-only files that require live
|
|
287
|
+
connections (SQLite, S3, module loader, internal HMAC wiring).
|
|
288
|
+
|
|
289
|
+
- 8285ec0: test(host): push @codemation/host coverage to ≥90% lines (Sprint 16 Story 01)
|
|
290
|
+
- 8285ec0: Surface unbound credential errors to workflow run dialog by fixing the swallowed catch block in CredentialBindingService.assertRequiredCredentialsBound.
|
|
291
|
+
- 8285ec0: fix(credentials): MCP server credential slots now appear in the properties panel
|
|
292
|
+
|
|
293
|
+
`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.
|
|
294
|
+
|
|
295
|
+
- 8285ec0: feat(host): warn at startup when pairing env vars are absent (Sprint 14 Story 05)
|
|
296
|
+
|
|
297
|
+
When WORKSPACE_ID, WORKSPACE_PAIRING_SECRET, or CONTROL_PLANE_URL are not set
|
|
298
|
+
at boot, the host now logs a named warning (codemation.pairing) listing the
|
|
299
|
+
missing variable names instead of silently skipping pairing registration.
|
|
300
|
+
This makes misconfigured managed-mode deployments immediately visible in logs.
|
|
301
|
+
|
|
302
|
+
- 8285ec0: feat(host/storage): artifact-to-object-storage + Run snapshot dedup (Sprint 14 Story 07)
|
|
303
|
+
- TelemetryArtifact payloads > 64 KB are now offloaded to BinaryStorage (payloadStorageKey column)
|
|
304
|
+
instead of stored inline in Postgres TEXT columns. Expired artifacts with storage keys have their
|
|
305
|
+
BinaryStorage blobs deleted during prune.
|
|
306
|
+
- Run snapshot deduplication: new WorkflowSnapshot table keyed by (workflowId, snapshotHash).
|
|
307
|
+
PrismaWorkflowRunRepository.createRun/save call findOrCreate to share identical snapshot JSON
|
|
308
|
+
across runs instead of storing redundant copies per run.
|
|
309
|
+
- Schema migrations added for both PostgreSQL and SQLite (with backfill of existing rows).
|
|
310
|
+
|
|
311
|
+
- 8285ec0: feat(host/security): HMAC verifier + credential cipher trust-boundary tests and `CredentialKeyRotatedError` for key rotation (Sprint 13 Story E framework-side).
|
|
312
|
+
- New `CredentialKeyRotatedError` thrown by `CredentialSecretCipher.decrypt` when the stored `encryptionKeyId` does not match the active master key — explicit fail-loud on key rotation.
|
|
313
|
+
- `CredentialSecretCipher` updated: decrypt now checks key id before attempting decryption, with missing-env → key-id-mismatch → auth-tag-failure ordering.
|
|
314
|
+
- `IncomingHmacVerifier` now throws explicitly when `pairingSecret` is empty (prevents silent signature-mismatch on misconfiguration).
|
|
315
|
+
- 8 unit tests for `IncomingHmacVerifier` (valid/wrong-workspace/tampered-body/tampered-header/skewed-timestamp/missing-secret-throws/replay/nonce-per-instance).
|
|
316
|
+
- 4 integration tests for `InternalHmacAuthMiddleware` hitting `/internal/ping` (valid 200/tampered 401/wrong-workspace 401/replay 401).
|
|
317
|
+
- 7 unit tests for `CredentialSecretCipher` (round-trip/tamper/missing-env-encrypt/missing-env-decrypt/IV-randomness/keyId-format/key-rotation-throws-CredentialKeyRotatedError).
|
|
318
|
+
- Fix pre-existing TS error: `ManagedAuthTestJwks` `KeyLike` → `CryptoKey` (jose v6 dropped the alias).
|
|
319
|
+
- New `docs/security-boundary.md` documenting HMAC trust boundary, in-memory nonce cache semantics, and cipher key rotation contract.
|
|
320
|
+
|
|
321
|
+
- 8285ec0: Allow SQLite in managed mode. The Sprint 3 Story 6 normalizer rule that
|
|
322
|
+
forced PostgreSQL when `auth.kind === "managed"` is removed for now —
|
|
323
|
+
the provisioner doesn't inject `DATABASE_URL` into spawned workspaces,
|
|
324
|
+
so the constraint blocked local provisioning. The managed scaffold
|
|
325
|
+
template now defaults to a per-workspace SQLite file.
|
|
326
|
+
- 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.
|
|
327
|
+
|
|
328
|
+
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.
|
|
329
|
+
|
|
330
|
+
`CredentialSessionServiceImpl.createSessionForInstance` is removed — it was only kept to feed this dead path. `McpOAuth2Session` (the fictional local type) is deleted.
|
|
331
|
+
|
|
332
|
+
- 8285ec0: MCP credential slots now live on the MCP connection node, matching ChatModel and Tool
|
|
333
|
+
connection nodes. Each declared `mcpServers` entry materializes an MCP connection node
|
|
334
|
+
and the credential slot is attached to that node with slot key `"credential"` (label
|
|
335
|
+
and accepted types derived from the MCP catalog declaration). The standard credential
|
|
336
|
+
slot traversal picks them up via `AgentConnectionNodeCollector` — no special-case path.
|
|
337
|
+
|
|
338
|
+
Removed the agent-owned `mcp:<serverId>` slot key. Removed the `mcpSlotKey(serverId)`
|
|
339
|
+
helper from `@codemation/core` (and its re-export from the type-only `contracts`
|
|
340
|
+
subpath). At runtime, `AgentMcpIntegration.prepareMcpTools` now resolves the binding at
|
|
341
|
+
`(workflowId, ConnectionNodeIdFactory.mcpConnectionNodeId(agentNodeId, serverId), "credential")`.
|
|
342
|
+
|
|
343
|
+
Gmail MCP `requiredScopes` trimmed to `["https://www.googleapis.com/auth/gmail.modify"]`
|
|
344
|
+
— `gmail.modify` is a superset of `gmail.readonly` + `gmail.send` for messages, threads,
|
|
345
|
+
drafts, and labels, so the previous list was redundant.
|
|
346
|
+
|
|
347
|
+
- 8285ec0: fix: validate edge output ports against declared node ports at load time
|
|
348
|
+
|
|
349
|
+
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).
|
|
350
|
+
|
|
351
|
+
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.
|
|
352
|
+
|
|
353
|
+
`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.
|
|
354
|
+
|
|
355
|
+
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.
|
|
356
|
+
|
|
357
|
+
- 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.
|
|
358
|
+
- 8285ec0: Add integration test coverage for managed-auth pipeline (Sprint 13 Story F).
|
|
359
|
+
- `managedAuth.integration.test.ts`: 5 new `/api/me` end-to-end cases (happy path, anonymous, tampered, expired, wrong audience) using a real signed JWT.
|
|
360
|
+
- `managedAuthSqlite.integration.test.ts`: boot regression guard for `auth.kind: "managed"` + sqlite combination (commit 35b8732c fix).
|
|
361
|
+
- `ManagedAuthTestJwks` testkit: reusable test EdDSA keypair + JWKS server helper.
|
|
362
|
+
|
|
363
|
+
- 8285ec0: fix(credentials): require ownership for ?withSecrets=1 (Sprint 14 Story 03)
|
|
364
|
+
|
|
365
|
+
`CredentialHttpRouteHandler.getCredentialInstance` now enforces workspace
|
|
366
|
+
ownership when `?withSecrets=1` is requested. In managed-auth mode a principal
|
|
367
|
+
with a `workspaceId` that differs from the installation's `pairingConfig.workspaceId`
|
|
368
|
+
receives 403 Forbidden. Local-auth mode (no pairingConfig) is unchanged.
|
|
369
|
+
|
|
370
|
+
- 8285ec0: fix(security): fail-closed on null principal for ?withSecrets=1 (Sprint 14.5 fix pass)
|
|
371
|
+
|
|
372
|
+
`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.
|
|
373
|
+
|
|
374
|
+
- 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)
|
|
375
|
+
- `S3BinaryStorage.isNotFoundError`: remove `statusCode === 403` from not-found check; propagate 403 (misconfiguration) instead of silently treating it as missing.
|
|
376
|
+
- `AppContainerFactory.createBinaryStorage`: throw `Error` for unknown `BINARY_STORAGE_KIND` values (e.g. `"gcs"`) instead of silently falling back to local storage.
|
|
377
|
+
- `WorkflowAuditLogPruneScheduler`: read interval from `CODEMATION_AUDIT_PRUNE_INTERVAL_MS` (dedicated env); fall back to `CODEMATION_RUN_PRUNE_INTERVAL_MS` then static default.
|
|
378
|
+
- `SsrfGuard.isPrivateIPv4`: add `100.64.0.0/10` (Carrier-Grade NAT, RFC 6598) to blocked ranges.
|
|
379
|
+
|
|
380
|
+
- 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`.
|
|
381
|
+
|
|
382
|
+
**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.
|
|
383
|
+
|
|
384
|
+
**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.
|
|
385
|
+
|
|
386
|
+
- 8285ec0: Make the unit-test suite pass on Windows.
|
|
387
|
+
- `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.
|
|
388
|
+
- `NodeInspectorTelemetryPresenter` + `DashboardCostAmountFormatter`: pin currency formatting to `en-US` with `currencyDisplay: "narrowSymbol"` so Node ICU versions produce `"$0.000039"` rather than `"US$0.000039"`.
|
|
389
|
+
- `DashboardAiUsageSummaryCard`: pin token-count formatting to `en-US` so the dashboard renders `"1,840"` regardless of system locale.
|
|
390
|
+
|
|
391
|
+
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.
|
|
392
|
+
|
|
393
|
+
- Updated dependencies [8285ec0]
|
|
394
|
+
- Updated dependencies [8285ec0]
|
|
395
|
+
- Updated dependencies [8285ec0]
|
|
396
|
+
- Updated dependencies [8285ec0]
|
|
397
|
+
- Updated dependencies [8285ec0]
|
|
398
|
+
- Updated dependencies [8285ec0]
|
|
399
|
+
- Updated dependencies [8285ec0]
|
|
400
|
+
- Updated dependencies [8285ec0]
|
|
401
|
+
- Updated dependencies [8285ec0]
|
|
402
|
+
- Updated dependencies [8285ec0]
|
|
403
|
+
- Updated dependencies [8285ec0]
|
|
404
|
+
- Updated dependencies [e4d3e1a]
|
|
405
|
+
- Updated dependencies [7b50018]
|
|
406
|
+
- Updated dependencies [8285ec0]
|
|
407
|
+
- Updated dependencies [8285ec0]
|
|
408
|
+
- Updated dependencies [8285ec0]
|
|
409
|
+
- Updated dependencies [8285ec0]
|
|
410
|
+
- Updated dependencies [8285ec0]
|
|
411
|
+
- Updated dependencies [8285ec0]
|
|
412
|
+
- Updated dependencies [e4d3e1a]
|
|
413
|
+
- Updated dependencies [0082ab5]
|
|
414
|
+
- Updated dependencies [8285ec0]
|
|
415
|
+
- Updated dependencies [8285ec0]
|
|
416
|
+
- Updated dependencies [8285ec0]
|
|
417
|
+
- Updated dependencies [8285ec0]
|
|
418
|
+
- Updated dependencies [8285ec0]
|
|
419
|
+
- Updated dependencies [8285ec0]
|
|
420
|
+
- Updated dependencies [8285ec0]
|
|
421
|
+
- Updated dependencies [8285ec0]
|
|
422
|
+
- Updated dependencies [8285ec0]
|
|
423
|
+
- Updated dependencies [8285ec0]
|
|
424
|
+
- Updated dependencies [8285ec0]
|
|
425
|
+
- Updated dependencies [8285ec0]
|
|
426
|
+
- Updated dependencies [8285ec0]
|
|
427
|
+
- Updated dependencies [8285ec0]
|
|
428
|
+
- Updated dependencies [f344d6d]
|
|
429
|
+
- @codemation/core-nodes@0.8.0
|
|
430
|
+
- @codemation/core@0.11.0
|
|
431
|
+
- @codemation/eventbus-redis@0.0.38
|
|
432
|
+
- @codemation/managed-auth@0.1.0
|
|
433
|
+
|
|
434
|
+
## 0.6.0
|
|
435
|
+
|
|
436
|
+
### Minor Changes
|
|
437
|
+
|
|
438
|
+
- [#133](https://github.com/MadeRelevant/codemation/pull/133) [`d283b48`](https://github.com/MadeRelevant/codemation/commit/d283b481f01a1a259d38d25c1482006eff963384) Thanks [@cblokland90](https://github.com/cblokland90)! - feat: deep-link from parent run to specific subworkflow execution
|
|
439
|
+
|
|
440
|
+
Adds `childRunId` to `NodeExecutionSnapshot` so the UI can navigate directly to the
|
|
441
|
+
child run when a `SubWorkflow` node is selected in the execution inspector, instead of
|
|
442
|
+
only linking to the child workflow's editor. Fixes the gap from PR [#131](https://github.com/MadeRelevant/codemation/issues/131).
|
|
443
|
+
- `@codemation/core` (patch): `NodeExecutionSnapshot` gains `childRunId?: RunId`;
|
|
444
|
+
`ExecutionInstanceDto` gains `childRunId?: string`;
|
|
445
|
+
`NodeExecutionStatePublisher` gains optional `setChildRunId` method;
|
|
446
|
+
`NodeExecutionSnapshotFactory` propagates `previous.childRunId` through
|
|
447
|
+
`completed`, `failed`, and `skipped` transitions.
|
|
448
|
+
- `@codemation/host` (minor): `ExecutionInstance` table gains `child_run_id` column
|
|
449
|
+
(nullable, backward-compatible); `PrismaWorkflowRunRepository` persists and reads
|
|
450
|
+
`childRunId` on node-activation snapshots.
|
|
451
|
+
- `@codemation/next-host` (minor): `NodeExecutionSnapshot` type gains `childRunId`;
|
|
452
|
+
`WorkflowExecutionInspectorDetailBody` renders "Open subworkflow run" (with
|
|
453
|
+
`?run=<childRunId>`) when a child run id is present, falling back to
|
|
454
|
+
"Open subworkflow editor" for pre-existing snapshots.
|
|
455
|
+
|
|
456
|
+
- [#131](https://github.com/MadeRelevant/codemation/pull/131) [`5b509e8`](https://github.com/MadeRelevant/codemation/commit/5b509e83e1e963e0c03cb0cbad018dc1fb0a04c5) Thanks [@cblokland90](https://github.com/cblokland90)! - feat: SubWorkflow editor link, workflow info popover, and child-run navigation
|
|
457
|
+
- **2.3a** — SubWorkflow nodes in the node-properties panel now show an "Open in editor" link that navigates to the referenced workflow. Requires the new `referencedWorkflowId` field added to `WorkflowNodeDto` (populated from `SubWorkflow.workflowId` in `WorkflowDefinitionMapper` and `PersistedWorkflowSnapshotMapper`).
|
|
458
|
+
- **2.3b** — A workflow info popover (ⓘ icon) appears in the detail-page header, showing workflow id, discovery-path segments, trigger type, and active status.
|
|
459
|
+
- **2.4** — When a SubWorkflow node is selected in the execution inspector, an "Open workflow" link appears navigating to that child workflow's editor. Note: jump to the _specific child run_ is not yet possible because the parent's node execution snapshot does not carry the child `runId`; this is a backend follow-up item.
|
|
460
|
+
|
|
461
|
+
### Patch Changes
|
|
462
|
+
|
|
463
|
+
- Updated dependencies [[`d283b48`](https://github.com/MadeRelevant/codemation/commit/d283b481f01a1a259d38d25c1482006eff963384), [`e8e3935`](https://github.com/MadeRelevant/codemation/commit/e8e39358a4282e0a780efb428ae0d71d105afd5f)]:
|
|
464
|
+
- @codemation/core@0.10.2
|
|
465
|
+
- @codemation/core-nodes@0.7.1
|
|
466
|
+
- @codemation/eventbus-redis@0.0.37
|
|
467
|
+
|
|
3
468
|
## 0.5.1
|
|
4
469
|
|
|
5
470
|
### Patch Changes
|
package/LICENSE
CHANGED
|
@@ -1,37 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Copyright (c) Made Relevant B.V. All rights reserved.
|
|
4
|
-
|
|
5
|
-
1. Definitions
|
|
6
|
-
|
|
7
|
-
"Software" means the Codemation source code, documentation, and artifacts in this repository and any published npm packages in the Codemation monorepo.
|
|
8
|
-
|
|
9
|
-
"Stable Version" means the first published release of the package `@codemation/core` on the public npm registry with version 1.0.0 or higher.
|
|
10
|
-
|
|
11
|
-
2. Permitted use (before Stable Version)
|
|
12
|
-
|
|
13
|
-
Until a Stable Version exists, you may use, copy, modify, and distribute the Software only for non-commercial purposes, including personal learning, research, evaluation, and internal use within your organization that does not charge third parties for access to the Software or a product or service whose primary value is the Software.
|
|
14
|
-
|
|
15
|
-
3. Restrictions (before Stable Version)
|
|
16
|
-
|
|
17
|
-
Until a Stable Version exists, you must not:
|
|
18
|
-
|
|
19
|
-
a) Sell, rent, lease, or sublicense the Software or a derivative work for a fee;
|
|
20
|
-
|
|
21
|
-
b) Offer the Software or a derivative work as part of a paid product or service (including hosting, support, or consulting) where the Software is a material part of the offering;
|
|
22
|
-
|
|
23
|
-
c) Use the Software or a derivative work primarily to generate revenue or commercial advantage for you or others.
|
|
24
|
-
|
|
25
|
-
These restrictions apply to all versions published before a Stable Version, even if a later Stable Version is released under different terms.
|
|
26
|
-
|
|
27
|
-
4. After Stable Version
|
|
28
|
-
|
|
29
|
-
The maintainers may publish a Stable Version under different license terms. If they do, those terms apply only to that Stable Version and subsequent releases they designate; they do not automatically apply to earlier pre-stable versions.
|
|
30
|
-
|
|
31
|
-
5. No warranty
|
|
32
|
-
|
|
33
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
34
|
-
|
|
35
|
-
6. Third-party components
|
|
36
|
-
|
|
37
|
-
The Software may include third-party components under their own licenses. Those licenses govern those components.
|
|
1
|
+
../../LICENSE
|
|
@@ -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-
|
|
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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"}
|