@smthrs/control 0.0.0-stage → 1.0.0-rc.3
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 +1280 -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 +740 -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 +1521 -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 +1585 -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 +807 -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 +5 -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 +2113 -0
- package/src/ControlRpcs.ts +443 -0
- package/src/ControlRuntime.ts +1597 -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 +2476 -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,135 @@
|
|
|
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 ScopedToken_exports = {};
|
|
20
|
+
__export(ScopedToken_exports, {
|
|
21
|
+
Claims: () => Claims,
|
|
22
|
+
authenticator: () => authenticator,
|
|
23
|
+
authorizes: () => authorizes,
|
|
24
|
+
isScopedToken: () => isScopedToken,
|
|
25
|
+
mint: () => mint,
|
|
26
|
+
prefix: () => prefix,
|
|
27
|
+
procedures: () => procedures,
|
|
28
|
+
scopeNames: () => scopeNames,
|
|
29
|
+
scopes: () => scopes,
|
|
30
|
+
verify: () => verify
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(ScopedToken_exports);
|
|
33
|
+
var import_effect = require("effect");
|
|
34
|
+
var import_ControlError = require("./ControlError.js");
|
|
35
|
+
var import_ControlRpcs = require("./ControlRpcs.js");
|
|
36
|
+
const prefix = "smt1";
|
|
37
|
+
const scopes = {
|
|
38
|
+
"read:runs": ["List", "Watch", "Projection.Snapshot", "Projection.Subscribe"],
|
|
39
|
+
"write:runs": ["Plan", "Run", "Steer", "Signal", "Cancel", "Resume", "Run.Fork", "Run.Verify"],
|
|
40
|
+
"approve:runs": ["Approve", "Deny", "Approval.Submit"]
|
|
41
|
+
};
|
|
42
|
+
const scopeNames = Object.keys(scopes);
|
|
43
|
+
const Claims = import_effect.Schema.Struct({
|
|
44
|
+
v: import_effect.Schema.Literal(1),
|
|
45
|
+
/** A random identifier, so two tokens with the same grant differ. */
|
|
46
|
+
id: import_effect.Schema.String,
|
|
47
|
+
procedures: import_effect.Schema.Array(import_effect.Schema.String),
|
|
48
|
+
runId: import_effect.Schema.optional(import_effect.Schema.String),
|
|
49
|
+
flowId: import_effect.Schema.optional(import_effect.Schema.String),
|
|
50
|
+
/** Minted at, milliseconds since the epoch. */
|
|
51
|
+
iat: import_effect.Schema.Number,
|
|
52
|
+
/** Expires at, milliseconds since the epoch; refused once `now >= exp`. */
|
|
53
|
+
exp: import_effect.Schema.Number
|
|
54
|
+
});
|
|
55
|
+
const encodeClaims = import_effect.Schema.encodeUnknownSync(Claims);
|
|
56
|
+
const decodeClaims = import_effect.Schema.decodeUnknownResult(Claims);
|
|
57
|
+
const encoder = new TextEncoder();
|
|
58
|
+
const subtle = () => {
|
|
59
|
+
const available = globalThis.crypto?.subtle;
|
|
60
|
+
if (available === void 0) throw new Error("Web Crypto is not available on this host");
|
|
61
|
+
return available;
|
|
62
|
+
};
|
|
63
|
+
const hmacKey = (key, usage) => subtle().importKey("raw", encoder.encode(key), { name: "HMAC", hash: "SHA-256" }, false, [usage]);
|
|
64
|
+
const isScopedToken = (credential) => credential.startsWith(`${prefix}.`);
|
|
65
|
+
const procedures = (names) => [...new Set(names.flatMap((name) => scopes[name]))];
|
|
66
|
+
const mint = (options) => import_effect.Effect.suspend(() => {
|
|
67
|
+
if (options.key.length === 0) return import_effect.Effect.die(new Error("A scoped token needs a non-empty signing key"));
|
|
68
|
+
if (options.scopes.length === 0) return import_effect.Effect.die(new Error("A scoped token needs at least one scope"));
|
|
69
|
+
if (!Number.isFinite(options.ttlMillis) || options.ttlMillis <= 0) {
|
|
70
|
+
return import_effect.Effect.die(new Error("A scoped token needs a positive lifetime"));
|
|
71
|
+
}
|
|
72
|
+
const now = options.now?.() ?? Date.now();
|
|
73
|
+
const id = import_effect.Encoding.encodeHex(crypto.getRandomValues(new Uint8Array(12)));
|
|
74
|
+
const claims = {
|
|
75
|
+
v: 1,
|
|
76
|
+
id,
|
|
77
|
+
procedures: procedures(options.scopes),
|
|
78
|
+
...options.runId === void 0 ? {} : { runId: options.runId },
|
|
79
|
+
...options.flowId === void 0 ? {} : { flowId: options.flowId },
|
|
80
|
+
iat: now,
|
|
81
|
+
exp: now + Math.floor(options.ttlMillis)
|
|
82
|
+
};
|
|
83
|
+
const body = import_effect.Encoding.encodeBase64Url(JSON.stringify(encodeClaims(claims)));
|
|
84
|
+
return import_effect.Effect.promise(async () => {
|
|
85
|
+
const key = await hmacKey(options.key, "sign");
|
|
86
|
+
const signature = new Uint8Array(await subtle().sign("HMAC", key, encoder.encode(`${prefix}.${body}`)));
|
|
87
|
+
return { token: `${prefix}.${body}.${import_effect.Encoding.encodeBase64Url(signature)}`, claims };
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
const refused = (message) => import_effect.Effect.fail(new import_ControlError.Unauthorized({ message }));
|
|
91
|
+
const verify = (key, token, now) => import_effect.Effect.suspend(() => {
|
|
92
|
+
const parts = token.split(".");
|
|
93
|
+
if (key.length === 0 || parts.length !== 3 || parts[0] !== prefix || parts[1].length === 0) {
|
|
94
|
+
return refused("A valid scoped token is required");
|
|
95
|
+
}
|
|
96
|
+
const signature = import_effect.Encoding.decodeBase64Url(parts[2]);
|
|
97
|
+
if (import_effect.Result.isFailure(signature)) return refused("A valid scoped token is required");
|
|
98
|
+
return import_effect.Effect.promise(async () => {
|
|
99
|
+
const hmac = await hmacKey(key, "verify");
|
|
100
|
+
return subtle().verify("HMAC", hmac, new Uint8Array(signature.success), encoder.encode(`${prefix}.${parts[1]}`));
|
|
101
|
+
}).pipe(
|
|
102
|
+
import_effect.Effect.flatMap((valid) => {
|
|
103
|
+
if (!valid) return refused("A valid scoped token is required");
|
|
104
|
+
const text = import_effect.Encoding.decodeBase64UrlString(parts[1]);
|
|
105
|
+
if (import_effect.Result.isFailure(text)) return refused("A valid scoped token is required");
|
|
106
|
+
let parsed;
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(text.success);
|
|
109
|
+
} catch {
|
|
110
|
+
return refused("A valid scoped token is required");
|
|
111
|
+
}
|
|
112
|
+
const claims = decodeClaims(parsed);
|
|
113
|
+
if (import_effect.Result.isFailure(claims)) return refused("A valid scoped token is required");
|
|
114
|
+
if (!(now < claims.success.exp)) return refused("The scoped token has expired");
|
|
115
|
+
return import_effect.Effect.succeed(claims.success);
|
|
116
|
+
})
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
const field = (value, name) => typeof value === "object" && value !== null ? value[name] : void 0;
|
|
120
|
+
const namedRun = (payload) => field(payload, "runId") ?? field(field(payload, "target"), "runId") ?? field(field(payload, "selector"), "runId") ?? field(field(payload, "filters"), "runId");
|
|
121
|
+
const namedFlow = (payload) => field(payload, "flowId") ?? field(field(payload, "filters"), "flowId");
|
|
122
|
+
const authorizes = (claims, call) => claims.procedures.includes(call.rpc) && (claims.runId === void 0 || namedRun(call.payload) === claims.runId) && (claims.flowId === void 0 || namedFlow(call.payload) === claims.flowId);
|
|
123
|
+
const authenticator = (options) => ({
|
|
124
|
+
authenticate: (headers, call) => {
|
|
125
|
+
const credential = (0, import_ControlRpcs.bearerCredential)(headers);
|
|
126
|
+
if (credential === void 0 || !isScopedToken(credential)) return refused("A valid scoped token is required");
|
|
127
|
+
const now = options.now?.() ?? Date.now();
|
|
128
|
+
return verify(options.key, credential, now).pipe(
|
|
129
|
+
import_effect.Effect.flatMap(
|
|
130
|
+
(claims) => call !== void 0 && !authorizes(claims, call) ? refused(`The scoped token does not authorize ${call.rpc}`) : import_effect.Effect.succeed({ ...options.principal, stampedAt: now })
|
|
131
|
+
)
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
//# sourceMappingURL=ScopedToken.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/ScopedToken.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Scoped, expiring gateway tokens.\n *\n * A gateway's configured bearer credential grants everything the gateway\n * serves, for as long as it is configured. A scoped token is a grant the\n * holder of that credential mints for someone else: a closed list of\n * procedures, optionally confined to one run or one flow, and an expiry. It\n * is signed with HMAC-SHA256 under the bearer credential, so a gateway\n * verifies it with the key it already holds and stores nothing; rotating the\n * bearer credential revokes every token minted under it.\n *\n * The wire form is `smt1.<claims>.<signature>`, both parts unpadded base64url,\n * the claims a canonical JSON document. A token names procedures rather than\n * scope words so that what it authorizes is readable off the token itself and\n * does not change when a scope grows.\n *\n * Web Crypto does the signing, so the same module runs on Node, Bun, and in a\n * browser that holds a token.\n *\n * @since 1.0.0\n */\n\nimport { Effect, Encoding, Result, Schema } from \"effect\"\nimport { Unauthorized } from \"./ControlError.ts\"\nimport { type Authenticator, bearerCredential, type Call } from \"./ControlRpcs.ts\"\nimport type { Principal } from \"./ControlSchema.ts\"\n\n/**\n * The version prefix every scoped token starts with.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const prefix = \"smt1\"\n\n/**\n * The scopes `smthrs token mint --scope` accepts, and the procedures each\n * one names.\n *\n * `read:runs` covers every read the control plane and the gateway serve.\n * `write:runs` covers the mutations that start, steer, signal, cancel, and\n * resume a run, and the gateway's `Run.Fork` and `Run.Verify`, which branch a\n * run or drive the project's flow code over a copy of it. `approve:runs` covers the approval decisions on both mounts.\n * A token holding `approve:runs` still needs the host's `ApprovalAuthority`\n * to delegate to its principal, exactly as the bearer does.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const scopes = {\n \"read:runs\": [\"List\", \"Watch\", \"Projection.Snapshot\", \"Projection.Subscribe\"],\n \"write:runs\": [\"Plan\", \"Run\", \"Steer\", \"Signal\", \"Cancel\", \"Resume\", \"Run.Fork\", \"Run.Verify\"],\n \"approve:runs\": [\"Approve\", \"Deny\", \"Approval.Submit\"]\n} as const satisfies Record<string, ReadonlyArray<string>>\n\n/**\n * One scope name.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Scope = keyof typeof scopes\n\n/**\n * Every scope name, in the order {@link scopes} declares them.\n *\n * @category constants\n * @since 1.0.0\n */\nexport const scopeNames: ReadonlyArray<Scope> = Object.keys(scopes) as Array<Scope>\n\n/**\n * What a token grants, as signed.\n *\n * @category models\n * @since 1.0.0\n */\nexport const Claims = Schema.Struct({\n v: Schema.Literal(1),\n /** A random identifier, so two tokens with the same grant differ. */\n id: Schema.String,\n procedures: Schema.Array(Schema.String),\n runId: Schema.optional(Schema.String),\n flowId: Schema.optional(Schema.String),\n /** Minted at, milliseconds since the epoch. */\n iat: Schema.Number,\n /** Expires at, milliseconds since the epoch; refused once `now >= exp`. */\n exp: Schema.Number\n})\n\n/**\n * What a token grants, as signed.\n *\n * @category models\n * @since 1.0.0\n */\nexport type Claims = typeof Claims.Type\n\n/**\n * What `mint` needs.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface MintOptions {\n /** The signing key: the gateway's configured bearer credential. */\n readonly key: string\n readonly scopes: ReadonlyArray<Scope>\n /** How long the token lives, in milliseconds; must be positive. */\n readonly ttlMillis: number\n /** Confine every call to this run. */\n readonly runId?: string | undefined\n /** Confine every call to this flow. */\n readonly flowId?: string | undefined\n readonly now?: (() => number) | undefined\n}\n\n/**\n * A minted token beside the claims it carries.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface Minted {\n readonly token: string\n readonly claims: Claims\n}\n\nconst encodeClaims = Schema.encodeUnknownSync(Claims)\nconst decodeClaims = Schema.decodeUnknownResult(Claims)\nconst encoder = new TextEncoder()\n\nconst subtle = (): SubtleCrypto => {\n const available = (globalThis.crypto as Crypto | undefined)?.subtle\n if (available === undefined) throw new Error(\"Web Crypto is not available on this host\")\n return available\n}\n\nconst hmacKey = (key: string, usage: \"sign\" | \"verify\") =>\n subtle().importKey(\"raw\", encoder.encode(key), { name: \"HMAC\", hash: \"SHA-256\" }, false, [usage])\n\n/**\n * Whether a bearer credential is spelled as a scoped token.\n *\n * @category predicates\n * @since 1.0.0\n */\nexport const isScopedToken = (credential: string): boolean => credential.startsWith(`${prefix}.`)\n\n/**\n * The procedures a list of scopes names, each once, in scope order.\n *\n * @category getters\n * @since 1.0.0\n */\nexport const procedures = (\n names: ReadonlyArray<Scope>\n): ReadonlyArray<string> => [...new Set(names.flatMap((name) => scopes[name]))]\n\n/**\n * Mints one token under the key.\n *\n * An empty key, no scopes, or a non-positive lifetime is a caller defect: it\n * cannot produce a token anyone should hold, so it dies rather than signs.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const mint = (options: MintOptions): Effect.Effect<Minted> =>\n Effect.suspend(() => {\n if (options.key.length === 0) return Effect.die(new Error(\"A scoped token needs a non-empty signing key\"))\n if (options.scopes.length === 0) return Effect.die(new Error(\"A scoped token needs at least one scope\"))\n if (!Number.isFinite(options.ttlMillis) || options.ttlMillis <= 0) {\n return Effect.die(new Error(\"A scoped token needs a positive lifetime\"))\n }\n const now = options.now?.() ?? Date.now()\n const id = Encoding.encodeHex(crypto.getRandomValues(new Uint8Array(12)))\n const claims: Claims = {\n v: 1,\n id,\n procedures: procedures(options.scopes),\n ...(options.runId === undefined ? {} : { runId: options.runId }),\n ...(options.flowId === undefined ? {} : { flowId: options.flowId }),\n iat: now,\n exp: now + Math.floor(options.ttlMillis)\n }\n const body = Encoding.encodeBase64Url(JSON.stringify(encodeClaims(claims)))\n return Effect.promise(async () => {\n const key = await hmacKey(options.key, \"sign\")\n const signature = new Uint8Array(await subtle().sign(\"HMAC\", key, encoder.encode(`${prefix}.${body}`)))\n return { token: `${prefix}.${body}.${Encoding.encodeBase64Url(signature)}`, claims }\n })\n })\n\nconst refused = (message: string) => Effect.fail(new Unauthorized({ message }))\n\n/**\n * Verifies a token's signature and expiry under the key and returns its\n * claims. Every malformation, a wrong key, and an expired token all fail with\n * the same `Unauthorized`, so the token is not a parsing oracle.\n *\n * @param now the moment to judge `exp` against, in milliseconds\n * @category verification\n * @since 1.0.0\n */\nexport const verify = (key: string, token: string, now: number): Effect.Effect<Claims, Unauthorized> =>\n Effect.suspend(() => {\n const parts = token.split(\".\")\n if (key.length === 0 || parts.length !== 3 || parts[0] !== prefix || parts[1]!.length === 0) {\n return refused(\"A valid scoped token is required\")\n }\n const signature = Encoding.decodeBase64Url(parts[2]!)\n if (Result.isFailure(signature)) return refused(\"A valid scoped token is required\")\n return Effect.promise(async () => {\n const hmac = await hmacKey(key, \"verify\")\n return subtle().verify(\"HMAC\", hmac, new Uint8Array(signature.success), encoder.encode(`${prefix}.${parts[1]}`))\n }).pipe(\n Effect.flatMap((valid) => {\n if (!valid) return refused(\"A valid scoped token is required\")\n const text = Encoding.decodeBase64UrlString(parts[1]!)\n if (Result.isFailure(text)) return refused(\"A valid scoped token is required\")\n let parsed: unknown\n try {\n parsed = JSON.parse(text.success)\n } catch {\n return refused(\"A valid scoped token is required\")\n }\n const claims = decodeClaims(parsed)\n if (Result.isFailure(claims)) return refused(\"A valid scoped token is required\")\n if (!(now < claims.success.exp)) return refused(\"The scoped token has expired\")\n return Effect.succeed(claims.success)\n })\n )\n })\n\nconst field = (value: unknown, name: string): unknown =>\n typeof value === \"object\" && value !== null ? (value as Record<string, unknown>)[name] : undefined\n\n/** The run a payload names, wherever the control and gateway schemas put it. */\nconst namedRun = (payload: unknown): unknown =>\n field(payload, \"runId\") ??\n field(field(payload, \"target\"), \"runId\") ??\n field(field(payload, \"selector\"), \"runId\") ??\n field(field(payload, \"filters\"), \"runId\")\n\n/** The flow a payload names. */\nconst namedFlow = (payload: unknown): unknown => field(payload, \"flowId\") ?? field(field(payload, \"filters\"), \"flowId\")\n\n/**\n * Whether verified claims authorize one call.\n *\n * The procedure must be named. A token confined to a run authorizes only a\n * call that names that run, and one confined to a flow only a call that names\n * that flow: a call that names neither, such as an unfiltered `List`, is\n * refused rather than widened.\n *\n * @category verification\n * @since 1.0.0\n */\nexport const authorizes = (claims: Claims, call: Call): boolean =>\n claims.procedures.includes(call.rpc) &&\n (claims.runId === undefined || namedRun(call.payload) === claims.runId) &&\n (claims.flowId === undefined || namedFlow(call.payload) === claims.flowId)\n\n/**\n * What the scoped-token authenticator needs.\n *\n * @category models\n * @since 1.0.0\n */\nexport interface AuthenticatorOptions {\n /** The verifying key: the gateway's configured bearer credential. */\n readonly key: string\n /** The principal every valid scoped token is stamped as. */\n readonly principal: Omit<Principal, \"stampedAt\">\n readonly now?: (() => number) | undefined\n}\n\n/**\n * Authenticates a bearer credential spelled as a scoped token: the signature\n * and expiry always, and the procedure plus run or flow confinement whenever\n * the boundary knows which call it is guarding. An edge that authenticates an\n * upgrade knows no call, so it admits the socket and leaves each frame to the\n * in-band check.\n *\n * A credential that is not a scoped token is refused here; compose with\n * `ControlRpcs.bearerAuthenticator` through `ControlRpcs.anyAuthenticator`\n * to accept both.\n *\n * @category constructors\n * @since 1.0.0\n */\nexport const authenticator = (options: AuthenticatorOptions): Authenticator => ({\n authenticate: (headers, call) => {\n const credential = bearerCredential(headers)\n if (credential === undefined || !isScopedToken(credential)) return refused(\"A valid scoped token is required\")\n const now = options.now?.() ?? Date.now()\n return verify(options.key, credential, now).pipe(\n Effect.flatMap((claims) =>\n call !== undefined && !authorizes(claims, call)\n ? refused(`The scoped token does not authorize ${call.rpc}`)\n : Effect.succeed({ ...options.principal, stampedAt: now })\n )\n )\n }\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable `ControlRuntime` over `@smthrs/journal`'s fenced `RunStore` and a
|
|
3
|
+
* SQL database.
|
|
4
|
+
*
|
|
5
|
+
* `layerMemory` models the production seams but keeps everything in a `Map`, so
|
|
6
|
+
* nothing it decides survives the process. This adapter supplies the durable
|
|
7
|
+
* boundary the header of `ControlRuntime` describes.
|
|
8
|
+
*
|
|
9
|
+
* ## Where ownership lives
|
|
10
|
+
*
|
|
11
|
+
* The run lifecycle is not re-implemented here. `RunStore` already owns it, and
|
|
12
|
+
* it is the piece that is hard to get right: every ownership move is a single
|
|
13
|
+
* SQL compare-and-swap, so a stale writer loses the `UPDATE` rather than
|
|
14
|
+
* racing a read-then-write. This module maps the control plane's vocabulary
|
|
15
|
+
* onto it:
|
|
16
|
+
*
|
|
17
|
+
* | control status | `RunStore` status | ownership |
|
|
18
|
+
* | --- | --- | --- |
|
|
19
|
+
* | `accepted`, `running` | `running` | held by this process |
|
|
20
|
+
* | `accepted` after an executor declines | `suspended` | released |
|
|
21
|
+
* | `parked`, `waiting-approval` | `suspended` | released |
|
|
22
|
+
* | `cancelled` / `completed` / `failed` | same | released, terminal |
|
|
23
|
+
*
|
|
24
|
+
* The authoritative `RunSummary` is written into the row's `state_json` by the
|
|
25
|
+
* same fenced `UPDATE` that moves the status, so a projection can never be read
|
|
26
|
+
* out of step with the lifecycle. `RunStore` has no list operation, so
|
|
27
|
+
* `control_runs` is kept as a plain id index and each summary is read back
|
|
28
|
+
* through the store rather than duplicated.
|
|
29
|
+
*
|
|
30
|
+
* ## Fences
|
|
31
|
+
*
|
|
32
|
+
* A fence is a serialized `OwnerId`. `hostId` and `pid` identify the process;
|
|
33
|
+
* the `nonce` is regenerated on **every** claim, so a fence taken before a
|
|
34
|
+
* park is not the fence held after the resume that follows it, and the stale
|
|
35
|
+
* one is refused by the CAS. This is the `rangeID`-style monotonic fence from
|
|
36
|
+
* `reference/temporal`'s history service, narrowed to a per-run token.
|
|
37
|
+
*
|
|
38
|
+
* ## Browser safety
|
|
39
|
+
*
|
|
40
|
+
* Nothing here imports `node:*`. Identity comes from `globalThis.crypto`, and
|
|
41
|
+
* persistence is the driver-neutral SQL contract, so this module runs anywhere
|
|
42
|
+
* `@smthrs/database` has a driver. Fibers are the exception and are
|
|
43
|
+
* deliberately process-local: a fiber is a live continuation, not a row, and
|
|
44
|
+
* cancellation is interruption of the fiber that this process owns.
|
|
45
|
+
*
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
*/
|
|
48
|
+
import { DurableWriter } from "@smthrs/database/DurableWriter";
|
|
49
|
+
import { Ownership, RunStore } from "@smthrs/run-store";
|
|
50
|
+
import { Crypto, Effect, Layer } from "effect";
|
|
51
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
52
|
+
import * as ApprovalAuthority from "./ApprovalAuthority.ts";
|
|
53
|
+
import { PersistenceError } from "./ControlError.ts";
|
|
54
|
+
import type { MemoryFlow, Service } from "./ControlRuntime.ts";
|
|
55
|
+
import { ControlRuntime } from "./ControlRuntime.ts";
|
|
56
|
+
import { Principal } from "./ControlSchema.ts";
|
|
57
|
+
/**
|
|
58
|
+
* A flow the durable runtime can plan.
|
|
59
|
+
*
|
|
60
|
+
* The same shape the memory runtime takes, so a composition can hand the same
|
|
61
|
+
* catalog to either.
|
|
62
|
+
*
|
|
63
|
+
* @category models
|
|
64
|
+
* @since 0.1.0
|
|
65
|
+
*/
|
|
66
|
+
export type DurableFlow = MemoryFlow;
|
|
67
|
+
/**
|
|
68
|
+
* Durable runtime configuration.
|
|
69
|
+
*
|
|
70
|
+
* `owner` is the process identity every claim is stamped with. When omitted,
|
|
71
|
+
* one valid synthetic identity is minted for this runtime only, so separately
|
|
72
|
+
* constructed runtimes cannot cross each other's fences. Hosts that can
|
|
73
|
+
* report their real process identity should still supply it so liveness probes
|
|
74
|
+
* can reason about the operating-system process.
|
|
75
|
+
*
|
|
76
|
+
* @category models
|
|
77
|
+
* @since 0.1.0
|
|
78
|
+
*/
|
|
79
|
+
export interface Options {
|
|
80
|
+
readonly flows?: ReadonlyArray<DurableFlow> | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Reads the current flow catalog for each plan and listing. When supplied,
|
|
83
|
+
* this replaces `flows`, including the default system catalog. A host with
|
|
84
|
+
* a refreshable registry should return one complete snapshot per call.
|
|
85
|
+
* Existing plans retain the definition they were approved against.
|
|
86
|
+
*/
|
|
87
|
+
readonly loadFlows?: (() => Effect.Effect<ReadonlyArray<DurableFlow>, PersistenceError>) | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Reads each flow's code as it is on disk now, for the drift check that runs
|
|
90
|
+
* before a run is re-driven and for the code an allowed drift adopts. A host
|
|
91
|
+
* whose `loadFlows` answers from a cached snapshot supplies this, so a flow
|
|
92
|
+
* edited or deleted after the run parked is refused before the claim rather
|
|
93
|
+
* than found by the executor after it. Defaults to `loadFlows`.
|
|
94
|
+
*/
|
|
95
|
+
readonly currentFlows?: (() => Effect.Effect<ReadonlyArray<DurableFlow>, PersistenceError>) | undefined;
|
|
96
|
+
/** Verifies a durable pinned source closure before consenting to resume it. */
|
|
97
|
+
readonly pinnedFlow?: ((flowId: string, digest: string) => Effect.Effect<boolean | undefined, PersistenceError>) | undefined;
|
|
98
|
+
/**
|
|
99
|
+
* Makes one flow's code on disk now the code this host executes, for a
|
|
100
|
+
* resume the operator allowed to drift, and answers the identity the host
|
|
101
|
+
* can now run, or `undefined` when it can run none. A host whose executor
|
|
102
|
+
* serves a loaded snapshot supplies this: recording a digest its executor
|
|
103
|
+
* does not hold accepted the resume and then failed the run (#2740).
|
|
104
|
+
* Defaults to the flow's entry in `currentFlows`.
|
|
105
|
+
*/
|
|
106
|
+
readonly adoptFlow?: ((flowId: string, runId: string) => Effect.Effect<DurableFlow | undefined, PersistenceError>) | undefined;
|
|
107
|
+
readonly owner?: Ownership.OwnerId | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* Whether the process a running run's owner names is still working. With
|
|
110
|
+
* it, `resume` takes over a running run whose owner is gone (a host killed
|
|
111
|
+
* mid-run) once that owner's lease has expired, instead of answering
|
|
112
|
+
* `ClaimLost`; the run store verifies the expired lease. Without it a
|
|
113
|
+
* running run belongs to its recorded owner for good.
|
|
114
|
+
*/
|
|
115
|
+
readonly isAlive?: Ownership.LivenessCheck | undefined;
|
|
116
|
+
readonly principal?: Omit<Principal, "stampedAt"> | undefined;
|
|
117
|
+
readonly approvalAuthority?: ApprovalAuthority.Service | undefined;
|
|
118
|
+
/** The engine version stamped on every run this runtime starts. */
|
|
119
|
+
readonly engineVersion?: string | undefined;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Creates every control-plane table.
|
|
123
|
+
*
|
|
124
|
+
* `RunStore`'s own migrations are the journal package's business and are
|
|
125
|
+
* applied by its layer. A read-only client installs nothing.
|
|
126
|
+
*
|
|
127
|
+
* @category migrations
|
|
128
|
+
* @since 0.1.0
|
|
129
|
+
*/
|
|
130
|
+
export declare const migrate: Effect.Effect<void, PersistenceError, SqlClient.SqlClient>;
|
|
131
|
+
/**
|
|
132
|
+
* Constructs a durable runtime over the ambient database and run store.
|
|
133
|
+
*
|
|
134
|
+
* Not exported under this name: `make` below is the single public constructor.
|
|
135
|
+
* Exporting both put two names for one function on the package's public
|
|
136
|
+
* surface, and only one of them was documented.
|
|
137
|
+
*/
|
|
138
|
+
declare const makeRuntime: (options?: Options) => Effect.Effect<Service, PersistenceError, Crypto.Crypto | DurableWriter | SqlClient.SqlClient | RunStore.RunStore>;
|
|
139
|
+
/**
|
|
140
|
+
* Provides a durable runtime over the ambient database and run store.
|
|
141
|
+
*
|
|
142
|
+
* @category layers
|
|
143
|
+
* @since 0.1.0
|
|
144
|
+
*/
|
|
145
|
+
export declare const layer: (options?: Options) => Layer.Layer<ControlRuntime, PersistenceError, Crypto.Crypto | DurableWriter | SqlClient.SqlClient | RunStore.RunStore>;
|
|
146
|
+
/**
|
|
147
|
+
* Provides a durable runtime and the run store it needs over the ambient
|
|
148
|
+
* database.
|
|
149
|
+
*
|
|
150
|
+
* @category layers
|
|
151
|
+
* @since 0.1.0
|
|
152
|
+
*/
|
|
153
|
+
export declare const layerWithStore: (options?: Options) => Layer.Layer<ControlRuntime, PersistenceError, Crypto.Crypto | DurableWriter | SqlClient.SqlClient>;
|
|
154
|
+
/**
|
|
155
|
+
* Constructs a durable runtime over the ambient database and run store.
|
|
156
|
+
*
|
|
157
|
+
* @category constructors
|
|
158
|
+
* @since 0.1.0
|
|
159
|
+
*/
|
|
160
|
+
export { makeRuntime as make };
|
|
161
|
+
//# sourceMappingURL=SqlControlRuntime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SqlControlRuntime.d.ts","sourceRoot":"","sources":["../../src/SqlControlRuntime.ts"],"names":[],"mappings":"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"}
|