@schema-weaver/pg-connector 0.0.0-stage → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/LICENSE +21 -0
- package/README.md +457 -2
- package/dist/cjs/audit/chain.d.ts +365 -0
- package/dist/cjs/audit/chain.d.ts.map +1 -0
- package/dist/cjs/audit/chain.js +959 -0
- package/dist/cjs/audit/chain.js.map +1 -0
- package/dist/cjs/audit/cloud-client.d.ts +142 -0
- package/dist/cjs/audit/cloud-client.d.ts.map +1 -0
- package/dist/cjs/audit/cloud-client.js +364 -0
- package/dist/cjs/audit/cloud-client.js.map +1 -0
- package/dist/cjs/audit/cloud-writer.d.ts +57 -0
- package/dist/cjs/audit/cloud-writer.d.ts.map +1 -0
- package/dist/cjs/audit/cloud-writer.js +95 -0
- package/dist/cjs/audit/cloud-writer.js.map +1 -0
- package/dist/cjs/audit/context.d.ts +51 -0
- package/dist/cjs/audit/context.d.ts.map +1 -0
- package/dist/cjs/audit/context.js +75 -0
- package/dist/cjs/audit/context.js.map +1 -0
- package/dist/cjs/audit/files.d.ts +111 -0
- package/dist/cjs/audit/files.d.ts.map +1 -0
- package/dist/cjs/audit/files.js +406 -0
- package/dist/cjs/audit/files.js.map +1 -0
- package/dist/cjs/audit/index.d.ts +9 -0
- package/dist/cjs/audit/index.d.ts.map +1 -0
- package/dist/cjs/audit/index.js +68 -0
- package/dist/cjs/audit/index.js.map +1 -0
- package/dist/cjs/audit/local-writer.d.ts +255 -0
- package/dist/cjs/audit/local-writer.d.ts.map +1 -0
- package/dist/cjs/audit/local-writer.js +829 -0
- package/dist/cjs/audit/local-writer.js.map +1 -0
- package/dist/cjs/audit/redact.d.ts +151 -0
- package/dist/cjs/audit/redact.d.ts.map +1 -0
- package/dist/cjs/audit/redact.js +549 -0
- package/dist/cjs/audit/redact.js.map +1 -0
- package/dist/cjs/audit/sanitize.d.ts +78 -0
- package/dist/cjs/audit/sanitize.d.ts.map +1 -0
- package/dist/cjs/audit/sanitize.js +315 -0
- package/dist/cjs/audit/sanitize.js.map +1 -0
- package/dist/cjs/audit/sink.d.ts +278 -0
- package/dist/cjs/audit/sink.d.ts.map +1 -0
- package/dist/cjs/audit/sink.js +819 -0
- package/dist/cjs/audit/sink.js.map +1 -0
- package/dist/cjs/audit/types.d.ts +226 -0
- package/dist/cjs/audit/types.d.ts.map +1 -0
- package/dist/cjs/audit/types.js +3 -0
- package/dist/cjs/audit/types.js.map +1 -0
- package/dist/cjs/audit/verify-cache.d.ts +127 -0
- package/dist/cjs/audit/verify-cache.d.ts.map +1 -0
- package/dist/cjs/audit/verify-cache.js +668 -0
- package/dist/cjs/audit/verify-cache.js.map +1 -0
- package/dist/cjs/channels/agent-session.d.ts +228 -0
- package/dist/cjs/channels/agent-session.d.ts.map +1 -0
- package/dist/cjs/channels/agent-session.js +604 -0
- package/dist/cjs/channels/agent-session.js.map +1 -0
- package/dist/cjs/channels/data-channel.d.ts +181 -0
- package/dist/cjs/channels/data-channel.d.ts.map +1 -0
- package/dist/cjs/channels/data-channel.js +607 -0
- package/dist/cjs/channels/data-channel.js.map +1 -0
- package/dist/cjs/channels/reconnect.d.ts +142 -0
- package/dist/cjs/channels/reconnect.d.ts.map +1 -0
- package/dist/cjs/channels/reconnect.js +247 -0
- package/dist/cjs/channels/reconnect.js.map +1 -0
- package/dist/cjs/channels/types.d.ts +112 -0
- package/dist/cjs/channels/types.d.ts.map +1 -0
- package/dist/cjs/channels/types.js +3 -0
- package/dist/cjs/channels/types.js.map +1 -0
- package/dist/cjs/channels/wake-channel.d.ts +232 -0
- package/dist/cjs/channels/wake-channel.d.ts.map +1 -0
- package/dist/cjs/channels/wake-channel.js +752 -0
- package/dist/cjs/channels/wake-channel.js.map +1 -0
- package/dist/cjs/cli/banner.d.ts +2 -0
- package/dist/cjs/cli/banner.d.ts.map +1 -0
- package/dist/cjs/cli/banner.js +150 -0
- package/dist/cjs/cli/banner.js.map +1 -0
- package/dist/cjs/cli/commands/agent.d.ts +30 -0
- package/dist/cjs/cli/commands/agent.d.ts.map +1 -0
- package/dist/cjs/cli/commands/agent.js +214 -0
- package/dist/cjs/cli/commands/agent.js.map +1 -0
- package/dist/cjs/cli/commands/audit-verify.d.ts +19 -0
- package/dist/cjs/cli/commands/audit-verify.d.ts.map +1 -0
- package/dist/cjs/cli/commands/audit-verify.js +382 -0
- package/dist/cjs/cli/commands/audit-verify.js.map +1 -0
- package/dist/cjs/cli/commands/clean.d.ts +23 -0
- package/dist/cjs/cli/commands/clean.d.ts.map +1 -0
- package/dist/cjs/cli/commands/clean.js +272 -0
- package/dist/cjs/cli/commands/clean.js.map +1 -0
- package/dist/cjs/cli/commands/config-show.d.ts +2 -0
- package/dist/cjs/cli/commands/config-show.d.ts.map +1 -0
- package/dist/cjs/cli/commands/config-show.js +10 -0
- package/dist/cjs/cli/commands/config-show.js.map +1 -0
- package/dist/cjs/cli/commands/config.d.ts +6 -0
- package/dist/cjs/cli/commands/config.d.ts.map +1 -0
- package/dist/cjs/cli/commands/config.js +266 -0
- package/dist/cjs/cli/commands/config.js.map +1 -0
- package/dist/cjs/cli/commands/db-add.d.ts +16 -0
- package/dist/cjs/cli/commands/db-add.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-add.js +613 -0
- package/dist/cjs/cli/commands/db-add.js.map +1 -0
- package/dist/cjs/cli/commands/db-edit.d.ts +2 -0
- package/dist/cjs/cli/commands/db-edit.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-edit.js +388 -0
- package/dist/cjs/cli/commands/db-edit.js.map +1 -0
- package/dist/cjs/cli/commands/db-logs.d.ts +3 -0
- package/dist/cjs/cli/commands/db-logs.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-logs.js +67 -0
- package/dist/cjs/cli/commands/db-logs.js.map +1 -0
- package/dist/cjs/cli/commands/db-ls.d.ts +2 -0
- package/dist/cjs/cli/commands/db-ls.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-ls.js +118 -0
- package/dist/cjs/cli/commands/db-ls.js.map +1 -0
- package/dist/cjs/cli/commands/db-query.d.ts +121 -0
- package/dist/cjs/cli/commands/db-query.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-query.js +802 -0
- package/dist/cjs/cli/commands/db-query.js.map +1 -0
- package/dist/cjs/cli/commands/db-remove.d.ts +2 -0
- package/dist/cjs/cli/commands/db-remove.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-remove.js +51 -0
- package/dist/cjs/cli/commands/db-remove.js.map +1 -0
- package/dist/cjs/cli/commands/db-show.d.ts +2 -0
- package/dist/cjs/cli/commands/db-show.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-show.js +134 -0
- package/dist/cjs/cli/commands/db-show.js.map +1 -0
- package/dist/cjs/cli/commands/db-test.d.ts +3 -0
- package/dist/cjs/cli/commands/db-test.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db-test.js +311 -0
- package/dist/cjs/cli/commands/db-test.js.map +1 -0
- package/dist/cjs/cli/commands/db.d.ts +11 -0
- package/dist/cjs/cli/commands/db.d.ts.map +1 -0
- package/dist/cjs/cli/commands/db.js +90 -0
- package/dist/cjs/cli/commands/db.js.map +1 -0
- package/dist/cjs/cli/commands/debug.d.ts +2 -0
- package/dist/cjs/cli/commands/debug.d.ts.map +1 -0
- package/dist/cjs/cli/commands/debug.js +241 -0
- package/dist/cjs/cli/commands/debug.js.map +1 -0
- package/dist/cjs/cli/commands/doctor.d.ts +5 -0
- package/dist/cjs/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cjs/cli/commands/doctor.js +117 -0
- package/dist/cjs/cli/commands/doctor.js.map +1 -0
- package/dist/cjs/cli/commands/index.d.ts +10 -0
- package/dist/cjs/cli/commands/index.d.ts.map +1 -0
- package/dist/cjs/cli/commands/index.js +30 -0
- package/dist/cjs/cli/commands/index.js.map +1 -0
- package/dist/cjs/cli/commands/init.d.ts +2 -0
- package/dist/cjs/cli/commands/init.d.ts.map +1 -0
- package/dist/cjs/cli/commands/init.js +199 -0
- package/dist/cjs/cli/commands/init.js.map +1 -0
- package/dist/cjs/cli/commands/link.d.ts +5 -0
- package/dist/cjs/cli/commands/link.d.ts.map +1 -0
- package/dist/cjs/cli/commands/link.js +44 -0
- package/dist/cjs/cli/commands/link.js.map +1 -0
- package/dist/cjs/cli/commands/logs.d.ts +17 -0
- package/dist/cjs/cli/commands/logs.d.ts.map +1 -0
- package/dist/cjs/cli/commands/logs.js +314 -0
- package/dist/cjs/cli/commands/logs.js.map +1 -0
- package/dist/cjs/cli/commands/project-show.d.ts +2 -0
- package/dist/cjs/cli/commands/project-show.d.ts.map +1 -0
- package/dist/cjs/cli/commands/project-show.js +105 -0
- package/dist/cjs/cli/commands/project-show.js.map +1 -0
- package/dist/cjs/cli/commands/project.d.ts +3 -0
- package/dist/cjs/cli/commands/project.d.ts.map +1 -0
- package/dist/cjs/cli/commands/project.js +64 -0
- package/dist/cjs/cli/commands/project.js.map +1 -0
- package/dist/cjs/cli/commands/service.d.ts +123 -0
- package/dist/cjs/cli/commands/service.d.ts.map +1 -0
- package/dist/cjs/cli/commands/service.js +554 -0
- package/dist/cjs/cli/commands/service.js.map +1 -0
- package/dist/cjs/cli/commands/start.d.ts +6 -0
- package/dist/cjs/cli/commands/start.d.ts.map +1 -0
- package/dist/cjs/cli/commands/start.js +308 -0
- package/dist/cjs/cli/commands/start.js.map +1 -0
- package/dist/cjs/cli/commands/status.d.ts +2 -0
- package/dist/cjs/cli/commands/status.d.ts.map +1 -0
- package/dist/cjs/cli/commands/status.js +225 -0
- package/dist/cjs/cli/commands/status.js.map +1 -0
- package/dist/cjs/cli/commands/stop.d.ts +6 -0
- package/dist/cjs/cli/commands/stop.d.ts.map +1 -0
- package/dist/cjs/cli/commands/stop.js +99 -0
- package/dist/cjs/cli/commands/stop.js.map +1 -0
- package/dist/cjs/cli/daemon/error-tracker.d.ts +119 -0
- package/dist/cjs/cli/daemon/error-tracker.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/error-tracker.js +500 -0
- package/dist/cjs/cli/daemon/error-tracker.js.map +1 -0
- package/dist/cjs/cli/daemon/fault-shutdown.d.ts +144 -0
- package/dist/cjs/cli/daemon/fault-shutdown.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/fault-shutdown.js +312 -0
- package/dist/cjs/cli/daemon/fault-shutdown.js.map +1 -0
- package/dist/cjs/cli/daemon/index.d.ts +12 -0
- package/dist/cjs/cli/daemon/index.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/index.js +23 -0
- package/dist/cjs/cli/daemon/index.js.map +1 -0
- package/dist/cjs/cli/daemon/pid-file.d.ts +13 -0
- package/dist/cjs/cli/daemon/pid-file.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/pid-file.js +90 -0
- package/dist/cjs/cli/daemon/pid-file.js.map +1 -0
- package/dist/cjs/cli/daemon/readiness.d.ts +30 -0
- package/dist/cjs/cli/daemon/readiness.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/readiness.js +74 -0
- package/dist/cjs/cli/daemon/readiness.js.map +1 -0
- package/dist/cjs/cli/daemon/runtime.d.ts +366 -0
- package/dist/cjs/cli/daemon/runtime.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/runtime.js +1343 -0
- package/dist/cjs/cli/daemon/runtime.js.map +1 -0
- package/dist/cjs/cli/daemon/shutdown.d.ts +7 -0
- package/dist/cjs/cli/daemon/shutdown.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/shutdown.js +66 -0
- package/dist/cjs/cli/daemon/shutdown.js.map +1 -0
- package/dist/cjs/cli/daemon/signal-handlers.d.ts +3 -0
- package/dist/cjs/cli/daemon/signal-handlers.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/signal-handlers.js +27 -0
- package/dist/cjs/cli/daemon/signal-handlers.js.map +1 -0
- package/dist/cjs/cli/daemon/state.d.ts +157 -0
- package/dist/cjs/cli/daemon/state.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/state.js +397 -0
- package/dist/cjs/cli/daemon/state.js.map +1 -0
- package/dist/cjs/cli/daemon/status-file.d.ts +139 -0
- package/dist/cjs/cli/daemon/status-file.d.ts.map +1 -0
- package/dist/cjs/cli/daemon/status-file.js +88 -0
- package/dist/cjs/cli/daemon/status-file.js.map +1 -0
- package/dist/cjs/cli/doctor/checks.d.ts +133 -0
- package/dist/cjs/cli/doctor/checks.d.ts.map +1 -0
- package/dist/cjs/cli/doctor/checks.js +677 -0
- package/dist/cjs/cli/doctor/checks.js.map +1 -0
- package/dist/cjs/cli/doctor/fixes.d.ts +9 -0
- package/dist/cjs/cli/doctor/fixes.d.ts.map +1 -0
- package/dist/cjs/cli/doctor/fixes.js +199 -0
- package/dist/cjs/cli/doctor/fixes.js.map +1 -0
- package/dist/cjs/cli/doctor/index.d.ts +7 -0
- package/dist/cjs/cli/doctor/index.d.ts.map +1 -0
- package/dist/cjs/cli/doctor/index.js +27 -0
- package/dist/cjs/cli/doctor/index.js.map +1 -0
- package/dist/cjs/cli/index.d.ts +3 -0
- package/dist/cjs/cli/index.d.ts.map +1 -0
- package/dist/cjs/cli/index.js +336 -0
- package/dist/cjs/cli/index.js.map +1 -0
- package/dist/cjs/cli/interactive.d.ts +8 -0
- package/dist/cjs/cli/interactive.d.ts.map +1 -0
- package/dist/cjs/cli/interactive.js +670 -0
- package/dist/cjs/cli/interactive.js.map +1 -0
- package/dist/cjs/cli/logs/format.d.ts +13 -0
- package/dist/cjs/cli/logs/format.d.ts.map +1 -0
- package/dist/cjs/cli/logs/format.js +178 -0
- package/dist/cjs/cli/logs/format.js.map +1 -0
- package/dist/cjs/cli/logs/index.d.ts +3 -0
- package/dist/cjs/cli/logs/index.d.ts.map +1 -0
- package/dist/cjs/cli/logs/index.js +13 -0
- package/dist/cjs/cli/logs/index.js.map +1 -0
- package/dist/cjs/cli/logs/viewer.d.ts +41 -0
- package/dist/cjs/cli/logs/viewer.d.ts.map +1 -0
- package/dist/cjs/cli/logs/viewer.js +417 -0
- package/dist/cjs/cli/logs/viewer.js.map +1 -0
- package/dist/cjs/cli/ops/operation-logger.d.ts +63 -0
- package/dist/cjs/cli/ops/operation-logger.d.ts.map +1 -0
- package/dist/cjs/cli/ops/operation-logger.js +183 -0
- package/dist/cjs/cli/ops/operation-logger.js.map +1 -0
- package/dist/cjs/cli/palette.d.ts +11 -0
- package/dist/cjs/cli/palette.d.ts.map +1 -0
- package/dist/cjs/cli/palette.js +243 -0
- package/dist/cjs/cli/palette.js.map +1 -0
- package/dist/cjs/cli/prompt.d.ts +186 -0
- package/dist/cjs/cli/prompt.d.ts.map +1 -0
- package/dist/cjs/cli/prompt.js +541 -0
- package/dist/cjs/cli/prompt.js.map +1 -0
- package/dist/cjs/cli/ui/box.d.ts +21 -0
- package/dist/cjs/cli/ui/box.d.ts.map +1 -0
- package/dist/cjs/cli/ui/box.js +72 -0
- package/dist/cjs/cli/ui/box.js.map +1 -0
- package/dist/cjs/cli/ui/clipboard.d.ts +6 -0
- package/dist/cjs/cli/ui/clipboard.d.ts.map +1 -0
- package/dist/cjs/cli/ui/clipboard.js +78 -0
- package/dist/cjs/cli/ui/clipboard.js.map +1 -0
- package/dist/cjs/cli/ui/colors.d.ts +57 -0
- package/dist/cjs/cli/ui/colors.d.ts.map +1 -0
- package/dist/cjs/cli/ui/colors.js +151 -0
- package/dist/cjs/cli/ui/colors.js.map +1 -0
- package/dist/cjs/cli/ui/index.d.ts +9 -0
- package/dist/cjs/cli/ui/index.d.ts.map +1 -0
- package/dist/cjs/cli/ui/index.js +55 -0
- package/dist/cjs/cli/ui/index.js.map +1 -0
- package/dist/cjs/cli/ui/spinner.d.ts +12 -0
- package/dist/cjs/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cjs/cli/ui/spinner.js +82 -0
- package/dist/cjs/cli/ui/spinner.js.map +1 -0
- package/dist/cjs/cli/ui/symbols.d.ts +47 -0
- package/dist/cjs/cli/ui/symbols.d.ts.map +1 -0
- package/dist/cjs/cli/ui/symbols.js +112 -0
- package/dist/cjs/cli/ui/symbols.js.map +1 -0
- package/dist/cjs/cli/ui/table.d.ts +23 -0
- package/dist/cjs/cli/ui/table.d.ts.map +1 -0
- package/dist/cjs/cli/ui/table.js +160 -0
- package/dist/cjs/cli/ui/table.js.map +1 -0
- package/dist/cjs/cli/ui/terminal.d.ts +7 -0
- package/dist/cjs/cli/ui/terminal.d.ts.map +1 -0
- package/dist/cjs/cli/ui/terminal.js +40 -0
- package/dist/cjs/cli/ui/terminal.js.map +1 -0
- package/dist/cjs/config/atomic-write.d.ts +69 -0
- package/dist/cjs/config/atomic-write.d.ts.map +1 -0
- package/dist/cjs/config/atomic-write.js +289 -0
- package/dist/cjs/config/atomic-write.js.map +1 -0
- package/dist/cjs/config/db-config.d.ts +134 -0
- package/dist/cjs/config/db-config.d.ts.map +1 -0
- package/dist/cjs/config/db-config.js +594 -0
- package/dist/cjs/config/db-config.js.map +1 -0
- package/dist/cjs/config/machine-config.d.ts +85 -0
- package/dist/cjs/config/machine-config.d.ts.map +1 -0
- package/dist/cjs/config/machine-config.js +232 -0
- package/dist/cjs/config/machine-config.js.map +1 -0
- package/dist/cjs/config/paths.d.ts +64 -0
- package/dist/cjs/config/paths.d.ts.map +1 -0
- package/dist/cjs/config/paths.js +155 -0
- package/dist/cjs/config/paths.js.map +1 -0
- package/dist/cjs/config/schema.d.ts +72 -0
- package/dist/cjs/config/schema.d.ts.map +1 -0
- package/dist/cjs/config/schema.js +197 -0
- package/dist/cjs/config/schema.js.map +1 -0
- package/dist/cjs/config/token.d.ts +63 -0
- package/dist/cjs/config/token.d.ts.map +1 -0
- package/dist/cjs/config/token.js +146 -0
- package/dist/cjs/config/token.js.map +1 -0
- package/dist/cjs/execution/canceller.d.ts +41 -0
- package/dist/cjs/execution/canceller.d.ts.map +1 -0
- package/dist/cjs/execution/canceller.js +209 -0
- package/dist/cjs/execution/canceller.js.map +1 -0
- package/dist/cjs/execution/database-lookup.d.ts +56 -0
- package/dist/cjs/execution/database-lookup.d.ts.map +1 -0
- package/dist/cjs/execution/database-lookup.js +43 -0
- package/dist/cjs/execution/database-lookup.js.map +1 -0
- package/dist/cjs/execution/dispatcher.d.ts +181 -0
- package/dist/cjs/execution/dispatcher.d.ts.map +1 -0
- package/dist/cjs/execution/dispatcher.js +1296 -0
- package/dist/cjs/execution/dispatcher.js.map +1 -0
- package/dist/cjs/execution/function-effects.d.ts +209 -0
- package/dist/cjs/execution/function-effects.d.ts.map +1 -0
- package/dist/cjs/execution/function-effects.js +596 -0
- package/dist/cjs/execution/function-effects.js.map +1 -0
- package/dist/cjs/execution/introspection.d.ts +76 -0
- package/dist/cjs/execution/introspection.d.ts.map +1 -0
- package/dist/cjs/execution/introspection.js +448 -0
- package/dist/cjs/execution/introspection.js.map +1 -0
- package/dist/cjs/execution/migration-runner.d.ts +128 -0
- package/dist/cjs/execution/migration-runner.d.ts.map +1 -0
- package/dist/cjs/execution/migration-runner.js +798 -0
- package/dist/cjs/execution/migration-runner.js.map +1 -0
- package/dist/cjs/execution/non-tx-detector.d.ts +23 -0
- package/dist/cjs/execution/non-tx-detector.d.ts.map +1 -0
- package/dist/cjs/execution/non-tx-detector.js +218 -0
- package/dist/cjs/execution/non-tx-detector.js.map +1 -0
- package/dist/cjs/execution/pool.d.ts +229 -0
- package/dist/cjs/execution/pool.d.ts.map +1 -0
- package/dist/cjs/execution/pool.js +738 -0
- package/dist/cjs/execution/pool.js.map +1 -0
- package/dist/cjs/execution/query-runner.d.ts +88 -0
- package/dist/cjs/execution/query-runner.d.ts.map +1 -0
- package/dist/cjs/execution/query-runner.js +751 -0
- package/dist/cjs/execution/query-runner.js.map +1 -0
- package/dist/cjs/execution/rate-limiter.d.ts +120 -0
- package/dist/cjs/execution/rate-limiter.d.ts.map +1 -0
- package/dist/cjs/execution/rate-limiter.js +273 -0
- package/dist/cjs/execution/rate-limiter.js.map +1 -0
- package/dist/cjs/execution/search-path.d.ts +161 -0
- package/dist/cjs/execution/search-path.d.ts.map +1 -0
- package/dist/cjs/execution/search-path.js +279 -0
- package/dist/cjs/execution/search-path.js.map +1 -0
- package/dist/cjs/execution/sql-parser.d.ts +195 -0
- package/dist/cjs/execution/sql-parser.d.ts.map +1 -0
- package/dist/cjs/execution/sql-parser.js +704 -0
- package/dist/cjs/execution/sql-parser.js.map +1 -0
- package/dist/cjs/execution/statement-classifier.d.ts +103 -0
- package/dist/cjs/execution/statement-classifier.d.ts.map +1 -0
- package/dist/cjs/execution/statement-classifier.js +535 -0
- package/dist/cjs/execution/statement-classifier.js.map +1 -0
- package/dist/cjs/execution/types.d.ts +189 -0
- package/dist/cjs/execution/types.d.ts.map +1 -0
- package/dist/cjs/execution/types.js +28 -0
- package/dist/cjs/execution/types.js.map +1 -0
- package/dist/cjs/index.d.ts +34 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +98 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permissions/auto-upgrade.d.ts +40 -0
- package/dist/cjs/permissions/auto-upgrade.d.ts.map +1 -0
- package/dist/cjs/permissions/auto-upgrade.js +168 -0
- package/dist/cjs/permissions/auto-upgrade.js.map +1 -0
- package/dist/cjs/permissions/checker.d.ts +53 -0
- package/dist/cjs/permissions/checker.d.ts.map +1 -0
- package/dist/cjs/permissions/checker.js +326 -0
- package/dist/cjs/permissions/checker.js.map +1 -0
- package/dist/cjs/permissions/manual-approval.d.ts +213 -0
- package/dist/cjs/permissions/manual-approval.d.ts.map +1 -0
- package/dist/cjs/permissions/manual-approval.js +541 -0
- package/dist/cjs/permissions/manual-approval.js.map +1 -0
- package/dist/cjs/permissions/plan-registry.d.ts +274 -0
- package/dist/cjs/permissions/plan-registry.d.ts.map +1 -0
- package/dist/cjs/permissions/plan-registry.js +454 -0
- package/dist/cjs/permissions/plan-registry.js.map +1 -0
- package/dist/cjs/permissions/role-policy.d.ts +217 -0
- package/dist/cjs/permissions/role-policy.d.ts.map +1 -0
- package/dist/cjs/permissions/role-policy.js +584 -0
- package/dist/cjs/permissions/role-policy.js.map +1 -0
- package/dist/cjs/permissions/types.d.ts +126 -0
- package/dist/cjs/permissions/types.d.ts.map +1 -0
- package/dist/cjs/permissions/types.js +3 -0
- package/dist/cjs/permissions/types.js.map +1 -0
- package/dist/cjs/protocol/constants.d.ts +72 -0
- package/dist/cjs/protocol/constants.d.ts.map +1 -0
- package/dist/cjs/protocol/constants.js +107 -0
- package/dist/cjs/protocol/constants.js.map +1 -0
- package/dist/cjs/protocol/envelope.d.ts +165 -0
- package/dist/cjs/protocol/envelope.d.ts.map +1 -0
- package/dist/cjs/protocol/envelope.js +309 -0
- package/dist/cjs/protocol/envelope.js.map +1 -0
- package/dist/cjs/protocol/errors.d.ts +33 -0
- package/dist/cjs/protocol/errors.d.ts.map +1 -0
- package/dist/cjs/protocol/errors.js +391 -0
- package/dist/cjs/protocol/errors.js.map +1 -0
- package/dist/cjs/protocol/messages.d.ts +327 -0
- package/dist/cjs/protocol/messages.d.ts.map +1 -0
- package/dist/cjs/protocol/messages.js +3 -0
- package/dist/cjs/protocol/messages.js.map +1 -0
- package/dist/cjs/protocol/serialize.d.ts +26 -0
- package/dist/cjs/protocol/serialize.d.ts.map +1 -0
- package/dist/cjs/protocol/serialize.js +71 -0
- package/dist/cjs/protocol/serialize.js.map +1 -0
- package/dist/cjs/protocol/validate.d.ts +135 -0
- package/dist/cjs/protocol/validate.d.ts.map +1 -0
- package/dist/cjs/protocol/validate.js +852 -0
- package/dist/cjs/protocol/validate.js.map +1 -0
- package/dist/esm/audit/chain.d.ts +365 -0
- package/dist/esm/audit/chain.d.ts.map +1 -0
- package/dist/esm/audit/chain.js +895 -0
- package/dist/esm/audit/chain.js.map +1 -0
- package/dist/esm/audit/cloud-client.d.ts +142 -0
- package/dist/esm/audit/cloud-client.d.ts.map +1 -0
- package/dist/esm/audit/cloud-client.js +326 -0
- package/dist/esm/audit/cloud-client.js.map +1 -0
- package/dist/esm/audit/cloud-writer.d.ts +57 -0
- package/dist/esm/audit/cloud-writer.d.ts.map +1 -0
- package/dist/esm/audit/cloud-writer.js +91 -0
- package/dist/esm/audit/cloud-writer.js.map +1 -0
- package/dist/esm/audit/context.d.ts +51 -0
- package/dist/esm/audit/context.d.ts.map +1 -0
- package/dist/esm/audit/context.js +69 -0
- package/dist/esm/audit/context.js.map +1 -0
- package/dist/esm/audit/files.d.ts +111 -0
- package/dist/esm/audit/files.d.ts.map +1 -0
- package/dist/esm/audit/files.js +361 -0
- package/dist/esm/audit/files.js.map +1 -0
- package/dist/esm/audit/index.d.ts +9 -0
- package/dist/esm/audit/index.d.ts.map +1 -0
- package/dist/esm/audit/index.js +8 -0
- package/dist/esm/audit/index.js.map +1 -0
- package/dist/esm/audit/local-writer.d.ts +255 -0
- package/dist/esm/audit/local-writer.d.ts.map +1 -0
- package/dist/esm/audit/local-writer.js +785 -0
- package/dist/esm/audit/local-writer.js.map +1 -0
- package/dist/esm/audit/redact.d.ts +151 -0
- package/dist/esm/audit/redact.d.ts.map +1 -0
- package/dist/esm/audit/redact.js +506 -0
- package/dist/esm/audit/redact.js.map +1 -0
- package/dist/esm/audit/sanitize.d.ts +78 -0
- package/dist/esm/audit/sanitize.d.ts.map +1 -0
- package/dist/esm/audit/sanitize.js +307 -0
- package/dist/esm/audit/sanitize.js.map +1 -0
- package/dist/esm/audit/sink.d.ts +278 -0
- package/dist/esm/audit/sink.d.ts.map +1 -0
- package/dist/esm/audit/sink.js +782 -0
- package/dist/esm/audit/sink.js.map +1 -0
- package/dist/esm/audit/types.d.ts +226 -0
- package/dist/esm/audit/types.d.ts.map +1 -0
- package/dist/esm/audit/types.js +2 -0
- package/dist/esm/audit/types.js.map +1 -0
- package/dist/esm/audit/verify-cache.d.ts +127 -0
- package/dist/esm/audit/verify-cache.d.ts.map +1 -0
- package/dist/esm/audit/verify-cache.js +628 -0
- package/dist/esm/audit/verify-cache.js.map +1 -0
- package/dist/esm/channels/agent-session.d.ts +228 -0
- package/dist/esm/channels/agent-session.d.ts.map +1 -0
- package/dist/esm/channels/agent-session.js +566 -0
- package/dist/esm/channels/agent-session.js.map +1 -0
- package/dist/esm/channels/data-channel.d.ts +181 -0
- package/dist/esm/channels/data-channel.d.ts.map +1 -0
- package/dist/esm/channels/data-channel.js +567 -0
- package/dist/esm/channels/data-channel.js.map +1 -0
- package/dist/esm/channels/reconnect.d.ts +142 -0
- package/dist/esm/channels/reconnect.d.ts.map +1 -0
- package/dist/esm/channels/reconnect.js +234 -0
- package/dist/esm/channels/reconnect.js.map +1 -0
- package/dist/esm/channels/types.d.ts +112 -0
- package/dist/esm/channels/types.d.ts.map +1 -0
- package/dist/esm/channels/types.js +2 -0
- package/dist/esm/channels/types.js.map +1 -0
- package/dist/esm/channels/wake-channel.d.ts +232 -0
- package/dist/esm/channels/wake-channel.d.ts.map +1 -0
- package/dist/esm/channels/wake-channel.js +715 -0
- package/dist/esm/channels/wake-channel.js.map +1 -0
- package/dist/esm/cli/banner.d.ts +2 -0
- package/dist/esm/cli/banner.d.ts.map +1 -0
- package/dist/esm/cli/banner.js +114 -0
- package/dist/esm/cli/banner.js.map +1 -0
- package/dist/esm/cli/commands/agent.d.ts +30 -0
- package/dist/esm/cli/commands/agent.d.ts.map +1 -0
- package/dist/esm/cli/commands/agent.js +204 -0
- package/dist/esm/cli/commands/agent.js.map +1 -0
- package/dist/esm/cli/commands/audit-verify.d.ts +19 -0
- package/dist/esm/cli/commands/audit-verify.d.ts.map +1 -0
- package/dist/esm/cli/commands/audit-verify.js +345 -0
- package/dist/esm/cli/commands/audit-verify.js.map +1 -0
- package/dist/esm/cli/commands/clean.d.ts +23 -0
- package/dist/esm/cli/commands/clean.d.ts.map +1 -0
- package/dist/esm/cli/commands/clean.js +235 -0
- package/dist/esm/cli/commands/clean.js.map +1 -0
- package/dist/esm/cli/commands/config-show.d.ts +2 -0
- package/dist/esm/cli/commands/config-show.d.ts.map +1 -0
- package/dist/esm/cli/commands/config-show.js +2 -0
- package/dist/esm/cli/commands/config-show.js.map +1 -0
- package/dist/esm/cli/commands/config.d.ts +6 -0
- package/dist/esm/cli/commands/config.d.ts.map +1 -0
- package/dist/esm/cli/commands/config.js +259 -0
- package/dist/esm/cli/commands/config.js.map +1 -0
- package/dist/esm/cli/commands/db-add.d.ts +16 -0
- package/dist/esm/cli/commands/db-add.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-add.js +576 -0
- package/dist/esm/cli/commands/db-add.js.map +1 -0
- package/dist/esm/cli/commands/db-edit.d.ts +2 -0
- package/dist/esm/cli/commands/db-edit.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-edit.js +352 -0
- package/dist/esm/cli/commands/db-edit.js.map +1 -0
- package/dist/esm/cli/commands/db-logs.d.ts +3 -0
- package/dist/esm/cli/commands/db-logs.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-logs.js +64 -0
- package/dist/esm/cli/commands/db-logs.js.map +1 -0
- package/dist/esm/cli/commands/db-ls.d.ts +2 -0
- package/dist/esm/cli/commands/db-ls.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-ls.js +115 -0
- package/dist/esm/cli/commands/db-ls.js.map +1 -0
- package/dist/esm/cli/commands/db-query.d.ts +121 -0
- package/dist/esm/cli/commands/db-query.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-query.js +754 -0
- package/dist/esm/cli/commands/db-query.js.map +1 -0
- package/dist/esm/cli/commands/db-remove.d.ts +2 -0
- package/dist/esm/cli/commands/db-remove.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-remove.js +48 -0
- package/dist/esm/cli/commands/db-remove.js.map +1 -0
- package/dist/esm/cli/commands/db-show.d.ts +2 -0
- package/dist/esm/cli/commands/db-show.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-show.js +131 -0
- package/dist/esm/cli/commands/db-show.js.map +1 -0
- package/dist/esm/cli/commands/db-test.d.ts +3 -0
- package/dist/esm/cli/commands/db-test.d.ts.map +1 -0
- package/dist/esm/cli/commands/db-test.js +307 -0
- package/dist/esm/cli/commands/db-test.js.map +1 -0
- package/dist/esm/cli/commands/db.d.ts +11 -0
- package/dist/esm/cli/commands/db.d.ts.map +1 -0
- package/dist/esm/cli/commands/db.js +76 -0
- package/dist/esm/cli/commands/db.js.map +1 -0
- package/dist/esm/cli/commands/debug.d.ts +2 -0
- package/dist/esm/cli/commands/debug.d.ts.map +1 -0
- package/dist/esm/cli/commands/debug.js +205 -0
- package/dist/esm/cli/commands/debug.js.map +1 -0
- package/dist/esm/cli/commands/doctor.d.ts +5 -0
- package/dist/esm/cli/commands/doctor.d.ts.map +1 -0
- package/dist/esm/cli/commands/doctor.js +114 -0
- package/dist/esm/cli/commands/doctor.js.map +1 -0
- package/dist/esm/cli/commands/index.d.ts +10 -0
- package/dist/esm/cli/commands/index.d.ts.map +1 -0
- package/dist/esm/cli/commands/index.js +10 -0
- package/dist/esm/cli/commands/index.js.map +1 -0
- package/dist/esm/cli/commands/init.d.ts +2 -0
- package/dist/esm/cli/commands/init.d.ts.map +1 -0
- package/dist/esm/cli/commands/init.js +163 -0
- package/dist/esm/cli/commands/init.js.map +1 -0
- package/dist/esm/cli/commands/link.d.ts +5 -0
- package/dist/esm/cli/commands/link.d.ts.map +1 -0
- package/dist/esm/cli/commands/link.js +41 -0
- package/dist/esm/cli/commands/link.js.map +1 -0
- package/dist/esm/cli/commands/logs.d.ts +17 -0
- package/dist/esm/cli/commands/logs.d.ts.map +1 -0
- package/dist/esm/cli/commands/logs.js +278 -0
- package/dist/esm/cli/commands/logs.js.map +1 -0
- package/dist/esm/cli/commands/project-show.d.ts +2 -0
- package/dist/esm/cli/commands/project-show.d.ts.map +1 -0
- package/dist/esm/cli/commands/project-show.js +69 -0
- package/dist/esm/cli/commands/project-show.js.map +1 -0
- package/dist/esm/cli/commands/project.d.ts +3 -0
- package/dist/esm/cli/commands/project.d.ts.map +1 -0
- package/dist/esm/cli/commands/project.js +60 -0
- package/dist/esm/cli/commands/project.js.map +1 -0
- package/dist/esm/cli/commands/service.d.ts +123 -0
- package/dist/esm/cli/commands/service.d.ts.map +1 -0
- package/dist/esm/cli/commands/service.js +505 -0
- package/dist/esm/cli/commands/service.js.map +1 -0
- package/dist/esm/cli/commands/start.d.ts +6 -0
- package/dist/esm/cli/commands/start.d.ts.map +1 -0
- package/dist/esm/cli/commands/start.js +272 -0
- package/dist/esm/cli/commands/start.js.map +1 -0
- package/dist/esm/cli/commands/status.d.ts +2 -0
- package/dist/esm/cli/commands/status.d.ts.map +1 -0
- package/dist/esm/cli/commands/status.js +222 -0
- package/dist/esm/cli/commands/status.js.map +1 -0
- package/dist/esm/cli/commands/stop.d.ts +6 -0
- package/dist/esm/cli/commands/stop.d.ts.map +1 -0
- package/dist/esm/cli/commands/stop.js +96 -0
- package/dist/esm/cli/commands/stop.js.map +1 -0
- package/dist/esm/cli/daemon/error-tracker.d.ts +119 -0
- package/dist/esm/cli/daemon/error-tracker.d.ts.map +1 -0
- package/dist/esm/cli/daemon/error-tracker.js +451 -0
- package/dist/esm/cli/daemon/error-tracker.js.map +1 -0
- package/dist/esm/cli/daemon/fault-shutdown.d.ts +144 -0
- package/dist/esm/cli/daemon/fault-shutdown.d.ts.map +1 -0
- package/dist/esm/cli/daemon/fault-shutdown.js +273 -0
- package/dist/esm/cli/daemon/fault-shutdown.js.map +1 -0
- package/dist/esm/cli/daemon/index.d.ts +12 -0
- package/dist/esm/cli/daemon/index.d.ts.map +1 -0
- package/dist/esm/cli/daemon/index.js +7 -0
- package/dist/esm/cli/daemon/index.js.map +1 -0
- package/dist/esm/cli/daemon/pid-file.d.ts +13 -0
- package/dist/esm/cli/daemon/pid-file.d.ts.map +1 -0
- package/dist/esm/cli/daemon/pid-file.js +51 -0
- package/dist/esm/cli/daemon/pid-file.js.map +1 -0
- package/dist/esm/cli/daemon/readiness.d.ts +30 -0
- package/dist/esm/cli/daemon/readiness.d.ts.map +1 -0
- package/dist/esm/cli/daemon/readiness.js +70 -0
- package/dist/esm/cli/daemon/readiness.js.map +1 -0
- package/dist/esm/cli/daemon/runtime.d.ts +366 -0
- package/dist/esm/cli/daemon/runtime.d.ts.map +1 -0
- package/dist/esm/cli/daemon/runtime.js +1284 -0
- package/dist/esm/cli/daemon/runtime.js.map +1 -0
- package/dist/esm/cli/daemon/shutdown.d.ts +7 -0
- package/dist/esm/cli/daemon/shutdown.d.ts.map +1 -0
- package/dist/esm/cli/daemon/shutdown.js +63 -0
- package/dist/esm/cli/daemon/shutdown.js.map +1 -0
- package/dist/esm/cli/daemon/signal-handlers.d.ts +3 -0
- package/dist/esm/cli/daemon/signal-handlers.d.ts.map +1 -0
- package/dist/esm/cli/daemon/signal-handlers.js +24 -0
- package/dist/esm/cli/daemon/signal-handlers.js.map +1 -0
- package/dist/esm/cli/daemon/state.d.ts +157 -0
- package/dist/esm/cli/daemon/state.d.ts.map +1 -0
- package/dist/esm/cli/daemon/state.js +352 -0
- package/dist/esm/cli/daemon/state.js.map +1 -0
- package/dist/esm/cli/daemon/status-file.d.ts +139 -0
- package/dist/esm/cli/daemon/status-file.d.ts.map +1 -0
- package/dist/esm/cli/daemon/status-file.js +50 -0
- package/dist/esm/cli/daemon/status-file.js.map +1 -0
- package/dist/esm/cli/doctor/checks.d.ts +133 -0
- package/dist/esm/cli/doctor/checks.d.ts.map +1 -0
- package/dist/esm/cli/doctor/checks.js +624 -0
- package/dist/esm/cli/doctor/checks.js.map +1 -0
- package/dist/esm/cli/doctor/fixes.d.ts +9 -0
- package/dist/esm/cli/doctor/fixes.d.ts.map +1 -0
- package/dist/esm/cli/doctor/fixes.js +163 -0
- package/dist/esm/cli/doctor/fixes.js.map +1 -0
- package/dist/esm/cli/doctor/index.d.ts +7 -0
- package/dist/esm/cli/doctor/index.d.ts.map +1 -0
- package/dist/esm/cli/doctor/index.js +5 -0
- package/dist/esm/cli/doctor/index.js.map +1 -0
- package/dist/esm/cli/index.d.ts +3 -0
- package/dist/esm/cli/index.d.ts.map +1 -0
- package/dist/esm/cli/index.js +333 -0
- package/dist/esm/cli/index.js.map +1 -0
- package/dist/esm/cli/interactive.d.ts +8 -0
- package/dist/esm/cli/interactive.d.ts.map +1 -0
- package/dist/esm/cli/interactive.js +665 -0
- package/dist/esm/cli/interactive.js.map +1 -0
- package/dist/esm/cli/logs/format.d.ts +13 -0
- package/dist/esm/cli/logs/format.d.ts.map +1 -0
- package/dist/esm/cli/logs/format.js +169 -0
- package/dist/esm/cli/logs/format.js.map +1 -0
- package/dist/esm/cli/logs/index.d.ts +3 -0
- package/dist/esm/cli/logs/index.d.ts.map +1 -0
- package/dist/esm/cli/logs/index.js +3 -0
- package/dist/esm/cli/logs/index.js.map +1 -0
- package/dist/esm/cli/logs/viewer.d.ts +41 -0
- package/dist/esm/cli/logs/viewer.d.ts.map +1 -0
- package/dist/esm/cli/logs/viewer.js +412 -0
- package/dist/esm/cli/logs/viewer.js.map +1 -0
- package/dist/esm/cli/ops/operation-logger.d.ts +63 -0
- package/dist/esm/cli/ops/operation-logger.d.ts.map +1 -0
- package/dist/esm/cli/ops/operation-logger.js +142 -0
- package/dist/esm/cli/ops/operation-logger.js.map +1 -0
- package/dist/esm/cli/palette.d.ts +11 -0
- package/dist/esm/cli/palette.d.ts.map +1 -0
- package/dist/esm/cli/palette.js +240 -0
- package/dist/esm/cli/palette.js.map +1 -0
- package/dist/esm/cli/prompt.d.ts +186 -0
- package/dist/esm/cli/prompt.d.ts.map +1 -0
- package/dist/esm/cli/prompt.js +483 -0
- package/dist/esm/cli/prompt.js.map +1 -0
- package/dist/esm/cli/ui/box.d.ts +21 -0
- package/dist/esm/cli/ui/box.d.ts.map +1 -0
- package/dist/esm/cli/ui/box.js +60 -0
- package/dist/esm/cli/ui/box.js.map +1 -0
- package/dist/esm/cli/ui/clipboard.d.ts +6 -0
- package/dist/esm/cli/ui/clipboard.d.ts.map +1 -0
- package/dist/esm/cli/ui/clipboard.js +42 -0
- package/dist/esm/cli/ui/clipboard.js.map +1 -0
- package/dist/esm/cli/ui/colors.d.ts +57 -0
- package/dist/esm/cli/ui/colors.d.ts.map +1 -0
- package/dist/esm/cli/ui/colors.js +126 -0
- package/dist/esm/cli/ui/colors.js.map +1 -0
- package/dist/esm/cli/ui/index.d.ts +9 -0
- package/dist/esm/cli/ui/index.d.ts.map +1 -0
- package/dist/esm/cli/ui/index.js +7 -0
- package/dist/esm/cli/ui/index.js.map +1 -0
- package/dist/esm/cli/ui/spinner.d.ts +12 -0
- package/dist/esm/cli/ui/spinner.d.ts.map +1 -0
- package/dist/esm/cli/ui/spinner.js +78 -0
- package/dist/esm/cli/ui/spinner.js.map +1 -0
- package/dist/esm/cli/ui/symbols.d.ts +47 -0
- package/dist/esm/cli/ui/symbols.d.ts.map +1 -0
- package/dist/esm/cli/ui/symbols.js +109 -0
- package/dist/esm/cli/ui/symbols.js.map +1 -0
- package/dist/esm/cli/ui/table.d.ts +23 -0
- package/dist/esm/cli/ui/table.d.ts.map +1 -0
- package/dist/esm/cli/ui/table.js +156 -0
- package/dist/esm/cli/ui/table.js.map +1 -0
- package/dist/esm/cli/ui/terminal.d.ts +7 -0
- package/dist/esm/cli/ui/terminal.d.ts.map +1 -0
- package/dist/esm/cli/ui/terminal.js +32 -0
- package/dist/esm/cli/ui/terminal.js.map +1 -0
- package/dist/esm/config/atomic-write.d.ts +69 -0
- package/dist/esm/config/atomic-write.d.ts.map +1 -0
- package/dist/esm/config/atomic-write.js +246 -0
- package/dist/esm/config/atomic-write.js.map +1 -0
- package/dist/esm/config/db-config.d.ts +134 -0
- package/dist/esm/config/db-config.d.ts.map +1 -0
- package/dist/esm/config/db-config.js +542 -0
- package/dist/esm/config/db-config.js.map +1 -0
- package/dist/esm/config/machine-config.d.ts +85 -0
- package/dist/esm/config/machine-config.d.ts.map +1 -0
- package/dist/esm/config/machine-config.js +190 -0
- package/dist/esm/config/machine-config.js.map +1 -0
- package/dist/esm/config/paths.d.ts +64 -0
- package/dist/esm/config/paths.d.ts.map +1 -0
- package/dist/esm/config/paths.js +108 -0
- package/dist/esm/config/paths.js.map +1 -0
- package/dist/esm/config/schema.d.ts +72 -0
- package/dist/esm/config/schema.d.ts.map +1 -0
- package/dist/esm/config/schema.js +180 -0
- package/dist/esm/config/schema.js.map +1 -0
- package/dist/esm/config/token.d.ts +63 -0
- package/dist/esm/config/token.d.ts.map +1 -0
- package/dist/esm/config/token.js +104 -0
- package/dist/esm/config/token.js.map +1 -0
- package/dist/esm/execution/canceller.d.ts +41 -0
- package/dist/esm/execution/canceller.d.ts.map +1 -0
- package/dist/esm/execution/canceller.js +205 -0
- package/dist/esm/execution/canceller.js.map +1 -0
- package/dist/esm/execution/database-lookup.d.ts +56 -0
- package/dist/esm/execution/database-lookup.d.ts.map +1 -0
- package/dist/esm/execution/database-lookup.js +38 -0
- package/dist/esm/execution/database-lookup.js.map +1 -0
- package/dist/esm/execution/dispatcher.d.ts +181 -0
- package/dist/esm/execution/dispatcher.d.ts.map +1 -0
- package/dist/esm/execution/dispatcher.js +1258 -0
- package/dist/esm/execution/dispatcher.js.map +1 -0
- package/dist/esm/execution/function-effects.d.ts +209 -0
- package/dist/esm/execution/function-effects.d.ts.map +1 -0
- package/dist/esm/execution/function-effects.js +586 -0
- package/dist/esm/execution/function-effects.js.map +1 -0
- package/dist/esm/execution/introspection.d.ts +76 -0
- package/dist/esm/execution/introspection.d.ts.map +1 -0
- package/dist/esm/execution/introspection.js +442 -0
- package/dist/esm/execution/introspection.js.map +1 -0
- package/dist/esm/execution/migration-runner.d.ts +128 -0
- package/dist/esm/execution/migration-runner.d.ts.map +1 -0
- package/dist/esm/execution/migration-runner.js +754 -0
- package/dist/esm/execution/migration-runner.js.map +1 -0
- package/dist/esm/execution/non-tx-detector.d.ts +23 -0
- package/dist/esm/execution/non-tx-detector.d.ts.map +1 -0
- package/dist/esm/execution/non-tx-detector.js +215 -0
- package/dist/esm/execution/non-tx-detector.js.map +1 -0
- package/dist/esm/execution/pool.d.ts +229 -0
- package/dist/esm/execution/pool.d.ts.map +1 -0
- package/dist/esm/execution/pool.js +685 -0
- package/dist/esm/execution/pool.js.map +1 -0
- package/dist/esm/execution/query-runner.d.ts +88 -0
- package/dist/esm/execution/query-runner.d.ts.map +1 -0
- package/dist/esm/execution/query-runner.js +743 -0
- package/dist/esm/execution/query-runner.js.map +1 -0
- package/dist/esm/execution/rate-limiter.d.ts +120 -0
- package/dist/esm/execution/rate-limiter.d.ts.map +1 -0
- package/dist/esm/execution/rate-limiter.js +269 -0
- package/dist/esm/execution/rate-limiter.js.map +1 -0
- package/dist/esm/execution/search-path.d.ts +161 -0
- package/dist/esm/execution/search-path.d.ts.map +1 -0
- package/dist/esm/execution/search-path.js +270 -0
- package/dist/esm/execution/search-path.js.map +1 -0
- package/dist/esm/execution/sql-parser.d.ts +195 -0
- package/dist/esm/execution/sql-parser.d.ts.map +1 -0
- package/dist/esm/execution/sql-parser.js +683 -0
- package/dist/esm/execution/sql-parser.js.map +1 -0
- package/dist/esm/execution/statement-classifier.d.ts +103 -0
- package/dist/esm/execution/statement-classifier.d.ts.map +1 -0
- package/dist/esm/execution/statement-classifier.js +526 -0
- package/dist/esm/execution/statement-classifier.js.map +1 -0
- package/dist/esm/execution/types.d.ts +189 -0
- package/dist/esm/execution/types.d.ts.map +1 -0
- package/dist/esm/execution/types.js +22 -0
- package/dist/esm/execution/types.js.map +1 -0
- package/dist/esm/index.d.ts +34 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +38 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/permissions/auto-upgrade.d.ts +40 -0
- package/dist/esm/permissions/auto-upgrade.d.ts.map +1 -0
- package/dist/esm/permissions/auto-upgrade.js +164 -0
- package/dist/esm/permissions/auto-upgrade.js.map +1 -0
- package/dist/esm/permissions/checker.d.ts +53 -0
- package/dist/esm/permissions/checker.d.ts.map +1 -0
- package/dist/esm/permissions/checker.js +322 -0
- package/dist/esm/permissions/checker.js.map +1 -0
- package/dist/esm/permissions/manual-approval.d.ts +213 -0
- package/dist/esm/permissions/manual-approval.d.ts.map +1 -0
- package/dist/esm/permissions/manual-approval.js +503 -0
- package/dist/esm/permissions/manual-approval.js.map +1 -0
- package/dist/esm/permissions/plan-registry.d.ts +274 -0
- package/dist/esm/permissions/plan-registry.d.ts.map +1 -0
- package/dist/esm/permissions/plan-registry.js +450 -0
- package/dist/esm/permissions/plan-registry.js.map +1 -0
- package/dist/esm/permissions/role-policy.d.ts +217 -0
- package/dist/esm/permissions/role-policy.d.ts.map +1 -0
- package/dist/esm/permissions/role-policy.js +570 -0
- package/dist/esm/permissions/role-policy.js.map +1 -0
- package/dist/esm/permissions/types.d.ts +126 -0
- package/dist/esm/permissions/types.d.ts.map +1 -0
- package/dist/esm/permissions/types.js +2 -0
- package/dist/esm/permissions/types.js.map +1 -0
- package/dist/esm/protocol/constants.d.ts +72 -0
- package/dist/esm/protocol/constants.d.ts.map +1 -0
- package/dist/esm/protocol/constants.js +104 -0
- package/dist/esm/protocol/constants.js.map +1 -0
- package/dist/esm/protocol/envelope.d.ts +165 -0
- package/dist/esm/protocol/envelope.d.ts.map +1 -0
- package/dist/esm/protocol/envelope.js +263 -0
- package/dist/esm/protocol/envelope.js.map +1 -0
- package/dist/esm/protocol/errors.d.ts +33 -0
- package/dist/esm/protocol/errors.d.ts.map +1 -0
- package/dist/esm/protocol/errors.js +384 -0
- package/dist/esm/protocol/errors.js.map +1 -0
- package/dist/esm/protocol/messages.d.ts +327 -0
- package/dist/esm/protocol/messages.d.ts.map +1 -0
- package/dist/esm/protocol/messages.js +2 -0
- package/dist/esm/protocol/messages.js.map +1 -0
- package/dist/esm/protocol/serialize.d.ts +26 -0
- package/dist/esm/protocol/serialize.d.ts.map +1 -0
- package/dist/esm/protocol/serialize.js +63 -0
- package/dist/esm/protocol/serialize.js.map +1 -0
- package/dist/esm/protocol/validate.d.ts +135 -0
- package/dist/esm/protocol/validate.d.ts.map +1 -0
- package/dist/esm/protocol/validate.js +830 -0
- package/dist/esm/protocol/validate.js.map +1 -0
- package/dist/types/audit/chain.d.ts +365 -0
- package/dist/types/audit/chain.d.ts.map +1 -0
- package/dist/types/audit/cloud-client.d.ts +142 -0
- package/dist/types/audit/cloud-client.d.ts.map +1 -0
- package/dist/types/audit/cloud-writer.d.ts +57 -0
- package/dist/types/audit/cloud-writer.d.ts.map +1 -0
- package/dist/types/audit/context.d.ts +51 -0
- package/dist/types/audit/context.d.ts.map +1 -0
- package/dist/types/audit/files.d.ts +111 -0
- package/dist/types/audit/files.d.ts.map +1 -0
- package/dist/types/audit/index.d.ts +9 -0
- package/dist/types/audit/index.d.ts.map +1 -0
- package/dist/types/audit/local-writer.d.ts +255 -0
- package/dist/types/audit/local-writer.d.ts.map +1 -0
- package/dist/types/audit/redact.d.ts +151 -0
- package/dist/types/audit/redact.d.ts.map +1 -0
- package/dist/types/audit/sanitize.d.ts +78 -0
- package/dist/types/audit/sanitize.d.ts.map +1 -0
- package/dist/types/audit/sink.d.ts +278 -0
- package/dist/types/audit/sink.d.ts.map +1 -0
- package/dist/types/audit/types.d.ts +226 -0
- package/dist/types/audit/types.d.ts.map +1 -0
- package/dist/types/audit/verify-cache.d.ts +127 -0
- package/dist/types/audit/verify-cache.d.ts.map +1 -0
- package/dist/types/channels/agent-session.d.ts +228 -0
- package/dist/types/channels/agent-session.d.ts.map +1 -0
- package/dist/types/channels/data-channel.d.ts +181 -0
- package/dist/types/channels/data-channel.d.ts.map +1 -0
- package/dist/types/channels/reconnect.d.ts +142 -0
- package/dist/types/channels/reconnect.d.ts.map +1 -0
- package/dist/types/channels/types.d.ts +112 -0
- package/dist/types/channels/types.d.ts.map +1 -0
- package/dist/types/channels/wake-channel.d.ts +232 -0
- package/dist/types/channels/wake-channel.d.ts.map +1 -0
- package/dist/types/cli/banner.d.ts +2 -0
- package/dist/types/cli/banner.d.ts.map +1 -0
- package/dist/types/cli/commands/agent.d.ts +30 -0
- package/dist/types/cli/commands/agent.d.ts.map +1 -0
- package/dist/types/cli/commands/audit-verify.d.ts +19 -0
- package/dist/types/cli/commands/audit-verify.d.ts.map +1 -0
- package/dist/types/cli/commands/clean.d.ts +23 -0
- package/dist/types/cli/commands/clean.d.ts.map +1 -0
- package/dist/types/cli/commands/config-show.d.ts +2 -0
- package/dist/types/cli/commands/config-show.d.ts.map +1 -0
- package/dist/types/cli/commands/config.d.ts +6 -0
- package/dist/types/cli/commands/config.d.ts.map +1 -0
- package/dist/types/cli/commands/db-add.d.ts +16 -0
- package/dist/types/cli/commands/db-add.d.ts.map +1 -0
- package/dist/types/cli/commands/db-edit.d.ts +2 -0
- package/dist/types/cli/commands/db-edit.d.ts.map +1 -0
- package/dist/types/cli/commands/db-logs.d.ts +3 -0
- package/dist/types/cli/commands/db-logs.d.ts.map +1 -0
- package/dist/types/cli/commands/db-ls.d.ts +2 -0
- package/dist/types/cli/commands/db-ls.d.ts.map +1 -0
- package/dist/types/cli/commands/db-query.d.ts +121 -0
- package/dist/types/cli/commands/db-query.d.ts.map +1 -0
- package/dist/types/cli/commands/db-remove.d.ts +2 -0
- package/dist/types/cli/commands/db-remove.d.ts.map +1 -0
- package/dist/types/cli/commands/db-show.d.ts +2 -0
- package/dist/types/cli/commands/db-show.d.ts.map +1 -0
- package/dist/types/cli/commands/db-test.d.ts +3 -0
- package/dist/types/cli/commands/db-test.d.ts.map +1 -0
- package/dist/types/cli/commands/db.d.ts +11 -0
- package/dist/types/cli/commands/db.d.ts.map +1 -0
- package/dist/types/cli/commands/debug.d.ts +2 -0
- package/dist/types/cli/commands/debug.d.ts.map +1 -0
- package/dist/types/cli/commands/doctor.d.ts +5 -0
- package/dist/types/cli/commands/doctor.d.ts.map +1 -0
- package/dist/types/cli/commands/index.d.ts +10 -0
- package/dist/types/cli/commands/index.d.ts.map +1 -0
- package/dist/types/cli/commands/init.d.ts +2 -0
- package/dist/types/cli/commands/init.d.ts.map +1 -0
- package/dist/types/cli/commands/link.d.ts +5 -0
- package/dist/types/cli/commands/link.d.ts.map +1 -0
- package/dist/types/cli/commands/logs.d.ts +17 -0
- package/dist/types/cli/commands/logs.d.ts.map +1 -0
- package/dist/types/cli/commands/project-show.d.ts +2 -0
- package/dist/types/cli/commands/project-show.d.ts.map +1 -0
- package/dist/types/cli/commands/project.d.ts +3 -0
- package/dist/types/cli/commands/project.d.ts.map +1 -0
- package/dist/types/cli/commands/service.d.ts +123 -0
- package/dist/types/cli/commands/service.d.ts.map +1 -0
- package/dist/types/cli/commands/start.d.ts +6 -0
- package/dist/types/cli/commands/start.d.ts.map +1 -0
- package/dist/types/cli/commands/status.d.ts +2 -0
- package/dist/types/cli/commands/status.d.ts.map +1 -0
- package/dist/types/cli/commands/stop.d.ts +6 -0
- package/dist/types/cli/commands/stop.d.ts.map +1 -0
- package/dist/types/cli/daemon/error-tracker.d.ts +119 -0
- package/dist/types/cli/daemon/error-tracker.d.ts.map +1 -0
- package/dist/types/cli/daemon/fault-shutdown.d.ts +144 -0
- package/dist/types/cli/daemon/fault-shutdown.d.ts.map +1 -0
- package/dist/types/cli/daemon/index.d.ts +12 -0
- package/dist/types/cli/daemon/index.d.ts.map +1 -0
- package/dist/types/cli/daemon/pid-file.d.ts +13 -0
- package/dist/types/cli/daemon/pid-file.d.ts.map +1 -0
- package/dist/types/cli/daemon/readiness.d.ts +30 -0
- package/dist/types/cli/daemon/readiness.d.ts.map +1 -0
- package/dist/types/cli/daemon/runtime.d.ts +366 -0
- package/dist/types/cli/daemon/runtime.d.ts.map +1 -0
- package/dist/types/cli/daemon/shutdown.d.ts +7 -0
- package/dist/types/cli/daemon/shutdown.d.ts.map +1 -0
- package/dist/types/cli/daemon/signal-handlers.d.ts +3 -0
- package/dist/types/cli/daemon/signal-handlers.d.ts.map +1 -0
- package/dist/types/cli/daemon/state.d.ts +157 -0
- package/dist/types/cli/daemon/state.d.ts.map +1 -0
- package/dist/types/cli/daemon/status-file.d.ts +139 -0
- package/dist/types/cli/daemon/status-file.d.ts.map +1 -0
- package/dist/types/cli/doctor/checks.d.ts +133 -0
- package/dist/types/cli/doctor/checks.d.ts.map +1 -0
- package/dist/types/cli/doctor/fixes.d.ts +9 -0
- package/dist/types/cli/doctor/fixes.d.ts.map +1 -0
- package/dist/types/cli/doctor/index.d.ts +7 -0
- package/dist/types/cli/doctor/index.d.ts.map +1 -0
- package/dist/types/cli/index.d.ts +3 -0
- package/dist/types/cli/index.d.ts.map +1 -0
- package/dist/types/cli/interactive.d.ts +8 -0
- package/dist/types/cli/interactive.d.ts.map +1 -0
- package/dist/types/cli/logs/format.d.ts +13 -0
- package/dist/types/cli/logs/format.d.ts.map +1 -0
- package/dist/types/cli/logs/index.d.ts +3 -0
- package/dist/types/cli/logs/index.d.ts.map +1 -0
- package/dist/types/cli/logs/viewer.d.ts +41 -0
- package/dist/types/cli/logs/viewer.d.ts.map +1 -0
- package/dist/types/cli/ops/operation-logger.d.ts +63 -0
- package/dist/types/cli/ops/operation-logger.d.ts.map +1 -0
- package/dist/types/cli/palette.d.ts +11 -0
- package/dist/types/cli/palette.d.ts.map +1 -0
- package/dist/types/cli/prompt.d.ts +186 -0
- package/dist/types/cli/prompt.d.ts.map +1 -0
- package/dist/types/cli/ui/box.d.ts +21 -0
- package/dist/types/cli/ui/box.d.ts.map +1 -0
- package/dist/types/cli/ui/clipboard.d.ts +6 -0
- package/dist/types/cli/ui/clipboard.d.ts.map +1 -0
- package/dist/types/cli/ui/colors.d.ts +57 -0
- package/dist/types/cli/ui/colors.d.ts.map +1 -0
- package/dist/types/cli/ui/index.d.ts +9 -0
- package/dist/types/cli/ui/index.d.ts.map +1 -0
- package/dist/types/cli/ui/spinner.d.ts +12 -0
- package/dist/types/cli/ui/spinner.d.ts.map +1 -0
- package/dist/types/cli/ui/symbols.d.ts +47 -0
- package/dist/types/cli/ui/symbols.d.ts.map +1 -0
- package/dist/types/cli/ui/table.d.ts +23 -0
- package/dist/types/cli/ui/table.d.ts.map +1 -0
- package/dist/types/cli/ui/terminal.d.ts +7 -0
- package/dist/types/cli/ui/terminal.d.ts.map +1 -0
- package/dist/types/config/atomic-write.d.ts +69 -0
- package/dist/types/config/atomic-write.d.ts.map +1 -0
- package/dist/types/config/db-config.d.ts +134 -0
- package/dist/types/config/db-config.d.ts.map +1 -0
- package/dist/types/config/machine-config.d.ts +85 -0
- package/dist/types/config/machine-config.d.ts.map +1 -0
- package/dist/types/config/paths.d.ts +64 -0
- package/dist/types/config/paths.d.ts.map +1 -0
- package/dist/types/config/schema.d.ts +72 -0
- package/dist/types/config/schema.d.ts.map +1 -0
- package/dist/types/config/token.d.ts +63 -0
- package/dist/types/config/token.d.ts.map +1 -0
- package/dist/types/execution/canceller.d.ts +41 -0
- package/dist/types/execution/canceller.d.ts.map +1 -0
- package/dist/types/execution/database-lookup.d.ts +56 -0
- package/dist/types/execution/database-lookup.d.ts.map +1 -0
- package/dist/types/execution/dispatcher.d.ts +181 -0
- package/dist/types/execution/dispatcher.d.ts.map +1 -0
- package/dist/types/execution/function-effects.d.ts +209 -0
- package/dist/types/execution/function-effects.d.ts.map +1 -0
- package/dist/types/execution/introspection.d.ts +76 -0
- package/dist/types/execution/introspection.d.ts.map +1 -0
- package/dist/types/execution/migration-runner.d.ts +128 -0
- package/dist/types/execution/migration-runner.d.ts.map +1 -0
- package/dist/types/execution/non-tx-detector.d.ts +23 -0
- package/dist/types/execution/non-tx-detector.d.ts.map +1 -0
- package/dist/types/execution/pool.d.ts +229 -0
- package/dist/types/execution/pool.d.ts.map +1 -0
- package/dist/types/execution/query-runner.d.ts +88 -0
- package/dist/types/execution/query-runner.d.ts.map +1 -0
- package/dist/types/execution/rate-limiter.d.ts +120 -0
- package/dist/types/execution/rate-limiter.d.ts.map +1 -0
- package/dist/types/execution/search-path.d.ts +161 -0
- package/dist/types/execution/search-path.d.ts.map +1 -0
- package/dist/types/execution/sql-parser.d.ts +195 -0
- package/dist/types/execution/sql-parser.d.ts.map +1 -0
- package/dist/types/execution/statement-classifier.d.ts +103 -0
- package/dist/types/execution/statement-classifier.d.ts.map +1 -0
- package/dist/types/execution/types.d.ts +189 -0
- package/dist/types/execution/types.d.ts.map +1 -0
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/permissions/auto-upgrade.d.ts +40 -0
- package/dist/types/permissions/auto-upgrade.d.ts.map +1 -0
- package/dist/types/permissions/checker.d.ts +53 -0
- package/dist/types/permissions/checker.d.ts.map +1 -0
- package/dist/types/permissions/manual-approval.d.ts +213 -0
- package/dist/types/permissions/manual-approval.d.ts.map +1 -0
- package/dist/types/permissions/plan-registry.d.ts +274 -0
- package/dist/types/permissions/plan-registry.d.ts.map +1 -0
- package/dist/types/permissions/role-policy.d.ts +217 -0
- package/dist/types/permissions/role-policy.d.ts.map +1 -0
- package/dist/types/permissions/types.d.ts +126 -0
- package/dist/types/permissions/types.d.ts.map +1 -0
- package/dist/types/protocol/constants.d.ts +72 -0
- package/dist/types/protocol/constants.d.ts.map +1 -0
- package/dist/types/protocol/envelope.d.ts +165 -0
- package/dist/types/protocol/envelope.d.ts.map +1 -0
- package/dist/types/protocol/errors.d.ts +33 -0
- package/dist/types/protocol/errors.d.ts.map +1 -0
- package/dist/types/protocol/messages.d.ts +327 -0
- package/dist/types/protocol/messages.d.ts.map +1 -0
- package/dist/types/protocol/serialize.d.ts +26 -0
- package/dist/types/protocol/serialize.d.ts.map +1 -0
- package/dist/types/protocol/validate.d.ts +135 -0
- package/dist/types/protocol/validate.d.ts.map +1 -0
- package/package.json +116 -4
- package/scripts/generate-systemd-service.mjs +117 -0
|
@@ -0,0 +1,1296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Dispatcher = void 0;
|
|
37
|
+
exports.evaluateEventGate = evaluateEventGate;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const pool_1 = require("./pool");
|
|
40
|
+
const errors_1 = require("../protocol/errors");
|
|
41
|
+
const role_policy_1 = require("../permissions/role-policy");
|
|
42
|
+
const manual_approval_1 = require("../permissions/manual-approval");
|
|
43
|
+
const context_1 = require("../audit/context");
|
|
44
|
+
const redact_1 = require("../audit/redact");
|
|
45
|
+
const rate_limiter_1 = require("./rate-limiter");
|
|
46
|
+
const database_lookup_1 = require("./database-lookup");
|
|
47
|
+
const validate_1 = require("../protocol/validate");
|
|
48
|
+
const function_effects_1 = require("./function-effects");
|
|
49
|
+
const sanitize_1 = require("../audit/sanitize");
|
|
50
|
+
class Dispatcher {
|
|
51
|
+
opts;
|
|
52
|
+
rateLimiter;
|
|
53
|
+
constructor(opts) {
|
|
54
|
+
this.opts = opts;
|
|
55
|
+
this.rateLimiter = opts.rateLimiter ?? new rate_limiter_1.RateLimiter();
|
|
56
|
+
}
|
|
57
|
+
async sendResponse(msg, payload, resolvedAlias) {
|
|
58
|
+
await this.opts.send({
|
|
59
|
+
v: 1,
|
|
60
|
+
id: crypto.randomUUID(),
|
|
61
|
+
type: 'response',
|
|
62
|
+
project: msg.project,
|
|
63
|
+
user: msg.user,
|
|
64
|
+
// The RESOLVED alias, so the browser's view of "which database answered"
|
|
65
|
+
// matches the audit trail. Falling back to the asserted alias is only for
|
|
66
|
+
// frames that resolved to no database at all (`ping`), where there is
|
|
67
|
+
// nothing truer to send.
|
|
68
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
69
|
+
ts: Date.now(),
|
|
70
|
+
payload: {
|
|
71
|
+
request_id: msg.id,
|
|
72
|
+
...payload,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* `pg_error` is deliberately limited to the two allow-listed fields. Passing
|
|
78
|
+
* `detail` or `hint` here is a compile error on purpose: both routinely carry
|
|
79
|
+
* row data (`DETAIL: Key (email)=(alice@corp.com) already exists.`) and the
|
|
80
|
+
* risk only ever grows.
|
|
81
|
+
*/
|
|
82
|
+
async sendError(msg, code, message, pg_error, resolvedAlias) {
|
|
83
|
+
await this.opts.send({
|
|
84
|
+
v: 1,
|
|
85
|
+
id: crypto.randomUUID(),
|
|
86
|
+
type: 'error',
|
|
87
|
+
project: msg.project,
|
|
88
|
+
user: msg.user,
|
|
89
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
90
|
+
ts: Date.now(),
|
|
91
|
+
payload: (0, errors_1.makeError)(code, msg.id, { message, pg_error }),
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Register a migration plan. Callers must have passed `evaluateEventGate`;
|
|
96
|
+
* this method re-checks the shape of the payload and never invents an
|
|
97
|
+
* effective permission level for the audit record.
|
|
98
|
+
*/
|
|
99
|
+
async handlePlanRegister(msg, statements, riskLevel, permissionLevel, resolvedAlias) {
|
|
100
|
+
// Re-asserted so the method is safe to call from anywhere, not only from
|
|
101
|
+
// `handleEvent`. Denials are audited by the caller, so nothing is logged
|
|
102
|
+
// twice.
|
|
103
|
+
const gate = this.evaluateGate(msg, permissionLevel);
|
|
104
|
+
if (!gate.allowed) {
|
|
105
|
+
return this.sendError(msg, gate.errorCode, gate.reason, undefined, resolvedAlias);
|
|
106
|
+
}
|
|
107
|
+
if (!Array.isArray(statements) ||
|
|
108
|
+
statements.length === 0 ||
|
|
109
|
+
statements.some((s) => typeof s !== 'string' || s.trim().length === 0)) {
|
|
110
|
+
return this.sendError(msg, 'payload_invalid', 'A migration plan must contain at least one non-empty statement.', undefined, resolvedAlias);
|
|
111
|
+
}
|
|
112
|
+
const planId = `plan_${crypto.randomUUID()}`;
|
|
113
|
+
// the plan is bound to the RESOLVED database, so a statement set
|
|
114
|
+
// reviewed here cannot later be executed against a different entry. The
|
|
115
|
+
// registry refuses a registration that cannot name one.
|
|
116
|
+
const registered = this.opts.planRegistry.register(planId, statements, msg.user.id, riskLevel, {
|
|
117
|
+
user_id: msg.user.id,
|
|
118
|
+
role: msg.user.role,
|
|
119
|
+
permission_level: permissionLevel,
|
|
120
|
+
project: msg.project,
|
|
121
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
122
|
+
});
|
|
123
|
+
// Fail closed. Without the principal the registry refuses to store
|
|
124
|
+
// anything, and issuing a plan_id for a plan that does not exist would be
|
|
125
|
+
// a lie in the audit trail and a dead end for the browser.
|
|
126
|
+
if (!registered.ok) {
|
|
127
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
128
|
+
action: 'plan_register',
|
|
129
|
+
denial_reason: registered.code,
|
|
130
|
+
});
|
|
131
|
+
return this.sendError(msg, 'permission_denied', registered.reason, undefined, resolvedAlias);
|
|
132
|
+
}
|
|
133
|
+
if (this.opts.auditSink) {
|
|
134
|
+
await this.opts.auditSink.logSync({
|
|
135
|
+
...this.auditBase(msg, permissionLevel),
|
|
136
|
+
action: 'plan_register',
|
|
137
|
+
decision: 'allow',
|
|
138
|
+
outcome: 'n/a',
|
|
139
|
+
// The level the registration was actually authorised at. This used to
|
|
140
|
+
// be the literal 'full', which misrepresented every registration.
|
|
141
|
+
migration_plan_id: planId,
|
|
142
|
+
statement_preview: (0, redact_1.previewStatement)(statements.join('; ')),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
await this.sendResponse(msg, {
|
|
146
|
+
ok: true,
|
|
147
|
+
data: { plan_id: planId, expires_in_ms: 300_000 },
|
|
148
|
+
}, resolvedAlias);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Derive the authorization decision for an inbound `event` frame.
|
|
152
|
+
*
|
|
153
|
+
* `PlanRegistry.canRegister` owns the plan-registration decision, so asking
|
|
154
|
+
* it directly is what keeps the entry gate and the registry from disagreeing.
|
|
155
|
+
*/
|
|
156
|
+
evaluateGate(msg, permissionLevel) {
|
|
157
|
+
const kind = msg.payload?.kind;
|
|
158
|
+
return evaluateEventGate(kind, msg.user.role, permissionLevel, (role, level) => this.opts.planRegistry.canRegister(role, level));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Handle an inbound `event` frame.
|
|
162
|
+
*
|
|
163
|
+
* Every kind is authorized before any handler runs. The previous
|
|
164
|
+
* implementation dispatched `approval_response` and `plan_register` from the
|
|
165
|
+
* top of `handle()`, ahead of the query/migration permission pipeline, so a
|
|
166
|
+
* `viewer` could resolve another user's pending manual approval and could
|
|
167
|
+
* register an arbitrary migration plan for later replay at `auto_upgrade`.
|
|
168
|
+
*/
|
|
169
|
+
async handleEvent(msg, permissionLevel, resolvedAlias) {
|
|
170
|
+
const payload = msg.payload;
|
|
171
|
+
const kind = payload?.kind;
|
|
172
|
+
const gate = this.evaluateGate(msg, permissionLevel);
|
|
173
|
+
if (!gate.allowed) {
|
|
174
|
+
if (gate.auditAction) {
|
|
175
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
176
|
+
action: gate.auditAction,
|
|
177
|
+
denial_reason: gate.code,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
return this.sendError(msg, gate.errorCode, gate.reason, undefined, resolvedAlias);
|
|
181
|
+
}
|
|
182
|
+
if (kind === 'plan_register') {
|
|
183
|
+
const data = payload.data;
|
|
184
|
+
return this.handlePlanRegister(msg, data.statements, data.risk_level || data.riskLevel, permissionLevel, resolvedAlias);
|
|
185
|
+
}
|
|
186
|
+
const data = payload.data;
|
|
187
|
+
// `approved_by` is deliberately not forwarded. It is free text supplied by
|
|
188
|
+
// the sender; the approver recorded in the audit trail comes from the
|
|
189
|
+
// verified envelope via `actorId`, so a spoofed string cannot fabricate an
|
|
190
|
+
// attestation.
|
|
191
|
+
const outcome = this.opts.permissionChecker.opts.manualApprovalHandler.handleResponse({
|
|
192
|
+
request_id: typeof data?.request_id === 'string' ? data.request_id : '',
|
|
193
|
+
approved: data?.approved === true,
|
|
194
|
+
// Forwarded verbatim: the handler consumes it exactly once.
|
|
195
|
+
approval_nonce: typeof data?.approval_nonce === 'string' ? data.approval_nonce : '',
|
|
196
|
+
}, { actorId: msg.user.id, actorRole: msg.user.role });
|
|
197
|
+
// Every refusal looks identical on the wire. The handler distinguishes
|
|
198
|
+
// "no pending approval", "not the requesting user", "role may not approve"
|
|
199
|
+
// and "nonce mismatch"; returning those reasons would tell an attacker
|
|
200
|
+
// that a request id they chose really does have an approval pending under
|
|
201
|
+
// somebody else's account.
|
|
202
|
+
await this.sendResponse(msg, {
|
|
203
|
+
ok: outcome.handled,
|
|
204
|
+
data: outcome.handled
|
|
205
|
+
? { resolved: true, request_id: data.request_id }
|
|
206
|
+
: { resolved: false, reason: 'no matching pending approval' },
|
|
207
|
+
}, resolvedAlias);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Handle one inbound frame.
|
|
212
|
+
*
|
|
213
|
+
* The frame's `(project, db_alias)` is resolved first and everything after —
|
|
214
|
+
* every authorization decision, every database call, every audit record —
|
|
215
|
+
* happens inside the resolved-database context. That ordering is the durable
|
|
216
|
+
* half of the fix: the audit sink takes the resolved identity from the
|
|
217
|
+
* context, so no call site can write the frame's own claim into the record, and
|
|
218
|
+
* a frame that resolves to nothing is recorded as `unresolved` rather than as
|
|
219
|
+
* the database it asked for.
|
|
220
|
+
*/
|
|
221
|
+
async handle(msg) {
|
|
222
|
+
const resolution = (0, database_lookup_1.normaliseLookupResult)(this.opts.lookupDb(msg.project, msg.db_alias), msg.project, msg.db_alias);
|
|
223
|
+
const identity = resolution.ok
|
|
224
|
+
? (0, context_1.resolvedIdentityOf)(resolution.entry)
|
|
225
|
+
: context_1.UNRESOLVED_DB_IDENTITY;
|
|
226
|
+
return (0, context_1.withResolvedDatabase)(identity, () => this.handleResolved(msg, resolution));
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The fields every audit record for one frame carries.
|
|
230
|
+
*
|
|
231
|
+
* Centralised so the asserted identity (`project`, `db_alias_asserted`) is
|
|
232
|
+
* recorded identically on allows and denials: the resolved identity comes from
|
|
233
|
+
* the sink's context, and these two come from the frame. A record that names
|
|
234
|
+
* what the frame claimed and what the agent resolved is the only way a
|
|
235
|
+
* mismatch like is visible to anyone reading the trail afterwards.
|
|
236
|
+
*/
|
|
237
|
+
auditBase(msg, permissionLevel) {
|
|
238
|
+
return {
|
|
239
|
+
id: msg.id,
|
|
240
|
+
project: msg.project,
|
|
241
|
+
db_alias_asserted: msg.db_alias,
|
|
242
|
+
user_id: msg.user.id,
|
|
243
|
+
role: msg.user.role,
|
|
244
|
+
permission_level: permissionLevel,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/** Awaited audit write, or a no-op when no sink is configured. */
|
|
248
|
+
async auditDeny(msg, permissionLevel, fields) {
|
|
249
|
+
if (!this.opts.auditSink)
|
|
250
|
+
return;
|
|
251
|
+
await this.opts.auditSink.logSync({
|
|
252
|
+
...this.auditBase(msg, permissionLevel),
|
|
253
|
+
decision: 'deny',
|
|
254
|
+
outcome: fields.outcome ?? 'n/a',
|
|
255
|
+
...fields,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
async handleResolved(msg, resolution) {
|
|
259
|
+
const dbEntry = resolution.ok ? resolution.entry : null;
|
|
260
|
+
/**
|
|
261
|
+
* The alias every outbound frame echoes. The RESOLVED one, never `msg.db_alias`:
|
|
262
|
+
* echoing the asserted alias back is how a frame that named one database and
|
|
263
|
+
* ran against another stayed invisible to the browser.
|
|
264
|
+
*/
|
|
265
|
+
const resolvedAlias = dbEntry?.db_alias;
|
|
266
|
+
const abortController = new AbortController();
|
|
267
|
+
const startTime = Date.now();
|
|
268
|
+
const machineConfig = this.opts.getMachineConfig();
|
|
269
|
+
const permissionLevel = dbEntry
|
|
270
|
+
? (dbEntry.permission_override ?? machineConfig.default_permission)
|
|
271
|
+
: machineConfig.default_permission;
|
|
272
|
+
// Admission control runs before any work, including the database: a single
|
|
273
|
+
// authenticated sender must not be able to saturate the connector or the
|
|
274
|
+
// customer's database. The permit is released in the `finally` below, so a
|
|
275
|
+
// rejected or failed request still gives its concurrency slot back.
|
|
276
|
+
const permit = this.rateLimiter.tryAcquire(mapMessageTypeToRateLimitAction(msg.type), {
|
|
277
|
+
agent_id: machineConfig.agent_id,
|
|
278
|
+
user_id: msg.user.id,
|
|
279
|
+
db_alias: dbEntry?.db_alias ?? msg.db_alias ?? '',
|
|
280
|
+
});
|
|
281
|
+
if (!permit.allowed) {
|
|
282
|
+
// Admission control refusals are refusals, and is the finding that a
|
|
283
|
+
// refusal nothing records is indistinguishable from a request that never
|
|
284
|
+
// arrived. Recorded with the reason code so the trail distinguishes a
|
|
285
|
+
// rate-limit from an authorization decision without leaking which was which
|
|
286
|
+
// to the caller (the wire error stays `rate_limited`).
|
|
287
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
288
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
289
|
+
denial_reason: safeAuditReason(permit.reason ?? 'rate_limit_exceeded'),
|
|
290
|
+
});
|
|
291
|
+
return this.sendError(msg, 'rate_limited', rateLimitMessage(permit.reason, permit.scope), undefined, resolvedAlias);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Independent of the approval promise. Released by the watchdog below
|
|
295
|
+
* if the request is still parked on a human when the approval window plus
|
|
296
|
+
* slack has elapsed, so a stranded promise can never hold a concurrency
|
|
297
|
+
* permit forever.
|
|
298
|
+
*/
|
|
299
|
+
let watchdog = null;
|
|
300
|
+
/** Whether this frame already passed an authorization decision. */
|
|
301
|
+
let authorized = false;
|
|
302
|
+
try {
|
|
303
|
+
if (!dbEntry && msg.type !== 'ping') {
|
|
304
|
+
// Every way a frame can fail to resolve a database is now audited under
|
|
305
|
+
// its own reason: unknown entry, out of scope, no allow-list configured,
|
|
306
|
+
// or a project/alias collision (, ).
|
|
307
|
+
const refusal = resolution;
|
|
308
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
309
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
310
|
+
denial_reason: refusal.code,
|
|
311
|
+
});
|
|
312
|
+
return this.sendError(msg, databaseRefusalErrorCode(refusal.code), databaseRefusalMessage(refusal), undefined, resolvedAlias);
|
|
313
|
+
}
|
|
314
|
+
if (msg.type === 'ping') {
|
|
315
|
+
return this.sendResponse(msg, { ok: true, data: { agent_time: Date.now() } }, resolvedAlias);
|
|
316
|
+
}
|
|
317
|
+
if (msg.type === 'cancel') {
|
|
318
|
+
return this.handleCancel(msg, permissionLevel, resolvedAlias, startTime);
|
|
319
|
+
}
|
|
320
|
+
if (msg.type === 'event') {
|
|
321
|
+
return this.handleEvent(msg, permissionLevel, resolvedAlias);
|
|
322
|
+
}
|
|
323
|
+
let sql = '';
|
|
324
|
+
/** Set from the permission decision so execution cannot disagree with it. */
|
|
325
|
+
let decisionClassification;
|
|
326
|
+
let statements;
|
|
327
|
+
let intent = 'read';
|
|
328
|
+
let planId;
|
|
329
|
+
if (msg.type === 'query' || msg.type === 'stream_query') {
|
|
330
|
+
const payload = msg.payload;
|
|
331
|
+
sql = payload.sql;
|
|
332
|
+
intent = payload.intent;
|
|
333
|
+
planId = payload.plan_id;
|
|
334
|
+
}
|
|
335
|
+
else if (msg.type === 'migration_run') {
|
|
336
|
+
const payload = msg.payload;
|
|
337
|
+
statements = payload.statements;
|
|
338
|
+
sql = statements[0] ?? '';
|
|
339
|
+
intent = 'migration';
|
|
340
|
+
planId = payload.plan_id;
|
|
341
|
+
}
|
|
342
|
+
else if (msg.type === 'introspect') {
|
|
343
|
+
if (!(0, role_policy_1.hasCapability)(msg.user.role, 'introspect')) {
|
|
344
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
345
|
+
action: 'introspect',
|
|
346
|
+
denial_reason: 'role_denied',
|
|
347
|
+
});
|
|
348
|
+
return this.sendError(msg, 'role_insufficient', `Role '${msg.user.role}' cannot introspect`, undefined, resolvedAlias);
|
|
349
|
+
}
|
|
350
|
+
authorized = true;
|
|
351
|
+
if (this.opts.auditSink) {
|
|
352
|
+
await this.opts.auditSink.logSync({
|
|
353
|
+
...this.auditBase(msg, permissionLevel),
|
|
354
|
+
action: 'introspect',
|
|
355
|
+
decision: 'allow',
|
|
356
|
+
outcome: 'n/a',
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
const result = await this.opts.introspector.introspect(msg.payload, dbEntry);
|
|
360
|
+
const elapsedMs = Date.now() - startTime;
|
|
361
|
+
// Introspection returns the whole schema, so a caller that loops it is
|
|
362
|
+
// exfiltrating. The rate limiter bounds how often it runs; this bounds
|
|
363
|
+
// how much leaves in one response.
|
|
364
|
+
const sizeVerdict = this.rateLimiter.checkIntrospectSize(serializedSizeOf(result));
|
|
365
|
+
if (!sizeVerdict.allowed) {
|
|
366
|
+
if (this.opts.auditSink) {
|
|
367
|
+
this.opts.auditSink.log({
|
|
368
|
+
...this.auditBase(msg, permissionLevel),
|
|
369
|
+
action: 'introspect',
|
|
370
|
+
decision: 'allow',
|
|
371
|
+
outcome: 'error',
|
|
372
|
+
duration_ms: elapsedMs,
|
|
373
|
+
error_code: 'RATE_LIMITED',
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
return this.sendError(msg, 'rate_limited', 'Introspection snapshot exceeds the configured response budget. Request a narrower ' +
|
|
377
|
+
'snapshot (for example without triggers or partitions).', undefined, resolvedAlias);
|
|
378
|
+
}
|
|
379
|
+
if (this.opts.auditSink) {
|
|
380
|
+
this.opts.auditSink.log({
|
|
381
|
+
...this.auditBase(msg, permissionLevel),
|
|
382
|
+
action: 'introspect',
|
|
383
|
+
decision: 'allow',
|
|
384
|
+
outcome: 'success',
|
|
385
|
+
duration_ms: elapsedMs,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
await this.sendResponse(msg, {
|
|
389
|
+
request_id: msg.id,
|
|
390
|
+
ok: true,
|
|
391
|
+
data: result,
|
|
392
|
+
}, resolvedAlias);
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
return this.sendError(msg, 'invalid_message', `Cannot handle message type '${msg.type}' from browser`, undefined, resolvedAlias);
|
|
397
|
+
}
|
|
398
|
+
if (msg.type === 'query' || msg.type === 'stream_query' || msg.type === 'migration_run') {
|
|
399
|
+
// a plan is bound to the database it was registered against. The
|
|
400
|
+
// registry cannot see this frame (the `consume()` call is made deeper in
|
|
401
|
+
// the permission pipeline), so the binding is checked here, before any
|
|
402
|
+
// authority is consulted. An unregistered plan id passes: a `migration_run`
|
|
403
|
+
// at `full` legitimately needs no plan.
|
|
404
|
+
if (planId) {
|
|
405
|
+
const scopeVerdict = this.opts.planRegistry.assertExecutionScope(planId, {
|
|
406
|
+
project: dbEntry?.project_name ?? msg.project,
|
|
407
|
+
db_alias: dbEntry?.db_alias ?? '',
|
|
408
|
+
});
|
|
409
|
+
if (!scopeVerdict.ok) {
|
|
410
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
411
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
412
|
+
denial_reason: 'plan_scope_mismatch',
|
|
413
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
414
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
415
|
+
migration_plan_id: planId,
|
|
416
|
+
});
|
|
417
|
+
return this.sendError(msg, 'plan_scope_mismatch', 'This migration plan was registered against a different project or database.', undefined, resolvedAlias);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// arm the independent watchdog BEFORE the check, because the
|
|
421
|
+
// check is what can park the request on a human. It releases the
|
|
422
|
+
// concurrency permit if the approval is still outstanding after the
|
|
423
|
+
// window plus slack, so permit release never depends on the approval
|
|
424
|
+
// promise settling.
|
|
425
|
+
watchdog = this.armApprovalWatchdog(msg, permissionLevel, permit, { planId, sql });
|
|
426
|
+
// The checker parses; we reuse its verdict rather than parsing again.
|
|
427
|
+
//
|
|
428
|
+
// the function-effect resolver answers "what can the functions
|
|
429
|
+
// this statement calls actually do?" from `pg_proc` on the target
|
|
430
|
+
// database. It is supplied here, and only here, because this is the one
|
|
431
|
+
// place that knows which database the frame resolved to: OIDs — and
|
|
432
|
+
// therefore which overloads exist — are per-database, so a resolver
|
|
433
|
+
// built anywhere else would be answering about the wrong cluster. If it
|
|
434
|
+
// cannot be built (no usable credentials, pool exhausted), the check
|
|
435
|
+
// gets `analysed: false` and every statement that calls a function is
|
|
436
|
+
// escalated rather than trusted.
|
|
437
|
+
const decision = await this.opts.permissionChecker.check({
|
|
438
|
+
role: msg.user.role,
|
|
439
|
+
permission_level: permissionLevel,
|
|
440
|
+
sql,
|
|
441
|
+
intent,
|
|
442
|
+
plan_id: planId,
|
|
443
|
+
message_type: msg.type,
|
|
444
|
+
request_id: msg.id,
|
|
445
|
+
db_alias: msg.db_alias,
|
|
446
|
+
project: msg.project,
|
|
447
|
+
// The RESOLVED pair, so a plan bound to production cannot be run by
|
|
448
|
+
// a frame that names dev and the audit trail names the
|
|
449
|
+
// database the statement actually reached.
|
|
450
|
+
resolved_project: dbEntry?.project_name,
|
|
451
|
+
resolved_db_alias: dbEntry?.db_alias,
|
|
452
|
+
user: msg.user,
|
|
453
|
+
}, statements, dbEntry ? (0, function_effects_1.functionEffectResolverForPool)(this.opts.poolManager, dbEntry) : undefined);
|
|
454
|
+
decisionClassification = decision.classification;
|
|
455
|
+
if (!decision.allowed) {
|
|
456
|
+
let errorCode = mapDecisionCodeToErrorCode(decision.code);
|
|
457
|
+
let isManualApprovalFailure = false;
|
|
458
|
+
if (decision.code === 'permission_denied' && decision.reason === 'timeout') {
|
|
459
|
+
errorCode = 'MANUAL_APPROVAL_TIMEOUT';
|
|
460
|
+
isManualApprovalFailure = true;
|
|
461
|
+
}
|
|
462
|
+
else if (decision.code === 'permission_denied' && decision.reason === 'denied') {
|
|
463
|
+
errorCode = 'MANUAL_APPROVAL_REJECTED';
|
|
464
|
+
isManualApprovalFailure = true;
|
|
465
|
+
}
|
|
466
|
+
if (this.opts.auditSink && !isManualApprovalFailure) {
|
|
467
|
+
await this.opts.auditSink.logSync({
|
|
468
|
+
...this.auditBase(msg, permissionLevel),
|
|
469
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
470
|
+
decision: 'deny',
|
|
471
|
+
outcome: 'n/a',
|
|
472
|
+
denial_reason: safeAuditReason(decision.code),
|
|
473
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
474
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
475
|
+
migration_plan_id: planId,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
// `decision.reason` can embed a parser error, and a parser error
|
|
479
|
+
// quotes the SQL that failed — so it is redacted before it goes out.
|
|
480
|
+
return this.sendError(msg, errorCode, (0, sanitize_1.sanitizeReason)(decision.reason, sanitizeOptions(dbEntry)), undefined, resolvedAlias);
|
|
481
|
+
}
|
|
482
|
+
authorized = true;
|
|
483
|
+
if (this.opts.auditSink) {
|
|
484
|
+
await this.opts.auditSink.logSync({
|
|
485
|
+
...this.auditBase(msg, permissionLevel),
|
|
486
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
487
|
+
decision: 'allow',
|
|
488
|
+
outcome: 'n/a',
|
|
489
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
490
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
491
|
+
migration_plan_id: planId,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
const classification = decisionClassification;
|
|
496
|
+
if (msg.type === 'query') {
|
|
497
|
+
try {
|
|
498
|
+
const result = await this.opts.queryRunner.runOneShot(msg.payload, {
|
|
499
|
+
dbEntry: dbEntry,
|
|
500
|
+
request_id: msg.id,
|
|
501
|
+
classification,
|
|
502
|
+
registerInFlight: (req) => {
|
|
503
|
+
req.message = msg;
|
|
504
|
+
// The canceller can only abort `req.abort`, so the controller the
|
|
505
|
+
// runner is already listening on is the one it must be handed.
|
|
506
|
+
// Previously the canceller aborted a controller nobody observed.
|
|
507
|
+
req.abort = abortController;
|
|
508
|
+
this.opts.canceller.register(req);
|
|
509
|
+
},
|
|
510
|
+
unregisterInFlight: (reqId) => {
|
|
511
|
+
this.opts.canceller.unregister(reqId);
|
|
512
|
+
},
|
|
513
|
+
abortSignal: abortController.signal,
|
|
514
|
+
});
|
|
515
|
+
const elapsedMs = Date.now() - startTime;
|
|
516
|
+
if (this.opts.auditSink) {
|
|
517
|
+
this.opts.auditSink.log({
|
|
518
|
+
...this.auditBase(msg, permissionLevel),
|
|
519
|
+
action: 'query',
|
|
520
|
+
decision: 'allow',
|
|
521
|
+
outcome: 'success',
|
|
522
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
523
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
524
|
+
duration_ms: elapsedMs,
|
|
525
|
+
rows_affected: result.rows_affected,
|
|
526
|
+
rows_returned: result.rows?.length ?? 0,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
await this.sendResponse(msg, {
|
|
530
|
+
request_id: msg.id,
|
|
531
|
+
ok: true,
|
|
532
|
+
data: result,
|
|
533
|
+
}, resolvedAlias);
|
|
534
|
+
}
|
|
535
|
+
catch (err) {
|
|
536
|
+
const elapsedMs = Date.now() - startTime;
|
|
537
|
+
const errorObj = err;
|
|
538
|
+
if (this.opts.auditSink) {
|
|
539
|
+
const outcome = errorObj.name === 'QueryCancelledError' || errorObj.code === '57014'
|
|
540
|
+
? 'cancelled'
|
|
541
|
+
: 'error';
|
|
542
|
+
this.opts.auditSink.log({
|
|
543
|
+
...this.auditBase(msg, permissionLevel),
|
|
544
|
+
action: 'query',
|
|
545
|
+
decision: 'allow',
|
|
546
|
+
outcome,
|
|
547
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
548
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
549
|
+
duration_ms: elapsedMs,
|
|
550
|
+
error_code: safeAuditCode(errorObj.code),
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
throw err;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
else if (msg.type === 'stream_query') {
|
|
557
|
+
// Exactly one terminal frame per request. A stream that dies partway
|
|
558
|
+
// ends with an `error`; a stream that finished must not be followed by
|
|
559
|
+
// a second `error` because the `stream_end` send itself failed after
|
|
560
|
+
// the frame was written.
|
|
561
|
+
let streamTerminated = false;
|
|
562
|
+
try {
|
|
563
|
+
await this.opts.queryRunner.runStreaming(msg.payload, {
|
|
564
|
+
dbEntry: dbEntry,
|
|
565
|
+
request_id: msg.id,
|
|
566
|
+
classification,
|
|
567
|
+
registerInFlight: (req) => {
|
|
568
|
+
req.message = msg;
|
|
569
|
+
req.abort = abortController;
|
|
570
|
+
this.opts.canceller.register(req);
|
|
571
|
+
},
|
|
572
|
+
unregisterInFlight: (reqId) => {
|
|
573
|
+
this.opts.canceller.unregister(reqId);
|
|
574
|
+
},
|
|
575
|
+
// Forwarded verbatim so the runner can observe the transport buffer.
|
|
576
|
+
// Undefined stays undefined: the runner then falls back to the
|
|
577
|
+
// awaited send instead of calling a missing hook.
|
|
578
|
+
waitForDrain: this.opts.waitForDrain,
|
|
579
|
+
onChunk: async (chunk) => {
|
|
580
|
+
// Not swallowed: a rejection here propagates out of the producer,
|
|
581
|
+
// which rolls the cursor back and reaches the catch below, where
|
|
582
|
+
// the terminal `error` frame is emitted.
|
|
583
|
+
await this.opts.send({
|
|
584
|
+
v: 1,
|
|
585
|
+
id: crypto.randomUUID(),
|
|
586
|
+
type: 'stream_chunk',
|
|
587
|
+
project: msg.project,
|
|
588
|
+
user: msg.user,
|
|
589
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
590
|
+
ts: Date.now(),
|
|
591
|
+
payload: chunk,
|
|
592
|
+
});
|
|
593
|
+
},
|
|
594
|
+
onEnd: async (end) => {
|
|
595
|
+
if (streamTerminated)
|
|
596
|
+
return;
|
|
597
|
+
await this.opts.send({
|
|
598
|
+
v: 1,
|
|
599
|
+
id: crypto.randomUUID(),
|
|
600
|
+
type: 'stream_end',
|
|
601
|
+
project: msg.project,
|
|
602
|
+
user: msg.user,
|
|
603
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
604
|
+
ts: Date.now(),
|
|
605
|
+
payload: end,
|
|
606
|
+
});
|
|
607
|
+
streamTerminated = true;
|
|
608
|
+
const elapsedMs = Date.now() - startTime;
|
|
609
|
+
if (this.opts.auditSink) {
|
|
610
|
+
this.opts.auditSink.log({
|
|
611
|
+
...this.auditBase(msg, permissionLevel),
|
|
612
|
+
action: 'stream_query',
|
|
613
|
+
decision: 'allow',
|
|
614
|
+
outcome: 'success',
|
|
615
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
616
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
617
|
+
duration_ms: elapsedMs,
|
|
618
|
+
rows_returned: end.total_rows,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
},
|
|
622
|
+
abortSignal: abortController.signal,
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
catch (err) {
|
|
626
|
+
const elapsedMs = Date.now() - startTime;
|
|
627
|
+
const errorObj = err;
|
|
628
|
+
if (this.opts.auditSink) {
|
|
629
|
+
const outcome = errorObj.name === 'QueryCancelledError' || errorObj.code === '57014'
|
|
630
|
+
? 'cancelled'
|
|
631
|
+
: 'error';
|
|
632
|
+
// Map common stream error names to code format for audit logging
|
|
633
|
+
let errorCode = safeAuditCode(errorObj.code);
|
|
634
|
+
if (errorObj.name === 'StreamTooLargeError') {
|
|
635
|
+
errorCode = 'STREAM_ROW_LIMIT';
|
|
636
|
+
}
|
|
637
|
+
else if (errorObj.name === 'CellSizeLimitError') {
|
|
638
|
+
errorCode = 'CELL_SIZE_LIMIT';
|
|
639
|
+
}
|
|
640
|
+
this.opts.auditSink.log({
|
|
641
|
+
...this.auditBase(msg, permissionLevel),
|
|
642
|
+
action: 'stream_query',
|
|
643
|
+
decision: 'allow',
|
|
644
|
+
outcome,
|
|
645
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
646
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
647
|
+
duration_ms: elapsedMs,
|
|
648
|
+
error_code: errorCode,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
// A terminal frame already reached the browser. A second one would
|
|
652
|
+
// leave it with two outcomes for a single request.
|
|
653
|
+
if (streamTerminated)
|
|
654
|
+
return;
|
|
655
|
+
throw err;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
else if (msg.type === 'migration_run') {
|
|
659
|
+
try {
|
|
660
|
+
const result = await this.opts.migrationRunner.run(msg.payload, {
|
|
661
|
+
dbEntry: dbEntry,
|
|
662
|
+
request_id: msg.id,
|
|
663
|
+
project: msg.project,
|
|
664
|
+
user: msg.user,
|
|
665
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
666
|
+
registerInFlight: (req) => {
|
|
667
|
+
req.message = msg;
|
|
668
|
+
req.abort = abortController;
|
|
669
|
+
this.opts.canceller.register(req);
|
|
670
|
+
},
|
|
671
|
+
unregisterInFlight: (reqId) => {
|
|
672
|
+
this.opts.canceller.unregister(reqId);
|
|
673
|
+
},
|
|
674
|
+
onProgress: async (progress) => {
|
|
675
|
+
await this.opts.send(progress);
|
|
676
|
+
},
|
|
677
|
+
abortSignal: abortController.signal,
|
|
678
|
+
});
|
|
679
|
+
const elapsedMs = Date.now() - startTime;
|
|
680
|
+
if (this.opts.auditSink) {
|
|
681
|
+
this.opts.auditSink.log({
|
|
682
|
+
...this.auditBase(msg, permissionLevel),
|
|
683
|
+
action: 'migration_run',
|
|
684
|
+
decision: 'allow',
|
|
685
|
+
outcome: result.status === 'committed' ? 'success' : 'error',
|
|
686
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
687
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
688
|
+
duration_ms: elapsedMs,
|
|
689
|
+
migration_plan_id: planId,
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
if (result.status === 'rolled_back') {
|
|
693
|
+
const failedCode = failedStatementCode(result);
|
|
694
|
+
// Curated by SQLSTATE, never the raw node-postgres message: a failed
|
|
695
|
+
// statement's `error` is verbatim `err.message`, which embeds the
|
|
696
|
+
// offending SQL, row values and connection details.
|
|
697
|
+
const pg_error = failedCode ? { code: failedCode, severity: 'ERROR' } : undefined;
|
|
698
|
+
const errorMsg = failedCode
|
|
699
|
+
? pgMessageForCode(failedCode)
|
|
700
|
+
: 'A migration statement failed.';
|
|
701
|
+
return this.sendError(msg, 'migration_statement_failed', errorMsg, pg_error, resolvedAlias);
|
|
702
|
+
}
|
|
703
|
+
if (result.status === 'partial') {
|
|
704
|
+
// A partial result means statements are already committed on the
|
|
705
|
+
// customer's database and the rest failed. Reporting `ok: true`
|
|
706
|
+
// for that is a data-integrity incident with no rollback path, so
|
|
707
|
+
// it leaves as an error even though the runner considers the run
|
|
708
|
+
// finished. This is deliberately independent of what the runner
|
|
709
|
+
// believes it can achieve.
|
|
710
|
+
const failedCode = failedStatementCode(result);
|
|
711
|
+
const pg_error = failedCode ? { code: failedCode, severity: 'ERROR' } : undefined;
|
|
712
|
+
return this.sendError(msg, 'migration_partial', 'Migration stopped partway: earlier statements are already committed and were not ' +
|
|
713
|
+
'rolled back. Verify the applied schema before retrying.', pg_error, resolvedAlias);
|
|
714
|
+
}
|
|
715
|
+
if (result.status !== 'committed' &&
|
|
716
|
+
result.status !== 'dry_run_ok' &&
|
|
717
|
+
result.status !== 'dry_run_failed') {
|
|
718
|
+
throw new Error(`migration_result_unexpected:${String(result.status)}`);
|
|
719
|
+
}
|
|
720
|
+
// The inbound migration_run payload is validated; the result leaving
|
|
721
|
+
// the agent was not. A malformed result is a local fault and must not
|
|
722
|
+
// be presented to the browser as a well-formed success.
|
|
723
|
+
(0, validate_1.validateMigrationResultPayload)(result);
|
|
724
|
+
await this.sendResponse(msg, {
|
|
725
|
+
request_id: msg.id,
|
|
726
|
+
ok: true,
|
|
727
|
+
data: sanitizeMigrationResult(result, dbEntry),
|
|
728
|
+
}, resolvedAlias);
|
|
729
|
+
}
|
|
730
|
+
catch (err) {
|
|
731
|
+
const elapsedMs = Date.now() - startTime;
|
|
732
|
+
const errorObj = err;
|
|
733
|
+
if (this.opts.auditSink) {
|
|
734
|
+
this.opts.auditSink.log({
|
|
735
|
+
...this.auditBase(msg, permissionLevel),
|
|
736
|
+
action: 'migration_run',
|
|
737
|
+
decision: 'allow',
|
|
738
|
+
outcome: 'error',
|
|
739
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(sql),
|
|
740
|
+
statement_preview: (0, redact_1.previewStatement)(sql),
|
|
741
|
+
duration_ms: elapsedMs,
|
|
742
|
+
error_code: safeAuditCode(errorObj.code),
|
|
743
|
+
migration_plan_id: planId,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
throw err;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
catch (err) {
|
|
751
|
+
const errorPayload = this.mapErrorToPayload(err, msg.id, dbEntry);
|
|
752
|
+
// an internal failure reached the browser and must reach the trail
|
|
753
|
+
// too. A path that fails before any authorization decision (or after one)
|
|
754
|
+
// still happened, and "the request vanished" is not an acceptable record.
|
|
755
|
+
if (this.opts.auditSink) {
|
|
756
|
+
const errorObj = err;
|
|
757
|
+
this.opts.auditSink.log({
|
|
758
|
+
...this.auditBase(msg, permissionLevel),
|
|
759
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
760
|
+
// Whatever the frame had already been authorised to do. An error
|
|
761
|
+
// before any authorization decision is not a denial of a permitted
|
|
762
|
+
// action, so it is not recorded as one.
|
|
763
|
+
decision: authorized ? 'allow' : 'deny',
|
|
764
|
+
outcome: 'error',
|
|
765
|
+
...(authorized ? {} : { denial_reason: 'internal_error' }),
|
|
766
|
+
error_code: safeAuditCode(errorObj.code ?? errorObj.name),
|
|
767
|
+
duration_ms: Date.now() - startTime,
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
await this.opts.send({
|
|
771
|
+
v: 1,
|
|
772
|
+
id: crypto.randomUUID(),
|
|
773
|
+
type: 'error',
|
|
774
|
+
project: msg.project,
|
|
775
|
+
user: msg.user,
|
|
776
|
+
db_alias: resolvedAlias ?? msg.db_alias,
|
|
777
|
+
ts: Date.now(),
|
|
778
|
+
payload: errorPayload,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
finally {
|
|
782
|
+
if (watchdog)
|
|
783
|
+
clearTimeout(watchdog);
|
|
784
|
+
permit.release();
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Arm the independent approval watchdog for one request.
|
|
789
|
+
*
|
|
790
|
+
* Returns the timer so the caller can clear it. The watchdog fires only if an
|
|
791
|
+
* approval for THIS request is still outstanding at the handler's reaper
|
|
792
|
+
* deadline; if the request is merely running a long query, or already finished,
|
|
793
|
+
* it does nothing. It releases the concurrency permit — `RateLimitPermit`
|
|
794
|
+
* releases are idempotent, so the ordinary `finally` remains correct — and
|
|
795
|
+
* records `approval_promise_stranded`, because a stranded promise is exactly
|
|
796
|
+
* the condition that used to leak a permit per attack and disable the database
|
|
797
|
+
* for everyone.
|
|
798
|
+
*/
|
|
799
|
+
armApprovalWatchdog(msg, permissionLevel, permit, context = {}) {
|
|
800
|
+
const handler = this.opts.permissionChecker.opts?.manualApprovalHandler;
|
|
801
|
+
// Deliberately LATER than the handler's own reaper. The handler settles the
|
|
802
|
+
// approval promise, which makes `isPending` false and retires this watchdog
|
|
803
|
+
// without a second record; the watchdog is the backstop for a handler that
|
|
804
|
+
// cannot settle at all, so exactly one `approval_promise_stranded` record is
|
|
805
|
+
// ever written for one stranding.
|
|
806
|
+
const deadlineMs = (handler?.getStrandedReaperMs?.() ?? 0) + manual_approval_1.APPROVAL_STRANDED_SLACK_MS || 250;
|
|
807
|
+
return setTimeout(() => {
|
|
808
|
+
try {
|
|
809
|
+
if (!handler?.isPending?.(msg.id, msg.user.id))
|
|
810
|
+
return;
|
|
811
|
+
permit.release();
|
|
812
|
+
this.opts.auditSink?.log({
|
|
813
|
+
...this.auditBase(msg, permissionLevel),
|
|
814
|
+
action: mapMessageTypeToAuditAction(msg.type),
|
|
815
|
+
decision: 'deny',
|
|
816
|
+
outcome: 'n/a',
|
|
817
|
+
denial_reason: 'approval_promise_stranded',
|
|
818
|
+
// The same identifying fields every other `migration_run` denial
|
|
819
|
+
// carries. Without them a stranded record says only that *something*
|
|
820
|
+
// was stranded: an investigator cannot tell which plan, or which
|
|
821
|
+
// statement, and a single stray approval in a busy log is
|
|
822
|
+
// indistinguishable from the leak this record exists to catch.
|
|
823
|
+
...(context.planId ? { migration_plan_id: context.planId } : {}),
|
|
824
|
+
...(context.sql
|
|
825
|
+
? {
|
|
826
|
+
statement_fingerprint: (0, redact_1.fingerprintStatement)(context.sql),
|
|
827
|
+
statement_preview: (0, redact_1.previewStatement)(context.sql),
|
|
828
|
+
}
|
|
829
|
+
: {}),
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
catch (err) {
|
|
833
|
+
console.error('[dispatcher] approval watchdog failed:', err);
|
|
834
|
+
}
|
|
835
|
+
}, deadlineMs);
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* `cancel`, bound to the request it names.
|
|
839
|
+
*
|
|
840
|
+
* The only gate used to be `hasCapability(role, 'cancel')`, so any developer
|
|
841
|
+
* could abort any other principal's in-flight query in any project, and the
|
|
842
|
+
* target's database was resolved from the ATTACKER's project when the target
|
|
843
|
+
* had none. Two binding conditions are now required on top of the capability:
|
|
844
|
+
* the caller is the requesting principal, or holds a STRICTLY more privileged
|
|
845
|
+
* role. The target's database comes from the target's own frame and nowhere
|
|
846
|
+
* else.
|
|
847
|
+
*/
|
|
848
|
+
async handleCancel(msg, permissionLevel, resolvedAlias, startTime) {
|
|
849
|
+
if (!(0, role_policy_1.hasCapability)(msg.user.role, 'cancel')) {
|
|
850
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
851
|
+
action: 'cancel',
|
|
852
|
+
denial_reason: 'role_denied',
|
|
853
|
+
});
|
|
854
|
+
return this.sendError(msg, 'role_insufficient', `Role '${msg.user.role}' cannot cancel requests`, undefined, resolvedAlias);
|
|
855
|
+
}
|
|
856
|
+
const targetId = msg.payload.target_id;
|
|
857
|
+
const targetReq = this.opts.canceller.getInFlight().get(targetId);
|
|
858
|
+
if (!targetReq) {
|
|
859
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
860
|
+
action: 'cancel',
|
|
861
|
+
denial_reason: 'cancel_target_not_found',
|
|
862
|
+
});
|
|
863
|
+
return this.sendError(msg, 'cancel_target_not_found', `No in-flight request matches the target_id.`, undefined, resolvedAlias);
|
|
864
|
+
}
|
|
865
|
+
const targetUser = targetReq.message?.user;
|
|
866
|
+
const targetRole = targetUser?.role;
|
|
867
|
+
// Both principals in the record: the refused caller and the owner of the
|
|
868
|
+
// request they tried to touch. Without the second one the trail attributes
|
|
869
|
+
// the attempt only to the attacker and says nothing about whose work it was.
|
|
870
|
+
const targetFields = {
|
|
871
|
+
cancel_target_user_id: targetUser?.id ?? '',
|
|
872
|
+
cancel_target_project: targetReq.message?.project ?? '',
|
|
873
|
+
cancel_target_db_alias: targetReq.message?.db_alias ?? '',
|
|
874
|
+
};
|
|
875
|
+
const ownsTarget = targetUser !== undefined && targetUser.id === msg.user.id;
|
|
876
|
+
const outranksTarget = targetRole !== undefined && (0, role_policy_1.isStrictlyMorePrivileged)(msg.user.role, targetRole);
|
|
877
|
+
if (targetUser === undefined || (!ownsTarget && !outranksTarget)) {
|
|
878
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
879
|
+
action: 'cancel',
|
|
880
|
+
denial_reason: 'cancel_not_permitted',
|
|
881
|
+
...targetFields,
|
|
882
|
+
});
|
|
883
|
+
return this.sendError(msg, 'cancel_not_permitted', 'This request is not yours to cancel.', undefined, resolvedAlias);
|
|
884
|
+
}
|
|
885
|
+
// The target's database, from the target's frame ONLY. The previous
|
|
886
|
+
// `targetReq.message?.project || msg.project` meant an attacker whose own
|
|
887
|
+
// project was configured could have a request in a different project
|
|
888
|
+
// cancelled against the attacker's connection.
|
|
889
|
+
const targetDbEntry = this.opts.lookupDb(targetReq.message?.project ?? '', targetReq.message?.db_alias);
|
|
890
|
+
const targetResolution = (0, database_lookup_1.normaliseLookupResult)(targetDbEntry, targetReq.message?.project ?? '', targetReq.message?.db_alias);
|
|
891
|
+
if (!targetResolution.ok) {
|
|
892
|
+
await this.auditDeny(msg, permissionLevel, {
|
|
893
|
+
action: 'cancel',
|
|
894
|
+
denial_reason: 'cancel_target_not_found',
|
|
895
|
+
...targetFields,
|
|
896
|
+
});
|
|
897
|
+
return this.sendError(msg, 'cancel_target_not_found', `No in-flight request matches the target_id.`, undefined, resolvedAlias);
|
|
898
|
+
}
|
|
899
|
+
// A cancellation acts on the TARGET's database, so the record is attributed
|
|
900
|
+
// to the database the cancellation actually reached.
|
|
901
|
+
return (0, context_1.withResolvedDatabase)((0, context_1.resolvedIdentityOf)(targetResolution.entry), async () => {
|
|
902
|
+
if (this.opts.auditSink) {
|
|
903
|
+
await this.opts.auditSink.logSync({
|
|
904
|
+
...this.auditBase(msg, permissionLevel),
|
|
905
|
+
action: 'cancel',
|
|
906
|
+
decision: 'allow',
|
|
907
|
+
outcome: 'n/a',
|
|
908
|
+
...targetFields,
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
const cancelResult = await this.opts.canceller.cancel(targetId, targetResolution.entry);
|
|
912
|
+
const elapsedMs = Date.now() - startTime;
|
|
913
|
+
if (this.opts.auditSink) {
|
|
914
|
+
this.opts.auditSink.log({
|
|
915
|
+
...this.auditBase(msg, permissionLevel),
|
|
916
|
+
action: 'cancel',
|
|
917
|
+
decision: 'allow',
|
|
918
|
+
outcome: 'success',
|
|
919
|
+
duration_ms: elapsedMs,
|
|
920
|
+
...targetFields,
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
return this.sendResponse(msg, {
|
|
924
|
+
request_id: msg.id,
|
|
925
|
+
ok: true,
|
|
926
|
+
data: { target_id: targetId, ...cancelResult },
|
|
927
|
+
}, targetResolution.entry.db_alias);
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
/**
|
|
931
|
+
* Map an internal failure to an outbound `error` payload.
|
|
932
|
+
*
|
|
933
|
+
* PostgreSQL errors are reduced to an allow-list of fields plus a curated
|
|
934
|
+
* message per SQLSTATE. `detail` and `hint` are never forwarded: a duplicate
|
|
935
|
+
* key violation ships `Key (email)=(alice@corp.com) already exists.` in
|
|
936
|
+
* `detail`, and messages embed the offending SQL and absolute paths.
|
|
937
|
+
*/
|
|
938
|
+
mapErrorToPayload(err, requestId, dbEntry) {
|
|
939
|
+
const opts = sanitizeOptions(dbEntry);
|
|
940
|
+
if (err instanceof pool_1.PoolError) {
|
|
941
|
+
// PoolError messages carry host, port, database user and file paths.
|
|
942
|
+
return (0, errors_1.makeError)(mapPoolErrorCode(err.code), requestId, {
|
|
943
|
+
message: sanitize_1.POOL_ERROR_MESSAGES[err.code] ?? (0, sanitize_1.sanitizePgError)(err, opts).message,
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
const errorObj = err;
|
|
947
|
+
if (errorObj.name === 'QueryTooLargeError') {
|
|
948
|
+
return (0, errors_1.makeError)('query_too_large', requestId, {
|
|
949
|
+
message: (0, sanitize_1.sanitizeErrorText)(errorObj.message, opts),
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
if (errorObj.name === 'StreamTooLargeError') {
|
|
953
|
+
return (0, errors_1.makeError)('STREAM_ROW_LIMIT', requestId, {
|
|
954
|
+
message: (0, sanitize_1.sanitizeErrorText)(errorObj.message, opts),
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
if (errorObj.name === 'CellSizeLimitError') {
|
|
958
|
+
return (0, errors_1.makeError)('CELL_SIZE_LIMIT', requestId, {
|
|
959
|
+
message: (0, sanitize_1.sanitizeErrorText)(errorObj.message, opts),
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
if (errorObj.name === 'MigrationInProgressError') {
|
|
963
|
+
return (0, errors_1.makeError)('migration_in_progress', requestId, {
|
|
964
|
+
message: (0, sanitize_1.sanitizeErrorText)(errorObj.message, opts),
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
if (errorObj.name === 'QueryCancelledError' || errorObj.code === '57014') {
|
|
968
|
+
return (0, errors_1.makeError)('query_cancelled', requestId, {
|
|
969
|
+
message: errorObj.name === 'QueryCancelledError'
|
|
970
|
+
? 'Query was cancelled'
|
|
971
|
+
: 'The statement exceeded the configured timeout.',
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
if (errorObj.message && errorObj.message.startsWith('invalid_message:')) {
|
|
975
|
+
return (0, errors_1.makeError)('invalid_message', requestId, {
|
|
976
|
+
message: 'The agent cannot accept this message.',
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
if (errorObj.message && errorObj.message.startsWith('unknown_message_type:')) {
|
|
980
|
+
return (0, errors_1.makeError)('unknown_message_type', requestId, {
|
|
981
|
+
message: 'The agent does not recognise this message type.',
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
if (safePgCode(errorObj.code)) {
|
|
985
|
+
const safe = (0, sanitize_1.sanitizePgError)(err, opts);
|
|
986
|
+
// `detail` is deliberately absent: it is where PostgreSQL puts
|
|
987
|
+
// `Key (email)=(alice@corp.com) already exists.`. `hint` is always one
|
|
988
|
+
// of our own curated strings, never the server's.
|
|
989
|
+
const pg_error = {
|
|
990
|
+
code: String(errorObj.code),
|
|
991
|
+
severity: safeSeverity(safe.severity),
|
|
992
|
+
hint: safe.hint,
|
|
993
|
+
};
|
|
994
|
+
return (0, errors_1.makeError)('execution_failed', requestId, {
|
|
995
|
+
pg_error,
|
|
996
|
+
message: safe.message,
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
return (0, errors_1.makeError)('internal_error', requestId, {
|
|
1000
|
+
message: (0, sanitize_1.sanitizeErrorText)(errorObj.message ?? String(err), opts),
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
exports.Dispatcher = Dispatcher;
|
|
1005
|
+
function mapDecisionCodeToErrorCode(code) {
|
|
1006
|
+
switch (code) {
|
|
1007
|
+
case 'role_insufficient':
|
|
1008
|
+
return 'role_insufficient';
|
|
1009
|
+
case 'permission_denied':
|
|
1010
|
+
return 'permission_denied';
|
|
1011
|
+
case 'plan_not_registered':
|
|
1012
|
+
return 'migration_plan_not_registered';
|
|
1013
|
+
case 'intent_mismatch':
|
|
1014
|
+
return 'permission_denied';
|
|
1015
|
+
case 'multiple_statements':
|
|
1016
|
+
return 'multiple_statements';
|
|
1017
|
+
case 'unparseable_statement':
|
|
1018
|
+
return 'unparseable_statement';
|
|
1019
|
+
case 'parser_unavailable':
|
|
1020
|
+
return 'parser_unavailable';
|
|
1021
|
+
default:
|
|
1022
|
+
return 'permission_denied';
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Wire code for a lookup refusal.
|
|
1027
|
+
*
|
|
1028
|
+
* `database_not_found` and `database_out_of_scope` deliberately share the
|
|
1029
|
+
* curated `db_unavailable` answer: telling a caller "that project exists but is
|
|
1030
|
+
* out of scope" is a database-existence oracle across tenants, and the
|
|
1031
|
+
* distinction is preserved in the audit record instead. The two codes that name
|
|
1032
|
+
* the caller's own mistake — a project/alias collision and a missing allow-list —
|
|
1033
|
+
* are specific, because both are things only the operator can fix and neither
|
|
1034
|
+
* reveals another tenant's configuration.
|
|
1035
|
+
*/
|
|
1036
|
+
function databaseRefusalErrorCode(code) {
|
|
1037
|
+
switch (code) {
|
|
1038
|
+
case 'db_alias_project_mismatch':
|
|
1039
|
+
return 'db_alias_project_mismatch';
|
|
1040
|
+
case 'database_scope_not_configured':
|
|
1041
|
+
return 'database_scope_not_configured';
|
|
1042
|
+
default:
|
|
1043
|
+
return 'db_unavailable';
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* Curated text for a lookup refusal. The refusal's own `reason` is agent-authored
|
|
1048
|
+
* and data-free by construction (see `DatabaseLookupRefusal.reason`), but it is
|
|
1049
|
+
* not forwarded verbatim here either: every refusal on the wire gets the catalog
|
|
1050
|
+
* text for its code, so nothing derived from configuration reaches the browser.
|
|
1051
|
+
*/
|
|
1052
|
+
function databaseRefusalMessage(refusal) {
|
|
1053
|
+
return errors_1.ERROR_CATALOG[databaseRefusalErrorCode(refusal.code)].default_message;
|
|
1054
|
+
}
|
|
1055
|
+
function mapMessageTypeToAuditAction(msgType) {
|
|
1056
|
+
switch (msgType) {
|
|
1057
|
+
case 'query':
|
|
1058
|
+
return 'query';
|
|
1059
|
+
case 'stream_query':
|
|
1060
|
+
return 'stream_query';
|
|
1061
|
+
case 'migration_run':
|
|
1062
|
+
return 'migration_run';
|
|
1063
|
+
default:
|
|
1064
|
+
return 'query';
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Every inbound type maps onto a budget bucket. `response`, `stream_chunk` and
|
|
1069
|
+
* `stream_end` are agent-originated and fall into `other`, so an unexpected
|
|
1070
|
+
* type is metered rather than waved through.
|
|
1071
|
+
*/
|
|
1072
|
+
function mapMessageTypeToRateLimitAction(msgType) {
|
|
1073
|
+
switch (msgType) {
|
|
1074
|
+
case 'ping':
|
|
1075
|
+
return 'ping';
|
|
1076
|
+
case 'introspect':
|
|
1077
|
+
return 'introspect';
|
|
1078
|
+
case 'query':
|
|
1079
|
+
return 'query';
|
|
1080
|
+
case 'stream_query':
|
|
1081
|
+
return 'stream_query';
|
|
1082
|
+
case 'migration_run':
|
|
1083
|
+
return 'migration_run';
|
|
1084
|
+
case 'cancel':
|
|
1085
|
+
return 'cancel';
|
|
1086
|
+
case 'event':
|
|
1087
|
+
return 'event';
|
|
1088
|
+
default:
|
|
1089
|
+
return 'other';
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
/** Curated text for a refusal. Never echoes an identifier the caller chose. */
|
|
1093
|
+
function rateLimitMessage(reason, scope) {
|
|
1094
|
+
if (reason === 'too_many_concurrent_requests' ||
|
|
1095
|
+
reason === 'too_many_concurrent_requests_for_database') {
|
|
1096
|
+
return 'Too many requests are already running. Wait for one to finish and retry.';
|
|
1097
|
+
}
|
|
1098
|
+
if (reason === 'introspection_snapshot_exceeds_budget') {
|
|
1099
|
+
return 'Introspection snapshot exceeds the configured response budget.';
|
|
1100
|
+
}
|
|
1101
|
+
if (scope === 'concurrency_global' || scope === 'concurrency_db') {
|
|
1102
|
+
return 'Too many requests are already running. Wait for one to finish and retry.';
|
|
1103
|
+
}
|
|
1104
|
+
return 'Request rate limit exceeded for this sender. Slow down and retry.';
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Serialized size of a response body. A value that cannot be measured counts as
|
|
1108
|
+
* infinite, so an unmeasurable payload is refused rather than forwarded.
|
|
1109
|
+
*/
|
|
1110
|
+
function serializedSizeOf(value) {
|
|
1111
|
+
try {
|
|
1112
|
+
return Buffer.byteLength(JSON.stringify(value) ?? '', 'utf8');
|
|
1113
|
+
}
|
|
1114
|
+
catch {
|
|
1115
|
+
return Number.POSITIVE_INFINITY;
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Decide whether an inbound `event` frame may be handled at all.
|
|
1120
|
+
*
|
|
1121
|
+
* This runs before any event handler. The `event` branch used to sit ahead of
|
|
1122
|
+
* the query/migration permission pipeline, so a `viewer` could resolve another
|
|
1123
|
+
* user's pending manual approval and could register an arbitrary migration
|
|
1124
|
+
* plan for later replay under `auto_upgrade` — the default level. Both kinds
|
|
1125
|
+
* now derive their required capability from the same `hasCapability` matrix
|
|
1126
|
+
* the query path uses, and any kind the agent does not accept inbound is
|
|
1127
|
+
* refused outright.
|
|
1128
|
+
*
|
|
1129
|
+
* `approval_response` requires both `query_write` and `ddl`: an approval can
|
|
1130
|
+
* authorise a write or a DDL statement, so the responder must be able to do
|
|
1131
|
+
* everything it can authorise.
|
|
1132
|
+
*/
|
|
1133
|
+
function evaluateEventGate(kind, role, permissionLevel, canRegisterPlan) {
|
|
1134
|
+
if (kind === 'plan_register') {
|
|
1135
|
+
if (!(0, role_policy_1.hasCapability)(role, 'migration_run')) {
|
|
1136
|
+
return {
|
|
1137
|
+
allowed: false,
|
|
1138
|
+
errorCode: 'role_insufficient',
|
|
1139
|
+
reason: `Role '${role}' cannot register migration plans`,
|
|
1140
|
+
auditAction: 'plan_register',
|
|
1141
|
+
code: 'role_denied',
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
if (permissionLevel === 'read_only') {
|
|
1145
|
+
return {
|
|
1146
|
+
allowed: false,
|
|
1147
|
+
errorCode: 'permission_denied',
|
|
1148
|
+
reason: 'Migration plans cannot be registered while the database is in read_only mode',
|
|
1149
|
+
auditAction: 'plan_register',
|
|
1150
|
+
code: 'read_only_mode',
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
// The registry is the authority; a refusal there overrides anything this
|
|
1154
|
+
// function concluded, because a plan that cannot be stored must not be
|
|
1155
|
+
// reported as registered.
|
|
1156
|
+
const verdict = canRegisterPlan?.(role, permissionLevel);
|
|
1157
|
+
if (verdict && !verdict.allowed) {
|
|
1158
|
+
return {
|
|
1159
|
+
allowed: false,
|
|
1160
|
+
errorCode: 'permission_denied',
|
|
1161
|
+
reason: verdict.reason ?? 'Plan registration refused',
|
|
1162
|
+
auditAction: 'plan_register',
|
|
1163
|
+
code: verdict.code ?? 'plan_registration_refused',
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
return {
|
|
1167
|
+
allowed: true,
|
|
1168
|
+
errorCode: 'invalid_message',
|
|
1169
|
+
reason: '',
|
|
1170
|
+
auditAction: null,
|
|
1171
|
+
code: 'allowed',
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
if (kind === 'approval_response') {
|
|
1175
|
+
const mayApprove = (0, role_policy_1.hasCapability)(role, 'query_write') && (0, role_policy_1.hasCapability)(role, 'ddl');
|
|
1176
|
+
if (!mayApprove) {
|
|
1177
|
+
return {
|
|
1178
|
+
allowed: false,
|
|
1179
|
+
errorCode: 'role_insufficient',
|
|
1180
|
+
reason: `Role '${role}' cannot approve write or DDL statements`,
|
|
1181
|
+
auditAction: 'manual_approval',
|
|
1182
|
+
code: 'role_denied',
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
return {
|
|
1186
|
+
allowed: true,
|
|
1187
|
+
errorCode: 'invalid_message',
|
|
1188
|
+
reason: '',
|
|
1189
|
+
auditAction: null,
|
|
1190
|
+
code: 'allowed',
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
// Agent-to-browser kinds and anything unrecognised are refused. They are not
|
|
1194
|
+
// audit-worthy: no database action was requested.
|
|
1195
|
+
return {
|
|
1196
|
+
allowed: false,
|
|
1197
|
+
errorCode: 'invalid_message',
|
|
1198
|
+
reason: 'The agent does not accept inbound event kind',
|
|
1199
|
+
auditAction: null,
|
|
1200
|
+
code: 'unsupported_event_kind',
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
/* ------------------------------------------------------------------ */
|
|
1204
|
+
/* Error sanitisation (H-05) */
|
|
1205
|
+
/* ------------------------------------------------------------------ */
|
|
1206
|
+
/** Curated `ErrorCode` for each `PoolError` variant. */
|
|
1207
|
+
const POOL_ERROR_CODES = {
|
|
1208
|
+
env_var_missing: 'env_var_missing',
|
|
1209
|
+
connection_failed: 'db_unavailable',
|
|
1210
|
+
auth_failed: 'db_auth_failed',
|
|
1211
|
+
db_not_found: 'db_unavailable',
|
|
1212
|
+
ssl_error: 'db_ssl_error',
|
|
1213
|
+
pool_exhausted: 'db_pool_exhausted',
|
|
1214
|
+
unsafe_session_setting: 'db_unavailable',
|
|
1215
|
+
};
|
|
1216
|
+
/** A SQLSTATE is five upper-case alphanumerics; anything else is not one. */
|
|
1217
|
+
function safePgCode(code) {
|
|
1218
|
+
return typeof code === 'string' && /^[0-9A-Z]{5}$/.test(code);
|
|
1219
|
+
}
|
|
1220
|
+
/** Severities PostgreSQL actually emits, plus a safe default. */
|
|
1221
|
+
const PG_SEVERITIES = new Set([
|
|
1222
|
+
'ERROR',
|
|
1223
|
+
'FATAL',
|
|
1224
|
+
'PANIC',
|
|
1225
|
+
'WARNING',
|
|
1226
|
+
'NOTICE',
|
|
1227
|
+
'DEBUG',
|
|
1228
|
+
'INFO',
|
|
1229
|
+
]);
|
|
1230
|
+
function safeSeverity(severity) {
|
|
1231
|
+
if (typeof severity !== 'string')
|
|
1232
|
+
return 'ERROR';
|
|
1233
|
+
const normalized = severity.toUpperCase();
|
|
1234
|
+
return PG_SEVERITIES.has(normalized) ? normalized : 'ERROR';
|
|
1235
|
+
}
|
|
1236
|
+
/** Audit `error_code` must be a code, never free text. */
|
|
1237
|
+
function safeAuditCode(code) {
|
|
1238
|
+
return typeof code === 'string' && /^[A-Za-z0-9_.]{1,32}$/.test(code) ? code : 'INTERNAL';
|
|
1239
|
+
}
|
|
1240
|
+
/** Audit `denial_reason` comes from a closed enum; refuse anything else. */
|
|
1241
|
+
function safeAuditReason(code) {
|
|
1242
|
+
return typeof code === 'string' && /^[a-z0-9_]{1,32}$/.test(code) ? code : 'denied';
|
|
1243
|
+
}
|
|
1244
|
+
function mapPoolErrorCode(code) {
|
|
1245
|
+
return POOL_ERROR_CODES[code] ?? 'db_unavailable';
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Curated, data-free text for a SQLSTATE. Delegates to `sanitizePgError` so
|
|
1249
|
+
* there is exactly one place where SQLSTATEs are described, and so the answer
|
|
1250
|
+
* can never be derived from raw PostgreSQL output.
|
|
1251
|
+
*/
|
|
1252
|
+
function pgMessageForCode(code) {
|
|
1253
|
+
return (0, sanitize_1.sanitizePgError)({ code }).message;
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Sanitisation options for one request. `topology` lets `scrubTopology` remove
|
|
1257
|
+
* the exact host / database / user this request was made against, in addition
|
|
1258
|
+
* to the generic host/user/path/URL rules.
|
|
1259
|
+
*/
|
|
1260
|
+
function sanitizeOptions(dbEntry) {
|
|
1261
|
+
if (!dbEntry)
|
|
1262
|
+
return {};
|
|
1263
|
+
return {
|
|
1264
|
+
topology: {
|
|
1265
|
+
host: dbEntry.host,
|
|
1266
|
+
port: dbEntry.port,
|
|
1267
|
+
user: dbEntry.user,
|
|
1268
|
+
database: dbEntry.database,
|
|
1269
|
+
project: dbEntry.project_name,
|
|
1270
|
+
},
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
/** The SQLSTATE of the statement that failed, when it is a real SQLSTATE. */
|
|
1274
|
+
function failedStatementCode(result) {
|
|
1275
|
+
const failed = result.statements.find((s) => s.status === 'failed');
|
|
1276
|
+
return failed?.pg_error_code !== undefined && safePgCode(failed.pg_error_code)
|
|
1277
|
+
? failed.pg_error_code
|
|
1278
|
+
: undefined;
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* Per-statement errors are verbatim PostgreSQL messages, and a migration
|
|
1282
|
+
* failure routinely includes row data (`Key (email)=(alice@corp.com) already
|
|
1283
|
+
* exists.`). Reduce every one of them before the result leaves the process.
|
|
1284
|
+
*/
|
|
1285
|
+
function sanitizeMigrationResult(result, dbEntry) {
|
|
1286
|
+
const opts = sanitizeOptions(dbEntry);
|
|
1287
|
+
return {
|
|
1288
|
+
...result,
|
|
1289
|
+
statements: result.statements.map((s) => {
|
|
1290
|
+
if (s.error === undefined)
|
|
1291
|
+
return s;
|
|
1292
|
+
return { ...s, error: (0, sanitize_1.sanitizeErrorText)(s.error, opts) };
|
|
1293
|
+
}),
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
//# sourceMappingURL=dispatcher.js.map
|