okengine 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +91 -0
- package/README.md +327 -0
- package/docs/spec/complete-example.md +1188 -0
- package/docs/spec/console.md +739 -0
- package/docs/spec/four-applications.md +1188 -0
- package/docs/spec/unified-theory.md +489 -0
- package/package.json +152 -0
- package/spec/manifest.v1.schema.json +624 -0
- package/src/auth/api-keys.ts +168 -0
- package/src/auth/attenuation.ts +116 -0
- package/src/auth/auth.test.ts +273 -0
- package/src/auth/cross-plane.ts +98 -0
- package/src/auth/index.ts +112 -0
- package/src/auth/invites.ts +66 -0
- package/src/auth/invoke-as.ts +49 -0
- package/src/auth/operator.ts +178 -0
- package/src/auth/planes.ts +102 -0
- package/src/auth/plugin.ts +44 -0
- package/src/auth/roles.ts +84 -0
- package/src/auth/sessions.ts +418 -0
- package/src/auth/tables.ts +131 -0
- package/src/cli/args.ts +50 -0
- package/src/cli/branch.ts +75 -0
- package/src/cli/build.ts +86 -0
- package/src/cli/client-add.test.ts +140 -0
- package/src/cli/client-add.ts +164 -0
- package/src/cli/completion.test.ts +58 -0
- package/src/cli/completion.ts +296 -0
- package/src/cli/dev-app-runner.ts +77 -0
- package/src/cli/dev.test.ts +435 -0
- package/src/cli/dev.ts +594 -0
- package/src/cli/doc-drift.test.ts +146 -0
- package/src/cli/doc-drift.ts +397 -0
- package/src/cli/docker-cli.test.ts +221 -0
- package/src/cli/docker.ts +127 -0
- package/src/cli/doctor-diff-examples.ts +92 -0
- package/src/cli/doctor-diff.test.ts +91 -0
- package/src/cli/doctor-diff.ts +274 -0
- package/src/cli/doctor-pii.test.ts +98 -0
- package/src/cli/doctor-pii.ts +151 -0
- package/src/cli/doctor.test.ts +150 -0
- package/src/cli/doctor.ts +223 -0
- package/src/cli/eval.ts +122 -0
- package/src/cli/exit.ts +19 -0
- package/src/cli/gates-list.test.ts +47 -0
- package/src/cli/gates-list.ts +84 -0
- package/src/cli/images.ts +277 -0
- package/src/cli/index.ts +99 -0
- package/src/cli/json-out.test.ts +129 -0
- package/src/cli/load-config.ts +71 -0
- package/src/cli/mcp-from-console.ts +50 -0
- package/src/cli/privacy-erase.ts +73 -0
- package/src/cli/registry.ts +455 -0
- package/src/cli/safe-defaults.test.ts +92 -0
- package/src/cli/schema.ts +196 -0
- package/src/cli/stack.ts +82 -0
- package/src/cli/start.ts +106 -0
- package/src/cli/upgrade.ts +105 -0
- package/src/cli/vault-cmd.ts +140 -0
- package/src/client/budget-entry.ts +34 -0
- package/src/client/budget.test.ts +17 -0
- package/src/client/create.test.ts +159 -0
- package/src/client/create.ts +152 -0
- package/src/client/errors.ts +60 -0
- package/src/client/index.ts +35 -0
- package/src/client/notes-contract.test.ts +289 -0
- package/src/client/transport.test.ts +123 -0
- package/src/client/transport.ts +254 -0
- package/src/client/types.ts +282 -0
- package/src/compiler/aot.test.ts +248 -0
- package/src/compiler/aot.ts +182 -0
- package/src/compiler/differential.test.ts +241 -0
- package/src/compiler/dynamic.ts +54 -0
- package/src/compiler/effects-infer.ts +541 -0
- package/src/compiler/emit.ts +40 -0
- package/src/compiler/extract.test.ts +177 -0
- package/src/compiler/extract.ts +1368 -0
- package/src/compiler/fixtures/raw/raw-unannotated.ts +28 -0
- package/src/compiler/fixtures/skyport/oke.config.ts +24 -0
- package/src/compiler/fixtures/skyport/src/ai.ts +15 -0
- package/src/compiler/fixtures/skyport/src/app.ts +10 -0
- package/src/compiler/fixtures/skyport/src/channels.ts +6 -0
- package/src/compiler/fixtures/skyport/src/core.ts +3 -0
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +57 -0
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +11 -0
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +14 -0
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +20 -0
- package/src/compiler/fixtures/skyport/src/gates.ts +14 -0
- package/src/compiler/fixtures/skyport/src/journeys.ts +9 -0
- package/src/compiler/fixtures/skyport/src/schema.ts +3 -0
- package/src/compiler/fixtures/skyport/src/vault.ts +6 -0
- package/src/compiler/fixtures/skyport.expected.json +241 -0
- package/src/compiler/fixtures/triggers/five-triggers.ts +69 -0
- package/src/compiler/http-parse.ts +214 -0
- package/src/compiler/index.ts +67 -0
- package/src/compiler/response.ts +89 -0
- package/src/compiler/sucrose.ts +238 -0
- package/src/config/index.ts +167 -0
- package/src/console/budget.test.ts +73 -0
- package/src/console/index.ts +30 -0
- package/src/console/server/access.test.ts +370 -0
- package/src/console/server/access.ts +777 -0
- package/src/console/server/ai.test.ts +172 -0
- package/src/console/server/ai.ts +632 -0
- package/src/console/server/app.ts +294 -0
- package/src/console/server/auth-rate.test.ts +81 -0
- package/src/console/server/auth-rate.ts +72 -0
- package/src/console/server/bind.ts +25 -0
- package/src/console/server/channels.test.ts +179 -0
- package/src/console/server/channels.ts +469 -0
- package/src/console/server/claim.test.ts +66 -0
- package/src/console/server/claim.ts +134 -0
- package/src/console/server/clock.test.ts +239 -0
- package/src/console/server/clock.ts +390 -0
- package/src/console/server/console.test.ts +338 -0
- package/src/console/server/diff.test.ts +299 -0
- package/src/console/server/diff.ts +352 -0
- package/src/console/server/dry-run.audit.test.ts +118 -0
- package/src/console/server/flows-invoke.test.ts +148 -0
- package/src/console/server/flows.ts +3633 -0
- package/src/console/server/gates.test.ts +360 -0
- package/src/console/server/gates.ts +869 -0
- package/src/console/server/index.ts +141 -0
- package/src/console/server/live.test.ts +30 -0
- package/src/console/server/live.ts +109 -0
- package/src/console/server/plugin.ts +50 -0
- package/src/console/server/plugins.test.ts +131 -0
- package/src/console/server/plugins.ts +429 -0
- package/src/console/server/runs-pii.ts +98 -0
- package/src/console/server/security-headers.ts +97 -0
- package/src/console/server/security.gate.test.ts +286 -0
- package/src/console/server/serve.ts +319 -0
- package/src/console/server/signals.test.ts +88 -0
- package/src/console/server/signals.ts +282 -0
- package/src/console/server/state.ts +982 -0
- package/src/console/server/store.test.ts +233 -0
- package/src/console/server/store.ts +861 -0
- package/src/console/server/structural.ts +95 -0
- package/src/console/server/vault.test.ts +251 -0
- package/src/console/server/vault.ts +430 -0
- package/src/console/ui/access/AccessA11yView.tsx +237 -0
- package/src/console/ui/access/a11y.test.tsx +122 -0
- package/src/console/ui/access/acknowledgement.test.ts +13 -0
- package/src/console/ui/access/acknowledgement.ts +35 -0
- package/src/console/ui/access/blast-radius.test.ts +26 -0
- package/src/console/ui/access/blast-radius.ts +40 -0
- package/src/console/ui/access/confirmation.test.ts +38 -0
- package/src/console/ui/access/confirmation.ts +36 -0
- package/src/console/ui/access/fixture.ts +203 -0
- package/src/console/ui/access/grantable.test.ts +17 -0
- package/src/console/ui/access/grantable.ts +36 -0
- package/src/console/ui/access/hygiene.test.ts +12 -0
- package/src/console/ui/access/hygiene.ts +39 -0
- package/src/console/ui/access/index.ts +54 -0
- package/src/console/ui/access/provenance.test.ts +12 -0
- package/src/console/ui/access/provenance.ts +29 -0
- package/src/console/ui/access/search.test.ts +17 -0
- package/src/console/ui/access/search.ts +72 -0
- package/src/console/ui/access/types.ts +111 -0
- package/src/console/ui/ai/AiA11yView.tsx +265 -0
- package/src/console/ui/ai/a11y.test.tsx +99 -0
- package/src/console/ui/ai/findings.ts +41 -0
- package/src/console/ui/ai/fixture.ts +182 -0
- package/src/console/ui/ai/format.ts +90 -0
- package/src/console/ui/ai/group.test.ts +37 -0
- package/src/console/ui/ai/group.ts +88 -0
- package/src/console/ui/ai/index.ts +66 -0
- package/src/console/ui/ai/promotion.test.ts +77 -0
- package/src/console/ui/ai/promotion.ts +150 -0
- package/src/console/ui/ai/search.test.ts +40 -0
- package/src/console/ui/ai/search.ts +89 -0
- package/src/console/ui/ai/types.ts +139 -0
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +163 -0
- package/src/console/ui/architecture/a11y.test.tsx +97 -0
- package/src/console/ui/architecture/boundary.ts +42 -0
- package/src/console/ui/architecture/declared.ts +165 -0
- package/src/console/ui/architecture/fixture.ts +74 -0
- package/src/console/ui/architecture/index.ts +84 -0
- package/src/console/ui/architecture/layers.ts +64 -0
- package/src/console/ui/architecture/layout.ts +68 -0
- package/src/console/ui/architecture/pathologies.ts +260 -0
- package/src/console/ui/architecture/search.ts +145 -0
- package/src/console/ui/architecture/traffic.ts +102 -0
- package/src/console/ui/architecture/types.ts +144 -0
- package/src/console/ui/architecture/view.test.ts +165 -0
- package/src/console/ui/architecture/view.ts +516 -0
- package/src/console/ui/channels/ChannelsA11yView.tsx +180 -0
- package/src/console/ui/channels/a11y.test.tsx +96 -0
- package/src/console/ui/channels/confirmation.test.ts +37 -0
- package/src/console/ui/channels/confirmation.ts +27 -0
- package/src/console/ui/channels/fallback.test.ts +15 -0
- package/src/console/ui/channels/fallback.ts +20 -0
- package/src/console/ui/channels/findings.ts +38 -0
- package/src/console/ui/channels/fixture.ts +134 -0
- package/src/console/ui/channels/group.ts +25 -0
- package/src/console/ui/channels/index.ts +57 -0
- package/src/console/ui/channels/locale.test.ts +17 -0
- package/src/console/ui/channels/locale.ts +31 -0
- package/src/console/ui/channels/mask.test.ts +14 -0
- package/src/console/ui/channels/mask.ts +12 -0
- package/src/console/ui/channels/search.ts +58 -0
- package/src/console/ui/channels/taxonomy.test.ts +17 -0
- package/src/console/ui/channels/taxonomy.ts +49 -0
- package/src/console/ui/channels/types.ts +117 -0
- package/src/console/ui/clock/ClockA11yView.tsx +182 -0
- package/src/console/ui/clock/a11y.test.tsx +99 -0
- package/src/console/ui/clock/confirmation.test.ts +32 -0
- package/src/console/ui/clock/confirmation.ts +34 -0
- package/src/console/ui/clock/findings.ts +40 -0
- package/src/console/ui/clock/fixture.ts +111 -0
- package/src/console/ui/clock/health.test.ts +25 -0
- package/src/console/ui/clock/health.ts +61 -0
- package/src/console/ui/clock/index.ts +49 -0
- package/src/console/ui/clock/search.test.ts +39 -0
- package/src/console/ui/clock/search.ts +76 -0
- package/src/console/ui/clock/timeline.test.ts +44 -0
- package/src/console/ui/clock/timeline.ts +41 -0
- package/src/console/ui/clock/types.ts +78 -0
- package/src/console/ui/clock/waiting-on.test.ts +34 -0
- package/src/console/ui/clock/waiting-on.ts +83 -0
- package/src/console/ui/confirmation.unify.test.ts +92 -0
- package/src/console/ui/diff/DiffA11yView.tsx +85 -0
- package/src/console/ui/diff/a11y.test.tsx +99 -0
- package/src/console/ui/diff/fixture.ts +85 -0
- package/src/console/ui/diff/group.test.ts +58 -0
- package/src/console/ui/diff/group.ts +97 -0
- package/src/console/ui/diff/index.ts +38 -0
- package/src/console/ui/diff/search.test.ts +32 -0
- package/src/console/ui/diff/search.ts +75 -0
- package/src/console/ui/diff/summary.ts +74 -0
- package/src/console/ui/diff/types.ts +48 -0
- package/src/console/ui/dist/assets/index-B71Yl_SS.js +10 -0
- package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +64 -0
- package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +1 -0
- package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +1 -0
- package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +1 -0
- package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +1 -0
- package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +1 -0
- package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +45 -0
- package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +1 -0
- package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +1 -0
- package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +1 -0
- package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +1 -0
- package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +1 -0
- package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +1 -0
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +1 -0
- package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
- package/src/console/ui/dist/assets/style-Cnl7WLya.css +3 -0
- package/src/console/ui/dist/index.html +14 -0
- package/src/console/ui/flows/FlowsA11yView.tsx +155 -0
- package/src/console/ui/flows/a11y.test.tsx +105 -0
- package/src/console/ui/flows/buffer.test.ts +91 -0
- package/src/console/ui/flows/buffer.ts +118 -0
- package/src/console/ui/flows/confirmation.ts +131 -0
- package/src/console/ui/flows/contract.test.ts +89 -0
- package/src/console/ui/flows/contract.ts +353 -0
- package/src/console/ui/flows/fixture.ts +81 -0
- package/src/console/ui/flows/graph.test.ts +101 -0
- package/src/console/ui/flows/graph.ts +549 -0
- package/src/console/ui/flows/index.ts +87 -0
- package/src/console/ui/flows/save-as-test.test.ts +47 -0
- package/src/console/ui/flows/save-as-test.ts +99 -0
- package/src/console/ui/flows/search.ts +255 -0
- package/src/console/ui/flows/tiers.ts +140 -0
- package/src/console/ui/gates/GatesA11yView.tsx +192 -0
- package/src/console/ui/gates/a11y.test.tsx +116 -0
- package/src/console/ui/gates/audit.test.ts +40 -0
- package/src/console/ui/gates/audit.ts +63 -0
- package/src/console/ui/gates/denial.test.ts +36 -0
- package/src/console/ui/gates/denial.ts +51 -0
- package/src/console/ui/gates/findings.ts +19 -0
- package/src/console/ui/gates/fixture.ts +189 -0
- package/src/console/ui/gates/group.test.ts +30 -0
- package/src/console/ui/gates/group.ts +102 -0
- package/src/console/ui/gates/index.ts +47 -0
- package/src/console/ui/gates/search.test.ts +49 -0
- package/src/console/ui/gates/search.ts +115 -0
- package/src/console/ui/gates/types.ts +121 -0
- package/src/console/ui/overview/OverviewA11yView.tsx +152 -0
- package/src/console/ui/overview/a11y.test.tsx +113 -0
- package/src/console/ui/overview/busiest.ts +26 -0
- package/src/console/ui/overview/compose.ts +133 -0
- package/src/console/ui/overview/cost.test.ts +39 -0
- package/src/console/ui/overview/cost.ts +138 -0
- package/src/console/ui/overview/fixture.ts +161 -0
- package/src/console/ui/overview/golden.ts +57 -0
- package/src/console/ui/overview/index.ts +59 -0
- package/src/console/ui/overview/rank.test.ts +136 -0
- package/src/console/ui/overview/rank.ts +210 -0
- package/src/console/ui/overview/slo.test.ts +73 -0
- package/src/console/ui/overview/slo.ts +229 -0
- package/src/console/ui/overview/types.ts +121 -0
- package/src/console/ui/overview/verdict.ts +131 -0
- package/src/console/ui/plugins/PluginsA11yView.tsx +227 -0
- package/src/console/ui/plugins/a11y.test.tsx +97 -0
- package/src/console/ui/plugins/command.test.ts +22 -0
- package/src/console/ui/plugins/command.ts +27 -0
- package/src/console/ui/plugins/findings.ts +39 -0
- package/src/console/ui/plugins/fixture.ts +233 -0
- package/src/console/ui/plugins/group.test.ts +38 -0
- package/src/console/ui/plugins/group.ts +67 -0
- package/src/console/ui/plugins/index.ts +40 -0
- package/src/console/ui/plugins/search.ts +67 -0
- package/src/console/ui/plugins/types.ts +115 -0
- package/src/console/ui/runs/RunsA11yView.tsx +267 -0
- package/src/console/ui/runs/a11y.test.tsx +99 -0
- package/src/console/ui/runs/explain.test.ts +23 -0
- package/src/console/ui/runs/explain.ts +32 -0
- package/src/console/ui/runs/fixture.ts +189 -0
- package/src/console/ui/runs/group.test.ts +24 -0
- package/src/console/ui/runs/group.ts +85 -0
- package/src/console/ui/runs/histogram.test.ts +31 -0
- package/src/console/ui/runs/histogram.ts +85 -0
- package/src/console/ui/runs/index.ts +75 -0
- package/src/console/ui/runs/project.ts +122 -0
- package/src/console/ui/runs/query.test.ts +50 -0
- package/src/console/ui/runs/query.ts +283 -0
- package/src/console/ui/runs/search.test.ts +45 -0
- package/src/console/ui/runs/search.ts +141 -0
- package/src/console/ui/runs/trace-link.test.ts +30 -0
- package/src/console/ui/runs/trace-link.ts +99 -0
- package/src/console/ui/runs/types.ts +137 -0
- package/src/console/ui/shell/App.tsx +56 -0
- package/src/console/ui/shell/client.ts +1715 -0
- package/src/console/ui/shell/components/ui.tsx +110 -0
- package/src/console/ui/shell/index.html +12 -0
- package/src/console/ui/shell/layout/Shell.tsx +95 -0
- package/src/console/ui/shell/main.tsx +281 -0
- package/src/console/ui/shell/panels/Access.tsx +5 -0
- package/src/console/ui/shell/panels/Ai.tsx +5 -0
- package/src/console/ui/shell/panels/Architecture.tsx +5 -0
- package/src/console/ui/shell/panels/Channels.tsx +5 -0
- package/src/console/ui/shell/panels/Clock.tsx +5 -0
- package/src/console/ui/shell/panels/Diff.tsx +5 -0
- package/src/console/ui/shell/panels/Flows.tsx +5 -0
- package/src/console/ui/shell/panels/Gates.tsx +5 -0
- package/src/console/ui/shell/panels/Overview.tsx +6 -0
- package/src/console/ui/shell/panels/Plugins.tsx +5 -0
- package/src/console/ui/shell/panels/Runs.tsx +5 -0
- package/src/console/ui/shell/panels/Signals.tsx +5 -0
- package/src/console/ui/shell/panels/Store.tsx +5 -0
- package/src/console/ui/shell/panels/Traces.tsx +5 -0
- package/src/console/ui/shell/panels/Vault.tsx +5 -0
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +813 -0
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +563 -0
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +377 -0
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +454 -0
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +479 -0
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +275 -0
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +301 -0
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +350 -0
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +502 -0
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +482 -0
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +428 -0
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +413 -0
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +649 -0
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +840 -0
- package/src/console/ui/shell/panels/store/StorePanel.tsx +787 -0
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +539 -0
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +449 -0
- package/src/console/ui/shell/plugin/Sandbox.tsx +29 -0
- package/src/console/ui/shell/setup/Wizard.tsx +189 -0
- package/src/console/ui/shell/styles.css +75 -0
- package/src/console/ui/signals/SignalsA11yView.tsx +276 -0
- package/src/console/ui/signals/a11y.test.tsx +99 -0
- package/src/console/ui/signals/confirmation.test.ts +39 -0
- package/src/console/ui/signals/confirmation.ts +63 -0
- package/src/console/ui/signals/dry-run.test.ts +18 -0
- package/src/console/ui/signals/dry-run.ts +36 -0
- package/src/console/ui/signals/durable.test.ts +22 -0
- package/src/console/ui/signals/durable.ts +41 -0
- package/src/console/ui/signals/findings.ts +33 -0
- package/src/console/ui/signals/fixture.ts +242 -0
- package/src/console/ui/signals/group.test.ts +32 -0
- package/src/console/ui/signals/group.ts +49 -0
- package/src/console/ui/signals/index.ts +52 -0
- package/src/console/ui/signals/monitor.test.ts +30 -0
- package/src/console/ui/signals/monitor.ts +79 -0
- package/src/console/ui/signals/schema-form.test.ts +34 -0
- package/src/console/ui/signals/schema-form.ts +112 -0
- package/src/console/ui/signals/search.ts +102 -0
- package/src/console/ui/signals/types.ts +71 -0
- package/src/console/ui/store/StoreA11yView.tsx +199 -0
- package/src/console/ui/store/a11y.test.tsx +99 -0
- package/src/console/ui/store/cache-view.test.ts +13 -0
- package/src/console/ui/store/cache-view.ts +36 -0
- package/src/console/ui/store/confirmation.test.ts +38 -0
- package/src/console/ui/store/confirmation.ts +55 -0
- package/src/console/ui/store/dry-run.test.ts +15 -0
- package/src/console/ui/store/dry-run.ts +29 -0
- package/src/console/ui/store/fixture.ts +163 -0
- package/src/console/ui/store/group.test.ts +21 -0
- package/src/console/ui/store/group.ts +41 -0
- package/src/console/ui/store/index.ts +40 -0
- package/src/console/ui/store/search.ts +78 -0
- package/src/console/ui/store/types.ts +65 -0
- package/src/console/ui/store/will-not-fire.test.ts +19 -0
- package/src/console/ui/store/will-not-fire.ts +40 -0
- package/src/console/ui/traces/TracesA11yView.tsx +200 -0
- package/src/console/ui/traces/a11y.test.tsx +97 -0
- package/src/console/ui/traces/chain.test.ts +61 -0
- package/src/console/ui/traces/chain.ts +144 -0
- package/src/console/ui/traces/critical-path.test.ts +24 -0
- package/src/console/ui/traces/critical-path.ts +59 -0
- package/src/console/ui/traces/filter.test.ts +78 -0
- package/src/console/ui/traces/filter.ts +112 -0
- package/src/console/ui/traces/fixture.ts +126 -0
- package/src/console/ui/traces/fold.test.ts +67 -0
- package/src/console/ui/traces/fold.ts +170 -0
- package/src/console/ui/traces/index.ts +64 -0
- package/src/console/ui/traces/mini.ts +65 -0
- package/src/console/ui/traces/replay.test.ts +24 -0
- package/src/console/ui/traces/replay.ts +35 -0
- package/src/console/ui/traces/sampling.test.ts +26 -0
- package/src/console/ui/traces/sampling.ts +66 -0
- package/src/console/ui/traces/search.ts +148 -0
- package/src/console/ui/traces/tier.ts +72 -0
- package/src/console/ui/traces/types.ts +125 -0
- package/src/console/ui/tsconfig.json +20 -0
- package/src/console/ui/vault/VaultA11yView.tsx +177 -0
- package/src/console/ui/vault/a11y.test.tsx +97 -0
- package/src/console/ui/vault/blast-radius.test.ts +35 -0
- package/src/console/ui/vault/blast-radius.ts +55 -0
- package/src/console/ui/vault/confirmation.test.ts +41 -0
- package/src/console/ui/vault/confirmation.ts +39 -0
- package/src/console/ui/vault/dormant.test.ts +37 -0
- package/src/console/ui/vault/dormant.ts +28 -0
- package/src/console/ui/vault/export-safe.test.ts +30 -0
- package/src/console/ui/vault/export-safe.ts +65 -0
- package/src/console/ui/vault/fixture.ts +75 -0
- package/src/console/ui/vault/group.test.ts +25 -0
- package/src/console/ui/vault/group.ts +50 -0
- package/src/console/ui/vault/index.ts +45 -0
- package/src/console/ui/vault/search.ts +62 -0
- package/src/console/ui/vault/types.ts +57 -0
- package/src/console/ui/vite.config.ts +84 -0
- package/src/console/xss.gate.test.ts +118 -0
- package/src/docker/compose.ts +226 -0
- package/src/docker/credentials.ts +25 -0
- package/src/docker/derive.ts +83 -0
- package/src/docker/docker.test.ts +185 -0
- package/src/docker/dockerfile.integration.test.ts +170 -0
- package/src/docker/dockerfile.ts +39 -0
- package/src/docker/helpers.ts +103 -0
- package/src/docker/index.ts +52 -0
- package/src/docker/pin.ts +90 -0
- package/src/docker/recipes/index.ts +33 -0
- package/src/docker/recipes/postgres.ts +18 -0
- package/src/docker/recipes/redis.ts +18 -0
- package/src/docker/stack.integration.test.ts +140 -0
- package/src/docker/stack.ts +62 -0
- package/src/docker/types.ts +134 -0
- package/src/drivers/ai-anthropic.ts +128 -0
- package/src/drivers/ai-mock.ts +82 -0
- package/src/drivers/ai-openai-compatible.ts +139 -0
- package/src/drivers/ai-providers.test.ts +163 -0
- package/src/drivers/ai-types.ts +83 -0
- package/src/drivers/bun-native-completeness.test.ts +155 -0
- package/src/drivers/channel-console.ts +118 -0
- package/src/drivers/channel-fcm.ts +96 -0
- package/src/drivers/channel-resend.ts +27 -0
- package/src/drivers/channel-smtp.ts +33 -0
- package/src/drivers/channel-types.ts +160 -0
- package/src/drivers/channel-unifonic.ts +79 -0
- package/src/drivers/channel-wa-cloud.ts +84 -0
- package/src/drivers/channel-webpush.ts +317 -0
- package/src/drivers/conformance.test.ts +89 -0
- package/src/drivers/conformance.ts +162 -0
- package/src/drivers/fs.ts +73 -0
- package/src/drivers/index.ts +194 -0
- package/src/drivers/kv-lua.ts +222 -0
- package/src/drivers/memory.ts +472 -0
- package/src/drivers/pgvector.ts +130 -0
- package/src/drivers/postgres.ts +221 -0
- package/src/drivers/redis.ts +254 -0
- package/src/drivers/s3.ts +129 -0
- package/src/drivers/signal-engine.ts +690 -0
- package/src/drivers/signal-memory.ts +27 -0
- package/src/drivers/signal-nats.ts +131 -0
- package/src/drivers/signal-postgres.ts +1089 -0
- package/src/drivers/signal-redis.ts +275 -0
- package/src/drivers/signal-types.ts +328 -0
- package/src/drivers/sqlite.ts +53 -0
- package/src/drivers/types.ts +334 -0
- package/src/drivers/vault-dotenv-parse.ts +56 -0
- package/src/drivers/vault-env.ts +101 -0
- package/src/drivers/vault-infisical.ts +61 -0
- package/src/drivers/vault-managed.ts +42 -0
- package/src/drivers/vault-memory.ts +38 -0
- package/src/drivers/vault-openbao.ts +80 -0
- package/src/drivers/vault-sops.ts +252 -0
- package/src/drivers/vault-types.ts +84 -0
- package/src/elements/ai/declare.ts +206 -0
- package/src/elements/ai/eval.ts +113 -0
- package/src/elements/ai/pii.ts +108 -0
- package/src/elements/ai/runtime.ts +540 -0
- package/src/elements/ai/schema.ts +194 -0
- package/src/elements/ai.test.ts +393 -0
- package/src/elements/ai.ts +56 -0
- package/src/elements/channel/consent.ts +81 -0
- package/src/elements/channel/costs.test.ts +62 -0
- package/src/elements/channel/costs.ts +130 -0
- package/src/elements/channel/declare.ts +141 -0
- package/src/elements/channel/email-auth.test.ts +47 -0
- package/src/elements/channel/email-auth.ts +109 -0
- package/src/elements/channel/locale.ts +97 -0
- package/src/elements/channel/mask.test.ts +19 -0
- package/src/elements/channel/mask.ts +60 -0
- package/src/elements/channel/mime.ts +23 -0
- package/src/elements/channel/outcomes.test.ts +40 -0
- package/src/elements/channel/outcomes.ts +126 -0
- package/src/elements/channel/receipts.ts +121 -0
- package/src/elements/channel/runtime.ts +500 -0
- package/src/elements/channel/suppression.ts +136 -0
- package/src/elements/channel.test.ts +232 -0
- package/src/elements/channel.ts +109 -0
- package/src/elements/clock/actions.ts +170 -0
- package/src/elements/clock/declare.ts +58 -0
- package/src/elements/clock/dst.ts +197 -0
- package/src/elements/clock/durable.ts +140 -0
- package/src/elements/clock/duration.ts +29 -0
- package/src/elements/clock/health.test.ts +103 -0
- package/src/elements/clock/health.ts +112 -0
- package/src/elements/clock/leader.ts +127 -0
- package/src/elements/clock/reconcile.ts +241 -0
- package/src/elements/clock/runtime.ts +243 -0
- package/src/elements/clock/schedule.ts +262 -0
- package/src/elements/clock/time-travel.ts +53 -0
- package/src/elements/clock.test.ts +365 -0
- package/src/elements/clock.ts +80 -0
- package/src/elements/gate/declare.ts +134 -0
- package/src/elements/gate/permissions.ts +104 -0
- package/src/elements/gate/runtime.ts +177 -0
- package/src/elements/gate/strategies.ts +388 -0
- package/src/elements/gate.test.ts +145 -0
- package/src/elements/gate.ts +41 -0
- package/src/elements/index.ts +169 -0
- package/src/elements/signal/chaos-child.ts +47 -0
- package/src/elements/signal/declare.ts +77 -0
- package/src/elements/signal/dry-run-replay.test.ts +95 -0
- package/src/elements/signal/dry-run-write-isolation.test.ts +94 -0
- package/src/elements/signal/reconcile.test.ts +23 -0
- package/src/elements/signal/reconcile.ts +122 -0
- package/src/elements/signal/runtime.ts +94 -0
- package/src/elements/signal.test.ts +457 -0
- package/src/elements/signal.ts +26 -0
- package/src/elements/store/cache.ts +197 -0
- package/src/elements/store/classify.ts +125 -0
- package/src/elements/store/declare.ts +200 -0
- package/src/elements/store/files-policy.test.ts +31 -0
- package/src/elements/store/files-policy.ts +70 -0
- package/src/elements/store/replica.ts +68 -0
- package/src/elements/store/runtime.ts +393 -0
- package/src/elements/store/sql-condition.ts +205 -0
- package/src/elements/store/sql-session.ts +579 -0
- package/src/elements/store/table.ts +282 -0
- package/src/elements/store.test.ts +370 -0
- package/src/elements/store.ts +99 -0
- package/src/elements/vault/declare.ts +143 -0
- package/src/elements/vault/fingerprint.ts +30 -0
- package/src/elements/vault/redact.ts +52 -0
- package/src/elements/vault/runtime.ts +461 -0
- package/src/elements/vault.test.ts +296 -0
- package/src/elements/vault.ts +44 -0
- package/src/index.ts +183 -0
- package/src/kernel/adopt-routes.ts +194 -0
- package/src/kernel/app.ts +1068 -0
- package/src/kernel/auth-resolve.ts +93 -0
- package/src/kernel/boot.test.ts +173 -0
- package/src/kernel/boot.ts +439 -0
- package/src/kernel/budget-entry.ts +55 -0
- package/src/kernel/budget.test.ts +19 -0
- package/src/kernel/call.test.ts +83 -0
- package/src/kernel/capability.ts +113 -0
- package/src/kernel/dry-run.test.ts +64 -0
- package/src/kernel/dry-run.ts +171 -0
- package/src/kernel/effects.test.ts +89 -0
- package/src/kernel/effects.ts +140 -0
- package/src/kernel/errors.registry.test.ts +39 -0
- package/src/kernel/errors.ts +225 -0
- package/src/kernel/flow.test.ts +154 -0
- package/src/kernel/flow.ts +290 -0
- package/src/kernel/fx.test.ts +245 -0
- package/src/kernel/fx.ts +996 -0
- package/src/kernel/hook-timing.test.ts +72 -0
- package/src/kernel/hook-timing.ts +190 -0
- package/src/kernel/hooks.test.ts +181 -0
- package/src/kernel/hooks.ts +275 -0
- package/src/kernel/index.ts +278 -0
- package/src/kernel/journal.ts +405 -0
- package/src/kernel/journey.ts +75 -0
- package/src/kernel/on.ts +74 -0
- package/src/kernel/pipeline.test.ts +349 -0
- package/src/kernel/pipeline.ts +245 -0
- package/src/kernel/plug.ts +82 -0
- package/src/kernel/plugin/capabilities.test.ts +84 -0
- package/src/kernel/plugin/conflicts.test.ts +106 -0
- package/src/kernel/plugin/decorate.test.ts +111 -0
- package/src/kernel/plugin/scoping.test.ts +138 -0
- package/src/kernel/plugin.ts +485 -0
- package/src/kernel/rate-limit.ts +25 -0
- package/src/kernel/registry.ts +398 -0
- package/src/kernel/router.test.ts +114 -0
- package/src/kernel/router.ts +556 -0
- package/src/kernel/routing-budget.test.ts +19 -0
- package/src/kernel/run-telemetry.ts +70 -0
- package/src/kernel/triggers.ts +324 -0
- package/src/kernel/unit.ts +88 -0
- package/src/manifest/diff.test.ts +866 -0
- package/src/manifest/diff.ts +1670 -0
- package/src/manifest/fixtures/base.manifest.json +112 -0
- package/src/manifest/fixtures/skyport.excerpt.json +51 -0
- package/src/manifest/fixtures/skyport.manifest.json +153 -0
- package/src/manifest/index.ts +27 -0
- package/src/manifest/types.ts +358 -0
- package/src/manifest/undeclared.test.ts +82 -0
- package/src/manifest/undeclared.ts +65 -0
- package/src/manifest/validate.test.ts +105 -0
- package/src/manifest/validate.ts +174 -0
- package/src/mcp/authorization.ts +340 -0
- package/src/mcp/confirmation.ts +174 -0
- package/src/mcp/data.ts +90 -0
- package/src/mcp/index.ts +80 -0
- package/src/mcp/injection.gate.test.ts +176 -0
- package/src/mcp/mcp.test.ts +348 -0
- package/src/mcp/protocol.ts +172 -0
- package/src/mcp/server.ts +283 -0
- package/src/mcp/session.ts +139 -0
- package/src/mcp/tools.ts +391 -0
- package/src/plugins/catalogue.test.ts +48 -0
- package/src/plugins/catalogue.ts +113 -0
- package/src/plugins/node-import-scan.test.ts +28 -0
- package/src/plugins/node-import-scan.ts +98 -0
- package/src/plugins/supply-chain.test.ts +48 -0
- package/src/plugins/supply-chain.ts +460 -0
- package/src/release/index.ts +30 -0
- package/src/release/limits.ts +20 -0
- package/src/release/measure.ts +443 -0
- package/src/release/publish.ts +56 -0
- package/src/runs/bench.test.ts +93 -0
- package/src/runs/collect.ts +144 -0
- package/src/runs/drivers/clickhouse.ts +108 -0
- package/src/runs/drivers/files.ts +201 -0
- package/src/runs/drivers/memory.ts +94 -0
- package/src/runs/drivers/postgres.ts +110 -0
- package/src/runs/duckdb.ts +99 -0
- package/src/runs/index.ts +82 -0
- package/src/runs/outlier.ts +180 -0
- package/src/runs/parquet.ts +210 -0
- package/src/runs/privacy.ts +49 -0
- package/src/runs/runs.test.ts +324 -0
- package/src/runs/runtime.ts +229 -0
- package/src/runs/shred.ts +243 -0
- package/src/runs/telemetry.ts +10 -0
- package/src/runs/types.ts +179 -0
- package/src/runtime/bun.ts +140 -0
- package/src/runtime/cold-start.bench.ts +20 -0
- package/src/runtime/index.ts +46 -0
- package/src/runtime/primitives.ts +242 -0
- package/src/runtime/security.test.ts +170 -0
- package/src/runtime/security.ts +168 -0
- package/src/runtime/serve.test.ts +223 -0
- package/src/runtime/types.ts +217 -0
- package/src/runtime/web-standard.ts +77 -0
- package/src/test/create-test-app.test.ts +161 -0
- package/src/test/create-test-app.ts +533 -0
- package/src/test/index.ts +21 -0
- package/src/test/provisions.integration.test.ts +174 -0
- package/src/upgrade/codemods.test.ts +58 -0
- package/src/upgrade/codemods.ts +83 -0
- package/src/validation/index.ts +23 -0
- package/src/validation/standard-schema.test.ts +96 -0
- package/src/validation/standard-schema.ts +316 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `flow` — the one species of backend behavior.
|
|
3
|
+
*
|
|
4
|
+
* A Flow is a typed contract (`in` / `out` / `errors`) plus a `do` body.
|
|
5
|
+
* Triggers are attached by {@link on}; a flow with no trigger is still a
|
|
6
|
+
* Flow and is callable via `fx.call` (unified-theory §4, Linkly ⑤).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { Effects, FlowPlane, Slo } from "../manifest/types.ts";
|
|
10
|
+
import type {
|
|
11
|
+
InferSchemaOutput,
|
|
12
|
+
SchemaInput,
|
|
13
|
+
} from "../validation/standard-schema.ts";
|
|
14
|
+
import type { FlowFailure } from "./errors.ts";
|
|
15
|
+
import type { Fx } from "./fx.ts";
|
|
16
|
+
import type { HookFn, HookStage } from "./hooks.ts";
|
|
17
|
+
import type { PluginDef } from "./plugin.ts";
|
|
18
|
+
import type { Trigger } from "./triggers.ts";
|
|
19
|
+
|
|
20
|
+
export type {
|
|
21
|
+
SchemaInput,
|
|
22
|
+
StandardSchemaV1,
|
|
23
|
+
} from "../validation/standard-schema.ts";
|
|
24
|
+
|
|
25
|
+
/** Result of a Standard Schema validate call (re-export shape). */
|
|
26
|
+
export type StandardSchemaResult<Output> =
|
|
27
|
+
| { readonly value: Output; readonly issues?: undefined }
|
|
28
|
+
| { readonly issues: ReadonlyArray<{ readonly message: string }> };
|
|
29
|
+
|
|
30
|
+
/** Map of declared flow-boundary error names to their schemas. */
|
|
31
|
+
export type FlowErrorMap = Readonly<Record<string, SchemaInput>>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Body of a Flow. Receives validated input and the `fx` door.
|
|
35
|
+
*
|
|
36
|
+
* @typeParam I - Input type
|
|
37
|
+
* @typeParam O - Output type
|
|
38
|
+
*/
|
|
39
|
+
export type FlowHandler<I = unknown, O = unknown> = (
|
|
40
|
+
input: I,
|
|
41
|
+
fx: Fx,
|
|
42
|
+
) => O | FlowFailure | Promise<O | FlowFailure>;
|
|
43
|
+
|
|
44
|
+
/** Options for {@link flow}. */
|
|
45
|
+
export interface FlowOptions<
|
|
46
|
+
I = unknown,
|
|
47
|
+
O = unknown,
|
|
48
|
+
E extends FlowErrorMap = FlowErrorMap,
|
|
49
|
+
> {
|
|
50
|
+
/** Optional stable name (used by `fx.call` and the Manifest). */
|
|
51
|
+
readonly name?: string;
|
|
52
|
+
/** Optional unit scope for unit-level hooks. */
|
|
53
|
+
readonly unit?: string;
|
|
54
|
+
/** Input schema (Standard Schema when present). */
|
|
55
|
+
readonly in?: SchemaInput;
|
|
56
|
+
/** Output schema (Standard Schema when present). */
|
|
57
|
+
readonly out?: SchemaInput;
|
|
58
|
+
/** Declared typed errors. */
|
|
59
|
+
readonly errors?: E;
|
|
60
|
+
/** Declared effects (capability token). Inferred later by AoT. */
|
|
61
|
+
readonly effects?: Effects;
|
|
62
|
+
/** Journal every effect call. */
|
|
63
|
+
readonly durable?: boolean;
|
|
64
|
+
/** Live-query / push result. */
|
|
65
|
+
readonly live?: boolean;
|
|
66
|
+
/** Cache TTL (`true` = default policy, or a duration string). */
|
|
67
|
+
readonly cache?: boolean | string;
|
|
68
|
+
/** Declared service-level objective. */
|
|
69
|
+
readonly slo?: Slo;
|
|
70
|
+
/**
|
|
71
|
+
* Plane — `user` (application) or `operator` (Console).
|
|
72
|
+
* Cross-plane invocation is a compile error.
|
|
73
|
+
*/
|
|
74
|
+
readonly plane?: FlowPlane;
|
|
75
|
+
/** The behavior. */
|
|
76
|
+
readonly do: FlowHandler<I, O>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Infer validated input from a flow options bag.
|
|
81
|
+
*
|
|
82
|
+
* @typeParam Opts - {@link FlowOptions} / call-site object
|
|
83
|
+
*/
|
|
84
|
+
export type InferFlowIn<Opts> = Opts extends { readonly in: infer S }
|
|
85
|
+
? InferSchemaOutput<S>
|
|
86
|
+
: Opts extends { readonly do: FlowHandler<infer I, infer _O> }
|
|
87
|
+
? I
|
|
88
|
+
: unknown;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Infer success output from a flow options bag.
|
|
92
|
+
*
|
|
93
|
+
* @typeParam Opts - {@link FlowOptions} / call-site object
|
|
94
|
+
*/
|
|
95
|
+
export type InferFlowOut<Opts> = Opts extends { readonly out: infer S }
|
|
96
|
+
? InferSchemaOutput<S>
|
|
97
|
+
: Opts extends { readonly do: FlowHandler<infer _I, infer O> }
|
|
98
|
+
? O
|
|
99
|
+
: unknown;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Infer the error schema map from a flow options bag.
|
|
103
|
+
*
|
|
104
|
+
* @typeParam Opts - {@link FlowOptions} / call-site object
|
|
105
|
+
*/
|
|
106
|
+
export type InferFlowErrors<Opts> = Opts extends {
|
|
107
|
+
readonly errors: infer E extends FlowErrorMap;
|
|
108
|
+
}
|
|
109
|
+
? E
|
|
110
|
+
: {};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Phantom brand for the bound trigger type parameter. Optional so
|
|
114
|
+
* `FlowDef<…, undefined>` remains assignable into `on()` before rebinding.
|
|
115
|
+
*/
|
|
116
|
+
declare const triggerPhantom: unique symbol;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* A Flow definition — one species, trigger-agnostic until {@link on} binds.
|
|
120
|
+
*
|
|
121
|
+
* @typeParam I - Input type
|
|
122
|
+
* @typeParam O - Output type
|
|
123
|
+
* @typeParam E - Error map (schemas)
|
|
124
|
+
* @typeParam D - Accumulated decoration types from `.plug()`
|
|
125
|
+
* @typeParam T - Bound trigger (set by {@link on}; `undefined` when untriggered)
|
|
126
|
+
*/
|
|
127
|
+
export interface FlowDef<
|
|
128
|
+
I = unknown,
|
|
129
|
+
O = unknown,
|
|
130
|
+
E extends FlowErrorMap = FlowErrorMap,
|
|
131
|
+
D extends Record<string, unknown> = {},
|
|
132
|
+
T extends Trigger | undefined = undefined,
|
|
133
|
+
> {
|
|
134
|
+
/** Brand for type guards. */
|
|
135
|
+
readonly [flowBrand]: true;
|
|
136
|
+
/**
|
|
137
|
+
* Type-level bound trigger (phantom). Not read at runtime — use
|
|
138
|
+
* `$trigger` / `triggers[0]` for the value.
|
|
139
|
+
*/
|
|
140
|
+
readonly [triggerPhantom]?: T;
|
|
141
|
+
/** Stable name (auto-assigned when omitted). */
|
|
142
|
+
readonly name: string;
|
|
143
|
+
/** Optional unit scope. */
|
|
144
|
+
readonly unit: string | undefined;
|
|
145
|
+
/** Input schema. */
|
|
146
|
+
readonly in: SchemaInput | undefined;
|
|
147
|
+
/** Output schema. */
|
|
148
|
+
readonly out: SchemaInput | undefined;
|
|
149
|
+
/** Declared errors. */
|
|
150
|
+
readonly errors: E | undefined;
|
|
151
|
+
/** Declared effects. */
|
|
152
|
+
readonly effects: Effects | undefined;
|
|
153
|
+
/** Durability flag. */
|
|
154
|
+
readonly durable: boolean;
|
|
155
|
+
/** Live flag. */
|
|
156
|
+
readonly live: boolean;
|
|
157
|
+
/** Cache option. */
|
|
158
|
+
readonly cache: boolean | string | undefined;
|
|
159
|
+
/** SLO. */
|
|
160
|
+
readonly slo: Slo | undefined;
|
|
161
|
+
/** Plane (user vs operator). */
|
|
162
|
+
readonly plane: FlowPlane | undefined;
|
|
163
|
+
/** Handler body. */
|
|
164
|
+
readonly do: FlowHandler<I, O>;
|
|
165
|
+
/** Triggers bound via {@link on} (zero or more). */
|
|
166
|
+
readonly triggers: readonly Trigger[];
|
|
167
|
+
/**
|
|
168
|
+
* First bound trigger at runtime (`undefined` when untriggered).
|
|
169
|
+
* The precise trigger literal lives in the {@link triggerPhantom} type param.
|
|
170
|
+
*/
|
|
171
|
+
readonly $trigger: Trigger | undefined;
|
|
172
|
+
/** Flow-scoped hooks, registration order. */
|
|
173
|
+
readonly hooks: Readonly<Partial<Record<HookStage, readonly HookFn[]>>>;
|
|
174
|
+
/**
|
|
175
|
+
* Plugins queued via {@link FlowDef.plug} until an app registry adopts them.
|
|
176
|
+
* @internal
|
|
177
|
+
*/
|
|
178
|
+
readonly pendingPlugins: readonly PluginDef[];
|
|
179
|
+
/** Accumulated decoration types from `.plug()` (type-level only). */
|
|
180
|
+
readonly decorations?: D;
|
|
181
|
+
/**
|
|
182
|
+
* Register a flow-scoped hook (registration order, no priority numbers).
|
|
183
|
+
*
|
|
184
|
+
* @param stage - Pipeline stage
|
|
185
|
+
* @param fn - Hook function
|
|
186
|
+
*/
|
|
187
|
+
hook(stage: HookStage, fn: HookFn): FlowDef<I, O, E, D, T>;
|
|
188
|
+
/**
|
|
189
|
+
* Attach a plugin to this flow only. Scope is the attachment point.
|
|
190
|
+
*
|
|
191
|
+
* @param pluginDef - Plugin from {@link plugin}
|
|
192
|
+
*/
|
|
193
|
+
plug<P extends PluginDef>(
|
|
194
|
+
pluginDef: P,
|
|
195
|
+
): FlowDef<
|
|
196
|
+
I,
|
|
197
|
+
O,
|
|
198
|
+
E,
|
|
199
|
+
D & (P extends PluginDef<infer PD> ? PD : Record<string, never>),
|
|
200
|
+
T
|
|
201
|
+
>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** Unique brand symbol for {@link FlowDef}. */
|
|
205
|
+
export const flowBrand: unique symbol = Symbol("oke.flow");
|
|
206
|
+
|
|
207
|
+
let flowSeq = 0;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Define a Flow — the one species of backend behavior.
|
|
211
|
+
*
|
|
212
|
+
* Input / output types are inferred from Standard Schema `in` / `out` when
|
|
213
|
+
* present; otherwise from the `do` handler signature.
|
|
214
|
+
*
|
|
215
|
+
* @param options - Contract and handler
|
|
216
|
+
*/
|
|
217
|
+
export function flow<Opts extends FlowOptions<any, any, any>>(
|
|
218
|
+
options: Opts,
|
|
219
|
+
): FlowDef<InferFlowIn<Opts>, InferFlowOut<Opts>, InferFlowErrors<Opts>> {
|
|
220
|
+
const name = options.name ?? `flow_${++flowSeq}`;
|
|
221
|
+
const triggers: Trigger[] = [];
|
|
222
|
+
const hooks: Partial<Record<HookStage, HookFn[]>> = {};
|
|
223
|
+
const pendingPlugins: PluginDef[] = [];
|
|
224
|
+
|
|
225
|
+
const def: FlowDef<
|
|
226
|
+
InferFlowIn<Opts>,
|
|
227
|
+
InferFlowOut<Opts>,
|
|
228
|
+
InferFlowErrors<Opts>
|
|
229
|
+
> = {
|
|
230
|
+
[flowBrand]: true,
|
|
231
|
+
name,
|
|
232
|
+
unit: options.unit,
|
|
233
|
+
in: options.in,
|
|
234
|
+
out: options.out,
|
|
235
|
+
errors: (options.errors ?? undefined) as InferFlowErrors<Opts> | undefined,
|
|
236
|
+
effects: options.effects,
|
|
237
|
+
durable: options.durable ?? false,
|
|
238
|
+
live: options.live ?? false,
|
|
239
|
+
cache: options.cache,
|
|
240
|
+
slo: options.slo,
|
|
241
|
+
plane: options.plane,
|
|
242
|
+
do: options.do as FlowHandler<InferFlowIn<Opts>, InferFlowOut<Opts>>,
|
|
243
|
+
triggers,
|
|
244
|
+
$trigger: undefined,
|
|
245
|
+
hooks,
|
|
246
|
+
pendingPlugins,
|
|
247
|
+
hook(stage, fn) {
|
|
248
|
+
const list = hooks[stage] ?? (hooks[stage] = []);
|
|
249
|
+
list.push(fn);
|
|
250
|
+
return def;
|
|
251
|
+
},
|
|
252
|
+
plug(pluginDef) {
|
|
253
|
+
pendingPlugins.push(pluginDef);
|
|
254
|
+
// Decorations accumulate on the interface; runtime object is unchanged.
|
|
255
|
+
return def as never;
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
return def;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Erased flow type for heterogenous registries (`on` bindings, app index).
|
|
264
|
+
* Individual flows keep their `I`/`O` at the declaration site; the registry
|
|
265
|
+
* cannot preserve every specialization without an erased carrier type.
|
|
266
|
+
*/
|
|
267
|
+
export type AnyFlowDef = FlowDef<any, any, any, any, any>;
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Type guard for {@link FlowDef}.
|
|
271
|
+
*
|
|
272
|
+
* @param value - Unknown value
|
|
273
|
+
*/
|
|
274
|
+
export function isFlow(value: unknown): value is AnyFlowDef {
|
|
275
|
+
return (
|
|
276
|
+
typeof value === "object" &&
|
|
277
|
+
value !== null &&
|
|
278
|
+
flowBrand in value &&
|
|
279
|
+
(value as AnyFlowDef)[flowBrand] === true
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Reset the auto-name sequence (tests only).
|
|
285
|
+
*
|
|
286
|
+
* @internal
|
|
287
|
+
*/
|
|
288
|
+
export function resetFlowSeq(): void {
|
|
289
|
+
flowSeq = 0;
|
|
290
|
+
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { createCapabilityToken } from "./capability.ts";
|
|
3
|
+
import { createEffectLedger, reversibilityOf } from "./effects.ts";
|
|
4
|
+
import {
|
|
5
|
+
fail,
|
|
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";
|
|
17
|
+
|
|
18
|
+
/** Narrow stub handle for tests that exercise the in-memory store. */
|
|
19
|
+
function stub(fx: Fx, ref: string): FxStubStoreHandle {
|
|
20
|
+
return fx.store(ref) as FxStubStoreHandle;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("fx — capability enforcement", () => {
|
|
24
|
+
test("undeclared store read throws OKE1001 with flow, resource, and fix", async () => {
|
|
25
|
+
const { fx } = createFxContext({
|
|
26
|
+
flow: "bookings.create",
|
|
27
|
+
effects: { reads: ["sql:bookings"] },
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
let err: unknown;
|
|
31
|
+
try {
|
|
32
|
+
await stub(fx, "sql:users").get("u1");
|
|
33
|
+
} catch (e) {
|
|
34
|
+
err = e;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
expect(err).toBeInstanceOf(OkeError);
|
|
38
|
+
const oke = err as OkeError;
|
|
39
|
+
expect(oke.code).toBe(1001);
|
|
40
|
+
expect(oke.causeText).toBe(
|
|
41
|
+
'Flow "bookings.create" reads "sql:users" without declaring it.',
|
|
42
|
+
);
|
|
43
|
+
expect(oke.fix).toBe(
|
|
44
|
+
'Add "sql:users" to this flow\'s effects.reads.',
|
|
45
|
+
);
|
|
46
|
+
expect(oke.docsUrl).toBe("https://oke.dev/e/1001");
|
|
47
|
+
expect(oke.message).toBe(
|
|
48
|
+
formatOkeMessage(1001, oke.causeText, oke.fix, oke.docsUrl),
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test("declared store read succeeds", async () => {
|
|
53
|
+
const fx = createFx({
|
|
54
|
+
flow: "bookings.create",
|
|
55
|
+
effects: { reads: ["sql:bookings"] },
|
|
56
|
+
storeData: { "sql:bookings": { b1: { id: "b1" } } },
|
|
57
|
+
});
|
|
58
|
+
await expect(stub(fx, "sql:bookings").get("b1")).resolves.toEqual({
|
|
59
|
+
id: "b1",
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe("fx — effect ledger", () => {
|
|
65
|
+
test("read, write, emit → exactly three ledger entries in order", async () => {
|
|
66
|
+
const ledger = createEffectLedger();
|
|
67
|
+
const fx = createFx({
|
|
68
|
+
flow: "bookings.create",
|
|
69
|
+
effects: {
|
|
70
|
+
reads: ["sql:bookings"],
|
|
71
|
+
writes: ["sql:bookings"],
|
|
72
|
+
emits: ["order-placed"],
|
|
73
|
+
},
|
|
74
|
+
ledger,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
await stub(fx, "sql:bookings").get("b1");
|
|
78
|
+
await stub(fx, "sql:bookings").insert({ seats: 2 });
|
|
79
|
+
await fx.emit("order-placed", { orderId: "o1" });
|
|
80
|
+
|
|
81
|
+
expect(ledger.entries).toHaveLength(3);
|
|
82
|
+
expect(ledger.entries.map((e) => e.kind)).toEqual([
|
|
83
|
+
"read",
|
|
84
|
+
"write",
|
|
85
|
+
"emit",
|
|
86
|
+
]);
|
|
87
|
+
expect(ledger.entries.map((e) => e.resource)).toEqual([
|
|
88
|
+
"sql:bookings",
|
|
89
|
+
"sql:bookings",
|
|
90
|
+
"order-placed",
|
|
91
|
+
]);
|
|
92
|
+
expect(ledger.entries.map((e) => e.reversibility)).toEqual([
|
|
93
|
+
"none",
|
|
94
|
+
"reversible",
|
|
95
|
+
"deferred",
|
|
96
|
+
]);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("all seven kinds receive the correct reversibility tier via fx", async () => {
|
|
100
|
+
const ledger = createEffectLedger();
|
|
101
|
+
const fx = createFx({
|
|
102
|
+
flow: "kitchen.sink",
|
|
103
|
+
effects: {
|
|
104
|
+
reads: ["sql:bookings"],
|
|
105
|
+
writes: ["sql:bookings"],
|
|
106
|
+
emits: ["order-placed"],
|
|
107
|
+
sends: ["order-confirmed"],
|
|
108
|
+
asks: ["triage@1"],
|
|
109
|
+
secrets: ["STRIPE_KEY"],
|
|
110
|
+
calls: ["payments.charge"],
|
|
111
|
+
},
|
|
112
|
+
ledger,
|
|
113
|
+
secrets: { STRIPE_KEY: "sk_test" },
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
await stub(fx, "sql:bookings").get("x");
|
|
117
|
+
await stub(fx, "sql:bookings").set("x", { ok: true });
|
|
118
|
+
await fx.emit("order-placed", {});
|
|
119
|
+
await fx.send("order-confirmed", { to: "u1" });
|
|
120
|
+
await fx.ask("triage@1", {});
|
|
121
|
+
expect(fx.vault("STRIPE_KEY")).toBe("sk_test");
|
|
122
|
+
await fx.call("payments.charge", {});
|
|
123
|
+
|
|
124
|
+
expect(ledger.entries).toHaveLength(7);
|
|
125
|
+
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
|
+
]);
|
|
135
|
+
for (const entry of ledger.entries) {
|
|
136
|
+
expect(entry.reversibility).toBe(reversibilityOf(entry.kind));
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("fx — wholesale swap", () => {
|
|
142
|
+
test("fx is swappable wholesale (plain object interface)", async () => {
|
|
143
|
+
const calls: string[] = [];
|
|
144
|
+
|
|
145
|
+
const fake: Fx = {
|
|
146
|
+
store() {
|
|
147
|
+
throw new Error("store must not be used");
|
|
148
|
+
},
|
|
149
|
+
async emit(signal) {
|
|
150
|
+
calls.push(`emit:${typeof signal === "string" ? signal : signal.name}`);
|
|
151
|
+
},
|
|
152
|
+
async call() {
|
|
153
|
+
return null;
|
|
154
|
+
},
|
|
155
|
+
clock: {
|
|
156
|
+
now: () => 0,
|
|
157
|
+
sleep: async () => undefined,
|
|
158
|
+
},
|
|
159
|
+
vault() {
|
|
160
|
+
return "";
|
|
161
|
+
},
|
|
162
|
+
cache: {
|
|
163
|
+
get: async () => undefined,
|
|
164
|
+
set: async () => undefined,
|
|
165
|
+
getOrSet: async (_k, _t, produce) => produce(),
|
|
166
|
+
},
|
|
167
|
+
async send() {
|
|
168
|
+
return { ok: true };
|
|
169
|
+
},
|
|
170
|
+
async ask() {
|
|
171
|
+
return {};
|
|
172
|
+
},
|
|
173
|
+
async search() {
|
|
174
|
+
return [];
|
|
175
|
+
},
|
|
176
|
+
async run() {
|
|
177
|
+
return {};
|
|
178
|
+
},
|
|
179
|
+
async *stream() {
|
|
180
|
+
/* empty */
|
|
181
|
+
},
|
|
182
|
+
log: {
|
|
183
|
+
debug() {},
|
|
184
|
+
info() {},
|
|
185
|
+
warn() {},
|
|
186
|
+
error() {},
|
|
187
|
+
},
|
|
188
|
+
t: (key) => key,
|
|
189
|
+
id: () => "fixed-id",
|
|
190
|
+
auth: { userId: "u1", scopes: new Set(["a"]) },
|
|
191
|
+
operator: { id: null },
|
|
192
|
+
tenant: { id: "t1" },
|
|
193
|
+
fail,
|
|
194
|
+
async step(_name, fn) {
|
|
195
|
+
return fn();
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Any code that accepts `Fx` can run against a total replacement.
|
|
200
|
+
async function runFlow(fx: Fx): Promise<string> {
|
|
201
|
+
await fx.emit("order-placed", { id: fx.id() });
|
|
202
|
+
return fx.t("hello");
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await expect(runFlow(fake)).resolves.toBe("hello");
|
|
206
|
+
expect(calls).toEqual(["emit:order-placed"]);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("errors — registry", () => {
|
|
211
|
+
test("OKE1042 is reserved with the §21 shape", () => {
|
|
212
|
+
const def = OKE_ERRORS.ORPHAN_EMIT;
|
|
213
|
+
expect(def.code).toBe(1042);
|
|
214
|
+
expect(lookupOkeError(1042)).toEqual(def);
|
|
215
|
+
const err = new OkeError(def, {
|
|
216
|
+
flow: "bookings.create",
|
|
217
|
+
resource: "order-placed",
|
|
218
|
+
});
|
|
219
|
+
expect(err.message).toContain("OKE1042");
|
|
220
|
+
expect(err.message).toContain("no subscriber");
|
|
221
|
+
expect(err.message).toContain("https://oke.dev/e/1042");
|
|
222
|
+
expect(err.message).toContain("→");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("fx.fail returns a value, not an exception", () => {
|
|
226
|
+
const fx = createFx({ flow: "x", effects: {} });
|
|
227
|
+
const result = fx.fail("FlightFull", { seatsLeft: 0 }, {
|
|
228
|
+
message: "full",
|
|
229
|
+
});
|
|
230
|
+
expect(result).toEqual({
|
|
231
|
+
data: null,
|
|
232
|
+
error: { code: "FlightFull", data: { seatsLeft: 0 }, message: "full" },
|
|
233
|
+
});
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("capability token allows only declared resources", () => {
|
|
237
|
+
const token = createCapabilityToken("f", {
|
|
238
|
+
reads: ["sql:a"],
|
|
239
|
+
emits: ["s"],
|
|
240
|
+
});
|
|
241
|
+
expect(token.allows("read", "sql:a")).toBe(true);
|
|
242
|
+
expect(token.allows("read", "sql:b")).toBe(false);
|
|
243
|
+
expect(() => token.assert("emit", "missing")).toThrow(OkeError);
|
|
244
|
+
});
|
|
245
|
+
});
|