@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,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record who admitted each signal command.
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
7
|
+
/**
|
|
8
|
+
* Adds the admitting principal to the signal inbox.
|
|
9
|
+
*
|
|
10
|
+
* NULL is intentional for existing rows: a command admitted before this column
|
|
11
|
+
* has no recorded identity, so it cannot answer a human wait, which requires
|
|
12
|
+
* `ApprovalAuthority` to authorize the admitting principal.
|
|
13
|
+
*
|
|
14
|
+
* @category migrations
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
export declare const signalPrincipals: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
18
|
+
//# sourceMappingURL=0005_signal_principals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0005_signal_principals.d.ts","sourceRoot":"","sources":["../../../src/migrations/0005_signal_principals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,2FAO3B,CAAA"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var signal_principals_exports = {};
|
|
30
|
+
__export(signal_principals_exports, {
|
|
31
|
+
signalPrincipals: () => signalPrincipals
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(signal_principals_exports);
|
|
34
|
+
var Dialect = __toESM(require("@smthrs/database/Dialect"), 1);
|
|
35
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
36
|
+
var SqlClient = __toESM(require("effect/unstable/sql/SqlClient"), 1);
|
|
37
|
+
const signalPrincipals = Effect.gen(function* () {
|
|
38
|
+
const sql = yield* SqlClient.SqlClient;
|
|
39
|
+
yield* sql.withTransaction(Effect.gen(function* () {
|
|
40
|
+
const columns = yield* Dialect.columns(sql, "control_signal_commands");
|
|
41
|
+
if (columns.some((column) => column.name === "principal_json")) return;
|
|
42
|
+
yield* sql`ALTER TABLE control_signal_commands ADD COLUMN principal_json TEXT`;
|
|
43
|
+
}));
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=0005_signal_principals.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/migrations/0005_signal_principals.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Record who admitted each signal command.\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\n/**\n * Adds the admitting principal to the signal inbox.\n *\n * NULL is intentional for existing rows: a command admitted before this column\n * has no recorded identity, so it cannot answer a human wait, which requires\n * `ApprovalAuthority` to authorize the admitting principal.\n *\n * @category migrations\n * @since 1.0.0\n */\nexport const signalPrincipals = Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n yield* sql.withTransaction(Effect.gen(function*() {\n const columns = yield* Dialect.columns(sql, \"control_signal_commands\")\n if (columns.some((column) => column.name === \"principal_json\")) return\n yield* sql`ALTER TABLE control_signal_commands ADD COLUMN principal_json TEXT`\n }))\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,cAAyB;AACzB,aAAwB;AACxB,gBAA2B;AAYpB,MAAM,mBAAmB,OAAO,IAAI,aAAY;AACrD,QAAM,MAAM,OAAO,UAAU;AAC7B,SAAO,IAAI,gBAAgB,OAAO,IAAI,aAAY;AAChD,UAAM,UAAU,OAAO,QAAQ,QAAQ,KAAK,yBAAyB;AACrE,QAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,gBAAgB,EAAG;AAChE,WAAO;AAAA,EACT,CAAC,CAAC;AACJ,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record who launched each run.
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
7
|
+
/**
|
|
8
|
+
* Adds the launching principal to the launch index.
|
|
9
|
+
*
|
|
10
|
+
* NULL is intentional for existing rows: a run launched before these columns
|
|
11
|
+
* has no recorded launcher, so only a reader that sees every run lists or
|
|
12
|
+
* watches it.
|
|
13
|
+
*
|
|
14
|
+
* @category migrations
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
export declare const runPrincipals: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
18
|
+
//# sourceMappingURL=0006_run_principals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0006_run_principals.d.ts","sourceRoot":"","sources":["../../../src/migrations/0006_run_principals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,2FAWxB,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var run_principals_exports = {};
|
|
30
|
+
__export(run_principals_exports, {
|
|
31
|
+
runPrincipals: () => runPrincipals
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(run_principals_exports);
|
|
34
|
+
var Dialect = __toESM(require("@smthrs/database/Dialect"), 1);
|
|
35
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
36
|
+
var SqlClient = __toESM(require("effect/unstable/sql/SqlClient"), 1);
|
|
37
|
+
const runPrincipals = Effect.gen(function* () {
|
|
38
|
+
const sql = yield* SqlClient.SqlClient;
|
|
39
|
+
yield* sql.withTransaction(Effect.gen(function* () {
|
|
40
|
+
const columns = yield* Dialect.columns(sql, "control_runs");
|
|
41
|
+
if (!columns.some((column) => column.name === "principal_id")) {
|
|
42
|
+
yield* sql`ALTER TABLE control_runs ADD COLUMN principal_id TEXT`;
|
|
43
|
+
}
|
|
44
|
+
if (!columns.some((column) => column.name === "principal_kind")) {
|
|
45
|
+
yield* sql`ALTER TABLE control_runs ADD COLUMN principal_kind TEXT`;
|
|
46
|
+
}
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=0006_run_principals.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/migrations/0006_run_principals.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Record who launched each run.\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\n/**\n * Adds the launching principal to the launch index.\n *\n * NULL is intentional for existing rows: a run launched before these columns\n * has no recorded launcher, so only a reader that sees every run lists or\n * watches it.\n *\n * @category migrations\n * @since 1.0.0\n */\nexport const runPrincipals = Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n yield* sql.withTransaction(Effect.gen(function*() {\n const columns = yield* Dialect.columns(sql, \"control_runs\")\n if (!columns.some((column) => column.name === \"principal_id\")) {\n yield* sql`ALTER TABLE control_runs ADD COLUMN principal_id TEXT`\n }\n if (!columns.some((column) => column.name === \"principal_kind\")) {\n yield* sql`ALTER TABLE control_runs ADD COLUMN principal_kind TEXT`\n }\n }))\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,cAAyB;AACzB,aAAwB;AACxB,gBAA2B;AAYpB,MAAM,gBAAgB,OAAO,IAAI,aAAY;AAClD,QAAM,MAAM,OAAO,UAAU;AAC7B,SAAO,IAAI,gBAAgB,OAAO,IAAI,aAAY;AAChD,UAAM,UAAU,OAAO,QAAQ,QAAQ,KAAK,cAAc;AAC1D,QAAI,CAAC,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,cAAc,GAAG;AAC7D,aAAO;AAAA,IACT;AACA,QAAI,CAAC,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,gBAAgB,GAAG;AAC/D,aAAO;AAAA,IACT;AAAA,EACF,CAAC,CAAC;AACJ,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Record the operator consent a resume delegation carries.
|
|
3
|
+
* @since 1.0.0
|
|
4
|
+
*/
|
|
5
|
+
import * as Effect from "effect/Effect";
|
|
6
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
7
|
+
/**
|
|
8
|
+
* Adds the journal sequence of an operator's explicit resume to the pending
|
|
9
|
+
* resume delegations.
|
|
10
|
+
*
|
|
11
|
+
* NULL is intentional for existing rows: a delegation recorded before this
|
|
12
|
+
* column is an approval or a wake, which is background intent.
|
|
13
|
+
*
|
|
14
|
+
* @category migrations
|
|
15
|
+
* @since 1.0.0
|
|
16
|
+
*/
|
|
17
|
+
export declare const resumeConsent: Effect.Effect<void, import("effect/unstable/sql/SqlError").SqlError, SqlClient.SqlClient>;
|
|
18
|
+
//# sourceMappingURL=0007_resume_consent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0007_resume_consent.d.ts","sourceRoot":"","sources":["../../../src/migrations/0007_resume_consent.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAE1D;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,2FAQxB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var resume_consent_exports = {};
|
|
30
|
+
__export(resume_consent_exports, {
|
|
31
|
+
resumeConsent: () => resumeConsent
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(resume_consent_exports);
|
|
34
|
+
var Dialect = __toESM(require("@smthrs/database/Dialect"), 1);
|
|
35
|
+
var Effect = __toESM(require("effect/Effect"), 1);
|
|
36
|
+
var SqlClient = __toESM(require("effect/unstable/sql/SqlClient"), 1);
|
|
37
|
+
const resumeConsent = Effect.gen(function* () {
|
|
38
|
+
const sql = yield* SqlClient.SqlClient;
|
|
39
|
+
yield* sql.withTransaction(Effect.gen(function* () {
|
|
40
|
+
const columns = yield* Dialect.columns(sql, "control_run_resumes");
|
|
41
|
+
if (!columns.some((column) => column.name === "consent_seq")) {
|
|
42
|
+
yield* sql`ALTER TABLE control_run_resumes ADD COLUMN consent_seq ${Dialect.integer(sql)}`;
|
|
43
|
+
}
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=0007_resume_consent.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/migrations/0007_resume_consent.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Record the operator consent a resume delegation carries.\n * @since 1.0.0\n */\n\nimport * as Dialect from \"@smthrs/database/Dialect\"\nimport * as Effect from \"effect/Effect\"\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\"\n\n/**\n * Adds the journal sequence of an operator's explicit resume to the pending\n * resume delegations.\n *\n * NULL is intentional for existing rows: a delegation recorded before this\n * column is an approval or a wake, which is background intent.\n *\n * @category migrations\n * @since 1.0.0\n */\nexport const resumeConsent = Effect.gen(function*() {\n const sql = yield* SqlClient.SqlClient\n yield* sql.withTransaction(Effect.gen(function*() {\n const columns = yield* Dialect.columns(sql, \"control_run_resumes\")\n if (!columns.some((column) => column.name === \"consent_seq\")) {\n yield* sql`ALTER TABLE control_run_resumes ADD COLUMN consent_seq ${Dialect.integer(sql)}`\n }\n }))\n})\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,cAAyB;AACzB,aAAwB;AACxB,gBAA2B;AAYpB,MAAM,gBAAgB,OAAO,IAAI,aAAY;AAClD,QAAM,MAAM,OAAO,UAAU;AAC7B,SAAO,IAAI,gBAAgB,OAAO,IAAI,aAAY;AAChD,UAAM,UAAU,OAAO,QAAQ,QAAQ,KAAK,qBAAqB;AACjE,QAAI,CAAC,QAAQ,KAAK,CAAC,WAAW,OAAO,SAAS,aAAa,GAAG;AAC5D,aAAO,6DAA6D,QAAQ,QAAQ,GAAG,CAAC;AAAA,IAC1F;AAAA,EACF,CAAC,CAAC;AACJ,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic in-memory Control stack for package and consumer tests.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.1.0
|
|
5
|
+
*/
|
|
6
|
+
import { NotificationQueue } from "@smthrs/notifications";
|
|
7
|
+
import { Registry } from "@smthrs/registry";
|
|
8
|
+
import { Layer } from "effect";
|
|
9
|
+
import * as ControlExecutor from "../ControlExecutor.ts";
|
|
10
|
+
import * as ControlRuntime from "../ControlRuntime.ts";
|
|
11
|
+
/**
|
|
12
|
+
* Provides Control, ControlRuntime, the in-memory journal bundle, and an empty
|
|
13
|
+
* registry. Runtime flow metadata falls back to the reserved system catalog.
|
|
14
|
+
*
|
|
15
|
+
* @category layers
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
*/
|
|
18
|
+
export declare const layer: (options?: ControlRuntime.MemoryOptions, executor?: ControlExecutor.Service) => Layer.Layer<import("@smthrs/journal/Journal").Journal | NotificationQueue.NotificationQueue | import("../Control.ts").Control | ControlRuntime.ControlRuntime | ControlExecutor.ControlExecutor | Registry.Registry, import("effect/unstable/sql/SqlError").SqlError | import("@smthrs/journal/Journal").JournalError | import("effect/unstable/sql/Migrator").MigrationError, never>;
|
|
19
|
+
//# sourceMappingURL=TestControl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TestControl.d.ts","sourceRoot":"","sources":["../../../src/test/TestControl.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAkB,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,KAAK,eAAe,MAAM,uBAAuB,CAAA;AAExD,OAAO,KAAK,cAAc,MAAM,sBAAsB,CAAA;AActD;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAChB,UAAU,cAAc,CAAC,aAAa,EACtC,WAAU,eAAe,CAAC,OAAoC,0XAW/D,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var TestControl_exports = {};
|
|
30
|
+
__export(TestControl_exports, {
|
|
31
|
+
layer: () => layer
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(TestControl_exports);
|
|
34
|
+
var TestJournal = __toESM(require("@smthrs/journal/test/TestJournal"), 1);
|
|
35
|
+
var import_notifications = require("@smthrs/notifications");
|
|
36
|
+
var import_registry = require("@smthrs/registry");
|
|
37
|
+
var import_effect = require("effect");
|
|
38
|
+
var ControlExecutor = __toESM(require("../ControlExecutor.js"), 1);
|
|
39
|
+
var ControlLive = __toESM(require("../ControlLive.js"), 1);
|
|
40
|
+
var ControlRuntime = __toESM(require("../ControlRuntime.js"), 1);
|
|
41
|
+
const browserCrypto = import_effect.Layer.succeed(
|
|
42
|
+
import_effect.Crypto.Crypto,
|
|
43
|
+
import_effect.Crypto.make({
|
|
44
|
+
/* v8 ignore next -- `Crypto.make` requires a random-byte primitive, and the deterministic runtime this bundle composes derives every identifier from a counter, so only `digest` is ever called here */
|
|
45
|
+
randomBytes: (size) => globalThis.crypto.getRandomValues(new Uint8Array(size)),
|
|
46
|
+
digest: (algorithm, data) => import_effect.Effect.promise(() => globalThis.crypto.subtle.digest(algorithm, data.slice().buffer)).pipe(
|
|
47
|
+
import_effect.Effect.map((buffer) => new Uint8Array(buffer))
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
);
|
|
51
|
+
const layer = (options, executor = ControlExecutor.makeNoop()) => {
|
|
52
|
+
const journal = TestJournal.layer();
|
|
53
|
+
const dependencies = import_effect.Layer.mergeAll(
|
|
54
|
+
ControlRuntime.layerMemory(options).pipe(import_effect.Layer.provide(browserCrypto)),
|
|
55
|
+
journal,
|
|
56
|
+
import_notifications.NotificationQueue.layer.pipe(import_effect.Layer.provide(journal)),
|
|
57
|
+
ControlExecutor.layer(executor),
|
|
58
|
+
import_registry.Registry.layerNoop()
|
|
59
|
+
);
|
|
60
|
+
return import_effect.Layer.provideMerge(ControlLive.layer, dependencies);
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=TestControl.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/test/TestControl.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Deterministic in-memory Control stack for package and consumer tests.\n *\n * @since 0.1.0\n */\n\nimport * as TestJournal from \"@smthrs/journal/test/TestJournal\"\nimport { NotificationQueue } from \"@smthrs/notifications\"\nimport { Registry } from \"@smthrs/registry\"\nimport { Crypto, Effect, Layer } from \"effect\"\nimport * as ControlExecutor from \"../ControlExecutor.ts\"\nimport * as ControlLive from \"../ControlLive.ts\"\nimport * as ControlRuntime from \"../ControlRuntime.ts\"\n\nconst browserCrypto = Layer.succeed(\n Crypto.Crypto,\n Crypto.make({\n /* v8 ignore next -- `Crypto.make` requires a random-byte primitive, and the deterministic runtime this bundle composes derives every identifier from a counter, so only `digest` is ever called here */\n randomBytes: (size) => globalThis.crypto.getRandomValues(new Uint8Array(size)),\n digest: (algorithm, data) =>\n Effect.promise(() => globalThis.crypto.subtle.digest(algorithm, data.slice().buffer)).pipe(\n Effect.map((buffer) => new Uint8Array(buffer))\n )\n })\n)\n\n/**\n * Provides Control, ControlRuntime, the in-memory journal bundle, and an empty\n * registry. Runtime flow metadata falls back to the reserved system catalog.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layer = (\n options?: ControlRuntime.MemoryOptions,\n executor: ControlExecutor.Service = ControlExecutor.makeNoop()\n) => {\n const journal = TestJournal.layer()\n const dependencies = Layer.mergeAll(\n ControlRuntime.layerMemory(options).pipe(Layer.provide(browserCrypto)),\n journal,\n NotificationQueue.layer.pipe(Layer.provide(journal)),\n ControlExecutor.layer(executor),\n Registry.layerNoop()\n )\n return Layer.provideMerge(ControlLive.layer, dependencies)\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,kBAA6B;AAC7B,2BAAkC;AAClC,sBAAyB;AACzB,oBAAsC;AACtC,sBAAiC;AACjC,kBAA6B;AAC7B,qBAAgC;AAEhC,MAAM,gBAAgB,oBAAM;AAAA,EAC1B,qBAAO;AAAA,EACP,qBAAO,KAAK;AAAA;AAAA,IAEV,aAAa,CAAC,SAAS,WAAW,OAAO,gBAAgB,IAAI,WAAW,IAAI,CAAC;AAAA,IAC7E,QAAQ,CAAC,WAAW,SAClB,qBAAO,QAAQ,MAAM,WAAW,OAAO,OAAO,OAAO,WAAW,KAAK,MAAM,EAAE,MAAM,CAAC,EAAE;AAAA,MACpF,qBAAO,IAAI,CAAC,WAAW,IAAI,WAAW,MAAM,CAAC;AAAA,IAC/C;AAAA,EACJ,CAAC;AACH;AASO,MAAM,QAAQ,CACnB,SACA,WAAoC,gBAAgB,SAAS,MAC1D;AACH,QAAM,UAAU,YAAY,MAAM;AAClC,QAAM,eAAe,oBAAM;AAAA,IACzB,eAAe,YAAY,OAAO,EAAE,KAAK,oBAAM,QAAQ,aAAa,CAAC;AAAA,IACrE;AAAA,IACA,uCAAkB,MAAM,KAAK,oBAAM,QAAQ,OAAO,CAAC;AAAA,IACnD,gBAAgB,MAAM,QAAQ;AAAA,IAC9B,yBAAS,UAAU;AAAA,EACrB;AACA,SAAO,oBAAM,aAAa,YAAY,OAAO,YAAY;AAC3D;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-owned approval authority, separate from principal attribution and from
|
|
3
|
+
* the permissions a workflow receives after approval.
|
|
4
|
+
*
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
import { Effect, Schema } from "effect";
|
|
8
|
+
import { InvalidInput, type PersistenceError, Unauthorized } from "./ControlError.ts";
|
|
9
|
+
import { type ApprovalTarget, GrantScope, type Principal } from "./ControlSchema.ts";
|
|
10
|
+
/**
|
|
11
|
+
* An approval decision whose caller has already been authenticated by its host.
|
|
12
|
+
* @category models
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
*/
|
|
15
|
+
export interface Request {
|
|
16
|
+
readonly principal: Principal;
|
|
17
|
+
readonly target: ApprovalTarget;
|
|
18
|
+
readonly decision: "approved" | "denied";
|
|
19
|
+
readonly scope: GrantScope;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A trusted host policy. Both refusals and unavailable policy storage fail
|
|
23
|
+
* closed. Implementations must be bounded and safe inside a write transaction;
|
|
24
|
+
* they must not recursively invoke Control or perform the gated work.
|
|
25
|
+
* @category services
|
|
26
|
+
* @since 1.0.0
|
|
27
|
+
*/
|
|
28
|
+
export interface Service {
|
|
29
|
+
readonly authorize: (request: Request) => Effect.Effect<void, Unauthorized | PersistenceError>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* An explicit delegation to one authenticated identity, not everyone whose
|
|
33
|
+
* kind resembles a role. Scopes are exact, not implicitly hierarchical. A
|
|
34
|
+
* delegation may approve only its listed scopes and may deny either target
|
|
35
|
+
* kind it names (denial installs no grant).
|
|
36
|
+
* Delegation is reusable: `scopes: ["once"]` permits once-scoped grants, not
|
|
37
|
+
* one lifetime decision. Use a host policy for expiry or one-use delegation.
|
|
38
|
+
* @category schemas
|
|
39
|
+
* @since 1.0.0
|
|
40
|
+
*/
|
|
41
|
+
export declare const Delegation: Schema.Struct<{
|
|
42
|
+
readonly principal: Schema.Struct<{
|
|
43
|
+
readonly id: Schema.String;
|
|
44
|
+
readonly kind: Schema.String;
|
|
45
|
+
}>;
|
|
46
|
+
readonly scopes: Schema.$Array<Schema.Literals<readonly ["once", "run", "remembered"]>>;
|
|
47
|
+
readonly targets: Schema.$Array<Schema.Literals<readonly ["Plan", "Node"]>>;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* One explicit host-owned approval delegation.
|
|
51
|
+
* @category models
|
|
52
|
+
* @since 1.0.0
|
|
53
|
+
*/
|
|
54
|
+
export type Delegation = typeof Delegation.Type;
|
|
55
|
+
/**
|
|
56
|
+
* Builds an immutable policy from explicit host configuration. Invalid
|
|
57
|
+
* configuration is refused without including its contents in the error.
|
|
58
|
+
* The caller's arrays and objects are not retained after acquisition.
|
|
59
|
+
* @category constructors
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
*/
|
|
62
|
+
export declare const make: (delegations: ReadonlyArray<Delegation>) => Effect.Effect<Service, InvalidInput>;
|
|
63
|
+
/**
|
|
64
|
+
* Default trusted-local policy. Only the local operator identity is an
|
|
65
|
+
* approver. A custom actor, gateway identity, or agent needs explicit host
|
|
66
|
+
* delegation; setting Principal.kind is not itself an authorization. The
|
|
67
|
+
* in-memory test adapter's `memory`/`test` identity is delegated only by that
|
|
68
|
+
* adapter's own default policy, never here.
|
|
69
|
+
* @category policies
|
|
70
|
+
* @since 1.0.0
|
|
71
|
+
*/
|
|
72
|
+
export declare const local: Service;
|
|
73
|
+
//# sourceMappingURL=ApprovalAuthority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalAuthority.d.ts","sourceRoot":"","sources":["../../src/ApprovalAuthority.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,KAAK,gBAAgB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrF,OAAO,EAAE,KAAK,cAAc,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEpF;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,UAAU,GAAG,QAAQ,CAAA;IACxC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CAAA;CAC/F;AAID;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU;;;;;;;EAIrB,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AA4B/C;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,GACf,aAAa,aAAa,CAAC,UAAU,CAAC,KACrC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAMnC,CAAA;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,KAAK,EAAE,OAElB,CAAA"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-owned approval authority, separate from principal attribution and from
|
|
3
|
+
* the permissions a workflow receives after approval.
|
|
4
|
+
*
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
import { Effect, Schema } from "effect";
|
|
8
|
+
import { InvalidInput, Unauthorized } from "./ControlError.js";
|
|
9
|
+
import { GrantScope } from "./ControlSchema.js";
|
|
10
|
+
const IdentityPart = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(1024));
|
|
11
|
+
/**
|
|
12
|
+
* An explicit delegation to one authenticated identity, not everyone whose
|
|
13
|
+
* kind resembles a role. Scopes are exact, not implicitly hierarchical. A
|
|
14
|
+
* delegation may approve only its listed scopes and may deny either target
|
|
15
|
+
* kind it names (denial installs no grant).
|
|
16
|
+
* Delegation is reusable: `scopes: ["once"]` permits once-scoped grants, not
|
|
17
|
+
* one lifetime decision. Use a host policy for expiry or one-use delegation.
|
|
18
|
+
* @category schemas
|
|
19
|
+
* @since 1.0.0
|
|
20
|
+
*/
|
|
21
|
+
export const Delegation = Schema.Struct({
|
|
22
|
+
principal: Schema.Struct({ id: IdentityPart, kind: IdentityPart }),
|
|
23
|
+
scopes: Schema.Array(GrantScope).check(Schema.isMinLength(1), Schema.isMaxLength(3)),
|
|
24
|
+
targets: Schema.Array(Schema.Literals(["Plan", "Node"])).check(Schema.isMinLength(1), Schema.isMaxLength(2))
|
|
25
|
+
});
|
|
26
|
+
const identity = (principal) => JSON.stringify([principal.id, principal.kind]);
|
|
27
|
+
const compile = (delegations) => {
|
|
28
|
+
// Separate target keys preserve each delegation's target/scope pairing;
|
|
29
|
+
// unioning both dimensions independently would grant a cross product.
|
|
30
|
+
const permissions = new Map();
|
|
31
|
+
for (const delegation of delegations) {
|
|
32
|
+
for (const target of delegation.targets) {
|
|
33
|
+
const key = JSON.stringify([identity(delegation.principal), target]);
|
|
34
|
+
const scopes = permissions.get(key) ?? new Set();
|
|
35
|
+
for (const scope of delegation.scopes)
|
|
36
|
+
scopes.add(scope);
|
|
37
|
+
permissions.set(key, scopes);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
authorize: (request) => Effect.suspend(() => {
|
|
42
|
+
const scopes = permissions.get(JSON.stringify([identity(request.principal), request.target._tag]));
|
|
43
|
+
return scopes !== undefined &&
|
|
44
|
+
(request.decision === "denied" || (request.decision === "approved" && scopes.has(request.scope)))
|
|
45
|
+
? Effect.void
|
|
46
|
+
: Effect.fail(new Unauthorized({ message: "This caller has no authority to make this approval decision" }));
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Builds an immutable policy from explicit host configuration. Invalid
|
|
52
|
+
* configuration is refused without including its contents in the error.
|
|
53
|
+
* The caller's arrays and objects are not retained after acquisition.
|
|
54
|
+
* @category constructors
|
|
55
|
+
* @since 1.0.0
|
|
56
|
+
*/
|
|
57
|
+
export const make = (delegations) => Schema.decodeUnknownEffect(Schema.Array(Delegation).check(Schema.isMaxLength(1024)))(delegations, {
|
|
58
|
+
onExcessProperty: "error"
|
|
59
|
+
}).pipe(Effect.mapError(() => new InvalidInput({ issue: "Invalid approval-authority delegation configuration" })), Effect.map(compile));
|
|
60
|
+
/**
|
|
61
|
+
* Default trusted-local policy. Only the local operator identity is an
|
|
62
|
+
* approver. A custom actor, gateway identity, or agent needs explicit host
|
|
63
|
+
* delegation; setting Principal.kind is not itself an authorization. The
|
|
64
|
+
* in-memory test adapter's `memory`/`test` identity is delegated only by that
|
|
65
|
+
* adapter's own default policy, never here.
|
|
66
|
+
* @category policies
|
|
67
|
+
* @since 1.0.0
|
|
68
|
+
*/
|
|
69
|
+
export const local = compile([
|
|
70
|
+
{ principal: { id: "local", kind: "operator" }, scopes: ["once", "run", "remembered"], targets: ["Plan", "Node"] }
|
|
71
|
+
]);
|
|
72
|
+
//# sourceMappingURL=ApprovalAuthority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalAuthority.js","sourceRoot":"","sources":["../../src/ApprovalAuthority.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,YAAY,EAAyB,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrF,OAAO,EAAuB,UAAU,EAAkB,MAAM,oBAAoB,CAAA;AAyBpF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;AAEzF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAClE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACpF,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;CAC7G,CAAC,CAAA;AASF,MAAM,QAAQ,GAAG,CAAC,SAAyC,EAAU,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;AAEtH,MAAM,OAAO,GAAG,CAAC,WAAsC,EAAW,EAAE;IAClE,wEAAwE;IACxE,sEAAsE;IACtE,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAA;IACtD,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,KAAK,MAAM,MAAM,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,CAAA;YACpE,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAc,CAAA;YAC5D,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACxD,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE,CAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;YAClB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YAClG,OAAO,MAAM,KAAK,SAAS;gBACvB,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,UAAU,IAAI,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;gBACnG,CAAC,CAAC,MAAM,CAAC,IAAI;gBACb,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,YAAY,CAAC,EAAE,OAAO,EAAE,6DAA6D,EAAE,CAAC,CAAC,CAAA;QAC/G,CAAC,CAAC;KACL,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,CAClB,WAAsC,EACA,EAAE,CACxC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;IAChG,gBAAgB,EAAE,OAAO;CAC1B,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,qDAAqD,EAAE,CAAC,CAAC,EACzG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CACpB,CAAA;AAEH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,KAAK,GAAY,OAAO,CAAC;IACpC,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;CACnH,CAAC,CAAA","sourcesContent":["/**\n * Host-owned approval authority, separate from principal attribution and from\n * the permissions a workflow receives after approval.\n *\n * @since 1.0.0\n */\n\nimport { Effect, Schema } from \"effect\"\nimport { InvalidInput, type PersistenceError, Unauthorized } from \"./ControlError.ts\"\nimport { type ApprovalTarget, GrantScope, type Principal } from \"./ControlSchema.ts\"\n\n/**\n * An approval decision whose caller has already been authenticated by its host.\n * @category models\n * @since 1.0.0\n */\nexport interface Request {\n readonly principal: Principal\n readonly target: ApprovalTarget\n readonly decision: \"approved\" | \"denied\"\n readonly scope: GrantScope\n}\n\n/**\n * A trusted host policy. Both refusals and unavailable policy storage fail\n * closed. Implementations must be bounded and safe inside a write transaction;\n * they must not recursively invoke Control or perform the gated work.\n * @category services\n * @since 1.0.0\n */\nexport interface Service {\n readonly authorize: (request: Request) => Effect.Effect<void, Unauthorized | PersistenceError>\n}\n\nconst IdentityPart = Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(1024))\n\n/**\n * An explicit delegation to one authenticated identity, not everyone whose\n * kind resembles a role. Scopes are exact, not implicitly hierarchical. A\n * delegation may approve only its listed scopes and may deny either target\n * kind it names (denial installs no grant).\n * Delegation is reusable: `scopes: [\"once\"]` permits once-scoped grants, not\n * one lifetime decision. Use a host policy for expiry or one-use delegation.\n * @category schemas\n * @since 1.0.0\n */\nexport const Delegation = Schema.Struct({\n principal: Schema.Struct({ id: IdentityPart, kind: IdentityPart }),\n scopes: Schema.Array(GrantScope).check(Schema.isMinLength(1), Schema.isMaxLength(3)),\n targets: Schema.Array(Schema.Literals([\"Plan\", \"Node\"])).check(Schema.isMinLength(1), Schema.isMaxLength(2))\n})\n\n/**\n * One explicit host-owned approval delegation.\n * @category models\n * @since 1.0.0\n */\nexport type Delegation = typeof Delegation.Type\n\nconst identity = (principal: Pick<Principal, \"id\" | \"kind\">): string => JSON.stringify([principal.id, principal.kind])\n\nconst compile = (delegations: ReadonlyArray<Delegation>): Service => {\n // Separate target keys preserve each delegation's target/scope pairing;\n // unioning both dimensions independently would grant a cross product.\n const permissions = new Map<string, Set<GrantScope>>()\n for (const delegation of delegations) {\n for (const target of delegation.targets) {\n const key = JSON.stringify([identity(delegation.principal), target])\n const scopes = permissions.get(key) ?? new Set<GrantScope>()\n for (const scope of delegation.scopes) scopes.add(scope)\n permissions.set(key, scopes)\n }\n }\n return Object.freeze({\n authorize: (request: Request) =>\n Effect.suspend(() => {\n const scopes = permissions.get(JSON.stringify([identity(request.principal), request.target._tag]))\n return scopes !== undefined &&\n (request.decision === \"denied\" || (request.decision === \"approved\" && scopes.has(request.scope)))\n ? Effect.void\n : Effect.fail(new Unauthorized({ message: \"This caller has no authority to make this approval decision\" }))\n })\n })\n}\n\n/**\n * Builds an immutable policy from explicit host configuration. Invalid\n * configuration is refused without including its contents in the error.\n * The caller's arrays and objects are not retained after acquisition.\n * @category constructors\n * @since 1.0.0\n */\nexport const make = (\n delegations: ReadonlyArray<Delegation>\n): Effect.Effect<Service, InvalidInput> =>\n Schema.decodeUnknownEffect(Schema.Array(Delegation).check(Schema.isMaxLength(1024)))(delegations, {\n onExcessProperty: \"error\"\n }).pipe(\n Effect.mapError(() => new InvalidInput({ issue: \"Invalid approval-authority delegation configuration\" })),\n Effect.map(compile)\n )\n\n/**\n * Default trusted-local policy. Only the local operator identity is an\n * approver. A custom actor, gateway identity, or agent needs explicit host\n * delegation; setting Principal.kind is not itself an authorization. The\n * in-memory test adapter's `memory`/`test` identity is delegated only by that\n * adapter's own default policy, never here.\n * @category policies\n * @since 1.0.0\n */\nexport const local: Service = compile([\n { principal: { id: \"local\", kind: \"operator\" }, scopes: [\"once\", \"run\", \"remembered\"], targets: [\"Plan\", \"Node\"] }\n])\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cancellation attribution as the control plane reads it back.
|
|
3
|
+
*
|
|
4
|
+
* A cancellation is durable but anonymous. `flows_runs.cancel_requested_at_ms`
|
|
5
|
+
* records that somebody asked, and nothing in the row records who, why, or
|
|
6
|
+
* whether the run was asked at all rather than swept up in an ancestor's
|
|
7
|
+
* cascade. Three journals hold the missing halves: the control plane's own
|
|
8
|
+
* `control.run.cancel-requested`, the engine's `flows.engine.interrupted`, and
|
|
9
|
+
* the ancestry the run store already keeps. This module folds them into one
|
|
10
|
+
* answer per run.
|
|
11
|
+
*
|
|
12
|
+
* The fold is pure and scope-independent: it reads whatever evidence it is
|
|
13
|
+
* handed and never issues a query, so the caller chooses how much to read.
|
|
14
|
+
* `SqlControlRuntime` uses two scopes. A listing folds the whole database,
|
|
15
|
+
* because every row is going to be answered for anyway. A single-run read
|
|
16
|
+
* folds only that run and its ancestor chain, which is the smallest scope that
|
|
17
|
+
* can still answer the question: cascade is a fact about a run's ancestors, so
|
|
18
|
+
* it cannot be decided one row at a time — a child's cancellation is
|
|
19
|
+
* attributed to whoever asked for its nearest cancelled ancestor's, however
|
|
20
|
+
* many rounds up that is.
|
|
21
|
+
*
|
|
22
|
+
* The two foreign event types are named as strings rather than imported,
|
|
23
|
+
* exactly as in {@link Lineage}: a control plane reads journals, not engines.
|
|
24
|
+
*
|
|
25
|
+
* @since 0.1.0
|
|
26
|
+
*/
|
|
27
|
+
import type { Cancellation, Principal } from "./ControlSchema.ts";
|
|
28
|
+
/**
|
|
29
|
+
* The journal event type the control plane records an attributed cancel under.
|
|
30
|
+
*
|
|
31
|
+
* @category constants
|
|
32
|
+
* @since 0.1.0
|
|
33
|
+
*/
|
|
34
|
+
export declare const requestedEventType = "control.run.cancel-requested";
|
|
35
|
+
/**
|
|
36
|
+
* The journal event type the engine records an interruption under.
|
|
37
|
+
*
|
|
38
|
+
* @category constants
|
|
39
|
+
* @since 0.1.0
|
|
40
|
+
*/
|
|
41
|
+
export declare const interruptedEventType = "flows.engine.interrupted";
|
|
42
|
+
/**
|
|
43
|
+
* One attributed cancel request, as the control plane journaled it.
|
|
44
|
+
*
|
|
45
|
+
* @category models
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
*/
|
|
48
|
+
export interface Request {
|
|
49
|
+
readonly requestedAt: number;
|
|
50
|
+
readonly principal?: Principal | undefined;
|
|
51
|
+
readonly reason?: string | undefined;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* What one run row discloses about its own cancellation.
|
|
55
|
+
*
|
|
56
|
+
* `cancelRequestedAt` is the run store's unfenced request column, and
|
|
57
|
+
* `cancelledAt` is the moment the engine journaled the interruption. Either
|
|
58
|
+
* one alone is evidence that this run was cancelled, and so is an attributed
|
|
59
|
+
* request naming the run: a control plane that cancels a run it owns
|
|
60
|
+
* interrupts the fiber rather than asking the column, and the journal entry it
|
|
61
|
+
* wrote is the whole record.
|
|
62
|
+
*
|
|
63
|
+
* @category models
|
|
64
|
+
* @since 0.1.0
|
|
65
|
+
*/
|
|
66
|
+
export interface Evidence {
|
|
67
|
+
readonly runId: string;
|
|
68
|
+
readonly parentRunId?: string | undefined;
|
|
69
|
+
readonly cancelRequestedAt?: number | undefined;
|
|
70
|
+
readonly cancelledAt?: number | undefined;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Everything the fold reads.
|
|
74
|
+
*
|
|
75
|
+
* @category models
|
|
76
|
+
* @since 0.1.0
|
|
77
|
+
*/
|
|
78
|
+
export interface Input {
|
|
79
|
+
readonly runs: ReadonlyArray<Evidence>;
|
|
80
|
+
/** Attributed requests the control plane journaled, by run id. */
|
|
81
|
+
readonly requests: ReadonlyMap<string, Request>;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Attributes every cancelled run in one pass.
|
|
85
|
+
*
|
|
86
|
+
* Three sources, in the order a run's own evidence outranks its ancestors':
|
|
87
|
+
*
|
|
88
|
+
* 1. A `control.run.cancel-requested` entry names this run. Somebody asked for
|
|
89
|
+
* this run by name, and the entry says who and why.
|
|
90
|
+
* 2. A cancelled ancestor exists. The run was swept up in that cancellation,
|
|
91
|
+
* so it reports `cascade`, names the ancestor whose request started it, and
|
|
92
|
+
* inherits that request's principal and reason — the honest answer to "who
|
|
93
|
+
* cancelled this child" is the operator who cancelled its parent.
|
|
94
|
+
* 3. Neither. The engine cancelled the run on its own account: a lease
|
|
95
|
+
* expiry, a budget, a supervisor. There is no principal to report, and
|
|
96
|
+
* inventing one would be worse than saying nothing.
|
|
97
|
+
*
|
|
98
|
+
* The ancestor walk carries a visited set. A cyclic parent chain is not
|
|
99
|
+
* reachable through the engine's cycle detection, but a projection that hung
|
|
100
|
+
* on corrupt ancestry would take the control plane down with it.
|
|
101
|
+
*
|
|
102
|
+
* @param input the run evidence and the attributed requests
|
|
103
|
+
* @category projections
|
|
104
|
+
* @since 0.1.0
|
|
105
|
+
*/
|
|
106
|
+
export declare const attribute: (input: Input) => ReadonlyMap<string, Cancellation>;
|
|
107
|
+
//# sourceMappingURL=Cancellation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cancellation.d.ts","sourceRoot":"","sources":["../../src/Cancellation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEjE;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,iCAAiC,CAAA;AAEhE;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,6BAA6B,CAAA;AAE9D;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACrC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1C;AAED;;;;;GAKG;AACH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAA;IACtC,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChD;AAwBD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,KAAG,WAAW,CAAC,MAAM,EAAE,YAAY,CAqCxE,CAAA"}
|