@smthrs/control 0.0.0-stage → 1.0.0-rc.4
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 +194 -0
- package/LICENSE +21 -0
- package/README.md +168 -2
- package/dist/cjs/ApprovalAuthority.d.ts +73 -0
- package/dist/cjs/ApprovalAuthority.d.ts.map +1 -0
- package/dist/cjs/ApprovalAuthority.js +62 -0
- package/dist/cjs/ApprovalAuthority.js.map +7 -0
- package/dist/cjs/Cancellation.d.ts +107 -0
- package/dist/cjs/Cancellation.d.ts.map +1 -0
- package/dist/cjs/Cancellation.js +72 -0
- package/dist/cjs/Cancellation.js.map +7 -0
- package/dist/cjs/Channels.d.ts +170 -0
- package/dist/cjs/Channels.d.ts.map +1 -0
- package/dist/cjs/Channels.js +278 -0
- package/dist/cjs/Channels.js.map +7 -0
- package/dist/cjs/Control.d.ts +202 -0
- package/dist/cjs/Control.d.ts.map +1 -0
- package/dist/cjs/Control.js +47 -0
- package/dist/cjs/Control.js.map +7 -0
- package/dist/cjs/ControlClient.d.ts +52 -0
- package/dist/cjs/ControlClient.d.ts.map +1 -0
- package/dist/cjs/ControlClient.js +191 -0
- package/dist/cjs/ControlClient.js.map +7 -0
- package/dist/cjs/ControlError.d.ts +318 -0
- package/dist/cjs/ControlError.d.ts.map +1 -0
- package/dist/cjs/ControlError.js +249 -0
- package/dist/cjs/ControlError.js.map +7 -0
- package/dist/cjs/ControlExecutor.d.ts +372 -0
- package/dist/cjs/ControlExecutor.d.ts.map +1 -0
- package/dist/cjs/ControlExecutor.js +123 -0
- package/dist/cjs/ControlExecutor.js.map +7 -0
- package/dist/cjs/ControlFacts.d.ts +454 -0
- package/dist/cjs/ControlFacts.d.ts.map +1 -0
- package/dist/cjs/ControlFacts.js +261 -0
- package/dist/cjs/ControlFacts.js.map +7 -0
- package/dist/cjs/ControlLive.d.ts +23 -0
- package/dist/cjs/ControlLive.d.ts.map +1 -0
- package/dist/cjs/ControlLive.js +1293 -0
- package/dist/cjs/ControlLive.js.map +7 -0
- package/dist/cjs/ControlRpcs.d.ts +1204 -0
- package/dist/cjs/ControlRpcs.d.ts.map +1 -0
- package/dist/cjs/ControlRpcs.js +247 -0
- package/dist/cjs/ControlRpcs.js.map +7 -0
- package/dist/cjs/ControlRuntime.d.ts +635 -0
- package/dist/cjs/ControlRuntime.d.ts.map +1 -0
- package/dist/cjs/ControlRuntime.js +744 -0
- package/dist/cjs/ControlRuntime.js.map +7 -0
- package/dist/cjs/ControlSchema.d.ts +2642 -0
- package/dist/cjs/ControlSchema.d.ts.map +1 -0
- package/dist/cjs/ControlSchema.js +634 -0
- package/dist/cjs/ControlSchema.js.map +7 -0
- package/dist/cjs/ControlServer.d.ts +51 -0
- package/dist/cjs/ControlServer.d.ts.map +1 -0
- package/dist/cjs/ControlServer.js +121 -0
- package/dist/cjs/ControlServer.js.map +7 -0
- package/dist/cjs/Credential.d.ts +136 -0
- package/dist/cjs/Credential.d.ts.map +1 -0
- package/dist/cjs/Credential.js +168 -0
- package/dist/cjs/Credential.js.map +7 -0
- package/dist/cjs/CredentialCipher.d.ts +90 -0
- package/dist/cjs/CredentialCipher.d.ts.map +1 -0
- package/dist/cjs/CredentialCipher.js +45 -0
- package/dist/cjs/CredentialCipher.js.map +7 -0
- package/dist/cjs/CredentialStore.d.ts +97 -0
- package/dist/cjs/CredentialStore.d.ts.map +1 -0
- package/dist/cjs/CredentialStore.js +81 -0
- package/dist/cjs/CredentialStore.js.map +7 -0
- package/dist/cjs/DispatchReader.d.ts +112 -0
- package/dist/cjs/DispatchReader.d.ts.map +1 -0
- package/dist/cjs/DispatchReader.js +45 -0
- package/dist/cjs/DispatchReader.js.map +7 -0
- package/dist/cjs/Health.d.ts +333 -0
- package/dist/cjs/Health.d.ts.map +1 -0
- package/dist/cjs/Health.js +311 -0
- package/dist/cjs/Health.js.map +7 -0
- package/dist/cjs/JevSessionChecker.d.ts +57 -0
- package/dist/cjs/JevSessionChecker.d.ts.map +1 -0
- package/dist/cjs/JevSessionChecker.js +113 -0
- package/dist/cjs/JevSessionChecker.js.map +7 -0
- package/dist/cjs/Lineage.d.ts +131 -0
- package/dist/cjs/Lineage.d.ts.map +1 -0
- package/dist/cjs/Lineage.js +81 -0
- package/dist/cjs/Lineage.js.map +7 -0
- package/dist/cjs/Migrations.d.ts +34 -0
- package/dist/cjs/Migrations.d.ts.map +1 -0
- package/dist/cjs/Migrations.js +60 -0
- package/dist/cjs/Migrations.js.map +7 -0
- package/dist/cjs/Monitor.d.ts +282 -0
- package/dist/cjs/Monitor.d.ts.map +1 -0
- package/dist/cjs/Monitor.js +283 -0
- package/dist/cjs/Monitor.js.map +7 -0
- package/dist/cjs/ScopedToken.d.ts +193 -0
- package/dist/cjs/ScopedToken.d.ts.map +1 -0
- package/dist/cjs/ScopedToken.js +135 -0
- package/dist/cjs/ScopedToken.js.map +7 -0
- package/dist/cjs/SqlControlRuntime.d.ts +161 -0
- package/dist/cjs/SqlControlRuntime.d.ts.map +1 -0
- package/dist/cjs/SqlControlRuntime.js +1522 -0
- package/dist/cjs/SqlControlRuntime.js.map +7 -0
- package/dist/cjs/SqlCredentialStore.d.ts +43 -0
- package/dist/cjs/SqlCredentialStore.d.ts.map +1 -0
- package/dist/cjs/SqlCredentialStore.js +113 -0
- package/dist/cjs/SqlCredentialStore.js.map +7 -0
- package/dist/cjs/Steering.d.ts +69 -0
- package/dist/cjs/Steering.d.ts.map +1 -0
- package/dist/cjs/Steering.js +49 -0
- package/dist/cjs/Steering.js.map +7 -0
- package/dist/cjs/SystemFlows.d.ts +223 -0
- package/dist/cjs/SystemFlows.d.ts.map +1 -0
- package/dist/cjs/SystemFlows.js +195 -0
- package/dist/cjs/SystemFlows.js.map +7 -0
- package/dist/cjs/WebCryptoCipher.d.ts +49 -0
- package/dist/cjs/WebCryptoCipher.d.ts.map +1 -0
- package/dist/cjs/WebCryptoCipher.js +129 -0
- package/dist/cjs/WebCryptoCipher.js.map +7 -0
- package/dist/cjs/WebhookChannel.d.ts +113 -0
- package/dist/cjs/WebhookChannel.d.ts.map +1 -0
- package/dist/cjs/WebhookChannel.js +98 -0
- package/dist/cjs/WebhookChannel.js.map +7 -0
- package/dist/cjs/index.d.ts +160 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +91 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/internal/MutationBoundary.d.ts +27 -0
- package/dist/cjs/internal/MutationBoundary.d.ts.map +1 -0
- package/dist/cjs/internal/MutationBoundary.js +50 -0
- package/dist/cjs/internal/MutationBoundary.js.map +7 -0
- package/dist/cjs/internal/activeFibers.d.ts +12 -0
- package/dist/cjs/internal/activeFibers.d.ts.map +1 -0
- package/dist/cjs/internal/activeFibers.js +30 -0
- package/dist/cjs/internal/activeFibers.js.map +7 -0
- package/dist/cjs/internal/issues.d.ts +28 -0
- package/dist/cjs/internal/issues.d.ts.map +1 -0
- package/dist/cjs/internal/issues.js +34 -0
- package/dist/cjs/internal/issues.js.map +7 -0
- package/dist/cjs/internal/planning.d.ts +347 -0
- package/dist/cjs/internal/planning.d.ts.map +1 -0
- package/dist/cjs/internal/planning.js +137 -0
- package/dist/cjs/internal/planning.js.map +7 -0
- package/dist/cjs/internal/sqlSchemaErrors.d.ts +18 -0
- package/dist/cjs/internal/sqlSchemaErrors.d.ts.map +1 -0
- package/dist/cjs/internal/sqlSchemaErrors.js +40 -0
- package/dist/cjs/internal/sqlSchemaErrors.js.map +7 -0
- package/dist/cjs/migrations/0001_control_tables.d.ts +18 -0
- package/dist/cjs/migrations/0001_control_tables.d.ts.map +1 -0
- package/dist/cjs/migrations/0001_control_tables.js +115 -0
- package/dist/cjs/migrations/0001_control_tables.js.map +7 -0
- package/dist/cjs/migrations/0002_run_keys.d.ts +15 -0
- package/dist/cjs/migrations/0002_run_keys.d.ts.map +1 -0
- package/dist/cjs/migrations/0002_run_keys.js +44 -0
- package/dist/cjs/migrations/0002_run_keys.js.map +7 -0
- package/dist/cjs/migrations/0003_signal_commands.d.ts +13 -0
- package/dist/cjs/migrations/0003_signal_commands.d.ts.map +1 -0
- package/dist/cjs/migrations/0003_signal_commands.js +50 -0
- package/dist/cjs/migrations/0003_signal_commands.js.map +7 -0
- package/dist/cjs/migrations/0004_approval_decisions.d.ts +13 -0
- package/dist/cjs/migrations/0004_approval_decisions.d.ts.map +1 -0
- package/dist/cjs/migrations/0004_approval_decisions.js +45 -0
- package/dist/cjs/migrations/0004_approval_decisions.js.map +7 -0
- package/dist/cjs/migrations/0005_signal_principals.d.ts +18 -0
- package/dist/cjs/migrations/0005_signal_principals.d.ts.map +1 -0
- package/dist/cjs/migrations/0005_signal_principals.js +45 -0
- package/dist/cjs/migrations/0005_signal_principals.js.map +7 -0
- package/dist/cjs/migrations/0006_run_principals.d.ts +18 -0
- package/dist/cjs/migrations/0006_run_principals.d.ts.map +1 -0
- package/dist/cjs/migrations/0006_run_principals.js +49 -0
- package/dist/cjs/migrations/0006_run_principals.js.map +7 -0
- package/dist/cjs/migrations/0007_resume_consent.d.ts +18 -0
- package/dist/cjs/migrations/0007_resume_consent.d.ts.map +1 -0
- package/dist/cjs/migrations/0007_resume_consent.js +46 -0
- package/dist/cjs/migrations/0007_resume_consent.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/TestControl.d.ts +19 -0
- package/dist/cjs/test/TestControl.d.ts.map +1 -0
- package/dist/cjs/test/TestControl.js +62 -0
- package/dist/cjs/test/TestControl.js.map +7 -0
- package/dist/esm/ApprovalAuthority.d.ts +73 -0
- package/dist/esm/ApprovalAuthority.d.ts.map +1 -0
- package/dist/esm/ApprovalAuthority.js +72 -0
- package/dist/esm/ApprovalAuthority.js.map +1 -0
- package/dist/esm/Cancellation.d.ts +107 -0
- package/dist/esm/Cancellation.d.ts.map +1 -0
- package/dist/esm/Cancellation.js +116 -0
- package/dist/esm/Cancellation.js.map +1 -0
- package/dist/esm/Channels.d.ts +170 -0
- package/dist/esm/Channels.d.ts.map +1 -0
- package/dist/esm/Channels.js +312 -0
- package/dist/esm/Channels.js.map +1 -0
- package/dist/esm/Control.d.ts +202 -0
- package/dist/esm/Control.d.ts.map +1 -0
- package/dist/esm/Control.js +42 -0
- package/dist/esm/Control.js.map +1 -0
- package/dist/esm/ControlClient.d.ts +52 -0
- package/dist/esm/ControlClient.d.ts.map +1 -0
- package/dist/esm/ControlClient.js +217 -0
- package/dist/esm/ControlClient.js.map +1 -0
- package/dist/esm/ControlError.d.ts +318 -0
- package/dist/esm/ControlError.d.ts.map +1 -0
- package/dist/esm/ControlError.js +359 -0
- package/dist/esm/ControlError.js.map +1 -0
- package/dist/esm/ControlExecutor.d.ts +372 -0
- package/dist/esm/ControlExecutor.d.ts.map +1 -0
- package/dist/esm/ControlExecutor.js +212 -0
- package/dist/esm/ControlExecutor.js.map +1 -0
- package/dist/esm/ControlFacts.d.ts +454 -0
- package/dist/esm/ControlFacts.d.ts.map +1 -0
- package/dist/esm/ControlFacts.js +324 -0
- package/dist/esm/ControlFacts.js.map +1 -0
- package/dist/esm/ControlLive.d.ts +23 -0
- package/dist/esm/ControlLive.d.ts.map +1 -0
- package/dist/esm/ControlLive.js +1589 -0
- package/dist/esm/ControlLive.js.map +1 -0
- package/dist/esm/ControlRpcs.d.ts +1204 -0
- package/dist/esm/ControlRpcs.d.ts.map +1 -0
- package/dist/esm/ControlRpcs.js +299 -0
- package/dist/esm/ControlRpcs.js.map +1 -0
- package/dist/esm/ControlRuntime.d.ts +635 -0
- package/dist/esm/ControlRuntime.d.ts.map +1 -0
- package/dist/esm/ControlRuntime.js +808 -0
- package/dist/esm/ControlRuntime.js.map +1 -0
- package/dist/esm/ControlSchema.d.ts +2642 -0
- package/dist/esm/ControlSchema.d.ts.map +1 -0
- package/dist/esm/ControlSchema.js +1030 -0
- package/dist/esm/ControlSchema.js.map +1 -0
- package/dist/esm/ControlServer.d.ts +51 -0
- package/dist/esm/ControlServer.d.ts.map +1 -0
- package/dist/esm/ControlServer.js +145 -0
- package/dist/esm/ControlServer.js.map +1 -0
- package/dist/esm/Credential.d.ts +136 -0
- package/dist/esm/Credential.d.ts.map +1 -0
- package/dist/esm/Credential.js +190 -0
- package/dist/esm/Credential.js.map +1 -0
- package/dist/esm/CredentialCipher.d.ts +90 -0
- package/dist/esm/CredentialCipher.d.ts.map +1 -0
- package/dist/esm/CredentialCipher.js +56 -0
- package/dist/esm/CredentialCipher.js.map +1 -0
- package/dist/esm/CredentialStore.d.ts +97 -0
- package/dist/esm/CredentialStore.d.ts.map +1 -0
- package/dist/esm/CredentialStore.js +101 -0
- package/dist/esm/CredentialStore.js.map +1 -0
- package/dist/esm/DispatchReader.d.ts +112 -0
- package/dist/esm/DispatchReader.d.ts.map +1 -0
- package/dist/esm/DispatchReader.js +76 -0
- package/dist/esm/DispatchReader.js.map +1 -0
- package/dist/esm/Health.d.ts +333 -0
- package/dist/esm/Health.d.ts.map +1 -0
- package/dist/esm/Health.js +400 -0
- package/dist/esm/Health.js.map +1 -0
- package/dist/esm/JevSessionChecker.d.ts +57 -0
- package/dist/esm/JevSessionChecker.d.ts.map +1 -0
- package/dist/esm/JevSessionChecker.js +108 -0
- package/dist/esm/JevSessionChecker.js.map +1 -0
- package/dist/esm/Lineage.d.ts +131 -0
- package/dist/esm/Lineage.d.ts.map +1 -0
- package/dist/esm/Lineage.js +174 -0
- package/dist/esm/Lineage.js.map +1 -0
- package/dist/esm/Migrations.d.ts +34 -0
- package/dist/esm/Migrations.d.ts.map +1 -0
- package/dist/esm/Migrations.js +53 -0
- package/dist/esm/Migrations.js.map +1 -0
- package/dist/esm/Monitor.d.ts +282 -0
- package/dist/esm/Monitor.d.ts.map +1 -0
- package/dist/esm/Monitor.js +415 -0
- package/dist/esm/Monitor.js.map +1 -0
- package/dist/esm/ScopedToken.d.ts +193 -0
- package/dist/esm/ScopedToken.d.ts.map +1 -0
- package/dist/esm/ScopedToken.js +224 -0
- package/dist/esm/ScopedToken.js.map +1 -0
- package/dist/esm/SqlControlRuntime.d.ts +161 -0
- package/dist/esm/SqlControlRuntime.d.ts.map +1 -0
- package/dist/esm/SqlControlRuntime.js +1756 -0
- package/dist/esm/SqlControlRuntime.js.map +1 -0
- package/dist/esm/SqlCredentialStore.d.ts +43 -0
- package/dist/esm/SqlCredentialStore.d.ts.map +1 -0
- package/dist/esm/SqlCredentialStore.js +97 -0
- package/dist/esm/SqlCredentialStore.js.map +1 -0
- package/dist/esm/Steering.d.ts +69 -0
- package/dist/esm/Steering.d.ts.map +1 -0
- package/dist/esm/Steering.js +89 -0
- package/dist/esm/Steering.js.map +1 -0
- package/dist/esm/SystemFlows.d.ts +223 -0
- package/dist/esm/SystemFlows.d.ts.map +1 -0
- package/dist/esm/SystemFlows.js +198 -0
- package/dist/esm/SystemFlows.js.map +1 -0
- package/dist/esm/WebCryptoCipher.d.ts +49 -0
- package/dist/esm/WebCryptoCipher.d.ts.map +1 -0
- package/dist/esm/WebCryptoCipher.js +123 -0
- package/dist/esm/WebCryptoCipher.js.map +1 -0
- package/dist/esm/WebhookChannel.d.ts +113 -0
- package/dist/esm/WebhookChannel.d.ts.map +1 -0
- package/dist/esm/WebhookChannel.js +109 -0
- package/dist/esm/WebhookChannel.js.map +1 -0
- package/dist/esm/index.d.ts +160 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +160 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/internal/MutationBoundary.d.ts +27 -0
- package/dist/esm/internal/MutationBoundary.d.ts.map +1 -0
- package/dist/esm/internal/MutationBoundary.js +40 -0
- package/dist/esm/internal/MutationBoundary.js.map +1 -0
- package/dist/esm/internal/activeFibers.d.ts +12 -0
- package/dist/esm/internal/activeFibers.d.ts.map +1 -0
- package/dist/esm/internal/activeFibers.js +17 -0
- package/dist/esm/internal/activeFibers.js.map +1 -0
- package/dist/esm/internal/issues.d.ts +28 -0
- package/dist/esm/internal/issues.d.ts.map +1 -0
- package/dist/esm/internal/issues.js +35 -0
- package/dist/esm/internal/issues.js.map +1 -0
- package/dist/esm/internal/planning.d.ts +347 -0
- package/dist/esm/internal/planning.d.ts.map +1 -0
- package/dist/esm/internal/planning.js +199 -0
- package/dist/esm/internal/planning.js.map +1 -0
- package/dist/esm/internal/sqlSchemaErrors.d.ts +18 -0
- package/dist/esm/internal/sqlSchemaErrors.d.ts.map +1 -0
- package/dist/esm/internal/sqlSchemaErrors.js +38 -0
- package/dist/esm/internal/sqlSchemaErrors.js.map +1 -0
- package/dist/esm/migrations/0001_control_tables.d.ts +18 -0
- package/dist/esm/migrations/0001_control_tables.d.ts.map +1 -0
- package/dist/esm/migrations/0001_control_tables.js +96 -0
- package/dist/esm/migrations/0001_control_tables.js.map +1 -0
- package/dist/esm/migrations/0002_run_keys.d.ts +15 -0
- package/dist/esm/migrations/0002_run_keys.d.ts.map +1 -0
- package/dist/esm/migrations/0002_run_keys.js +22 -0
- package/dist/esm/migrations/0002_run_keys.js.map +1 -0
- package/dist/esm/migrations/0003_signal_commands.d.ts +13 -0
- package/dist/esm/migrations/0003_signal_commands.d.ts.map +1 -0
- package/dist/esm/migrations/0003_signal_commands.js +26 -0
- package/dist/esm/migrations/0003_signal_commands.js.map +1 -0
- package/dist/esm/migrations/0004_approval_decisions.d.ts +13 -0
- package/dist/esm/migrations/0004_approval_decisions.d.ts.map +1 -0
- package/dist/esm/migrations/0004_approval_decisions.js +25 -0
- package/dist/esm/migrations/0004_approval_decisions.js.map +1 -0
- package/dist/esm/migrations/0005_signal_principals.d.ts +18 -0
- package/dist/esm/migrations/0005_signal_principals.d.ts.map +1 -0
- package/dist/esm/migrations/0005_signal_principals.js +27 -0
- package/dist/esm/migrations/0005_signal_principals.js.map +1 -0
- package/dist/esm/migrations/0006_run_principals.d.ts +18 -0
- package/dist/esm/migrations/0006_run_principals.d.ts.map +1 -0
- package/dist/esm/migrations/0006_run_principals.js +30 -0
- package/dist/esm/migrations/0006_run_principals.js.map +1 -0
- package/dist/esm/migrations/0007_resume_consent.d.ts +18 -0
- package/dist/esm/migrations/0007_resume_consent.d.ts.map +1 -0
- package/dist/esm/migrations/0007_resume_consent.js +27 -0
- package/dist/esm/migrations/0007_resume_consent.js.map +1 -0
- package/dist/esm/test/TestControl.d.ts +19 -0
- package/dist/esm/test/TestControl.d.ts.map +1 -0
- package/dist/esm/test/TestControl.js +30 -0
- package/dist/esm/test/TestControl.js.map +1 -0
- package/docs/README.md +189 -0
- package/docs/api.md +982 -0
- package/docs/concepts/authority.md +109 -0
- package/docs/concepts/cancellation.md +129 -0
- package/docs/concepts/lineage.md +132 -0
- package/docs/concepts/ownership.md +139 -0
- package/docs/concepts/projections.md +203 -0
- package/docs/concepts/receipts.md +128 -0
- package/docs/guides/approvals.md +284 -0
- package/docs/guides/cancel-and-resume.md +162 -0
- package/docs/guides/durable-storage.md +147 -0
- package/docs/guides/implement-an-executor.md +173 -0
- package/docs/guides/ingest-a-webhook.md +177 -0
- package/docs/guides/list-runs.md +160 -0
- package/docs/guides/monitor-runs.md +176 -0
- package/docs/guides/observe-health.md +147 -0
- package/docs/guides/postgres-tests.md +7 -0
- package/docs/guides/serve-over-rpc.md +220 -0
- package/docs/guides/signal-a-run.md +53 -0
- package/docs/guides/steer-a-run.md +138 -0
- package/docs/guides/store-credentials.md +164 -0
- package/docs/guides/testing.md +139 -0
- package/docs/guides/watch-a-run.md +154 -0
- package/docs/installation.md +106 -0
- package/docs/quickstart.md +163 -0
- package/docs/troubleshooting.md +208 -0
- package/package.json +405 -3
- package/src/ApprovalAuthority.ts +114 -0
- package/src/Cancellation.ts +172 -0
- package/src/Channels.ts +493 -0
- package/src/Control.ts +337 -0
- package/src/ControlClient.ts +319 -0
- package/src/ControlError.ts +378 -0
- package/src/ControlExecutor.ts +490 -0
- package/src/ControlFacts.ts +383 -0
- package/src/ControlLive.ts +2127 -0
- package/src/ControlRpcs.ts +443 -0
- package/src/ControlRuntime.ts +1601 -0
- package/src/ControlSchema.ts +1380 -0
- package/src/ControlServer.ts +182 -0
- package/src/Credential.ts +310 -0
- package/src/CredentialCipher.ts +110 -0
- package/src/CredentialStore.ts +152 -0
- package/src/DispatchReader.ts +122 -0
- package/src/Health.ts +591 -0
- package/src/JevSessionChecker.ts +127 -0
- package/src/Lineage.ts +203 -0
- package/src/Migrations.ts +56 -0
- package/src/Monitor.ts +600 -0
- package/src/ScopedToken.ts +306 -0
- package/src/SqlControlRuntime.ts +2478 -0
- package/src/SqlCredentialStore.ts +148 -0
- package/src/Steering.ts +96 -0
- package/src/SystemFlows.ts +225 -0
- package/src/WebCryptoCipher.ts +169 -0
- package/src/WebhookChannel.ts +166 -0
- package/src/index.ts +188 -0
- package/src/internal/MutationBoundary.ts +46 -0
- package/src/internal/activeFibers.ts +22 -0
- package/src/internal/issues.ts +40 -0
- package/src/internal/planning.ts +262 -0
- package/src/internal/sqlSchemaErrors.ts +37 -0
- package/src/migrations/0001_control_tables.ts +99 -0
- package/src/migrations/0002_run_keys.ts +23 -0
- package/src/migrations/0003_signal_commands.ts +27 -0
- package/src/migrations/0004_approval_decisions.ts +25 -0
- package/src/migrations/0005_signal_principals.ts +27 -0
- package/src/migrations/0006_run_principals.ts +31 -0
- package/src/migrations/0007_resume_consent.ts +28 -0
- package/src/test/TestControl.ts +47 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/Channels.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Channel contracts and the in-memory channel coordinator.\n *\n * A channel verifies opaque transport data before it decodes or maps it. The\n * resulting request is then dispatched through the Control service; channels\n * do not acquire an execution path of their own.\n *\n * @since 0.1.0\n */\n\nimport * as Sha256 from \"@smthrs/crypto/Sha256\"\nimport { Clock, Context, Effect, Layer, Ref, type Schema, Semaphore } from \"effect\"\nimport { Control } from \"./Control.ts\"\nimport { type ControlError, InvalidInput, type Unauthorized, Unavailable } from \"./ControlError.ts\"\nimport { ControlRuntime } from \"./ControlRuntime.ts\"\nimport type { FlowId, IdempotencyKey, Receipt, RunId, RunSummary, SignalPayload } from \"./ControlSchema.ts\"\nimport { alreadyApplied } from \"./internal/planning.ts\"\n\n/**\n * Opaque request data passed to a channel before decoding.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface RawInbound {\n readonly body: Uint8Array\n readonly headers: Readonly<Record<string, string | undefined>>\n readonly idempotencyKey: IdempotencyKey\n}\n\n/**\n * The channel mapping after a verified payload has been decoded.\n *\n * @category models\n * @since 0.1.0\n */\nexport type InboundResult =\n | { readonly _tag: \"Start\"; readonly flowId: FlowId; readonly input: unknown }\n | { readonly _tag: \"Signal\"; readonly runId: RunId; readonly signal: SignalPayload }\n\n/**\n * A process-local per-channel delivery record. `messageId` identifies an existing\n * platform message, so a reconnect can update it instead of posting again.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Delivery {\n readonly cursor: string\n readonly messageId?: string | undefined\n}\n\n/**\n * A side-effect-free outbound projection. Network delivery belongs to the\n * transport adapter, which consumes this value after it is journaled.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface DeliveryProjection {\n readonly cursor: string\n readonly messageId?: string | undefined\n readonly operation: \"post\" | \"edit\" | \"noop\"\n readonly message: unknown\n}\n\n/**\n * A bidirectional platform adapter.\n *\n * `verify` must only inspect opaque bytes and headers. It always precedes\n * `decode`, preventing untrusted public requests from reaching planning.\n *\n * @category services\n * @since 0.1.0\n */\nexport interface Channel<A = unknown> {\n readonly name: string\n readonly schema: Schema.Schema<A>\n /**\n * Non-secret HTTP header names whose values change the decoded command.\n * Names are matched case-insensitively and folded into durable idempotency;\n * signature, authorization, and credential headers must not be declared.\n */\n readonly fingerprintHeaders?: ReadonlyArray<string> | undefined\n readonly verify: (raw: RawInbound) => Effect.Effect<void, Unauthorized>\n /** Deterministic, side-effect-free decoding; retries may evaluate it again. */\n readonly decode: (raw: RawInbound) => Effect.Effect<A, InvalidInput>\n /** Deterministic, side-effect-free mapping; retries may evaluate it again. */\n readonly map: (payload: A) => Effect.Effect<InboundResult, InvalidInput>\n readonly project: (run: RunSummary, delivery: Delivery | undefined) => DeliveryProjection\n}\n\n/**\n * A registered channel with its payload type hidden. Decoding and mapping stay\n * paired, so lookup never exposes a mapper accepting arbitrary unknown data.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface RegisteredChannel extends Omit<Channel, \"decode\" | \"map\"> {\n readonly decodeAndMap: (raw: RawInbound) => Effect.Effect<InboundResult, InvalidInput>\n}\n\nconst eraseChannel = <A>(channel: Channel<A>): RegisteredChannel => ({\n name: channel.name,\n schema: channel.schema,\n fingerprintHeaders: channel.fingerprintHeaders,\n verify: (raw) => channel.verify(raw),\n decodeAndMap: (raw) => Effect.flatMap(channel.decode(raw), (payload) => channel.map(payload)),\n project: (run, delivery) => channel.project(run, delivery)\n})\n\n/**\n * Arguments for ingesting one authenticated channel request.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface IngestRequest {\n readonly channel: string\n readonly raw: RawInbound\n}\n\n/**\n * Arguments for projecting one run onto a channel.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface ProjectRequest {\n readonly channel: string\n readonly run: RunSummary\n}\n\n/**\n * The channel coordinator.\n *\n * @category services\n * @since 0.1.0\n */\nexport interface Channels {\n readonly register: <A>(channel: Channel<A>) => Effect.Effect<void>\n readonly lookup: (name: string) => Effect.Effect<RegisteredChannel, Unavailable>\n readonly ingest: (request: IngestRequest) => Effect.Effect<Receipt, ControlError>\n readonly project: (request: ProjectRequest) => Effect.Effect<DeliveryProjection, Unavailable>\n}\n\n/**\n * Service tag for channel registration, ingestion, and pure projection.\n *\n * @category services\n * @since 0.1.0\n */\nexport const Channels: Context.Service<Channels, Channels> = Context.Service(\"/control/Channels\")\n\nconst unavailable = (feature: string): Unavailable =>\n new Unavailable({\n feature,\n ticket: \"control-channel-registry\"\n })\n\nconst deliveryKey = (channel: string, run: RunSummary): string => `${channel.length}:${channel}:${run.runId}`\n\n/** Collision-free control-plane key for one channel-owned external key. */\nconst scopedKey = (channel: string, key: IdempotencyKey): IdempotencyKey =>\n `channel:${channel.length}:${channel}:${key}`\n\nconst mutationKey = (channel: string, key: IdempotencyKey): IdempotencyKey =>\n `channel.ingest:${scopedKey(channel, key)}`\n\nconst typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object\nconst typedArrayBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype, \"buffer\")?.get\nconst typedArrayByteOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype, \"byteOffset\")?.get\nconst typedArrayByteLength = Object.getOwnPropertyDescriptor(typedArrayPrototype, \"byteLength\")?.get\n\nclass InboundBoundaryError extends TypeError {\n readonly issue: string\n constructor(issue: string) {\n super(issue)\n this.issue = issue\n }\n}\n\nconst boundary = (issue: string): never => {\n throw new InboundBoundaryError(issue)\n}\n\nconst plainRecord = (input: unknown, path: string): Record<PropertyKey, unknown> => {\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return boundary(`${path}: must be a plain record`)\n }\n const prototype = Object.getPrototypeOf(input)\n if (prototype !== Object.prototype && prototype !== null) {\n return boundary(`${path}: must have a plain prototype`)\n }\n return input as Record<PropertyKey, unknown>\n}\n\nconst ownData = (input: Record<PropertyKey, unknown>, key: PropertyKey, path: string): unknown => {\n const descriptor = Object.getOwnPropertyDescriptor(input, key)\n if (descriptor === undefined || !(\"value\" in descriptor)) return boundary(`${path}: must be an own data property`)\n return descriptor.value\n}\n\nconst copyBody = (input: unknown): Uint8Array => {\n /* v8 ignore next 4 -- every host that has `Uint8Array` has its prototype accessors; the refusal exists so a host without them fails closed rather than reading a caller-owned buffer */\n if (\n typedArrayBuffer === undefined || typedArrayByteOffset === undefined ||\n typedArrayByteLength === undefined\n ) return boundary(\"raw.body: this host cannot inspect typed arrays\")\n try {\n const buffer = Reflect.apply(typedArrayBuffer, input, []) as ArrayBufferLike\n const byteOffset = Reflect.apply(typedArrayByteOffset, input, []) as number\n const byteLength = Reflect.apply(typedArrayByteLength, input, []) as number\n const source = new Uint8Array(buffer, byteOffset, byteLength)\n const snapshot = new Uint8Array(byteLength)\n snapshot.set(source)\n return snapshot\n } catch {\n return boundary(\"raw.body: must be a Uint8Array\")\n }\n}\n\nconst snapshotHeaders = (input: unknown): Readonly<Record<string, string | undefined>> => {\n const record = plainRecord(input, \"raw.headers\")\n const snapshot = Object.create(null) as Record<string, string | undefined>\n for (const key of Reflect.ownKeys(record)) {\n if (typeof key !== \"string\") return boundary(\"raw.headers: symbol keys are not supported\")\n const descriptor = Object.getOwnPropertyDescriptor(record, key)\n if (descriptor === undefined || !(\"value\" in descriptor) || !descriptor.enumerable) {\n return boundary(`raw.headers.${key}: must be an enumerable data property`)\n }\n if (descriptor.value !== undefined && typeof descriptor.value !== \"string\") {\n return boundary(`raw.headers.${key}: must be a string or undefined`)\n }\n const normalized = key.toLowerCase()\n if (Object.hasOwn(snapshot, normalized)) {\n return boundary(`raw.headers.${normalized}: duplicate case-insensitive name`)\n }\n snapshot[normalized] = descriptor.value as string | undefined\n }\n return Object.freeze(snapshot)\n}\n\nconst snapshotRequest = (\n input: IngestRequest\n): Effect.Effect<{ readonly channel: string; readonly raw: RawInbound }, InvalidInput> =>\n Effect.try({\n try: () => {\n const request = plainRecord(input, \"request\")\n const channel = ownData(request, \"channel\", \"request.channel\")\n const candidate = plainRecord(ownData(request, \"raw\", \"request.raw\"), \"request.raw\")\n const idempotencyKey = ownData(candidate, \"idempotencyKey\", \"raw.idempotencyKey\")\n if (typeof channel !== \"string\" || channel.length === 0) return boundary(\"request.channel: must be non-empty\")\n if (typeof idempotencyKey !== \"string\" || idempotencyKey.length === 0) {\n return boundary(\"raw.idempotencyKey: must be non-empty\")\n }\n return Object.freeze({\n channel,\n raw: Object.freeze({\n body: copyBody(ownData(candidate, \"body\", \"raw.body\")),\n headers: snapshotHeaders(ownData(candidate, \"headers\", \"raw.headers\")),\n idempotencyKey\n })\n })\n },\n catch: (cause) =>\n new InvalidInput({\n issue: cause instanceof InboundBoundaryError ? cause.issue : \"channel request could not be inspected safely\"\n })\n })\n\nconst normalizedFingerprintHeaders = (channel: RegisteredChannel): ReadonlyArray<string> =>\n Array.from(new Set((channel.fingerprintHeaders ?? []).map((name) => name.toLowerCase()))).sort()\n\n/** Digests the body plus only the adapter-declared, non-secret semantic headers. */\nconst fingerprint = (\n body: Uint8Array,\n headers: Readonly<Record<string, string | undefined>>,\n names: ReadonlyArray<string>\n): string => {\n const document = JSON.stringify([\n Sha256.digestSync(body),\n names.map((name) => [name, headers[name] ?? null])\n ])\n return `channel-ingress:v2:${Sha256.digestSync(new TextEncoder().encode(document))}`\n}\n\nconst externalReceipt = (receipt: Receipt, key: IdempotencyKey): Receipt => {\n switch (receipt._tag) {\n case \"Accepted\":\n case \"AlreadyApplied\":\n case \"Parked\":\n return { ...receipt, receiptId: key }\n default:\n return receipt\n }\n}\n\n/** The slice of the control runtime's mutation store that inbound idempotency uses. */\ninterface InboundReceiptStore {\n readonly lookupMutation: (\n key: IdempotencyKey,\n fingerprint: string\n ) => Effect.Effect<Receipt | undefined, ControlError>\n readonly recordMutation: (\n key: IdempotencyKey,\n fingerprint: string,\n receipt: Receipt\n ) => Effect.Effect<void, ControlError>\n}\n\n/**\n * Builds an in-memory channel registry and delivery map over Control's durable\n * mutation store. Inbound idempotency therefore survives coordinator restarts;\n * only registration and outbound projection cursors are process-local.\n */\nconst makeWith = (runtime: InboundReceiptStore) =>\n Effect.gen(function*() {\n const channels = yield* Ref.make(new Map<string, RegisteredChannel>())\n const deliveries = new Map<string, Delivery>()\n // Live identities are never evicted. Terminal identities have a FIFO window\n // for reconnects; retaining one per historical run would grow without bound.\n const terminalDeliveries = new Set<string>()\n const maximumTerminalDeliveries = 1024\n const ingestion = yield* Semaphore.make(1)\n const control = yield* Control\n\n const lookup = Effect.fn(\"Channels.lookup\")(\n function*(name: string): Effect.fn.Return<RegisteredChannel, Unavailable> {\n return yield* Effect.flatMap(Ref.get(channels), (registered) => {\n const channel = registered.get(name)\n return channel === undefined\n ? Effect.fail(unavailable(`channel \"${name}\" is not registered`))\n : Effect.succeed(channel)\n })\n }\n )\n\n return Channels.of({\n register: Effect.fn(\"Channels.register\")(<A>(channel: Channel<A>) =>\n Ref.update(channels, (registered) => {\n const next = new Map(registered)\n next.set(channel.name, eraseChannel(channel))\n return next\n })\n ),\n lookup,\n ingest: Effect.fn(\"Channels.ingest\")((request) =>\n Effect.flatMap(snapshotRequest(request), (snapshot) =>\n ingestion.withPermits(1)(Effect.gen(function*() {\n const channel = yield* lookup(snapshot.channel)\n const fingerprintHeaders = normalizedFingerprintHeaders(channel)\n const bodyFingerprint = fingerprint(snapshot.raw.body, snapshot.raw.headers, fingerprintHeaders)\n // This ordering is intentional: signature verification is the\n // amplification guard and must happen before decode or Control access.\n // The verifier receives its own body copy, so even a verifier that\n // edits bytes cannot change what the decoder sees after approval.\n yield* channel.verify({ ...snapshot.raw, body: copyBody(snapshot.raw.body) })\n const externalKey = snapshot.raw.idempotencyKey\n const durableKey = mutationKey(snapshot.channel, externalKey)\n const prior = yield* runtime.lookupMutation(durableKey, bodyFingerprint)\n if (prior !== undefined) return externalReceipt(prior, externalKey)\n\n const mapped = yield* channel.decodeAndMap(snapshot.raw)\n const key = scopedKey(snapshot.channel, externalKey)\n let receipt: Receipt\n if (mapped._tag === \"Signal\") {\n // The channel is the caller, not the local operator: a webhook\n // body names the run and wait, so a signal it maps to answers a\n // human wait only if the host delegates approval to this channel.\n receipt = yield* control.signal({\n runId: mapped.runId,\n signal: mapped.signal,\n idempotencyKey: key,\n principal: { id: snapshot.channel, kind: \"channel\", stampedAt: yield* Clock.currentTimeMillis }\n })\n } else {\n const plan = yield* control.plan({\n flowId: mapped.flowId,\n input: mapped.input,\n idempotencyKey: key\n })\n receipt = yield* control.run({\n _tag: \"Plan\",\n planId: plan.planId,\n digest: plan.digest,\n envelope: plan.envelope,\n idempotencyKey: key\n })\n }\n // A parked start has not launched. Leave ingress unsettled so a\n // redelivery can retry the same Control key after plan approval.\n if (receipt._tag !== \"Conflict\" && receipt._tag !== \"Parked\") {\n yield* runtime.recordMutation(durableKey, bodyFingerprint, receipt)\n }\n return externalReceipt(receipt, externalKey)\n })))\n ),\n project: Effect.fn(\"Channels.project\")(function*(request) {\n const channel = yield* lookup(request.channel)\n const key = deliveryKey(request.channel, request.run)\n // Keep the read, projection and update synchronous so concurrent fibers\n // cannot project from the same stale delivery identity.\n return yield* Effect.sync(() => {\n const prior = deliveries.get(key)\n const projection = channel.project(request.run, prior)\n if (\n projection.operation !== \"noop\" &&\n (prior === undefined || prior.cursor !== projection.cursor || prior.messageId !== projection.messageId)\n ) {\n deliveries.set(key, { cursor: projection.cursor, messageId: projection.messageId })\n }\n if (deliveries.has(key)) {\n const status = request.run.status\n if (status === \"completed\" || status === \"failed\" || status === \"cancelled\") {\n terminalDeliveries.add(key)\n if (terminalDeliveries.size > maximumTerminalDeliveries) {\n // The set is nonempty because it just exceeded the limit.\n const oldest = terminalDeliveries.values().next().value!\n terminalDeliveries.delete(oldest)\n deliveries.delete(oldest)\n }\n } else {\n terminalDeliveries.delete(key)\n }\n }\n return projection\n })\n })\n })\n })\n\n/**\n * Builds the coordinator over Control's durable mutation store.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const make = Effect.gen(function*() {\n const runtime = yield* ControlRuntime\n return yield* makeWith(runtime)\n})\n\n/**\n * Builds a process-local coordinator for adapter unit tests.\n *\n * Production hosts use {@link layer}; this constructor deliberately makes no\n * restart guarantee.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const makeMemory = Effect.gen(function*() {\n const records = yield* Ref.make(\n new Map<IdempotencyKey, {\n readonly fingerprint: string\n readonly receipt: Receipt\n }>()\n )\n return yield* makeWith({\n lookupMutation: (key, candidate) =>\n Ref.get(records).pipe(Effect.map((stored) => {\n const prior = stored.get(key)\n if (prior === undefined) return undefined\n return prior.fingerprint === candidate\n ? alreadyApplied(key, prior.receipt)\n : { _tag: \"Conflict\", message: `idempotency key ${key} was used for another mutation` }\n })),\n recordMutation: (key, candidate, receipt) =>\n Ref.update(records, (stored) => {\n const next = new Map(stored)\n next.set(key, { fingerprint: candidate, receipt })\n return next\n })\n })\n})\n\n/**\n * Channel layer with durable inbound receipts supplied by `ControlRuntime`.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer = Layer.effect(Channels, make)\n\n/**\n * Process-local channel layer for adapter unit tests only.\n *\n * @category layers\n * @since 1.0.0\n */\nexport const layerMemory: Layer.Layer<Channels, never, Control> = Layer.effect(Channels, makeMemory)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport-independent control-plane vtable.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
import type { NotificationError } from "@smthrs/notifications/NotificationQueue";
|
|
7
|
+
import { Context, Effect, Layer, Stream } from "effect";
|
|
8
|
+
import type { AlreadyResolved, ClaimLost, CodeDrift, ControlError, EnvelopeMismatch, FlowNotFound, InvalidInput, LaunchFailed, NoMatchingWait, PersistenceError, PlanDenied, PlanDigestMismatch, PlanNotFound, RunNotFound, TransportError, Unauthorized, Unavailable } from "./ControlError.ts";
|
|
9
|
+
import type { ApprovalPayload, ControlEvent, Envelope, FlowId, IdempotencyKey, ListRequest, ListResponse, PlanCard, Principal, Receipt, RunId, RunInputSchema, SignalInputSchema, SteerInputSchema, WatchFilter } from "./ControlSchema.ts";
|
|
10
|
+
/**
|
|
11
|
+
* Raw input submitted to planning. Decoding is owned by `ControlRuntime`.
|
|
12
|
+
*
|
|
13
|
+
* This local contract accepts `unknown` so the selected flow can decode its
|
|
14
|
+
* own input. `ControlSchema.PlanInputSchema` is the narrower JSON wire
|
|
15
|
+
* contract used by RPC clients.
|
|
16
|
+
*
|
|
17
|
+
* @category models
|
|
18
|
+
* @since 0.1.0
|
|
19
|
+
*/
|
|
20
|
+
export interface PlanInput {
|
|
21
|
+
readonly flowId: FlowId;
|
|
22
|
+
readonly input: unknown;
|
|
23
|
+
readonly idempotencyKey?: IdempotencyKey | undefined;
|
|
24
|
+
/** Budget fields that replace the flow's declared ones on this plan's envelope. */
|
|
25
|
+
readonly budget?: Envelope["budget"] | undefined;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Starts an approved plan or joins/resumes an existing run.
|
|
29
|
+
*
|
|
30
|
+
* @category models
|
|
31
|
+
* @since 0.1.0
|
|
32
|
+
*/
|
|
33
|
+
export type RunInput = typeof RunInputSchema.Type & {
|
|
34
|
+
/** Trusted runtime caller reserves the execution identity; absent from public RPC. */
|
|
35
|
+
readonly reservedRunId?: RunId | undefined;
|
|
36
|
+
/** Authenticated actor used only to scope durable idempotency. */
|
|
37
|
+
readonly principal?: Principal | undefined;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* @category models
|
|
41
|
+
* @since 0.1.0
|
|
42
|
+
*/
|
|
43
|
+
export type { ApprovalTarget } from "./ControlSchema.ts";
|
|
44
|
+
/**
|
|
45
|
+
* A listing request, restricted to one reader's runs when `reader` is set.
|
|
46
|
+
*
|
|
47
|
+
* The server sets `reader` to the authenticated principal unless its
|
|
48
|
+
* `RunVisibility` lets that principal see every run; `ControlSchema.ListRequest`
|
|
49
|
+
* excludes it from the wire, so a remote client cannot widen or borrow a view.
|
|
50
|
+
* A restricted reader sees only the runs its principal launched, and the fires
|
|
51
|
+
* that started them; an in-process caller that names no reader sees every run.
|
|
52
|
+
*
|
|
53
|
+
* @category models
|
|
54
|
+
* @since 1.0.0
|
|
55
|
+
*/
|
|
56
|
+
export type ListInput = ListRequest & {
|
|
57
|
+
readonly reader?: Principal | undefined;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* A watch filter, restricted to one reader's runs when `reader` is set.
|
|
61
|
+
*
|
|
62
|
+
* A restricted reader receives the events of the runs its principal launched
|
|
63
|
+
* and nothing from a plan or from a run it did not launch. See {@link ListInput}.
|
|
64
|
+
*
|
|
65
|
+
* @category models
|
|
66
|
+
* @since 1.0.0
|
|
67
|
+
*/
|
|
68
|
+
export type WatchInput = WatchFilter & {
|
|
69
|
+
readonly reader?: Principal | undefined;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Full approval decision submitted to the authenticated server boundary.
|
|
73
|
+
*
|
|
74
|
+
* The local service may receive a runtime-stamped principal.
|
|
75
|
+
* `ControlSchema.ApprovalInputSchema` excludes it from the wire so a remote
|
|
76
|
+
* client cannot claim another identity.
|
|
77
|
+
*
|
|
78
|
+
* @category models
|
|
79
|
+
* @since 0.1.0
|
|
80
|
+
*/
|
|
81
|
+
export interface ApprovalInput extends ApprovalPayload {
|
|
82
|
+
readonly principal?: Principal | undefined;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Steering mutation arguments.
|
|
86
|
+
*
|
|
87
|
+
* @category models
|
|
88
|
+
* @since 0.1.0
|
|
89
|
+
*/
|
|
90
|
+
export type SteerInput = typeof SteerInputSchema.Type & {
|
|
91
|
+
/**
|
|
92
|
+
* Set by the server to the authenticated principal unless its
|
|
93
|
+
* `RunVisibility` lets that principal see every run. A run the reader may
|
|
94
|
+
* not see fails `RunNotFound`, exactly as a missing run does. Not on the
|
|
95
|
+
* wire; an in-process caller that names no reader mutates any run.
|
|
96
|
+
*/
|
|
97
|
+
readonly reader?: Principal | undefined;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Signal mutation arguments.
|
|
101
|
+
*
|
|
102
|
+
* @category models
|
|
103
|
+
* @since 0.1.0
|
|
104
|
+
*/
|
|
105
|
+
export type SignalInput = typeof SignalInputSchema.Type & {
|
|
106
|
+
/** Authenticated actor used only to scope durable idempotency. */
|
|
107
|
+
readonly principal?: Principal | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Set by the server to the authenticated principal unless its
|
|
110
|
+
* `RunVisibility` lets that principal see every run. A run the reader may
|
|
111
|
+
* not see fails `RunNotFound`, exactly as a missing run does. Not on the
|
|
112
|
+
* wire; an in-process caller that names no reader mutates any run.
|
|
113
|
+
*/
|
|
114
|
+
readonly reader?: Principal | undefined;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Run lifecycle mutation arguments.
|
|
118
|
+
*
|
|
119
|
+
* The local contract includes the runtime-stamped principal.
|
|
120
|
+
* `ControlSchema.ReasonedMutationInputSchema` carries only the caller's reason
|
|
121
|
+
* over RPC.
|
|
122
|
+
*
|
|
123
|
+
* @category models
|
|
124
|
+
* @since 0.1.0
|
|
125
|
+
*/
|
|
126
|
+
export interface RunMutationInput {
|
|
127
|
+
readonly runId: RunId;
|
|
128
|
+
readonly idempotencyKey: IdempotencyKey;
|
|
129
|
+
/**
|
|
130
|
+
* Why the run is being cancelled or resumed.
|
|
131
|
+
*
|
|
132
|
+
* Free text, recorded on the journal entry the mutation writes and projected
|
|
133
|
+
* back onto `RunSummary.cancellation`. An operator reading a cancelled run a
|
|
134
|
+
* week later asks "why", and a control plane that never carried the answer
|
|
135
|
+
* cannot produce one afterwards.
|
|
136
|
+
*/
|
|
137
|
+
readonly reason?: string | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* Who is asking. Stamped by the runtime, which supplies its own principal
|
|
140
|
+
* when the caller names none.
|
|
141
|
+
*/
|
|
142
|
+
readonly principal?: Principal | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* Resume only: run the flow's current code even when its execution digest
|
|
145
|
+
* differs from the one the run started with. Without it such a resume fails
|
|
146
|
+
* `CodeDrift` and leaves the run where it was.
|
|
147
|
+
*/
|
|
148
|
+
readonly allowCodeDrift?: boolean | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Set by the server to the authenticated principal unless its
|
|
151
|
+
* `RunVisibility` lets that principal see every run. A run the reader may
|
|
152
|
+
* not see fails `RunNotFound`, exactly as a missing run does. Not on the
|
|
153
|
+
* wire; an in-process caller that names no reader mutates any run.
|
|
154
|
+
*/
|
|
155
|
+
readonly reader?: Principal | undefined;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Transport-independent control operations.
|
|
159
|
+
*
|
|
160
|
+
* Every operation admits transport and authentication failures so the same
|
|
161
|
+
* service key can be provided by either a local implementation or an RPC client.
|
|
162
|
+
*
|
|
163
|
+
* @category models
|
|
164
|
+
* @since 0.1.0
|
|
165
|
+
*/
|
|
166
|
+
export interface Service {
|
|
167
|
+
readonly plan: (input: PlanInput) => Effect.Effect<PlanCard, FlowNotFound | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized>;
|
|
168
|
+
readonly run: (input: RunInput) => Effect.Effect<Receipt, RunNotFound | PlanNotFound | PlanDenied | PlanDigestMismatch | EnvelopeMismatch | ClaimLost | CodeDrift | InvalidInput | LaunchFailed | PersistenceError | Unavailable | TransportError | Unauthorized>;
|
|
169
|
+
readonly approve: (input: ApprovalInput) => Effect.Effect<Receipt, PlanDigestMismatch | EnvelopeMismatch | AlreadyResolved | PlanNotFound | RunNotFound | CodeDrift | InvalidInput | Unauthorized | PersistenceError | Unavailable | TransportError>;
|
|
170
|
+
readonly deny: (input: ApprovalInput) => Effect.Effect<Receipt, PlanDigestMismatch | EnvelopeMismatch | AlreadyResolved | PlanNotFound | RunNotFound | CodeDrift | InvalidInput | Unauthorized | PersistenceError | Unavailable | TransportError>;
|
|
171
|
+
readonly steer: (input: SteerInput) => Effect.Effect<Receipt, RunNotFound | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized | NotificationError>;
|
|
172
|
+
readonly signal: (input: SignalInput) => Effect.Effect<Receipt, RunNotFound | NoMatchingWait | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized>;
|
|
173
|
+
readonly cancel: (input: RunMutationInput) => Effect.Effect<Receipt, RunNotFound | ClaimLost | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized>;
|
|
174
|
+
readonly resume: (input: RunMutationInput) => Effect.Effect<Receipt, RunNotFound | ClaimLost | CodeDrift | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized>;
|
|
175
|
+
readonly list: (input: ListInput) => Effect.Effect<ListResponse, ControlError>;
|
|
176
|
+
/** Checkpoint `event.cursor` after processing each event and resume with `afterCursor`. */
|
|
177
|
+
readonly watch: (filter: WatchInput) => Stream.Stream<ControlEvent, ControlError>;
|
|
178
|
+
}
|
|
179
|
+
declare const Control_base: Context.ServiceClass<Control, "/control/Control", Service>;
|
|
180
|
+
/**
|
|
181
|
+
* Service key for the authoritative control-plane vtable.
|
|
182
|
+
*
|
|
183
|
+
* @category services
|
|
184
|
+
* @since 0.1.0
|
|
185
|
+
*/
|
|
186
|
+
export declare class Control extends Control_base {
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Constructs a control service from an implementation record.
|
|
190
|
+
*
|
|
191
|
+
* @category constructors
|
|
192
|
+
* @since 0.1.0
|
|
193
|
+
*/
|
|
194
|
+
export declare const make: (implementation: Service) => Service;
|
|
195
|
+
/**
|
|
196
|
+
* Provides an unavailable control implementation for optional integrations.
|
|
197
|
+
*
|
|
198
|
+
* @category layers
|
|
199
|
+
* @since 0.1.0
|
|
200
|
+
*/
|
|
201
|
+
export declare const layerNoop: Layer.Layer<Control>;
|
|
202
|
+
//# sourceMappingURL=Control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Control.d.ts","sourceRoot":"","sources":["../../src/Control.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var Control_exports = {};
|
|
20
|
+
__export(Control_exports, {
|
|
21
|
+
Control: () => Control,
|
|
22
|
+
layerNoop: () => layerNoop,
|
|
23
|
+
make: () => make
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(Control_exports);
|
|
26
|
+
var import_effect = require("effect");
|
|
27
|
+
var import_ControlError = require("./ControlError.js");
|
|
28
|
+
class Control extends import_effect.Context.Service()("/control/Control") {
|
|
29
|
+
}
|
|
30
|
+
const make = (implementation) => Control.of(implementation);
|
|
31
|
+
const unavailable = (feature) => new import_ControlError.Unavailable({ feature, ticket: "control-runtime-engine-integration" });
|
|
32
|
+
const layerNoop = import_effect.Layer.succeed(
|
|
33
|
+
Control,
|
|
34
|
+
make({
|
|
35
|
+
plan: import_effect.Effect.fn("Control.plan")(() => import_effect.Effect.fail(unavailable("plan"))),
|
|
36
|
+
run: import_effect.Effect.fn("Control.run")(() => import_effect.Effect.fail(unavailable("run"))),
|
|
37
|
+
approve: import_effect.Effect.fn("Control.approve")(() => import_effect.Effect.fail(unavailable("approve"))),
|
|
38
|
+
deny: import_effect.Effect.fn("Control.deny")(() => import_effect.Effect.fail(unavailable("deny"))),
|
|
39
|
+
steer: import_effect.Effect.fn("Control.steer")(() => import_effect.Effect.fail(unavailable("steer"))),
|
|
40
|
+
signal: import_effect.Effect.fn("Control.signal")(() => import_effect.Effect.fail(unavailable("signal"))),
|
|
41
|
+
cancel: import_effect.Effect.fn("Control.cancel")(() => import_effect.Effect.fail(unavailable("cancel"))),
|
|
42
|
+
resume: import_effect.Effect.fn("Control.resume")(() => import_effect.Effect.fail(unavailable("resume"))),
|
|
43
|
+
list: import_effect.Effect.fn("Control.list")(() => import_effect.Effect.fail(unavailable("list"))),
|
|
44
|
+
watch: () => import_effect.Stream.fail(unavailable("watch"))
|
|
45
|
+
})
|
|
46
|
+
);
|
|
47
|
+
//# sourceMappingURL=Control.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/Control.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Transport-independent control-plane vtable.\n *\n * @since 0.1.0\n */\n\nimport type { NotificationError } from \"@smthrs/notifications/NotificationQueue\"\nimport { Context, Effect, Layer, Stream } from \"effect\"\nimport type {\n AlreadyResolved,\n ClaimLost,\n CodeDrift,\n ControlError,\n EnvelopeMismatch,\n FlowNotFound,\n InvalidInput,\n LaunchFailed,\n NoMatchingWait,\n PersistenceError,\n PlanDenied,\n PlanDigestMismatch,\n PlanNotFound,\n RunNotFound,\n TransportError,\n Unauthorized,\n Unavailable\n} from \"./ControlError.ts\"\nimport { Unavailable as UnavailableError } from \"./ControlError.ts\"\nimport type {\n ApprovalPayload,\n ControlEvent,\n Envelope,\n FlowId,\n IdempotencyKey,\n ListRequest,\n ListResponse,\n PlanCard,\n Principal,\n Receipt,\n RunId,\n RunInputSchema,\n SignalInputSchema,\n SteerInputSchema,\n WatchFilter\n} from \"./ControlSchema.ts\"\n\n/**\n * Raw input submitted to planning. Decoding is owned by `ControlRuntime`.\n *\n * This local contract accepts `unknown` so the selected flow can decode its\n * own input. `ControlSchema.PlanInputSchema` is the narrower JSON wire\n * contract used by RPC clients.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface PlanInput {\n readonly flowId: FlowId\n readonly input: unknown\n readonly idempotencyKey?: IdempotencyKey | undefined\n /** Budget fields that replace the flow's declared ones on this plan's envelope. */\n readonly budget?: Envelope[\"budget\"] | undefined\n}\n\n/**\n * Starts an approved plan or joins/resumes an existing run.\n *\n * @category models\n * @since 0.1.0\n */\nexport type RunInput = typeof RunInputSchema.Type & {\n /** Trusted runtime caller reserves the execution identity; absent from public RPC. */\n readonly reservedRunId?: RunId | undefined\n /** Authenticated actor used only to scope durable idempotency. */\n readonly principal?: Principal | undefined\n}\n\n/**\n * @category models\n * @since 0.1.0\n */\nexport type { ApprovalTarget } from \"./ControlSchema.ts\"\n\n/**\n * A listing request, restricted to one reader's runs when `reader` is set.\n *\n * The server sets `reader` to the authenticated principal unless its\n * `RunVisibility` lets that principal see every run; `ControlSchema.ListRequest`\n * excludes it from the wire, so a remote client cannot widen or borrow a view.\n * A restricted reader sees only the runs its principal launched, and the fires\n * that started them; an in-process caller that names no reader sees every run.\n *\n * @category models\n * @since 1.0.0\n */\nexport type ListInput = ListRequest & {\n readonly reader?: Principal | undefined\n}\n\n/**\n * A watch filter, restricted to one reader's runs when `reader` is set.\n *\n * A restricted reader receives the events of the runs its principal launched\n * and nothing from a plan or from a run it did not launch. See {@link ListInput}.\n *\n * @category models\n * @since 1.0.0\n */\nexport type WatchInput = WatchFilter & {\n readonly reader?: Principal | undefined\n}\n\n/**\n * Full approval decision submitted to the authenticated server boundary.\n *\n * The local service may receive a runtime-stamped principal.\n * `ControlSchema.ApprovalInputSchema` excludes it from the wire so a remote\n * client cannot claim another identity.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface ApprovalInput extends ApprovalPayload {\n readonly principal?: Principal | undefined\n}\n\n/**\n * Steering mutation arguments.\n *\n * @category models\n * @since 0.1.0\n */\nexport type SteerInput = typeof SteerInputSchema.Type & {\n /**\n * Set by the server to the authenticated principal unless its\n * `RunVisibility` lets that principal see every run. A run the reader may\n * not see fails `RunNotFound`, exactly as a missing run does. Not on the\n * wire; an in-process caller that names no reader mutates any run.\n */\n readonly reader?: Principal | undefined\n}\n\n/**\n * Signal mutation arguments.\n *\n * @category models\n * @since 0.1.0\n */\nexport type SignalInput = typeof SignalInputSchema.Type & {\n /** Authenticated actor used only to scope durable idempotency. */\n readonly principal?: Principal | undefined\n /**\n * Set by the server to the authenticated principal unless its\n * `RunVisibility` lets that principal see every run. A run the reader may\n * not see fails `RunNotFound`, exactly as a missing run does. Not on the\n * wire; an in-process caller that names no reader mutates any run.\n */\n readonly reader?: Principal | undefined\n}\n\n/**\n * Run lifecycle mutation arguments.\n *\n * The local contract includes the runtime-stamped principal.\n * `ControlSchema.ReasonedMutationInputSchema` carries only the caller's reason\n * over RPC.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface RunMutationInput {\n readonly runId: RunId\n readonly idempotencyKey: IdempotencyKey\n /**\n * Why the run is being cancelled or resumed.\n *\n * Free text, recorded on the journal entry the mutation writes and projected\n * back onto `RunSummary.cancellation`. An operator reading a cancelled run a\n * week later asks \"why\", and a control plane that never carried the answer\n * cannot produce one afterwards.\n */\n readonly reason?: string | undefined\n /**\n * Who is asking. Stamped by the runtime, which supplies its own principal\n * when the caller names none.\n */\n readonly principal?: Principal | undefined\n /**\n * Resume only: run the flow's current code even when its execution digest\n * differs from the one the run started with. Without it such a resume fails\n * `CodeDrift` and leaves the run where it was.\n */\n readonly allowCodeDrift?: boolean | undefined\n /**\n * Set by the server to the authenticated principal unless its\n * `RunVisibility` lets that principal see every run. A run the reader may\n * not see fails `RunNotFound`, exactly as a missing run does. Not on the\n * wire; an in-process caller that names no reader mutates any run.\n */\n readonly reader?: Principal | undefined\n}\n\n/**\n * Transport-independent control operations.\n *\n * Every operation admits transport and authentication failures so the same\n * service key can be provided by either a local implementation or an RPC client.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Service {\n readonly plan: (\n input: PlanInput\n ) => Effect.Effect<\n PlanCard,\n FlowNotFound | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized\n >\n readonly run: (\n input: RunInput\n ) => Effect.Effect<\n Receipt,\n | RunNotFound\n | PlanNotFound\n | PlanDenied\n | PlanDigestMismatch\n | EnvelopeMismatch\n | ClaimLost\n | CodeDrift\n | InvalidInput\n | LaunchFailed\n | PersistenceError\n | Unavailable\n | TransportError\n | Unauthorized\n >\n readonly approve: (\n input: ApprovalInput\n ) => Effect.Effect<\n Receipt,\n | PlanDigestMismatch\n | EnvelopeMismatch\n | AlreadyResolved\n | PlanNotFound\n | RunNotFound\n | CodeDrift\n | InvalidInput\n | Unauthorized\n | PersistenceError\n | Unavailable\n | TransportError\n >\n readonly deny: (\n input: ApprovalInput\n ) => Effect.Effect<\n Receipt,\n | PlanDigestMismatch\n | EnvelopeMismatch\n | AlreadyResolved\n | PlanNotFound\n | RunNotFound\n | CodeDrift\n | InvalidInput\n | Unauthorized\n | PersistenceError\n | Unavailable\n | TransportError\n >\n readonly steer: (\n input: SteerInput\n ) => Effect.Effect<\n Receipt,\n RunNotFound | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized | NotificationError\n >\n readonly signal: (\n input: SignalInput\n ) => Effect.Effect<\n Receipt,\n RunNotFound | NoMatchingWait | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized\n >\n readonly cancel: (\n input: RunMutationInput\n ) => Effect.Effect<\n Receipt,\n RunNotFound | ClaimLost | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized\n >\n readonly resume: (\n input: RunMutationInput\n ) => Effect.Effect<\n Receipt,\n RunNotFound | ClaimLost | CodeDrift | InvalidInput | PersistenceError | Unavailable | TransportError | Unauthorized\n >\n readonly list: (input: ListInput) => Effect.Effect<ListResponse, ControlError>\n /** Checkpoint `event.cursor` after processing each event and resume with `afterCursor`. */\n readonly watch: (filter: WatchInput) => Stream.Stream<ControlEvent, ControlError>\n}\n\n/**\n * Service key for the authoritative control-plane vtable.\n *\n * @category services\n * @since 0.1.0\n */\nexport class Control extends Context.Service<Control, Service>()(\"/control/Control\") {}\n\n/**\n * Constructs a control service from an implementation record.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = (implementation: Service): Service => Control.of(implementation)\n\nconst unavailable = (feature: string): Unavailable =>\n new UnavailableError({ feature, ticket: \"control-runtime-engine-integration\" })\n\n/**\n * Provides an unavailable control implementation for optional integrations.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerNoop: Layer.Layer<Control> = Layer.succeed(\n Control,\n make({\n plan: Effect.fn(\"Control.plan\")(() => Effect.fail(unavailable(\"plan\"))),\n run: Effect.fn(\"Control.run\")(() => Effect.fail(unavailable(\"run\"))),\n approve: Effect.fn(\"Control.approve\")(() => Effect.fail(unavailable(\"approve\"))),\n deny: Effect.fn(\"Control.deny\")(() => Effect.fail(unavailable(\"deny\"))),\n steer: Effect.fn(\"Control.steer\")(() => Effect.fail(unavailable(\"steer\"))),\n signal: Effect.fn(\"Control.signal\")(() => Effect.fail(unavailable(\"signal\"))),\n cancel: Effect.fn(\"Control.cancel\")(() => Effect.fail(unavailable(\"cancel\"))),\n resume: Effect.fn(\"Control.resume\")(() => Effect.fail(unavailable(\"resume\"))),\n list: Effect.fn(\"Control.list\")(() => Effect.fail(unavailable(\"list\"))),\n watch: () => Stream.fail(unavailable(\"watch\"))\n })\n)\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,oBAA+C;AAoB/C,0BAAgD;AAoRzC,MAAM,gBAAgB,sBAAQ,QAA0B,EAAE,kBAAkB,EAAE;AAAC;AAQ/E,MAAM,OAAO,CAAC,mBAAqC,QAAQ,GAAG,cAAc;AAEnF,MAAM,cAAc,CAAC,YACnB,IAAI,oBAAAA,YAAiB,EAAE,SAAS,QAAQ,qCAAqC,CAAC;AAQzE,MAAM,YAAkC,oBAAM;AAAA,EACnD;AAAA,EACA,KAAK;AAAA,IACH,MAAM,qBAAO,GAAG,cAAc,EAAE,MAAM,qBAAO,KAAK,YAAY,MAAM,CAAC,CAAC;AAAA,IACtE,KAAK,qBAAO,GAAG,aAAa,EAAE,MAAM,qBAAO,KAAK,YAAY,KAAK,CAAC,CAAC;AAAA,IACnE,SAAS,qBAAO,GAAG,iBAAiB,EAAE,MAAM,qBAAO,KAAK,YAAY,SAAS,CAAC,CAAC;AAAA,IAC/E,MAAM,qBAAO,GAAG,cAAc,EAAE,MAAM,qBAAO,KAAK,YAAY,MAAM,CAAC,CAAC;AAAA,IACtE,OAAO,qBAAO,GAAG,eAAe,EAAE,MAAM,qBAAO,KAAK,YAAY,OAAO,CAAC,CAAC;AAAA,IACzE,QAAQ,qBAAO,GAAG,gBAAgB,EAAE,MAAM,qBAAO,KAAK,YAAY,QAAQ,CAAC,CAAC;AAAA,IAC5E,QAAQ,qBAAO,GAAG,gBAAgB,EAAE,MAAM,qBAAO,KAAK,YAAY,QAAQ,CAAC,CAAC;AAAA,IAC5E,QAAQ,qBAAO,GAAG,gBAAgB,EAAE,MAAM,qBAAO,KAAK,YAAY,QAAQ,CAAC,CAAC;AAAA,IAC5E,MAAM,qBAAO,GAAG,cAAc,EAAE,MAAM,qBAAO,KAAK,YAAY,MAAM,CAAC,CAAC;AAAA,IACtE,OAAO,MAAM,qBAAO,KAAK,YAAY,OAAO,CAAC;AAAA,EAC/C,CAAC;AACH;",
|
|
6
|
+
"names": ["UnavailableError"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RPC client layer projected back into the control service interface.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
import { Layer } from "effect";
|
|
7
|
+
import { HttpClient } from "effect/unstable/http";
|
|
8
|
+
import { Control } from "./Control.ts";
|
|
9
|
+
import { TransportError, Unauthorized } from "./ControlError.ts";
|
|
10
|
+
/**
|
|
11
|
+
* Whether a value is one of the control plane's declared failures, as opposed
|
|
12
|
+
* to a defect that escaped some other layer.
|
|
13
|
+
*
|
|
14
|
+
* Derived from `ControlError.ControlErrorSchema` rather than restated, so a new
|
|
15
|
+
* error class cannot be a member of the union and a stranger to the client.
|
|
16
|
+
*
|
|
17
|
+
* @category refinements
|
|
18
|
+
* @since 0.1.0
|
|
19
|
+
*/
|
|
20
|
+
export declare const isControlError: <I>(input: I) => input is I & (import("@smthrs/notifications/NotificationQueue").NotificationError | import("./ControlError.ts").RunNotFound | import("./ControlError.ts").PlanNotFound | import("./ControlError.ts").PlanDenied | import("./ControlError.ts").FlowNotFound | import("./ControlError.ts").PlanDigestMismatch | import("./ControlError.ts").EnvelopeMismatch | import("./ControlError.ts").ClaimLost | import("./ControlError.ts").CodeDrift | import("./ControlError.ts").AlreadyResolved | import("./ControlError.ts").InvalidInput | Unauthorized | import("./ControlError.ts").Unavailable | TransportError | import("./ControlError.ts").PersistenceError | import("./ControlError.ts").LaunchFailed | import("./ControlError.ts").NoMatchingWait | import("./ControlError.ts").CredentialConflict);
|
|
21
|
+
/**
|
|
22
|
+
* Client transport configuration. Unary procedures use HTTP at this URL;
|
|
23
|
+
* `watch` uses the abstract WebSocket supplied by the platform layer.
|
|
24
|
+
*
|
|
25
|
+
* `credential` reaches the HTTP protocol only. It is attached as a bearer
|
|
26
|
+
* token on each HTTP RPC request; the `watch` stream rides a WebSocket whose
|
|
27
|
+
* upgrade request a browser cannot add headers to, so the socket carries no
|
|
28
|
+
* credential at all in a browser deployment. A deployment that authenticates
|
|
29
|
+
* control traffic must therefore front the socket (terminate auth at a proxy
|
|
30
|
+
* that injects the credential on the upgrade) or serve `watch` over the HTTP
|
|
31
|
+
* protocol instead.
|
|
32
|
+
*
|
|
33
|
+
* @category models
|
|
34
|
+
* @since 0.1.0
|
|
35
|
+
*/
|
|
36
|
+
export interface ClientConfig {
|
|
37
|
+
readonly url: string;
|
|
38
|
+
/**
|
|
39
|
+
* Bearer token attached to every HTTP RPC request when present.
|
|
40
|
+
*
|
|
41
|
+
* Not sent on the `watch` WebSocket: see {@link ClientConfig}.
|
|
42
|
+
*/
|
|
43
|
+
readonly credential?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Provides `Control` through an RPC client while preserving the local vtable.
|
|
47
|
+
*
|
|
48
|
+
* @category layers
|
|
49
|
+
* @since 0.1.0
|
|
50
|
+
*/
|
|
51
|
+
export declare const layer: (config: ClientConfig) => Layer.Layer<Control, never, import("effect/unstable/rpc/RpcSerialization").RpcSerialization | HttpClient.HttpClient | import("effect/unstable/socket/Socket").Socket>;
|
|
52
|
+
//# sourceMappingURL=ControlClient.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ControlClient.d.ts","sourceRoot":"","sources":["../../src/ControlClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAiB,KAAK,EAA0B,MAAM,QAAQ,CAAA;AACrE,OAAO,EAAE,UAAU,EAAqB,MAAM,sBAAsB,CAAA;AAEpE,OAAO,EAAE,OAAO,EAAQ,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAyC,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAcvG;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,yxBAAgC,CAAA;AAiM3D;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACzC;AAED;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,QAAQ,YAAY,0KA4DzC,CAAA"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var ControlClient_exports = {};
|
|
20
|
+
__export(ControlClient_exports, {
|
|
21
|
+
isControlError: () => isControlError,
|
|
22
|
+
layer: () => layer
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(ControlClient_exports);
|
|
25
|
+
var import_effect = require("effect");
|
|
26
|
+
var import_http = require("effect/unstable/http");
|
|
27
|
+
var import_rpc = require("effect/unstable/rpc");
|
|
28
|
+
var import_Control = require("./Control.js");
|
|
29
|
+
var import_ControlError = require("./ControlError.js");
|
|
30
|
+
var import_ControlRpcs = require("./ControlRpcs.js");
|
|
31
|
+
var import_ControlSchema = require("./ControlSchema.js");
|
|
32
|
+
const isControlError = import_effect.Schema.is(import_ControlError.ControlErrorSchema);
|
|
33
|
+
const requestEncoding = {
|
|
34
|
+
message: "The control request could not be encoded.",
|
|
35
|
+
retryable: false
|
|
36
|
+
};
|
|
37
|
+
const responseDecoding = {
|
|
38
|
+
message: "The control response could not be decoded.",
|
|
39
|
+
retryable: false
|
|
40
|
+
};
|
|
41
|
+
const connectionFailure = {
|
|
42
|
+
message: "The control server could not be reached.",
|
|
43
|
+
retryable: true
|
|
44
|
+
};
|
|
45
|
+
const clientHttpFailure = {
|
|
46
|
+
message: "The control server rejected the HTTP request.",
|
|
47
|
+
retryable: false
|
|
48
|
+
};
|
|
49
|
+
const serverHttpFailure = {
|
|
50
|
+
message: "The control server failed while handling the HTTP request.",
|
|
51
|
+
retryable: true
|
|
52
|
+
};
|
|
53
|
+
const invalidClientUrl = {
|
|
54
|
+
message: "The control server URL is invalid.",
|
|
55
|
+
retryable: false
|
|
56
|
+
};
|
|
57
|
+
const unknownClientFailure = {
|
|
58
|
+
message: "The control RPC client failed.",
|
|
59
|
+
retryable: false
|
|
60
|
+
};
|
|
61
|
+
const transportError = (cause, classification) => new import_ControlError.TransportError({
|
|
62
|
+
...classification,
|
|
63
|
+
cause
|
|
64
|
+
});
|
|
65
|
+
const statusFrom = (cause) => {
|
|
66
|
+
if (typeof cause !== "object" || cause === null || !("response" in cause)) return void 0;
|
|
67
|
+
const response = cause.response;
|
|
68
|
+
if (typeof response !== "object" || response === null || !("status" in response)) return void 0;
|
|
69
|
+
return typeof response.status === "number" ? response.status : void 0;
|
|
70
|
+
};
|
|
71
|
+
const httpClassification = {
|
|
72
|
+
TransportError: connectionFailure,
|
|
73
|
+
EncodeError: requestEncoding,
|
|
74
|
+
InvalidUrlError: invalidClientUrl,
|
|
75
|
+
DecodeError: responseDecoding,
|
|
76
|
+
EmptyBodyError: responseDecoding
|
|
77
|
+
};
|
|
78
|
+
const reasonClassification = {
|
|
79
|
+
RpcClientDefect: responseDecoding,
|
|
80
|
+
SocketReadError: connectionFailure,
|
|
81
|
+
SocketWriteError: connectionFailure,
|
|
82
|
+
SocketOpenError: connectionFailure,
|
|
83
|
+
// The socket cannot perform a requested protocol upgrade; retries of the
|
|
84
|
+
// same unsupported operation cannot change that host capability.
|
|
85
|
+
SocketUpgradeError: unknownClientFailure,
|
|
86
|
+
SocketCloseError: connectionFailure,
|
|
87
|
+
// A worker transport is not composable with this client, which speaks HTTP
|
|
88
|
+
// and WebSocket. The entries exist so the table stays exhaustive.
|
|
89
|
+
WorkerSpawnError: unknownClientFailure,
|
|
90
|
+
WorkerSendError: unknownClientFailure,
|
|
91
|
+
WorkerReceiveError: unknownClientFailure,
|
|
92
|
+
WorkerUnknownError: unknownClientFailure
|
|
93
|
+
};
|
|
94
|
+
const classifyRpcClientError = (error) => {
|
|
95
|
+
const reason = error.reason;
|
|
96
|
+
if (reason._tag !== "HttpError") return reasonClassification[reason._tag];
|
|
97
|
+
if (reason.kind !== "StatusCodeError") return httpClassification[reason.kind];
|
|
98
|
+
const status = statusFrom(reason.cause);
|
|
99
|
+
return status !== void 0 && status >= 500 && status <= 599 ? serverHttpFailure : clientHttpFailure;
|
|
100
|
+
};
|
|
101
|
+
const isRpcClientError = import_effect.Schema.is(import_rpc.RpcClientError.RpcClientError);
|
|
102
|
+
const classify = (error) => {
|
|
103
|
+
if (import_effect.Schema.isSchemaError(error)) return responseDecoding;
|
|
104
|
+
if (isRpcClientError(error)) return classifyRpcClientError(error);
|
|
105
|
+
return unknownClientFailure;
|
|
106
|
+
};
|
|
107
|
+
const normalizedFailure = (cause) => {
|
|
108
|
+
const failure = import_effect.Cause.findError(cause);
|
|
109
|
+
if (import_effect.Result.isSuccess(failure)) {
|
|
110
|
+
return import_effect.Effect.fail(
|
|
111
|
+
isControlError(failure.success) ? failure.success : transportError(failure.success, classify(failure.success))
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const defect = import_effect.Cause.findDefect(cause);
|
|
115
|
+
return import_effect.Result.isSuccess(defect) ? import_effect.Effect.fail(transportError(defect.success, classify(defect.success))) : import_effect.Effect.failCause(cause);
|
|
116
|
+
};
|
|
117
|
+
const normalize = (effect) => import_effect.Effect.catchCause(effect, normalizedFailure);
|
|
118
|
+
const encoder = (schema) => (
|
|
119
|
+
// Every request schema in this module is service-free. `Schema.Top` erases
|
|
120
|
+
// that fact to `unknown`, so restore it at this one construction boundary.
|
|
121
|
+
import_effect.Schema.encodeUnknownEffect(import_effect.Schema.toCodecJson(schema))
|
|
122
|
+
);
|
|
123
|
+
const planEncoder = encoder(import_ControlSchema.PlanInputSchema);
|
|
124
|
+
const runEncoder = encoder(import_ControlSchema.RunInputSchema);
|
|
125
|
+
const approvalEncoder = encoder(import_ControlSchema.ApprovalInputSchema);
|
|
126
|
+
const steerEncoder = encoder(import_ControlSchema.SteerInputSchema);
|
|
127
|
+
const signalEncoder = encoder(import_ControlSchema.SignalInputSchema);
|
|
128
|
+
const cancelEncoder = encoder(import_ControlSchema.CancelInputSchema);
|
|
129
|
+
const resumeEncoder = encoder(import_ControlSchema.ResumeInputSchema);
|
|
130
|
+
const listEncoder = encoder(import_ControlSchema.ListRequest);
|
|
131
|
+
const watchEncoder = encoder(import_ControlSchema.WatchFilter);
|
|
132
|
+
const normalizeRequest = (encode, input, request) => encode(input).pipe(
|
|
133
|
+
import_effect.Effect.mapError((cause) => transportError(cause, requestEncoding)),
|
|
134
|
+
import_effect.Effect.andThen(import_effect.Effect.suspend(() => normalize(request())))
|
|
135
|
+
);
|
|
136
|
+
const normalizeStream = (stream) => import_effect.Stream.catchCause(stream, (cause) => import_effect.Stream.fromEffect(normalizedFailure(cause)));
|
|
137
|
+
const normalizeStreamRequest = (encode, input, request) => import_effect.Stream.unwrap(
|
|
138
|
+
encode(input).pipe(
|
|
139
|
+
import_effect.Effect.mapError((cause) => transportError(cause, requestEncoding)),
|
|
140
|
+
import_effect.Effect.map(() => normalizeStream(request()))
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
const layer = (config) => {
|
|
144
|
+
const http = import_rpc.RpcClient.layerProtocolHttp({
|
|
145
|
+
url: config.url,
|
|
146
|
+
transformClient: (client) => {
|
|
147
|
+
const checked = import_http.HttpClient.filterStatusOk(client);
|
|
148
|
+
return config.credential === void 0 ? checked : import_http.HttpClient.mapRequest(checked, import_http.HttpClientRequest.bearerToken(config.credential));
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
const websocket = import_rpc.RpcClient.layerProtocolSocket();
|
|
152
|
+
return import_effect.Layer.effect(
|
|
153
|
+
import_Control.Control,
|
|
154
|
+
import_effect.Effect.gen(function* () {
|
|
155
|
+
const httpServices = yield* import_effect.Layer.build(http);
|
|
156
|
+
const websocketServices = yield* import_effect.Layer.build(websocket);
|
|
157
|
+
const unary = yield* import_rpc.RpcClient.make(import_ControlRpcs.ControlRpcs).pipe(import_effect.Effect.provide(httpServices));
|
|
158
|
+
const streaming = yield* import_rpc.RpcClient.make(import_ControlRpcs.ControlRpcs).pipe(import_effect.Effect.provide(websocketServices));
|
|
159
|
+
return (0, import_Control.make)({
|
|
160
|
+
plan: import_effect.Effect.fn("Control.plan")((input) => normalizeRequest(planEncoder, input, () => unary.Plan(input))),
|
|
161
|
+
run: import_effect.Effect.fn("Control.run")((input) => normalizeRequest(runEncoder, input, () => unary.Run(input))),
|
|
162
|
+
// RPC authenticates with this client's credential and does not carry
|
|
163
|
+
// local attribution. Refuse here before an agent becomes that operator.
|
|
164
|
+
approve: import_effect.Effect.fn("Control.approve")(
|
|
165
|
+
(input) => normalizeRequest(approvalEncoder, input, () => input.principal?.kind === "agent" ? import_effect.Effect.fail(new import_ControlError.Unauthorized({ message: "Approval decisions are operator-only" })) : unary.Approve(input))
|
|
166
|
+
),
|
|
167
|
+
deny: import_effect.Effect.fn("Control.deny")(
|
|
168
|
+
(input) => normalizeRequest(approvalEncoder, input, () => input.principal?.kind === "agent" ? import_effect.Effect.fail(new import_ControlError.Unauthorized({ message: "Approval decisions are operator-only" })) : unary.Deny(input))
|
|
169
|
+
),
|
|
170
|
+
steer: import_effect.Effect.fn("Control.steer")((input) => normalizeRequest(steerEncoder, input, () => unary.Steer(input))),
|
|
171
|
+
signal: import_effect.Effect.fn("Control.signal")(
|
|
172
|
+
(input) => normalizeRequest(signalEncoder, input, () => unary.Signal(input))
|
|
173
|
+
),
|
|
174
|
+
cancel: import_effect.Effect.fn("Control.cancel")(
|
|
175
|
+
(input) => normalizeRequest(cancelEncoder, input, () => unary.Cancel(input))
|
|
176
|
+
),
|
|
177
|
+
resume: import_effect.Effect.fn("Control.resume")(
|
|
178
|
+
(input) => normalizeRequest(resumeEncoder, input, () => unary.Resume(input))
|
|
179
|
+
),
|
|
180
|
+
list: import_effect.Effect.fn("Control.list")((input) => normalizeRequest(listEncoder, input, () => unary.List(input))),
|
|
181
|
+
// `watch` is the only procedure on the socket protocol, and the
|
|
182
|
+
// socket is why `credential` cannot protect it: a browser's WebSocket
|
|
183
|
+
// upgrade takes no headers, so the bearer token that authenticates
|
|
184
|
+
// every unary call above never reaches this stream. Credentialed
|
|
185
|
+
// deployments front the socket or use the HTTP protocol for watch.
|
|
186
|
+
watch: (input) => normalizeStreamRequest(watchEncoder, input, () => streaming.Watch(input))
|
|
187
|
+
});
|
|
188
|
+
})
|
|
189
|
+
);
|
|
190
|
+
};
|
|
191
|
+
//# sourceMappingURL=ControlClient.js.map
|