@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,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scoped, expiring gateway tokens.
|
|
3
|
+
*
|
|
4
|
+
* A gateway's configured bearer credential grants everything the gateway
|
|
5
|
+
* serves, for as long as it is configured. A scoped token is a grant the
|
|
6
|
+
* holder of that credential mints for someone else: a closed list of
|
|
7
|
+
* procedures, optionally confined to one run or one flow, and an expiry. It
|
|
8
|
+
* is signed with HMAC-SHA256 under the bearer credential, so a gateway
|
|
9
|
+
* verifies it with the key it already holds and stores nothing; rotating the
|
|
10
|
+
* bearer credential revokes every token minted under it.
|
|
11
|
+
*
|
|
12
|
+
* The wire form is `smt1.<claims>.<signature>`, both parts unpadded base64url,
|
|
13
|
+
* the claims a canonical JSON document. A token names procedures rather than
|
|
14
|
+
* scope words so that what it authorizes is readable off the token itself and
|
|
15
|
+
* does not change when a scope grows.
|
|
16
|
+
*
|
|
17
|
+
* Web Crypto does the signing, so the same module runs on Node, Bun, and in a
|
|
18
|
+
* browser that holds a token.
|
|
19
|
+
*
|
|
20
|
+
* @since 1.0.0
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { Effect, Encoding, Result, Schema } from "effect"
|
|
24
|
+
import { Unauthorized } from "./ControlError.ts"
|
|
25
|
+
import { type Authenticator, bearerCredential, type Call } from "./ControlRpcs.ts"
|
|
26
|
+
import type { Principal } from "./ControlSchema.ts"
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The version prefix every scoped token starts with.
|
|
30
|
+
*
|
|
31
|
+
* @category constants
|
|
32
|
+
* @since 1.0.0
|
|
33
|
+
*/
|
|
34
|
+
export const prefix = "smt1"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The scopes `smthrs token mint --scope` accepts, and the procedures each
|
|
38
|
+
* one names.
|
|
39
|
+
*
|
|
40
|
+
* `read:runs` covers every read the control plane and the gateway serve.
|
|
41
|
+
* `write:runs` covers the mutations that start, steer, signal, cancel, and
|
|
42
|
+
* resume a run, and the gateway's `Run.Fork` and `Run.Verify`, which branch a
|
|
43
|
+
* run or drive the project's flow code over a copy of it. `approve:runs` covers the approval decisions on both mounts.
|
|
44
|
+
* A token holding `approve:runs` still needs the host's `ApprovalAuthority`
|
|
45
|
+
* to delegate to its principal, exactly as the bearer does.
|
|
46
|
+
*
|
|
47
|
+
* @category constants
|
|
48
|
+
* @since 1.0.0
|
|
49
|
+
*/
|
|
50
|
+
export const scopes = {
|
|
51
|
+
"read:runs": ["List", "Watch", "Projection.Snapshot", "Projection.Subscribe"],
|
|
52
|
+
"write:runs": ["Plan", "Run", "Steer", "Signal", "Cancel", "Resume", "Run.Fork", "Run.Verify"],
|
|
53
|
+
"approve:runs": ["Approve", "Deny", "Approval.Submit"]
|
|
54
|
+
} as const satisfies Record<string, ReadonlyArray<string>>
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* One scope name.
|
|
58
|
+
*
|
|
59
|
+
* @category models
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
*/
|
|
62
|
+
export type Scope = keyof typeof scopes
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Every scope name, in the order {@link scopes} declares them.
|
|
66
|
+
*
|
|
67
|
+
* @category constants
|
|
68
|
+
* @since 1.0.0
|
|
69
|
+
*/
|
|
70
|
+
export const scopeNames: ReadonlyArray<Scope> = Object.keys(scopes) as Array<Scope>
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* What a token grants, as signed.
|
|
74
|
+
*
|
|
75
|
+
* @category models
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
*/
|
|
78
|
+
export const Claims = Schema.Struct({
|
|
79
|
+
v: Schema.Literal(1),
|
|
80
|
+
/** A random identifier, so two tokens with the same grant differ. */
|
|
81
|
+
id: Schema.String,
|
|
82
|
+
procedures: Schema.Array(Schema.String),
|
|
83
|
+
runId: Schema.optional(Schema.String),
|
|
84
|
+
flowId: Schema.optional(Schema.String),
|
|
85
|
+
/** Minted at, milliseconds since the epoch. */
|
|
86
|
+
iat: Schema.Number,
|
|
87
|
+
/** Expires at, milliseconds since the epoch; refused once `now >= exp`. */
|
|
88
|
+
exp: Schema.Number
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* What a token grants, as signed.
|
|
93
|
+
*
|
|
94
|
+
* @category models
|
|
95
|
+
* @since 1.0.0
|
|
96
|
+
*/
|
|
97
|
+
export type Claims = typeof Claims.Type
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* What `mint` needs.
|
|
101
|
+
*
|
|
102
|
+
* @category models
|
|
103
|
+
* @since 1.0.0
|
|
104
|
+
*/
|
|
105
|
+
export interface MintOptions {
|
|
106
|
+
/** The signing key: the gateway's configured bearer credential. */
|
|
107
|
+
readonly key: string
|
|
108
|
+
readonly scopes: ReadonlyArray<Scope>
|
|
109
|
+
/** How long the token lives, in milliseconds; must be positive. */
|
|
110
|
+
readonly ttlMillis: number
|
|
111
|
+
/** Confine every call to this run. */
|
|
112
|
+
readonly runId?: string | undefined
|
|
113
|
+
/** Confine every call to this flow. */
|
|
114
|
+
readonly flowId?: string | undefined
|
|
115
|
+
readonly now?: (() => number) | undefined
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* A minted token beside the claims it carries.
|
|
120
|
+
*
|
|
121
|
+
* @category models
|
|
122
|
+
* @since 1.0.0
|
|
123
|
+
*/
|
|
124
|
+
export interface Minted {
|
|
125
|
+
readonly token: string
|
|
126
|
+
readonly claims: Claims
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const encodeClaims = Schema.encodeUnknownSync(Claims)
|
|
130
|
+
const decodeClaims = Schema.decodeUnknownResult(Claims)
|
|
131
|
+
const encoder = new TextEncoder()
|
|
132
|
+
|
|
133
|
+
const subtle = (): SubtleCrypto => {
|
|
134
|
+
const available = (globalThis.crypto as Crypto | undefined)?.subtle
|
|
135
|
+
if (available === undefined) throw new Error("Web Crypto is not available on this host")
|
|
136
|
+
return available
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const hmacKey = (key: string, usage: "sign" | "verify") =>
|
|
140
|
+
subtle().importKey("raw", encoder.encode(key), { name: "HMAC", hash: "SHA-256" }, false, [usage])
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Whether a bearer credential is spelled as a scoped token.
|
|
144
|
+
*
|
|
145
|
+
* @category predicates
|
|
146
|
+
* @since 1.0.0
|
|
147
|
+
*/
|
|
148
|
+
export const isScopedToken = (credential: string): boolean => credential.startsWith(`${prefix}.`)
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The procedures a list of scopes names, each once, in scope order.
|
|
152
|
+
*
|
|
153
|
+
* @category getters
|
|
154
|
+
* @since 1.0.0
|
|
155
|
+
*/
|
|
156
|
+
export const procedures = (
|
|
157
|
+
names: ReadonlyArray<Scope>
|
|
158
|
+
): ReadonlyArray<string> => [...new Set(names.flatMap((name) => scopes[name]))]
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Mints one token under the key.
|
|
162
|
+
*
|
|
163
|
+
* An empty key, no scopes, or a non-positive lifetime is a caller defect: it
|
|
164
|
+
* cannot produce a token anyone should hold, so it dies rather than signs.
|
|
165
|
+
*
|
|
166
|
+
* @category constructors
|
|
167
|
+
* @since 1.0.0
|
|
168
|
+
*/
|
|
169
|
+
export const mint = (options: MintOptions): Effect.Effect<Minted> =>
|
|
170
|
+
Effect.suspend(() => {
|
|
171
|
+
if (options.key.length === 0) return Effect.die(new Error("A scoped token needs a non-empty signing key"))
|
|
172
|
+
if (options.scopes.length === 0) return Effect.die(new Error("A scoped token needs at least one scope"))
|
|
173
|
+
if (!Number.isFinite(options.ttlMillis) || options.ttlMillis <= 0) {
|
|
174
|
+
return Effect.die(new Error("A scoped token needs a positive lifetime"))
|
|
175
|
+
}
|
|
176
|
+
const now = options.now?.() ?? Date.now()
|
|
177
|
+
const id = Encoding.encodeHex(crypto.getRandomValues(new Uint8Array(12)))
|
|
178
|
+
const claims: Claims = {
|
|
179
|
+
v: 1,
|
|
180
|
+
id,
|
|
181
|
+
procedures: procedures(options.scopes),
|
|
182
|
+
...(options.runId === undefined ? {} : { runId: options.runId }),
|
|
183
|
+
...(options.flowId === undefined ? {} : { flowId: options.flowId }),
|
|
184
|
+
iat: now,
|
|
185
|
+
exp: now + Math.floor(options.ttlMillis)
|
|
186
|
+
}
|
|
187
|
+
const body = Encoding.encodeBase64Url(JSON.stringify(encodeClaims(claims)))
|
|
188
|
+
return Effect.promise(async () => {
|
|
189
|
+
const key = await hmacKey(options.key, "sign")
|
|
190
|
+
const signature = new Uint8Array(await subtle().sign("HMAC", key, encoder.encode(`${prefix}.${body}`)))
|
|
191
|
+
return { token: `${prefix}.${body}.${Encoding.encodeBase64Url(signature)}`, claims }
|
|
192
|
+
})
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
const refused = (message: string) => Effect.fail(new Unauthorized({ message }))
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Verifies a token's signature and expiry under the key and returns its
|
|
199
|
+
* claims. Every malformation, a wrong key, and an expired token all fail with
|
|
200
|
+
* the same `Unauthorized`, so the token is not a parsing oracle.
|
|
201
|
+
*
|
|
202
|
+
* @param now the moment to judge `exp` against, in milliseconds
|
|
203
|
+
* @category verification
|
|
204
|
+
* @since 1.0.0
|
|
205
|
+
*/
|
|
206
|
+
export const verify = (key: string, token: string, now: number): Effect.Effect<Claims, Unauthorized> =>
|
|
207
|
+
Effect.suspend(() => {
|
|
208
|
+
const parts = token.split(".")
|
|
209
|
+
if (key.length === 0 || parts.length !== 3 || parts[0] !== prefix || parts[1]!.length === 0) {
|
|
210
|
+
return refused("A valid scoped token is required")
|
|
211
|
+
}
|
|
212
|
+
const signature = Encoding.decodeBase64Url(parts[2]!)
|
|
213
|
+
if (Result.isFailure(signature)) return refused("A valid scoped token is required")
|
|
214
|
+
return Effect.promise(async () => {
|
|
215
|
+
const hmac = await hmacKey(key, "verify")
|
|
216
|
+
return subtle().verify("HMAC", hmac, new Uint8Array(signature.success), encoder.encode(`${prefix}.${parts[1]}`))
|
|
217
|
+
}).pipe(
|
|
218
|
+
Effect.flatMap((valid) => {
|
|
219
|
+
if (!valid) return refused("A valid scoped token is required")
|
|
220
|
+
const text = Encoding.decodeBase64UrlString(parts[1]!)
|
|
221
|
+
if (Result.isFailure(text)) return refused("A valid scoped token is required")
|
|
222
|
+
let parsed: unknown
|
|
223
|
+
try {
|
|
224
|
+
parsed = JSON.parse(text.success)
|
|
225
|
+
} catch {
|
|
226
|
+
return refused("A valid scoped token is required")
|
|
227
|
+
}
|
|
228
|
+
const claims = decodeClaims(parsed)
|
|
229
|
+
if (Result.isFailure(claims)) return refused("A valid scoped token is required")
|
|
230
|
+
if (!(now < claims.success.exp)) return refused("The scoped token has expired")
|
|
231
|
+
return Effect.succeed(claims.success)
|
|
232
|
+
})
|
|
233
|
+
)
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
const field = (value: unknown, name: string): unknown =>
|
|
237
|
+
typeof value === "object" && value !== null ? (value as Record<string, unknown>)[name] : undefined
|
|
238
|
+
|
|
239
|
+
/** The run a payload names, wherever the control and gateway schemas put it. */
|
|
240
|
+
const namedRun = (payload: unknown): unknown =>
|
|
241
|
+
field(payload, "runId") ??
|
|
242
|
+
field(field(payload, "target"), "runId") ??
|
|
243
|
+
field(field(payload, "selector"), "runId") ??
|
|
244
|
+
field(field(payload, "filters"), "runId")
|
|
245
|
+
|
|
246
|
+
/** The flow a payload names. */
|
|
247
|
+
const namedFlow = (payload: unknown): unknown => field(payload, "flowId") ?? field(field(payload, "filters"), "flowId")
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Whether verified claims authorize one call.
|
|
251
|
+
*
|
|
252
|
+
* The procedure must be named. A token confined to a run authorizes only a
|
|
253
|
+
* call that names that run, and one confined to a flow only a call that names
|
|
254
|
+
* that flow: a call that names neither, such as an unfiltered `List`, is
|
|
255
|
+
* refused rather than widened.
|
|
256
|
+
*
|
|
257
|
+
* @category verification
|
|
258
|
+
* @since 1.0.0
|
|
259
|
+
*/
|
|
260
|
+
export const authorizes = (claims: Claims, call: Call): boolean =>
|
|
261
|
+
claims.procedures.includes(call.rpc) &&
|
|
262
|
+
(claims.runId === undefined || namedRun(call.payload) === claims.runId) &&
|
|
263
|
+
(claims.flowId === undefined || namedFlow(call.payload) === claims.flowId)
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* What the scoped-token authenticator needs.
|
|
267
|
+
*
|
|
268
|
+
* @category models
|
|
269
|
+
* @since 1.0.0
|
|
270
|
+
*/
|
|
271
|
+
export interface AuthenticatorOptions {
|
|
272
|
+
/** The verifying key: the gateway's configured bearer credential. */
|
|
273
|
+
readonly key: string
|
|
274
|
+
/** The principal every valid scoped token is stamped as. */
|
|
275
|
+
readonly principal: Omit<Principal, "stampedAt">
|
|
276
|
+
readonly now?: (() => number) | undefined
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Authenticates a bearer credential spelled as a scoped token: the signature
|
|
281
|
+
* and expiry always, and the procedure plus run or flow confinement whenever
|
|
282
|
+
* the boundary knows which call it is guarding. An edge that authenticates an
|
|
283
|
+
* upgrade knows no call, so it admits the socket and leaves each frame to the
|
|
284
|
+
* in-band check.
|
|
285
|
+
*
|
|
286
|
+
* A credential that is not a scoped token is refused here; compose with
|
|
287
|
+
* `ControlRpcs.bearerAuthenticator` through `ControlRpcs.anyAuthenticator`
|
|
288
|
+
* to accept both.
|
|
289
|
+
*
|
|
290
|
+
* @category constructors
|
|
291
|
+
* @since 1.0.0
|
|
292
|
+
*/
|
|
293
|
+
export const authenticator = (options: AuthenticatorOptions): Authenticator => ({
|
|
294
|
+
authenticate: (headers, call) => {
|
|
295
|
+
const credential = bearerCredential(headers)
|
|
296
|
+
if (credential === undefined || !isScopedToken(credential)) return refused("A valid scoped token is required")
|
|
297
|
+
const now = options.now?.() ?? Date.now()
|
|
298
|
+
return verify(options.key, credential, now).pipe(
|
|
299
|
+
Effect.flatMap((claims) =>
|
|
300
|
+
call !== undefined && !authorizes(claims, call)
|
|
301
|
+
? refused(`The scoped token does not authorize ${call.rpc}`)
|
|
302
|
+
: Effect.succeed({ ...options.principal, stampedAt: now })
|
|
303
|
+
)
|
|
304
|
+
)
|
|
305
|
+
}
|
|
306
|
+
})
|