okengine 0.2.6 → 0.2.8
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/AGENTS.md +24 -23
- package/README.md +52 -346
- package/docs/spec/console.md +165 -142
- package/docs/spec/example.md +490 -312
- package/docs/spec/four-applications.md +495 -314
- package/docs/spec/unified-theory.md +184 -175
- package/package.json +45 -37
- package/spec/manifest.v1.schema.json +40 -9
- package/src/auth/api-keys.ts +2 -5
- package/src/auth/attenuation.ts +2 -6
- package/src/auth/auth.test.ts +53 -31
- package/src/auth/invoke-as.ts +1 -3
- package/src/auth/operator.ts +8 -26
- package/src/auth/planes.ts +2 -7
- package/src/auth/plugin.ts +4 -7
- package/src/auth/roles.ts +1 -5
- package/src/auth/sessions.ts +10 -39
- package/src/cli/args.ts +1 -5
- package/src/cli/ask-dev-mode.ts +40 -0
- package/src/cli/build.ts +1 -2
- package/src/cli/client-add.test.ts +8 -15
- package/src/cli/client-add.ts +5 -14
- package/src/cli/completion.test.ts +1 -5
- package/src/cli/completion.ts +4 -17
- package/src/cli/db-auto-push.test.ts +64 -0
- package/src/cli/db-auto-push.ts +72 -0
- package/src/cli/db.test.ts +189 -0
- package/src/cli/db.ts +386 -0
- package/src/cli/dev-app-runner.ts +2 -8
- package/src/cli/dev-db-push.test.ts +163 -0
- package/src/cli/dev-mode.test.ts +45 -0
- package/src/cli/dev-mode.ts +78 -0
- package/src/cli/dev.test.ts +148 -21
- package/src/cli/dev.ts +208 -134
- package/src/cli/doc-drift.test.ts +3 -2
- package/src/cli/doc-drift.ts +21 -50
- package/src/cli/doc-staleness.test.ts +69 -0
- package/src/cli/docker-cli.test.ts +7 -8
- package/src/cli/docker.ts +1 -3
- package/src/cli/doctor-diff-examples.ts +1 -3
- package/src/cli/doctor-diff.test.ts +1 -5
- package/src/cli/doctor-diff.ts +17 -46
- package/src/cli/doctor-pii.ts +2 -7
- package/src/cli/doctor.test.ts +26 -4
- package/src/cli/doctor.ts +35 -11
- package/src/cli/eval.ts +4 -14
- package/src/cli/gates-list.ts +1 -4
- package/src/cli/hero-meta.test.ts +17 -19
- package/src/cli/hero-meta.ts +20 -30
- package/src/cli/images.ts +3 -8
- package/src/cli/index.ts +11 -2
- package/src/cli/load-config.images.test.ts +14 -14
- package/src/cli/load-config.ts +41 -47
- package/src/cli/mcp-from-console.ts +1 -4
- package/src/cli/mode.ts +45 -0
- package/src/cli/ports.test.ts +4 -13
- package/src/cli/ports.ts +1 -3
- package/src/cli/privacy-erase.ts +1 -3
- package/src/cli/registry.ts +75 -25
- package/src/cli/schema.ts +3 -10
- package/src/cli/stack.ts +2 -7
- package/src/cli/start.ts +4 -15
- package/src/cli/upgrade.ts +1 -4
- package/src/client/budget-entry.ts +1 -6
- package/src/client/create.test.ts +6 -12
- package/src/client/create.ts +2 -8
- package/src/client/errors.ts +1 -4
- package/src/client/index.ts +1 -6
- package/src/client/notes-contract.test.ts +4 -13
- package/src/client/transport.ts +9 -30
- package/src/client/types.ts +8 -29
- package/src/compiler/aot.test.ts +2 -9
- package/src/compiler/aot.ts +1 -4
- package/src/compiler/differential.test.ts +3 -11
- package/src/compiler/dynamic.ts +1 -4
- package/src/compiler/effects-infer.ts +8 -34
- package/src/compiler/emit.ts +1 -3
- package/src/compiler/extract.test.ts +96 -30
- package/src/compiler/extract.ts +362 -156
- package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
- package/src/compiler/fixtures/skyport.expected.json +24 -83
- package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
- package/src/compiler/http-parse.ts +2 -9
- package/src/compiler/index.ts +1 -5
- package/src/compiler/response.ts +4 -7
- package/src/compiler/sucrose.ts +11 -31
- package/src/config/define-config.test.ts +57 -34
- package/src/config/index.ts +181 -37
- package/src/config/resolve-driver.test.ts +28 -17
- package/src/console/budget.test.ts +1 -4
- package/src/console/index.ts +1 -4
- package/src/console/server/access.test.ts +15 -43
- package/src/console/server/access.ts +19 -49
- package/src/console/server/ai.test.ts +3 -11
- package/src/console/server/ai.ts +23 -46
- package/src/console/server/app.ts +14 -45
- package/src/console/server/auth-rate.test.ts +4 -12
- package/src/console/server/bind.ts +1 -5
- package/src/console/server/channels.test.ts +2 -6
- package/src/console/server/channels.ts +10 -35
- package/src/console/server/claim.ts +2 -8
- package/src/console/server/clock.test.ts +2 -6
- package/src/console/server/clock.ts +8 -26
- package/src/console/server/console.test.ts +1 -3
- package/src/console/server/diff.test.ts +5 -17
- package/src/console/server/diff.ts +10 -31
- package/src/console/server/dry-run.audit.test.ts +2 -8
- package/src/console/server/flows.ts +64 -233
- package/src/console/server/gates.test.ts +14 -50
- package/src/console/server/gates.ts +13 -48
- package/src/console/server/index.ts +2 -9
- package/src/console/server/live.ts +3 -12
- package/src/console/server/operator-db.test.ts +4 -15
- package/src/console/server/operator-db.ts +13 -32
- package/src/console/server/plugin.ts +50 -53
- package/src/console/server/plugins.test.ts +2 -6
- package/src/console/server/plugins.ts +17 -56
- package/src/console/server/runs-pii.ts +2 -7
- package/src/console/server/security.gate.test.ts +18 -40
- package/src/console/server/serve.ts +10 -25
- package/src/console/server/signals.test.ts +1 -3
- package/src/console/server/signals.ts +17 -40
- package/src/console/server/state.ts +21 -59
- package/src/console/server/store.test.ts +20 -22
- package/src/console/server/store.ts +31 -76
- package/src/console/server/vault.test.ts +12 -29
- package/src/console/server/vault.ts +23 -60
- package/src/console/ui/access/AccessA11yView.tsx +6 -21
- package/src/console/ui/access/a11y.test.tsx +3 -12
- package/src/console/ui/access/acknowledgement.test.ts +1 -4
- package/src/console/ui/access/acknowledgement.ts +1 -3
- package/src/console/ui/access/blast-radius.ts +1 -3
- package/src/console/ui/access/confirmation.test.ts +1 -5
- package/src/console/ui/access/confirmation.ts +1 -4
- package/src/console/ui/access/fixture.ts +1 -5
- package/src/console/ui/access/grantable.test.ts +1 -3
- package/src/console/ui/access/grantable.ts +2 -7
- package/src/console/ui/access/index.ts +2 -9
- package/src/console/ui/access/provenance.test.ts +1 -3
- package/src/console/ui/access/provenance.ts +2 -6
- package/src/console/ui/access/search.test.ts +1 -5
- package/src/console/ui/access/search.ts +2 -6
- package/src/console/ui/ai/AiA11yView.tsx +6 -17
- package/src/console/ui/ai/a11y.test.tsx +2 -5
- package/src/console/ui/ai/fixture.ts +2 -7
- package/src/console/ui/ai/format.ts +1 -3
- package/src/console/ui/ai/group.test.ts +1 -3
- package/src/console/ui/ai/group.ts +4 -12
- package/src/console/ui/ai/index.ts +2 -9
- package/src/console/ui/ai/promotion.test.ts +2 -7
- package/src/console/ui/ai/promotion.ts +4 -13
- package/src/console/ui/ai/search.test.ts +2 -11
- package/src/console/ui/ai/search.ts +3 -13
- package/src/console/ui/ai/types.ts +1 -8
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
- package/src/console/ui/architecture/a11y.test.tsx +1 -2
- package/src/console/ui/architecture/declared.ts +1 -5
- package/src/console/ui/architecture/index.ts +7 -35
- package/src/console/ui/architecture/layout.ts +1 -3
- package/src/console/ui/architecture/pathologies.ts +10 -19
- package/src/console/ui/architecture/search.ts +6 -15
- package/src/console/ui/architecture/traffic.ts +4 -14
- package/src/console/ui/architecture/types.ts +2 -10
- package/src/console/ui/architecture/view.test.ts +7 -19
- package/src/console/ui/architecture/view.ts +9 -36
- package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
- package/src/console/ui/channels/a11y.test.tsx +1 -2
- package/src/console/ui/channels/confirmation.test.ts +1 -4
- package/src/console/ui/channels/confirmation.ts +1 -4
- package/src/console/ui/channels/findings.ts +1 -5
- package/src/console/ui/channels/index.ts +2 -8
- package/src/console/ui/channels/locale.test.ts +1 -3
- package/src/console/ui/channels/locale.ts +2 -8
- package/src/console/ui/channels/search.ts +4 -13
- package/src/console/ui/channels/taxonomy.ts +1 -3
- package/src/console/ui/clock/ClockA11yView.tsx +9 -26
- package/src/console/ui/clock/a11y.test.tsx +2 -5
- package/src/console/ui/clock/confirmation.test.ts +1 -3
- package/src/console/ui/clock/confirmation.ts +1 -4
- package/src/console/ui/clock/findings.ts +1 -4
- package/src/console/ui/clock/health.ts +2 -7
- package/src/console/ui/clock/index.ts +2 -10
- package/src/console/ui/clock/search.test.ts +1 -3
- package/src/console/ui/clock/search.ts +2 -6
- package/src/console/ui/clock/timeline.test.ts +1 -3
- package/src/console/ui/clock/waiting-on.test.ts +1 -5
- package/src/console/ui/clock/waiting-on.ts +2 -7
- package/src/console/ui/diff/DiffA11yView.tsx +8 -17
- package/src/console/ui/diff/a11y.test.tsx +2 -5
- package/src/console/ui/diff/group.test.ts +3 -13
- package/src/console/ui/diff/group.ts +2 -8
- package/src/console/ui/diff/index.ts +2 -8
- package/src/console/ui/diff/search.test.ts +1 -5
- package/src/console/ui/diff/search.ts +4 -16
- package/src/console/ui/diff/summary.ts +1 -2
- package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
- package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
- package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
- package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
- package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
- package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
- package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
- package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
- package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
- package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
- package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
- package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
- package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
- package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
- package/src/console/ui/flows/a11y.test.tsx +2 -8
- package/src/console/ui/flows/buffer.test.ts +3 -11
- package/src/console/ui/flows/buffer.ts +4 -11
- package/src/console/ui/flows/confirmation.ts +1 -3
- package/src/console/ui/flows/contract.test.ts +3 -7
- package/src/console/ui/flows/contract.ts +12 -36
- package/src/console/ui/flows/graph.test.ts +3 -11
- package/src/console/ui/flows/graph.ts +5 -15
- package/src/console/ui/flows/index.ts +1 -6
- package/src/console/ui/flows/save-as-test.ts +1 -3
- package/src/console/ui/flows/search.ts +8 -25
- package/src/console/ui/flows/tiers.ts +2 -9
- package/src/console/ui/gates/GatesA11yView.tsx +4 -13
- package/src/console/ui/gates/a11y.test.tsx +2 -5
- package/src/console/ui/gates/audit.ts +1 -3
- package/src/console/ui/gates/denial.test.ts +1 -3
- package/src/console/ui/gates/denial.ts +4 -12
- package/src/console/ui/gates/findings.ts +1 -3
- package/src/console/ui/gates/group.test.ts +3 -3
- package/src/console/ui/gates/group.ts +3 -11
- package/src/console/ui/gates/index.ts +2 -10
- package/src/console/ui/gates/search.ts +3 -10
- package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
- package/src/console/ui/overview/a11y.test.tsx +1 -2
- package/src/console/ui/overview/busiest.ts +1 -3
- package/src/console/ui/overview/compose.ts +1 -13
- package/src/console/ui/overview/cost.ts +34 -38
- package/src/console/ui/overview/fixture.ts +21 -26
- package/src/console/ui/overview/golden.ts +4 -14
- package/src/console/ui/overview/index.ts +2 -9
- package/src/console/ui/overview/rank.test.ts +3 -10
- package/src/console/ui/overview/rank.ts +2 -7
- package/src/console/ui/overview/slo.test.ts +5 -9
- package/src/console/ui/overview/slo.ts +6 -23
- package/src/console/ui/overview/verdict.ts +3 -10
- package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
- package/src/console/ui/plugins/a11y.test.tsx +1 -2
- package/src/console/ui/plugins/fixture.ts +2 -4
- package/src/console/ui/plugins/group.test.ts +1 -3
- package/src/console/ui/plugins/group.ts +1 -6
- package/src/console/ui/plugins/index.ts +3 -13
- package/src/console/ui/plugins/search.ts +7 -19
- package/src/console/ui/runs/RunsA11yView.tsx +5 -20
- package/src/console/ui/runs/a11y.test.tsx +2 -5
- package/src/console/ui/runs/explain.ts +2 -6
- package/src/console/ui/runs/group.ts +3 -12
- package/src/console/ui/runs/histogram.test.ts +2 -11
- package/src/console/ui/runs/histogram.ts +1 -4
- package/src/console/ui/runs/index.ts +4 -18
- package/src/console/ui/runs/project.ts +2 -6
- package/src/console/ui/runs/query.test.ts +1 -3
- package/src/console/ui/runs/query.ts +12 -35
- package/src/console/ui/runs/search.ts +5 -19
- package/src/console/ui/runs/trace-link.test.ts +2 -6
- package/src/console/ui/runs/trace-link.ts +4 -16
- package/src/console/ui/runs/types.ts +1 -3
- package/src/console/ui/shell/App.tsx +2 -10
- package/src/console/ui/shell/client.ts +22 -115
- package/src/console/ui/shell/components/ui.tsx +1 -4
- package/src/console/ui/shell/layout/Shell.tsx +2 -4
- package/src/console/ui/shell/main.tsx +31 -96
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
- package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
- package/src/console/ui/shell/setup/Wizard.tsx +3 -5
- package/src/console/ui/shell/styles.css +1 -2
- package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
- package/src/console/ui/signals/a11y.test.tsx +2 -5
- package/src/console/ui/signals/confirmation.test.ts +1 -5
- package/src/console/ui/signals/confirmation.ts +2 -6
- package/src/console/ui/signals/dry-run.ts +1 -3
- package/src/console/ui/signals/durable.ts +1 -3
- package/src/console/ui/signals/findings.ts +1 -3
- package/src/console/ui/signals/group.test.ts +2 -8
- package/src/console/ui/signals/group.ts +2 -10
- package/src/console/ui/signals/index.ts +1 -4
- package/src/console/ui/signals/monitor.ts +2 -7
- package/src/console/ui/signals/schema-form.test.ts +3 -14
- package/src/console/ui/signals/schema-form.ts +1 -4
- package/src/console/ui/signals/search.ts +4 -13
- package/src/console/ui/store/StoreA11yView.tsx +3 -9
- package/src/console/ui/store/a11y.test.tsx +2 -5
- package/src/console/ui/store/confirmation.test.ts +1 -3
- package/src/console/ui/store/confirmation.ts +1 -4
- package/src/console/ui/store/dry-run.ts +2 -5
- package/src/console/ui/store/fixture.ts +1 -2
- package/src/console/ui/store/group.test.ts +1 -6
- package/src/console/ui/store/group.ts +1 -4
- package/src/console/ui/store/index.ts +1 -5
- package/src/console/ui/store/search.ts +2 -6
- package/src/console/ui/store/will-not-fire.ts +1 -2
- package/src/console/ui/traces/TracesA11yView.tsx +10 -29
- package/src/console/ui/traces/a11y.test.tsx +1 -2
- package/src/console/ui/traces/chain.test.ts +5 -19
- package/src/console/ui/traces/chain.ts +1 -3
- package/src/console/ui/traces/critical-path.test.ts +1 -3
- package/src/console/ui/traces/critical-path.ts +2 -6
- package/src/console/ui/traces/filter.test.ts +2 -6
- package/src/console/ui/traces/filter.ts +5 -13
- package/src/console/ui/traces/fold.test.ts +4 -12
- package/src/console/ui/traces/fold.ts +1 -3
- package/src/console/ui/traces/mini.ts +1 -3
- package/src/console/ui/traces/replay.test.ts +1 -3
- package/src/console/ui/traces/replay.ts +1 -3
- package/src/console/ui/traces/sampling.ts +1 -4
- package/src/console/ui/traces/search.ts +4 -17
- package/src/console/ui/traces/tier.ts +1 -3
- package/src/console/ui/vault/VaultA11yView.tsx +5 -17
- package/src/console/ui/vault/a11y.test.tsx +1 -2
- package/src/console/ui/vault/blast-radius.ts +1 -3
- package/src/console/ui/vault/confirmation.test.ts +1 -5
- package/src/console/ui/vault/confirmation.ts +1 -4
- package/src/console/ui/vault/dormant.test.ts +1 -4
- package/src/console/ui/vault/export-safe.test.ts +1 -5
- package/src/console/ui/vault/export-safe.ts +1 -4
- package/src/console/ui/vault/fixture.ts +3 -3
- package/src/console/ui/vault/group.ts +1 -2
- package/src/console/ui/vault/index.ts +2 -10
- package/src/console/ui/vault/search.ts +2 -6
- package/src/console/ui/vault/types.ts +1 -1
- package/src/console/xss.gate.test.ts +1 -3
- package/src/docker/compose.ts +112 -20
- package/src/docker/derive.ts +5 -19
- package/src/docker/docker.test.ts +15 -15
- package/src/docker/dockerfile.integration.test.ts +12 -21
- package/src/docker/helpers.ts +5 -4
- package/src/docker/index.ts +4 -11
- package/src/docker/pin.ts +1 -9
- package/src/docker/recipes/index.ts +5 -6
- package/src/docker/recipes/mailpit.ts +22 -0
- package/src/docker/recipes/postgres.ts +17 -6
- package/src/docker/recipes/redis.ts +6 -1
- package/src/docker/recipes/rustfs.ts +33 -0
- package/src/docker/stack-id.test.ts +33 -0
- package/src/docker/stack-id.ts +25 -13
- package/src/docker/stack.integration.test.ts +6 -21
- package/src/docker/types.ts +13 -4
- package/src/drivers/ai-anthropic.ts +5 -14
- package/src/drivers/ai-mock.ts +2 -5
- package/src/drivers/ai-openai-compatible.ts +4 -10
- package/src/drivers/ai-providers.test.ts +6 -13
- package/src/drivers/bun-native-completeness.test.ts +6 -15
- package/src/drivers/channel-console.ts +6 -7
- package/src/drivers/channel-fcm.ts +20 -30
- package/src/drivers/channel-resend.ts +1 -3
- package/src/drivers/channel-smtp.ts +2 -6
- package/src/drivers/channel-types.ts +2 -12
- package/src/drivers/channel-unifonic.ts +2 -6
- package/src/drivers/channel-wa-cloud.ts +2 -6
- package/src/drivers/channel-webpush.ts +21 -60
- package/src/drivers/conformance.test.ts +2 -10
- package/src/drivers/conformance.ts +8 -21
- package/src/drivers/fs.ts +2 -8
- package/src/drivers/index.ts +12 -56
- package/src/drivers/memory.ts +14 -41
- package/src/drivers/pgvector.ts +7 -11
- package/src/drivers/postgres.ts +7 -13
- package/src/drivers/redis.ts +13 -37
- package/src/drivers/s3.ts +5 -17
- package/src/drivers/signal-engine.ts +12 -49
- package/src/drivers/signal-memory.ts +2 -8
- package/src/drivers/signal-nats.ts +4 -9
- package/src/drivers/signal-postgres.ts +62 -129
- package/src/drivers/signal-redis.ts +7 -21
- package/src/drivers/signal-types.ts +1 -4
- package/src/drivers/sqlite.ts +3 -12
- package/src/drivers/types.ts +4 -23
- package/src/drivers/vault-env.ts +2 -6
- package/src/drivers/vault-infisical.ts +1 -5
- package/src/drivers/vault-managed.ts +1 -5
- package/src/drivers/vault-memory.ts +1 -5
- package/src/drivers/vault-openbao.ts +1 -5
- package/src/drivers/vault-sops.ts +10 -35
- package/src/drivers/vault-types.ts +1 -7
- package/src/elements/ai/declare.ts +4 -14
- package/src/elements/ai/eval.ts +2 -6
- package/src/elements/ai/pii.ts +1 -3
- package/src/elements/ai/runtime.ts +12 -50
- package/src/elements/ai/schema.ts +4 -15
- package/src/elements/ai.test.ts +13 -24
- package/src/elements/ai.ts +1 -5
- package/src/elements/channel/consent.ts +3 -12
- package/src/elements/channel/costs.ts +4 -15
- package/src/elements/channel/declare.ts +1 -4
- package/src/elements/channel/email-auth.ts +1 -4
- package/src/elements/channel/locale.ts +2 -10
- package/src/elements/channel/mask.ts +1 -3
- package/src/elements/channel/mime.ts +2 -12
- package/src/elements/channel/outcomes.test.ts +1 -5
- package/src/elements/channel/outcomes.ts +5 -15
- package/src/elements/channel/receipts.ts +2 -7
- package/src/elements/channel/runtime.ts +28 -74
- package/src/elements/channel/suppression.ts +8 -14
- package/src/elements/channel.test.ts +8 -31
- package/src/elements/channel.ts +3 -14
- package/src/elements/clock/actions.ts +6 -18
- package/src/elements/clock/declare.ts +1 -3
- package/src/elements/clock/dst.ts +1 -5
- package/src/elements/clock/durable.ts +4 -16
- package/src/elements/clock/health.ts +2 -7
- package/src/elements/clock/leader.ts +2 -9
- package/src/elements/clock/reconcile.ts +4 -15
- package/src/elements/clock/runtime.ts +2 -5
- package/src/elements/clock/schedule.ts +4 -20
- package/src/elements/clock.test.ts +2 -7
- package/src/elements/clock.ts +5 -23
- package/src/elements/gate/permissions.ts +1 -4
- package/src/elements/gate/runtime.ts +7 -28
- package/src/elements/gate.ts +1 -5
- package/src/elements/index.ts +9 -7
- package/src/elements/signal/declare.ts +2 -7
- package/src/elements/signal/reconcile.test.ts +1 -4
- package/src/elements/signal/runtime.ts +1 -3
- package/src/elements/signal.test.ts +3 -15
- package/src/elements/signal.ts +2 -8
- package/src/elements/store/cache.test.ts +46 -0
- package/src/elements/store/cache.ts +3 -11
- package/src/elements/store/classify.ts +5 -22
- package/src/elements/store/declare.ts +8 -17
- package/src/elements/store/domain-ddl.test.ts +86 -0
- package/src/elements/store/emit-drizzle.ts +363 -0
- package/src/elements/store/files-policy.test.ts +1 -5
- package/src/elements/store/files-policy.ts +4 -12
- package/src/elements/store/load-plugin-tables.ts +103 -0
- package/src/elements/store/missing-relation.test.ts +83 -0
- package/src/elements/store/missing-relation.ts +38 -0
- package/src/elements/store/replica.ts +1 -4
- package/src/elements/store/runtime.ts +25 -28
- package/src/elements/store/schema-decl.test.ts +227 -0
- package/src/elements/store/schema-decl.ts +516 -0
- package/src/elements/store/sql-condition.ts +11 -21
- package/src/elements/store/sql-session.test.ts +50 -0
- package/src/elements/store/sql-session.ts +60 -63
- package/src/elements/store/table.ts +35 -19
- package/src/elements/store.test.ts +17 -39
- package/src/elements/store.ts +37 -31
- package/src/elements/vault/chain.ts +34 -0
- package/src/elements/vault/declare.ts +22 -32
- package/src/elements/vault/fingerprint.ts +2 -7
- package/src/elements/vault/redact.ts +2 -6
- package/src/elements/vault/runtime.ts +18 -32
- package/src/elements/vault.test.ts +12 -28
- package/src/elements/vault.ts +8 -12
- package/src/index.ts +5 -2
- package/src/kernel/adopt-routes.ts +15 -29
- package/src/kernel/app.ts +34 -94
- package/src/kernel/auth-resolve.ts +2 -9
- package/src/kernel/boot-bind/ai.ts +1 -4
- package/src/kernel/boot-bind/channel.ts +2 -8
- package/src/kernel/boot-bind/clock.ts +2 -6
- package/src/kernel/boot-bind/gate.ts +2 -8
- package/src/kernel/boot-bind/runs.ts +1 -3
- package/src/kernel/boot-bind/signal.ts +3 -10
- package/src/kernel/boot-bind/store.test.ts +17 -17
- package/src/kernel/boot-bind/store.ts +44 -50
- package/src/kernel/boot-bind/vault.ts +2 -8
- package/src/kernel/boot.test.ts +4 -9
- package/src/kernel/boot.ts +29 -76
- package/src/kernel/budget.test.ts +1 -3
- package/src/kernel/capability.ts +3 -10
- package/src/kernel/dry-run.test.ts +1 -4
- package/src/kernel/dry-run.ts +3 -11
- package/src/kernel/effects.test.ts +1 -5
- package/src/kernel/effects.ts +4 -11
- package/src/kernel/errors.registry.test.ts +2 -8
- package/src/kernel/errors.ts +23 -32
- package/src/kernel/flow.test.ts +12 -25
- package/src/kernel/flow.ts +5 -25
- package/src/kernel/fx.test.ts +15 -44
- package/src/kernel/fx.ts +27 -79
- package/src/kernel/hook-timing.test.ts +3 -6
- package/src/kernel/hook-timing.ts +5 -14
- package/src/kernel/hooks.test.ts +10 -10
- package/src/kernel/hooks.ts +3 -12
- package/src/kernel/index.ts +4 -17
- package/src/kernel/journal.ts +7 -31
- package/src/kernel/on.ts +1 -6
- package/src/kernel/pipeline.test.ts +10 -19
- package/src/kernel/pipeline.ts +5 -17
- package/src/kernel/plug.ts +4 -11
- package/src/kernel/plugin/conflicts.test.ts +13 -25
- package/src/kernel/plugin/decorate.test.ts +8 -13
- package/src/kernel/plugin/scoping.test.ts +4 -11
- package/src/kernel/plugin.ts +48 -24
- package/src/kernel/registry.ts +80 -29
- package/src/kernel/router.test.ts +15 -13
- package/src/kernel/router.ts +9 -29
- package/src/kernel/routing-budget.test.ts +1 -3
- package/src/kernel/run-telemetry.ts +1 -3
- package/src/kernel/triggers.ts +4 -21
- package/src/manifest/diff.test.ts +26 -91
- package/src/manifest/diff.ts +95 -225
- package/src/manifest/index.ts +2 -9
- package/src/manifest/types.ts +29 -5
- package/src/manifest/undeclared.test.ts +4 -12
- package/src/manifest/undeclared.ts +1 -2
- package/src/manifest/validate.test.ts +2 -6
- package/src/manifest/validate.ts +4 -14
- package/src/mcp/authorization.ts +8 -27
- package/src/mcp/confirmation.ts +3 -10
- package/src/mcp/data.ts +2 -6
- package/src/mcp/docs-index.ts +4 -7
- package/src/mcp/docs-mcp.test.ts +3 -12
- package/src/mcp/docs-server.ts +7 -27
- package/src/mcp/docs-tools.ts +2 -6
- package/src/mcp/index.ts +1 -6
- package/src/mcp/injection.gate.test.ts +4 -18
- package/src/mcp/mcp.test.ts +18 -49
- package/src/mcp/protocol.ts +3 -10
- package/src/mcp/server.ts +11 -52
- package/src/mcp/session.ts +4 -14
- package/src/mcp/tools.ts +14 -50
- package/src/plugins/catalogue.test.ts +3 -7
- package/src/plugins/catalogue.ts +1 -3
- package/src/plugins/node-import-scan.ts +2 -5
- package/src/plugins/supply-chain.ts +5 -17
- package/src/release/exports.ts +3 -8
- package/src/release/measure.exports.test.ts +1 -3
- package/src/release/measure.ts +15 -43
- package/src/runs/bench.test.ts +1 -3
- package/src/runs/collect.ts +8 -25
- package/src/runs/drivers/clickhouse.ts +2 -9
- package/src/runs/drivers/files.ts +9 -31
- package/src/runs/drivers/memory.ts +5 -22
- package/src/runs/drivers/postgres.ts +8 -20
- package/src/runs/duckdb.ts +2 -8
- package/src/runs/index.ts +3 -14
- package/src/runs/outlier.ts +3 -10
- package/src/runs/parquet.ts +8 -26
- package/src/runs/privacy.ts +2 -8
- package/src/runs/runs.test.ts +3 -9
- package/src/runs/runtime.ts +7 -32
- package/src/runs/shred.ts +10 -29
- package/src/runs/types.ts +1 -4
- package/src/runtime/bun.ts +4 -15
- package/src/runtime/cold-start.bench.ts +1 -3
- package/src/runtime/dev-request-log.test.ts +1 -4
- package/src/runtime/dev-request-log.ts +1 -4
- package/src/runtime/index.ts +1 -6
- package/src/runtime/primitives.ts +5 -4
- package/src/runtime/security.ts +3 -13
- package/src/runtime/serve.test.ts +4 -7
- package/src/runtime/types.ts +1 -4
- package/src/runtime/web-standard.ts +3 -15
- package/src/term.test.ts +4 -6
- package/src/term.ts +49 -98
- package/src/test/create-test-app.test.ts +4 -14
- package/src/test/create-test-app.ts +13 -31
- package/src/test/provisions.integration.test.ts +3 -11
- package/src/upgrade/codemods.test.ts +25 -6
- package/src/upgrade/codemods.ts +116 -3
- package/src/validation/standard-schema.test.ts +2 -5
- package/src/validation/standard-schema.ts +13 -33
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
package/src/kernel/errors.ts
CHANGED
|
@@ -99,50 +99,43 @@ export const OKE_ERRORS = {
|
|
|
99
99
|
/** Flow reads a store resource not listed in `effects.reads`. */
|
|
100
100
|
UNDECLARED_READ: {
|
|
101
101
|
code: 1001,
|
|
102
|
-
cause:
|
|
103
|
-
'Flow "{flow}" reads "{resource}" without declaring it.',
|
|
102
|
+
cause: 'Flow "{flow}" reads "{resource}" without declaring it.',
|
|
104
103
|
fix: 'Add "{resource}" to this flow\'s effects.reads.',
|
|
105
104
|
},
|
|
106
105
|
/** Flow writes a store resource not listed in `effects.writes`. */
|
|
107
106
|
UNDECLARED_WRITE: {
|
|
108
107
|
code: 1002,
|
|
109
|
-
cause:
|
|
110
|
-
'Flow "{flow}" writes "{resource}" without declaring it.',
|
|
108
|
+
cause: 'Flow "{flow}" writes "{resource}" without declaring it.',
|
|
111
109
|
fix: 'Add "{resource}" to this flow\'s effects.writes.',
|
|
112
110
|
},
|
|
113
111
|
/** Flow emits a signal not listed in `effects.emits`. */
|
|
114
112
|
UNDECLARED_EMIT: {
|
|
115
113
|
code: 1003,
|
|
116
|
-
cause:
|
|
117
|
-
'Flow "{flow}" emits "{resource}" without declaring it.',
|
|
114
|
+
cause: 'Flow "{flow}" emits "{resource}" without declaring it.',
|
|
118
115
|
fix: 'Add "{resource}" to this flow\'s effects.emits.',
|
|
119
116
|
},
|
|
120
117
|
/** Flow sends a channel template not listed in `effects.sends`. */
|
|
121
118
|
UNDECLARED_SEND: {
|
|
122
119
|
code: 1004,
|
|
123
|
-
cause:
|
|
124
|
-
'Flow "{flow}" sends "{resource}" without declaring it.',
|
|
120
|
+
cause: 'Flow "{flow}" sends "{resource}" without declaring it.',
|
|
125
121
|
fix: 'Add "{resource}" to this flow\'s effects.sends.',
|
|
126
122
|
},
|
|
127
123
|
/** Flow asks a prompt not listed in `effects.asks`. */
|
|
128
124
|
UNDECLARED_ASK: {
|
|
129
125
|
code: 1005,
|
|
130
|
-
cause:
|
|
131
|
-
'Flow "{flow}" asks "{resource}" without declaring it.',
|
|
126
|
+
cause: 'Flow "{flow}" asks "{resource}" without declaring it.',
|
|
132
127
|
fix: 'Add "{resource}" to this flow\'s effects.asks.',
|
|
133
128
|
},
|
|
134
129
|
/** Flow reads a secret not listed in `effects.secrets`. */
|
|
135
130
|
UNDECLARED_SECRET: {
|
|
136
131
|
code: 1006,
|
|
137
|
-
cause:
|
|
138
|
-
'Flow "{flow}" reads secret "{resource}" without declaring it.',
|
|
132
|
+
cause: 'Flow "{flow}" reads secret "{resource}" without declaring it.',
|
|
139
133
|
fix: 'Add "{resource}" to this flow\'s effects.secrets.',
|
|
140
134
|
},
|
|
141
135
|
/** Flow calls another flow not listed in `effects.calls`. */
|
|
142
136
|
UNDECLARED_CALL: {
|
|
143
137
|
code: 1007,
|
|
144
|
-
cause:
|
|
145
|
-
'Flow "{flow}" calls "{resource}" without declaring it.',
|
|
138
|
+
cause: 'Flow "{flow}" calls "{resource}" without declaring it.',
|
|
146
139
|
fix: 'Add "{resource}" to this flow\'s effects.calls.',
|
|
147
140
|
},
|
|
148
141
|
/**
|
|
@@ -151,9 +144,17 @@ export const OKE_ERRORS = {
|
|
|
151
144
|
*/
|
|
152
145
|
ORPHAN_EMIT: {
|
|
153
146
|
code: 1042,
|
|
154
|
-
cause:
|
|
155
|
-
|
|
156
|
-
|
|
147
|
+
cause: 'Flow "{flow}" emits signal "{resource}" with no subscriber.',
|
|
148
|
+
fix: "Add `on({resource}, …)` or mark the signal `{ optional: true }`.",
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* Domain table/column missing under docker/prod (migrations not applied).
|
|
152
|
+
* Store/DDL band starts at 1100.
|
|
153
|
+
*/
|
|
154
|
+
DOMAIN_SCHEMA_MISSING: {
|
|
155
|
+
code: 1101,
|
|
156
|
+
cause: "domain table not found — migrations have not been applied.",
|
|
157
|
+
fix: "run `oke db migrate` against this environment.",
|
|
157
158
|
},
|
|
158
159
|
} as const satisfies Record<string, OkeErrorDefinition>;
|
|
159
160
|
|
|
@@ -164,10 +165,7 @@ export const OKE_ERRORS = {
|
|
|
164
165
|
* @param params - Interpolation params
|
|
165
166
|
* @returns Never
|
|
166
167
|
*/
|
|
167
|
-
export function throwOke(
|
|
168
|
-
key: keyof typeof OKE_ERRORS,
|
|
169
|
-
params: OkeErrorParams = {},
|
|
170
|
-
): never {
|
|
168
|
+
export function throwOke(key: keyof typeof OKE_ERRORS, params: OkeErrorParams = {}): never {
|
|
171
169
|
throw new OkeError(OKE_ERRORS[key], params);
|
|
172
170
|
}
|
|
173
171
|
|
|
@@ -176,9 +174,7 @@ export function throwOke(
|
|
|
176
174
|
*
|
|
177
175
|
* @param code - Permanent numeric code
|
|
178
176
|
*/
|
|
179
|
-
export function lookupOkeError(
|
|
180
|
-
code: OkeErrorCode,
|
|
181
|
-
): OkeErrorDefinition | undefined {
|
|
177
|
+
export function lookupOkeError(code: OkeErrorCode): OkeErrorDefinition | undefined {
|
|
182
178
|
for (const def of Object.values(OKE_ERRORS)) {
|
|
183
179
|
if (def.code === code) return def;
|
|
184
180
|
}
|
|
@@ -192,14 +188,9 @@ export function lookupOkeError(
|
|
|
192
188
|
* @param data - Error payload
|
|
193
189
|
* @param opts - Optional message override
|
|
194
190
|
*/
|
|
195
|
-
export function fail<E>(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
opts?: FailOptions,
|
|
199
|
-
): FlowFailure<E> {
|
|
200
|
-
const error: FlowErrorValue<E> = opts?.message !== undefined
|
|
201
|
-
? { code, data, message: opts.message }
|
|
202
|
-
: { code, data };
|
|
191
|
+
export function fail<E>(code: string, data: E, opts?: FailOptions): FlowFailure<E> {
|
|
192
|
+
const error: FlowErrorValue<E> =
|
|
193
|
+
opts?.message !== undefined ? { code, data, message: opts.message } : { code, data };
|
|
203
194
|
return { data: null, error };
|
|
204
195
|
}
|
|
205
196
|
|
package/src/kernel/flow.test.ts
CHANGED
|
@@ -2,12 +2,7 @@ import { describe, expect, test, beforeEach } from "bun:test";
|
|
|
2
2
|
import { oke } from "./app.ts";
|
|
3
3
|
import { flow, isFlow, resetFlowSeq } from "./flow.ts";
|
|
4
4
|
import { on, resetBindings } from "./on.ts";
|
|
5
|
-
import {
|
|
6
|
-
every,
|
|
7
|
-
http,
|
|
8
|
-
internal,
|
|
9
|
-
table,
|
|
10
|
-
} from "./triggers.ts";
|
|
5
|
+
import { every, http, internal, table } from "./triggers.ts";
|
|
11
6
|
|
|
12
7
|
beforeEach(() => {
|
|
13
8
|
resetBindings();
|
|
@@ -55,11 +50,7 @@ describe("flow — one species", () => {
|
|
|
55
50
|
expect(app.bindings[0]?.flow).toBe(shared);
|
|
56
51
|
expect(app.bindings[1]?.flow).toBe(shared);
|
|
57
52
|
|
|
58
|
-
const httpResult = await app.execute(
|
|
59
|
-
shared,
|
|
60
|
-
{ n: 3 },
|
|
61
|
-
shared.triggers[0]!,
|
|
62
|
-
);
|
|
53
|
+
const httpResult = await app.execute(shared, { n: 3 }, shared.triggers[0]!);
|
|
63
54
|
const signalResults = await app.dispatchSignal("order-placed", { n: 4 });
|
|
64
55
|
|
|
65
56
|
expect(httpResult.output).toEqual({ n: 6 });
|
|
@@ -126,29 +117,25 @@ describe("five trigger kinds", () => {
|
|
|
126
117
|
|
|
127
118
|
const app = oke({ name: "five" });
|
|
128
119
|
|
|
129
|
-
const res = await app.fetch(
|
|
130
|
-
new Request("http://localhost/abc", { method: "GET" }),
|
|
131
|
-
);
|
|
120
|
+
const res = await app.fetch(new Request("http://localhost/abc", { method: "GET" }));
|
|
132
121
|
expect(res.status).toBe(200);
|
|
133
122
|
expect(await res.json()).toEqual({ data: { code: "abc" }, error: null });
|
|
134
123
|
|
|
135
124
|
await app.dispatchEvery("1h");
|
|
136
125
|
await app.dispatchSignal("link-clicked", { code: "sa" });
|
|
137
|
-
await app.dispatchCdc(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
126
|
+
await app.dispatchCdc(
|
|
127
|
+
"orders",
|
|
128
|
+
{
|
|
129
|
+
before: { status: "open" },
|
|
130
|
+
after: { status: "paid" },
|
|
131
|
+
},
|
|
132
|
+
"status",
|
|
133
|
+
);
|
|
141
134
|
|
|
142
135
|
const internalResult = await app.call("t.internal");
|
|
143
136
|
expect(internalResult).toEqual({ ok: true });
|
|
144
137
|
|
|
145
|
-
expect(seen).toEqual([
|
|
146
|
-
"http:abc",
|
|
147
|
-
"every",
|
|
148
|
-
"signal:sa",
|
|
149
|
-
"cdc:open->paid",
|
|
150
|
-
"internal",
|
|
151
|
-
]);
|
|
138
|
+
expect(seen).toEqual(["http:abc", "every", "signal:sa", "cdc:open->paid", "internal"]);
|
|
152
139
|
expect(httpFlow.triggers[0]?.kind).toBe("http");
|
|
153
140
|
});
|
|
154
141
|
});
|
package/src/kernel/flow.ts
CHANGED
|
@@ -7,20 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Effects, FlowPlane, Slo } from "../manifest/types.ts";
|
|
10
|
-
import type {
|
|
11
|
-
InferSchemaOutput,
|
|
12
|
-
SchemaInput,
|
|
13
|
-
} from "../validation/standard-schema.ts";
|
|
10
|
+
import type { InferSchemaOutput, SchemaInput } from "../validation/standard-schema.ts";
|
|
14
11
|
import type { FlowFailure } from "./errors.ts";
|
|
15
12
|
import type { Fx } from "./fx.ts";
|
|
16
13
|
import type { HookFn, HookStage } from "./hooks.ts";
|
|
17
14
|
import type { PluginDef } from "./plugin.ts";
|
|
18
15
|
import type { Trigger } from "./triggers.ts";
|
|
19
16
|
|
|
20
|
-
export type {
|
|
21
|
-
SchemaInput,
|
|
22
|
-
StandardSchemaV1,
|
|
23
|
-
} from "../validation/standard-schema.ts";
|
|
17
|
+
export type { SchemaInput, StandardSchemaV1 } from "../validation/standard-schema.ts";
|
|
24
18
|
|
|
25
19
|
/** Result of a Standard Schema validate call (re-export shape). */
|
|
26
20
|
export type StandardSchemaResult<Output> =
|
|
@@ -42,11 +36,7 @@ export type FlowHandler<I = unknown, O = unknown> = (
|
|
|
42
36
|
) => O | FlowFailure | Promise<O | FlowFailure>;
|
|
43
37
|
|
|
44
38
|
/** Options for {@link flow}. */
|
|
45
|
-
export interface FlowOptions<
|
|
46
|
-
I = unknown,
|
|
47
|
-
O = unknown,
|
|
48
|
-
E extends FlowErrorMap = FlowErrorMap,
|
|
49
|
-
> {
|
|
39
|
+
export interface FlowOptions<I = unknown, O = unknown, E extends FlowErrorMap = FlowErrorMap> {
|
|
50
40
|
/** Optional stable name (used by `fx.call` and the Manifest). */
|
|
51
41
|
readonly name?: string;
|
|
52
42
|
/** Optional unit scope for unit-level hooks. */
|
|
@@ -192,13 +182,7 @@ export interface FlowDef<
|
|
|
192
182
|
*/
|
|
193
183
|
plug<P extends PluginDef>(
|
|
194
184
|
pluginDef: P,
|
|
195
|
-
): FlowDef<
|
|
196
|
-
I,
|
|
197
|
-
O,
|
|
198
|
-
E,
|
|
199
|
-
D & (P extends PluginDef<infer PD> ? PD : Record<string, never>),
|
|
200
|
-
T
|
|
201
|
-
>;
|
|
185
|
+
): FlowDef<I, O, E, D & (P extends PluginDef<infer PD> ? PD : Record<string, never>), T>;
|
|
202
186
|
}
|
|
203
187
|
|
|
204
188
|
/** Unique brand symbol for {@link FlowDef}. */
|
|
@@ -222,11 +206,7 @@ export function flow<Opts extends FlowOptions<any, any, any>>(
|
|
|
222
206
|
const hooks: Partial<Record<HookStage, HookFn[]>> = {};
|
|
223
207
|
const pendingPlugins: PluginDef[] = [];
|
|
224
208
|
|
|
225
|
-
const def: FlowDef<
|
|
226
|
-
InferFlowIn<Opts>,
|
|
227
|
-
InferFlowOut<Opts>,
|
|
228
|
-
InferFlowErrors<Opts>
|
|
229
|
-
> = {
|
|
209
|
+
const def: FlowDef<InferFlowIn<Opts>, InferFlowOut<Opts>, InferFlowErrors<Opts>> = {
|
|
230
210
|
[flowBrand]: true,
|
|
231
211
|
name,
|
|
232
212
|
unit: options.unit,
|
package/src/kernel/fx.test.ts
CHANGED
|
@@ -1,19 +1,8 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { createCapabilityToken } from "./capability.ts";
|
|
3
3
|
import { createEffectLedger, reversibilityOf } from "./effects.ts";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
formatOkeMessage,
|
|
7
|
-
lookupOkeError,
|
|
8
|
-
OKE_ERRORS,
|
|
9
|
-
OkeError,
|
|
10
|
-
} from "./errors.ts";
|
|
11
|
-
import {
|
|
12
|
-
createFx,
|
|
13
|
-
createFxContext,
|
|
14
|
-
type Fx,
|
|
15
|
-
type FxStubStoreHandle,
|
|
16
|
-
} from "./fx.ts";
|
|
4
|
+
import { fail, formatOkeMessage, lookupOkeError, OKE_ERRORS, OkeError } from "./errors.ts";
|
|
5
|
+
import { createFx, createFxContext, type Fx, type FxStubStoreHandle } from "./fx.ts";
|
|
17
6
|
|
|
18
7
|
/** Narrow stub handle for tests that exercise the in-memory store. */
|
|
19
8
|
function stub(fx: Fx, ref: string): FxStubStoreHandle {
|
|
@@ -37,16 +26,10 @@ describe("fx — capability enforcement", () => {
|
|
|
37
26
|
expect(err).toBeInstanceOf(OkeError);
|
|
38
27
|
const oke = err as OkeError;
|
|
39
28
|
expect(oke.code).toBe(1001);
|
|
40
|
-
expect(oke.causeText).toBe(
|
|
41
|
-
|
|
42
|
-
);
|
|
43
|
-
expect(oke.fix).toBe(
|
|
44
|
-
'Add "sql:users" to this flow\'s effects.reads.',
|
|
45
|
-
);
|
|
29
|
+
expect(oke.causeText).toBe('Flow "bookings.create" reads "sql:users" without declaring it.');
|
|
30
|
+
expect(oke.fix).toBe('Add "sql:users" to this flow\'s effects.reads.');
|
|
46
31
|
expect(oke.docsUrl).toBe("https://okengine.vercel.app/e/1001");
|
|
47
|
-
expect(oke.message).toBe(
|
|
48
|
-
formatOkeMessage(1001, oke.causeText, oke.fix, oke.docsUrl),
|
|
49
|
-
);
|
|
32
|
+
expect(oke.message).toBe(formatOkeMessage(1001, oke.causeText, oke.fix, oke.docsUrl));
|
|
50
33
|
});
|
|
51
34
|
|
|
52
35
|
test("declared store read succeeds", async () => {
|
|
@@ -79,21 +62,13 @@ describe("fx — effect ledger", () => {
|
|
|
79
62
|
await fx.emit("order-placed", { orderId: "o1" });
|
|
80
63
|
|
|
81
64
|
expect(ledger.entries).toHaveLength(3);
|
|
82
|
-
expect(ledger.entries.map((e) => e.kind)).toEqual([
|
|
83
|
-
"read",
|
|
84
|
-
"write",
|
|
85
|
-
"emit",
|
|
86
|
-
]);
|
|
65
|
+
expect(ledger.entries.map((e) => e.kind)).toEqual(["read", "write", "emit"]);
|
|
87
66
|
expect(ledger.entries.map((e) => e.resource)).toEqual([
|
|
88
67
|
"sql:bookings",
|
|
89
68
|
"sql:bookings",
|
|
90
69
|
"order-placed",
|
|
91
70
|
]);
|
|
92
|
-
expect(ledger.entries.map((e) => e.reversibility)).toEqual([
|
|
93
|
-
"none",
|
|
94
|
-
"reversible",
|
|
95
|
-
"deferred",
|
|
96
|
-
]);
|
|
71
|
+
expect(ledger.entries.map((e) => e.reversibility)).toEqual(["none", "reversible", "deferred"]);
|
|
97
72
|
});
|
|
98
73
|
|
|
99
74
|
test("all seven kinds receive the correct reversibility tier via fx", async () => {
|
|
@@ -123,15 +98,7 @@ describe("fx — effect ledger", () => {
|
|
|
123
98
|
|
|
124
99
|
expect(ledger.entries).toHaveLength(7);
|
|
125
100
|
const kinds = ledger.entries.map((e) => e.kind);
|
|
126
|
-
expect(kinds).toEqual([
|
|
127
|
-
"read",
|
|
128
|
-
"write",
|
|
129
|
-
"emit",
|
|
130
|
-
"send",
|
|
131
|
-
"ask",
|
|
132
|
-
"secret",
|
|
133
|
-
"call",
|
|
134
|
-
]);
|
|
101
|
+
expect(kinds).toEqual(["read", "write", "emit", "send", "ask", "secret", "call"]);
|
|
135
102
|
for (const entry of ledger.entries) {
|
|
136
103
|
expect(entry.reversibility).toBe(reversibilityOf(entry.kind));
|
|
137
104
|
}
|
|
@@ -224,9 +191,13 @@ describe("errors — registry", () => {
|
|
|
224
191
|
|
|
225
192
|
test("fx.fail returns a value, not an exception", () => {
|
|
226
193
|
const fx = createFx({ flow: "x", effects: {} });
|
|
227
|
-
const result = fx.fail(
|
|
228
|
-
|
|
229
|
-
|
|
194
|
+
const result = fx.fail(
|
|
195
|
+
"FlightFull",
|
|
196
|
+
{ seatsLeft: 0 },
|
|
197
|
+
{
|
|
198
|
+
message: "full",
|
|
199
|
+
},
|
|
200
|
+
);
|
|
230
201
|
expect(result).toEqual({
|
|
231
202
|
data: null,
|
|
232
203
|
error: { code: "FlightFull", data: { seatsLeft: 0 }, message: "full" },
|
package/src/kernel/fx.ts
CHANGED
|
@@ -10,27 +10,14 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { Effects, ResourceRef } from "../manifest/types.ts";
|
|
13
|
-
import type {
|
|
14
|
-
StoreDecl,
|
|
15
|
-
StoreHandle,
|
|
16
|
-
StoreRuntime,
|
|
17
|
-
SqlStoreHandle,
|
|
18
|
-
} from "../elements/store.ts";
|
|
13
|
+
import type { StoreDecl, StoreHandle, StoreRuntime, SqlStoreHandle } from "../elements/store.ts";
|
|
19
14
|
import type { SignalRuntime } from "../elements/signal.ts";
|
|
20
15
|
import type { VaultRuntime } from "../elements/vault.ts";
|
|
21
16
|
import type { ChannelRuntime } from "../elements/channel.ts";
|
|
22
17
|
import type { AiRuntime } from "../elements/ai.ts";
|
|
23
18
|
import { parseDurationMs } from "../elements/clock/duration.ts";
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
type CapabilityToken,
|
|
27
|
-
} from "./capability.ts";
|
|
28
|
-
import {
|
|
29
|
-
createEffectLedger,
|
|
30
|
-
recordEffect,
|
|
31
|
-
reversibilityOf,
|
|
32
|
-
type EffectLedger,
|
|
33
|
-
} from "./effects.ts";
|
|
19
|
+
import { createCapabilityToken, type CapabilityToken } from "./capability.ts";
|
|
20
|
+
import { createEffectLedger, recordEffect, reversibilityOf, type EffectLedger } from "./effects.ts";
|
|
34
21
|
import {
|
|
35
22
|
DryRunWriteIsolationError,
|
|
36
23
|
isDryRun,
|
|
@@ -202,17 +189,15 @@ export interface FxSearchOptions {
|
|
|
202
189
|
* Implementations must be plain objects so tests can replace `fx` wholesale.
|
|
203
190
|
*/
|
|
204
191
|
export interface Fx {
|
|
205
|
-
/**
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
store(
|
|
214
|
-
ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl,
|
|
215
|
-
): FxStoreHandle;
|
|
192
|
+
/**
|
|
193
|
+
* Open a store handle for `ref` (capability checked on each op).
|
|
194
|
+
*
|
|
195
|
+
* When a {@link CreateFxOptions.storeRuntime} is bound and `ref` is a
|
|
196
|
+
* registered store declaration, returns the driver-backed handle.
|
|
197
|
+
*
|
|
198
|
+
* @param ref - Store resource ref, named handle, or store declaration
|
|
199
|
+
*/
|
|
200
|
+
store(ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl): FxStoreHandle;
|
|
216
201
|
/**
|
|
217
202
|
* Emit a signal (records `emit`).
|
|
218
203
|
*
|
|
@@ -251,11 +236,7 @@ export interface Fx {
|
|
|
251
236
|
* @param input - Prompt input
|
|
252
237
|
* @param opts - Model routing opts
|
|
253
238
|
*/
|
|
254
|
-
ask(
|
|
255
|
-
prompt: NamedRef,
|
|
256
|
-
input?: unknown,
|
|
257
|
-
opts?: FxAskOptions,
|
|
258
|
-
): Promise<Record<string, unknown>>;
|
|
239
|
+
ask(prompt: NamedRef, input?: unknown, opts?: FxAskOptions): Promise<Record<string, unknown>>;
|
|
259
240
|
/**
|
|
260
241
|
* Similarity search over an index/embed (records `read` on the embed ref).
|
|
261
242
|
*
|
|
@@ -263,21 +244,14 @@ export interface Fx {
|
|
|
263
244
|
* @param query - Query text or vector
|
|
264
245
|
* @param opts - Search options
|
|
265
246
|
*/
|
|
266
|
-
search(
|
|
267
|
-
embed: NamedRef,
|
|
268
|
-
query: unknown,
|
|
269
|
-
opts?: FxSearchOptions,
|
|
270
|
-
): Promise<unknown[]>;
|
|
247
|
+
search(embed: NamedRef, query: unknown, opts?: FxSearchOptions): Promise<unknown[]>;
|
|
271
248
|
/**
|
|
272
249
|
* Run a bounded AI agent (records `ask`).
|
|
273
250
|
*
|
|
274
251
|
* @param agent - Agent name or handle
|
|
275
252
|
* @param input - Agent input (`{ message }` or string)
|
|
276
253
|
*/
|
|
277
|
-
run(
|
|
278
|
-
agent: NamedRef,
|
|
279
|
-
input?: unknown,
|
|
280
|
-
): Promise<unknown>;
|
|
254
|
+
run(agent: NamedRef, input?: unknown): Promise<unknown>;
|
|
281
255
|
/**
|
|
282
256
|
* Stream model tokens (records `ask`). Returns an async iterable of chunks.
|
|
283
257
|
*
|
|
@@ -326,10 +300,7 @@ export interface Fx {
|
|
|
326
300
|
* Dispatch target for {@link Fx.call}. Wired by the app so untriggered
|
|
327
301
|
* flows execute through the same pipeline as triggered ones.
|
|
328
302
|
*/
|
|
329
|
-
export type FxCallHandler = (
|
|
330
|
-
name: string,
|
|
331
|
-
input: unknown,
|
|
332
|
-
) => Promise<unknown>;
|
|
303
|
+
export type FxCallHandler = (name: string, input: unknown) => Promise<unknown>;
|
|
333
304
|
|
|
334
305
|
/** Options for {@link createFx}. */
|
|
335
306
|
export interface CreateFxOptions {
|
|
@@ -352,9 +323,7 @@ export interface CreateFxOptions {
|
|
|
352
323
|
/** Secret name → value map for `fx.vault`. */
|
|
353
324
|
readonly secrets?: Readonly<Record<string, string>>;
|
|
354
325
|
/** Seed data for in-memory stores: ref → key → value. */
|
|
355
|
-
readonly storeData?: Readonly<
|
|
356
|
-
Record<string, Readonly<Record<string, unknown>>>
|
|
357
|
-
>;
|
|
326
|
+
readonly storeData?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
358
327
|
/** Optional log sink (defaults to no-op). */
|
|
359
328
|
readonly onLog?: (
|
|
360
329
|
level: "debug" | "info" | "warn" | "error",
|
|
@@ -435,9 +404,7 @@ export function createFx(options: CreateFxOptions): Fx {
|
|
|
435
404
|
*/
|
|
436
405
|
export function createFxContext(options: CreateFxOptions): FxContext {
|
|
437
406
|
const ledger = options.ledger ?? createEffectLedger();
|
|
438
|
-
const capability =
|
|
439
|
-
options.capability ??
|
|
440
|
-
createCapabilityToken(options.flow, options.effects);
|
|
407
|
+
const capability = options.capability ?? createCapabilityToken(options.flow, options.effects);
|
|
441
408
|
const now = options.now ?? (() => Date.now());
|
|
442
409
|
const secrets = options.secrets ?? {};
|
|
443
410
|
const onLog = options.onLog;
|
|
@@ -499,15 +466,12 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
499
466
|
select(): Promise<unknown[]> {
|
|
500
467
|
return gated("read", ref, () => {
|
|
501
468
|
const values = [...table().values()];
|
|
502
|
-
return isDryRun()
|
|
503
|
-
? values.map((v) => structuredClone(v))
|
|
504
|
-
: values;
|
|
469
|
+
return isDryRun() ? values.map((v) => structuredClone(v)) : values;
|
|
505
470
|
});
|
|
506
471
|
},
|
|
507
472
|
insert(row: Record<string, unknown>): Promise<{ id: string }> {
|
|
508
473
|
return gated("write", ref, () => {
|
|
509
|
-
const id =
|
|
510
|
-
typeof row.id === "string" ? row.id : crypto.randomUUID();
|
|
474
|
+
const id = typeof row.id === "string" ? row.id : crypto.randomUUID();
|
|
511
475
|
table().set(id, { ...row, id });
|
|
512
476
|
return { id };
|
|
513
477
|
});
|
|
@@ -532,10 +496,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
532
496
|
* @param decl - Store declaration
|
|
533
497
|
* @param open - Opens (and caches) the runtime handle
|
|
534
498
|
*/
|
|
535
|
-
function gatedSqlHandle(
|
|
536
|
-
decl: StoreDecl,
|
|
537
|
-
open: () => Promise<SqlStoreHandle>,
|
|
538
|
-
): SqlStoreHandle {
|
|
499
|
+
function gatedSqlHandle(decl: StoreDecl, open: () => Promise<SqlStoreHandle>): SqlStoreHandle {
|
|
539
500
|
const ref = decl.ref as `sql:${string}`;
|
|
540
501
|
let cached: SqlStoreHandle | undefined;
|
|
541
502
|
const ensure = async (): Promise<SqlStoreHandle> => {
|
|
@@ -684,9 +645,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
684
645
|
} as SqlStoreHandle;
|
|
685
646
|
}
|
|
686
647
|
|
|
687
|
-
function storeHandle(
|
|
688
|
-
ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl,
|
|
689
|
-
): FxStoreHandle {
|
|
648
|
+
function storeHandle(ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl): FxStoreHandle {
|
|
690
649
|
const runtime = options.storeRuntime;
|
|
691
650
|
if (runtime && typeof ref === "object" && ref !== null && "facet" in ref) {
|
|
692
651
|
const decl = ref;
|
|
@@ -714,8 +673,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
714
673
|
get(_t, prop) {
|
|
715
674
|
if (prop === "ref") return baseRef;
|
|
716
675
|
if (prop === "then") return undefined;
|
|
717
|
-
const isRead =
|
|
718
|
-
prop === "get" || prop === "search" || prop === "list";
|
|
676
|
+
const isRead = prop === "get" || prop === "search" || prop === "list";
|
|
719
677
|
return (...args: unknown[]) =>
|
|
720
678
|
gated(isRead ? "read" : "write", baseRef, async () => {
|
|
721
679
|
if (!isRead && isDryRun()) {
|
|
@@ -724,18 +682,14 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
724
682
|
);
|
|
725
683
|
}
|
|
726
684
|
const h = await open();
|
|
727
|
-
const fn = (h as unknown as Record<string | symbol, unknown>)[
|
|
728
|
-
prop
|
|
729
|
-
];
|
|
685
|
+
const fn = (h as unknown as Record<string | symbol, unknown>)[prop];
|
|
730
686
|
if (typeof fn !== "function") return undefined;
|
|
731
687
|
return (fn as (...a: unknown[]) => unknown).apply(h, args);
|
|
732
688
|
});
|
|
733
689
|
},
|
|
734
690
|
});
|
|
735
691
|
}
|
|
736
|
-
return stubStoreHandle(
|
|
737
|
-
resolveStoreRef(ref as NamedRef | { readonly ref: ResourceRef }),
|
|
738
|
-
);
|
|
692
|
+
return stubStoreHandle(resolveStoreRef(ref as NamedRef | { readonly ref: ResourceRef }));
|
|
739
693
|
}
|
|
740
694
|
|
|
741
695
|
const clock: FxClock = {
|
|
@@ -768,11 +722,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
768
722
|
if (aiDisablesCache) return;
|
|
769
723
|
cacheStore.set(key, value);
|
|
770
724
|
},
|
|
771
|
-
async getOrSet<T>(
|
|
772
|
-
key: string,
|
|
773
|
-
_ttl: string,
|
|
774
|
-
produce: () => T | Promise<T>,
|
|
775
|
-
): Promise<T> {
|
|
725
|
+
async getOrSet<T>(key: string, _ttl: string, produce: () => T | Promise<T>): Promise<T> {
|
|
776
726
|
if (aiDisablesCache) return await produce();
|
|
777
727
|
if (cacheStore.has(key)) {
|
|
778
728
|
if (telemetry) telemetry.cacheHits += 1;
|
|
@@ -792,9 +742,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
792
742
|
const vault = options.vaultRuntime;
|
|
793
743
|
if (!vault) return { message, data };
|
|
794
744
|
const safeMessage = vault.redactString(message);
|
|
795
|
-
const safeData = data
|
|
796
|
-
? (vault.redact(data) as Record<string, unknown>)
|
|
797
|
-
: undefined;
|
|
745
|
+
const safeData = data ? (vault.redact(data) as Record<string, unknown>) : undefined;
|
|
798
746
|
return { message: safeMessage, data: safeData };
|
|
799
747
|
}
|
|
800
748
|
|
|
@@ -49,12 +49,9 @@ describe("hook timing", () => {
|
|
|
49
49
|
|
|
50
50
|
test("registry tags hooks at plug time", async () => {
|
|
51
51
|
const registry = createPluginRegistry();
|
|
52
|
-
const p = plugin("metered", { version: "1.0.0" }).hook(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
await Bun.sleep(1);
|
|
56
|
-
},
|
|
57
|
-
);
|
|
52
|
+
const p = plugin("metered", { version: "1.0.0" }).hook("onRequest", async () => {
|
|
53
|
+
await Bun.sleep(1);
|
|
54
|
+
});
|
|
58
55
|
applyPlugin(registry, p, appPluginScope);
|
|
59
56
|
const hooks = registry.hooksAt("app", undefined, "x");
|
|
60
57
|
const ctx: InvocationContext = {
|
|
@@ -132,10 +132,7 @@ export function resetHookCosts(): void {
|
|
|
132
132
|
filled = 0;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function summarize(
|
|
136
|
-
pluginId: string,
|
|
137
|
-
mine: readonly HookCostSample[],
|
|
138
|
-
): HookCostSummary {
|
|
135
|
+
function summarize(pluginId: string, mine: readonly HookCostSample[]): HookCostSummary {
|
|
139
136
|
if (mine.length === 0) {
|
|
140
137
|
return {
|
|
141
138
|
pluginId,
|
|
@@ -149,18 +146,15 @@ function summarize(
|
|
|
149
146
|
}
|
|
150
147
|
const durations = mine.map((s) => s.durationMs).sort((a, b) => a - b);
|
|
151
148
|
const sum = durations.reduce((a, b) => a + b, 0);
|
|
152
|
-
const byStageAcc: Partial<
|
|
153
|
-
Record<HookStage, { count: number; total: number }>
|
|
154
|
-
> = {};
|
|
149
|
+
const byStageAcc: Partial<Record<HookStage, { count: number; total: number }>> = {};
|
|
155
150
|
for (const s of mine) {
|
|
156
151
|
const cur = byStageAcc[s.stage] ?? { count: 0, total: 0 };
|
|
157
152
|
cur.count++;
|
|
158
153
|
cur.total += s.durationMs;
|
|
159
154
|
byStageAcc[s.stage] = cur;
|
|
160
155
|
}
|
|
161
|
-
const byStage: Partial<
|
|
162
|
-
|
|
163
|
-
> = {};
|
|
156
|
+
const byStage: Partial<Record<HookStage, { readonly count: number; readonly meanMs: number }>> =
|
|
157
|
+
{};
|
|
164
158
|
for (const [stage, acc] of Object.entries(byStageAcc) as Array<
|
|
165
159
|
[HookStage, { count: number; total: number }]
|
|
166
160
|
>) {
|
|
@@ -182,9 +176,6 @@ function summarize(
|
|
|
182
176
|
|
|
183
177
|
function percentile(sorted: readonly number[], p: number): number {
|
|
184
178
|
if (sorted.length === 0) return 0;
|
|
185
|
-
const idx = Math.min(
|
|
186
|
-
sorted.length - 1,
|
|
187
|
-
Math.max(0, Math.ceil(p * sorted.length) - 1),
|
|
188
|
-
);
|
|
179
|
+
const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil(p * sorted.length) - 1));
|
|
189
180
|
return sorted[idx]!;
|
|
190
181
|
}
|
package/src/kernel/hooks.test.ts
CHANGED
|
@@ -26,11 +26,9 @@ describe("hooks — order and composition", () => {
|
|
|
26
26
|
|
|
27
27
|
test("mergeHooks is app → unit → flow, registration order within", () => {
|
|
28
28
|
const order: string[] = [];
|
|
29
|
-
const mark =
|
|
30
|
-
(label
|
|
31
|
-
|
|
32
|
-
order.push(label);
|
|
33
|
-
};
|
|
29
|
+
const mark = (label: string) => () => {
|
|
30
|
+
order.push(label);
|
|
31
|
+
};
|
|
34
32
|
|
|
35
33
|
const merged = mergeHooks(
|
|
36
34
|
{ onRequest: [mark("app1"), mark("app2")] },
|
|
@@ -66,11 +64,13 @@ describe("hooks — order and composition", () => {
|
|
|
66
64
|
order.push("handler");
|
|
67
65
|
return { ok: true };
|
|
68
66
|
},
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
})
|
|
68
|
+
.hook("beforeHandle", () => {
|
|
69
|
+
order.push("flow:beforeHandle");
|
|
70
|
+
})
|
|
71
|
+
.hook("afterHandle", () => {
|
|
72
|
+
order.push("flow:afterHandle");
|
|
73
|
+
});
|
|
74
74
|
|
|
75
75
|
on(http.get("/ordered"), f);
|
|
76
76
|
|