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/runtime/index.ts
CHANGED
|
@@ -2,12 +2,7 @@
|
|
|
2
2
|
* Runtime adapters: Bun (primary) · Web Standards (Node / Deno / edge).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export {
|
|
6
|
-
createBunRuntime,
|
|
7
|
-
buildBunRoutes,
|
|
8
|
-
isBunNativePath,
|
|
9
|
-
type BunRuntime,
|
|
10
|
-
} from "./bun.ts";
|
|
5
|
+
export { createBunRuntime, buildBunRoutes, isBunNativePath, type BunRuntime } from "./bun.ts";
|
|
11
6
|
|
|
12
7
|
export {
|
|
13
8
|
createEnv,
|
|
@@ -44,8 +44,8 @@ export function createTimers(): RuntimeTimers {
|
|
|
44
44
|
export function createEnv(): RuntimeEnv {
|
|
45
45
|
return {
|
|
46
46
|
get(key) {
|
|
47
|
-
const bunEnv = (globalThis as { Bun?: { env?: Record<string, string | undefined> } })
|
|
48
|
-
|
|
47
|
+
const bunEnv = (globalThis as { Bun?: { env?: Record<string, string | undefined> } }).Bun
|
|
48
|
+
?.env;
|
|
49
49
|
if (bunEnv && key in bunEnv) return bunEnv[key];
|
|
50
50
|
const proc = (globalThis as { process?: { env?: Record<string, string | undefined> } })
|
|
51
51
|
.process?.env;
|
|
@@ -70,8 +70,9 @@ export function createEnv(): RuntimeEnv {
|
|
|
70
70
|
export function createFiles(): RuntimeFiles {
|
|
71
71
|
return {
|
|
72
72
|
async read(path) {
|
|
73
|
-
const bun = (
|
|
74
|
-
|
|
73
|
+
const bun = (
|
|
74
|
+
globalThis as { Bun?: { file?(p: string): { arrayBuffer(): Promise<ArrayBuffer> } } }
|
|
75
|
+
).Bun;
|
|
75
76
|
if (bun?.file) {
|
|
76
77
|
return new Uint8Array(await bun.file(path).arrayBuffer());
|
|
77
78
|
}
|
package/src/runtime/security.ts
CHANGED
|
@@ -10,12 +10,7 @@
|
|
|
10
10
|
import type { ServeOptions } from "./types.ts";
|
|
11
11
|
|
|
12
12
|
/** Loopback names always accepted alongside the listen hostname. */
|
|
13
|
-
const LOOPBACK_HOSTS: readonly string[] = [
|
|
14
|
-
"localhost",
|
|
15
|
-
"127.0.0.1",
|
|
16
|
-
"::1",
|
|
17
|
-
"[::1]",
|
|
18
|
-
];
|
|
13
|
+
const LOOPBACK_HOSTS: readonly string[] = ["localhost", "127.0.0.1", "::1", "[::1]"];
|
|
19
14
|
|
|
20
15
|
/**
|
|
21
16
|
* Build the effective allow-list: loopback + listen hostname + user extras.
|
|
@@ -76,10 +71,7 @@ export function normalizeHost(raw: string): string {
|
|
|
76
71
|
* @param host - Normalized host
|
|
77
72
|
* @param allowed - Allow-list
|
|
78
73
|
*/
|
|
79
|
-
export function isHostAllowed(
|
|
80
|
-
host: string,
|
|
81
|
-
allowed: ReadonlySet<string>,
|
|
82
|
-
): boolean {
|
|
74
|
+
export function isHostAllowed(host: string, allowed: ReadonlySet<string>): boolean {
|
|
83
75
|
if (host.length === 0) return false;
|
|
84
76
|
if (allowed.has(host)) return true;
|
|
85
77
|
// Bracketed IPv6 sibling
|
|
@@ -138,9 +130,7 @@ export function checkRequestSecurity(
|
|
|
138
130
|
/** 403 body for a failed Host / Origin check. */
|
|
139
131
|
export function forbiddenResponse(reason: "host" | "origin"): Response {
|
|
140
132
|
const message =
|
|
141
|
-
reason === "host"
|
|
142
|
-
? "Forbidden: unexpected Host header"
|
|
143
|
-
: "Forbidden: unexpected Origin header";
|
|
133
|
+
reason === "host" ? "Forbidden: unexpected Host header" : "Forbidden: unexpected Origin header";
|
|
144
134
|
return new Response(message, {
|
|
145
135
|
status: 403,
|
|
146
136
|
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
@@ -107,13 +107,10 @@ describe("Bun.serve — real HTTP", () => {
|
|
|
107
107
|
expect(await direct.text()).toContain("Host");
|
|
108
108
|
|
|
109
109
|
// On the wire — the DNS-rebinding shape (CVE-2025-66414 class).
|
|
110
|
-
const wire = await rawHttp(
|
|
111
|
-
|
|
112
|
-
"Host: attacker.com",
|
|
113
|
-
|
|
114
|
-
"",
|
|
115
|
-
"",
|
|
116
|
-
].join("\r\n"));
|
|
110
|
+
const wire = await rawHttp(
|
|
111
|
+
handle.port,
|
|
112
|
+
["GET /ping HTTP/1.1", "Host: attacker.com", "Connection: close", "", ""].join("\r\n"),
|
|
113
|
+
);
|
|
117
114
|
expect(wire).toContain("403");
|
|
118
115
|
expect(wire).toContain("Host");
|
|
119
116
|
});
|
package/src/runtime/types.ts
CHANGED
|
@@ -151,10 +151,7 @@ export interface RuntimeCrypto {
|
|
|
151
151
|
* @param password - Plaintext
|
|
152
152
|
* @param algorithm - Hash algorithm (Bun default `argon2id`)
|
|
153
153
|
*/
|
|
154
|
-
hashPassword(
|
|
155
|
-
password: string,
|
|
156
|
-
algorithm?: PasswordAlgorithm,
|
|
157
|
-
): Promise<string>;
|
|
154
|
+
hashPassword(password: string, algorithm?: PasswordAlgorithm): Promise<string>;
|
|
158
155
|
/**
|
|
159
156
|
* Verify a password against a hash from {@link RuntimeCrypto.hashPassword}.
|
|
160
157
|
*
|
|
@@ -13,12 +13,7 @@
|
|
|
13
13
|
* Host / Origin validation is identical to the Bun adapter (console §10.1).
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import {
|
|
17
|
-
createEnv,
|
|
18
|
-
createFiles,
|
|
19
|
-
createTimers,
|
|
20
|
-
createWebCrypto,
|
|
21
|
-
} from "./primitives.ts";
|
|
16
|
+
import { createEnv, createFiles, createTimers, createWebCrypto } from "./primitives.ts";
|
|
22
17
|
import { secureFetch } from "./security.ts";
|
|
23
18
|
import {
|
|
24
19
|
APP_PORT,
|
|
@@ -50,17 +45,10 @@ export function createWebStandardRuntime(): Runtime {
|
|
|
50
45
|
* @param app - Application
|
|
51
46
|
* @param options - Port/hostname metadata + `allowedHosts`
|
|
52
47
|
*/
|
|
53
|
-
function createFetchHandle(
|
|
54
|
-
app: FetchApp,
|
|
55
|
-
options?: ServeOptions,
|
|
56
|
-
): ServerHandle {
|
|
48
|
+
function createFetchHandle(app: FetchApp, options?: ServeOptions): ServerHandle {
|
|
57
49
|
const port = options?.port ?? APP_PORT;
|
|
58
50
|
const hostname = options?.hostname ?? "127.0.0.1";
|
|
59
|
-
const fetchHandler = secureFetch(
|
|
60
|
-
(req) => app.fetch(req),
|
|
61
|
-
options,
|
|
62
|
-
hostname,
|
|
63
|
-
);
|
|
51
|
+
const fetchHandler = secureFetch((req) => app.fetch(req), options, hostname);
|
|
64
52
|
const url = new URL(
|
|
65
53
|
`http://${hostname.includes(":") && !hostname.startsWith("[") ? `[${hostname}]` : hostname}:${port}/`,
|
|
66
54
|
);
|
package/src/term.test.ts
CHANGED
|
@@ -34,7 +34,7 @@ describe("term", () => {
|
|
|
34
34
|
const out = formatDevBanner({
|
|
35
35
|
color: false,
|
|
36
36
|
version: "0.2.4",
|
|
37
|
-
profile: "
|
|
37
|
+
profile: "docker",
|
|
38
38
|
runtimeEnv: "local",
|
|
39
39
|
system: "darwin 25.4.0 · bun 1.3.14",
|
|
40
40
|
elements: [
|
|
@@ -45,7 +45,7 @@ describe("term", () => {
|
|
|
45
45
|
});
|
|
46
46
|
expect(out).toContain("oke dev v0.2.4");
|
|
47
47
|
expect(out).toContain("profile");
|
|
48
|
-
expect(out).toContain("
|
|
48
|
+
expect(out).toContain("docker");
|
|
49
49
|
expect(out).toContain("env");
|
|
50
50
|
expect(out).toContain("local");
|
|
51
51
|
expect(out).toContain("system");
|
|
@@ -62,9 +62,7 @@ describe("term", () => {
|
|
|
62
62
|
expect(formatServiceLine("Console", "http://127.0.0.1:6533", false)).toContain(
|
|
63
63
|
"http://127.0.0.1:6533",
|
|
64
64
|
);
|
|
65
|
-
expect(formatAppReadyLine("http://127.0.0.1:6530", false)).toContain(
|
|
66
|
-
"http://127.0.0.1:6530",
|
|
67
|
-
);
|
|
65
|
+
expect(formatAppReadyLine("http://127.0.0.1:6530", false)).toContain("http://127.0.0.1:6530");
|
|
68
66
|
});
|
|
69
67
|
|
|
70
68
|
test("formatDevHero keeps App Console MCP URLs", () => {
|
|
@@ -137,7 +135,7 @@ describe("term", () => {
|
|
|
137
135
|
appDrivers: ["postgres", "redis"],
|
|
138
136
|
color: false,
|
|
139
137
|
});
|
|
140
|
-
expect(out).toContain("
|
|
138
|
+
expect(out).toContain("Docker");
|
|
141
139
|
expect(out).toContain(":15975");
|
|
142
140
|
expect(out).not.toMatch(/\u001b\[/);
|
|
143
141
|
});
|
package/src/term.ts
CHANGED
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/** Whether ANSI color should be applied. */
|
|
9
|
-
export function termColorEnabled(
|
|
10
|
-
stream: { readonly isTTY?: boolean } = process.stdout,
|
|
11
|
-
): boolean {
|
|
9
|
+
export function termColorEnabled(stream: { readonly isTTY?: boolean } = process.stdout): boolean {
|
|
12
10
|
if (process.env["NO_COLOR"] !== undefined) return false;
|
|
13
11
|
if (process.env["FORCE_COLOR"] === "0") return false;
|
|
14
12
|
if (process.env["FORCE_COLOR"]) return true;
|
|
@@ -70,7 +68,7 @@ export type DevHeroElement = {
|
|
|
70
68
|
|
|
71
69
|
/** Shared options for the `oke dev` hero / banner. */
|
|
72
70
|
export type DevHeroMeta = {
|
|
73
|
-
/** `local` · `
|
|
71
|
+
/** `local` · `docker` · `test` · `production` */
|
|
74
72
|
readonly profile?: string;
|
|
75
73
|
/** Data plane: `local` · `production` */
|
|
76
74
|
readonly runtimeEnv?: string;
|
|
@@ -88,20 +86,20 @@ export type DevHeroMeta = {
|
|
|
88
86
|
*
|
|
89
87
|
* @param color - Color on/off
|
|
90
88
|
*/
|
|
91
|
-
export function formatOkeWordmark(
|
|
92
|
-
color: boolean = termColorEnabled(),
|
|
93
|
-
): string {
|
|
89
|
+
export function formatOkeWordmark(color: boolean = termColorEnabled()): string {
|
|
94
90
|
const s = termStyle(color);
|
|
95
91
|
const ink = `${s.green}${s.bold}`;
|
|
96
92
|
const r = s.reset;
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
return (
|
|
94
|
+
[
|
|
95
|
+
`${ink} ██████╗ ██╗ ██╗███████╗${r}`,
|
|
96
|
+
`${ink} ██╔═══██╗██║ ██╔╝██╔════╝${r}`,
|
|
97
|
+
`${ink} ██║ ██║█████╔╝ █████╗ ${r}`,
|
|
98
|
+
`${ink} ██║ ██║██╔═██╗ ██╔══╝ ${r}`,
|
|
99
|
+
`${ink} ╚██████╔╝██║ ██╗███████╗${r}`,
|
|
100
|
+
`${ink} ╚═════╝ ╚═╝ ╚═╝╚══════╝${r}`,
|
|
101
|
+
].join("\n") + "\n"
|
|
102
|
+
);
|
|
105
103
|
}
|
|
106
104
|
|
|
107
105
|
/**
|
|
@@ -109,39 +107,27 @@ export function formatOkeWordmark(
|
|
|
109
107
|
*
|
|
110
108
|
* @param options - Snapshot fields from {@link import("./cli/hero-meta.ts").buildDevHeroSnapshot}
|
|
111
109
|
*/
|
|
112
|
-
export function formatDevHeroDetails(
|
|
113
|
-
options: DevHeroMeta = {},
|
|
114
|
-
): string {
|
|
110
|
+
export function formatDevHeroDetails(options: DevHeroMeta = {}): string {
|
|
115
111
|
const s = termStyle(options.color ?? termColorEnabled());
|
|
116
112
|
const bar = `${s.dim}│${s.reset}`;
|
|
117
113
|
const label = (name: string) => `${s.dim}${name.padEnd(9)}${s.reset}`;
|
|
118
114
|
const lines: string[] = [];
|
|
119
115
|
if (options.profile) {
|
|
120
|
-
lines.push(
|
|
121
|
-
`${bar} ${label("profile")} ${s.cyan}${options.profile}${s.reset}`,
|
|
122
|
-
);
|
|
116
|
+
lines.push(`${bar} ${label("profile")} ${s.cyan}${options.profile}${s.reset}`);
|
|
123
117
|
}
|
|
124
118
|
if (options.runtimeEnv) {
|
|
125
|
-
lines.push(
|
|
126
|
-
`${bar} ${label("env")} ${s.cyan}${options.runtimeEnv}${s.reset}`,
|
|
127
|
-
);
|
|
119
|
+
lines.push(`${bar} ${label("env")} ${s.cyan}${options.runtimeEnv}${s.reset}`);
|
|
128
120
|
}
|
|
129
121
|
if (options.system) {
|
|
130
|
-
lines.push(
|
|
131
|
-
`${bar} ${label("system")} ${s.dim}${options.system}${s.reset}`,
|
|
132
|
-
);
|
|
122
|
+
lines.push(`${bar} ${label("system")} ${s.dim}${options.system}${s.reset}`);
|
|
133
123
|
}
|
|
134
124
|
const elements = options.elements ?? [];
|
|
135
125
|
if (elements.length > 0) {
|
|
136
126
|
lines.push(`${bar} ${s.dim}elements${s.reset}`);
|
|
137
127
|
for (const row of elements) {
|
|
138
128
|
const idle = row.detail === "—";
|
|
139
|
-
const detail = idle
|
|
140
|
-
|
|
141
|
-
: `${s.cyan}${row.detail}${s.reset}`;
|
|
142
|
-
lines.push(
|
|
143
|
-
`${bar} ${s.dim}${row.element.padEnd(9)}${s.reset} ${detail}`,
|
|
144
|
-
);
|
|
129
|
+
const detail = idle ? `${s.dim}—${s.reset}` : `${s.cyan}${row.detail}${s.reset}`;
|
|
130
|
+
lines.push(`${bar} ${s.dim}${row.element.padEnd(9)}${s.reset} ${detail}`);
|
|
145
131
|
}
|
|
146
132
|
}
|
|
147
133
|
return lines.length > 0 ? `${lines.join("\n")}\n` : "";
|
|
@@ -164,9 +150,7 @@ export function formatDevBanner(options: DevHeroMeta = {}): string {
|
|
|
164
150
|
`${s.green}◇${s.reset} Starting`,
|
|
165
151
|
];
|
|
166
152
|
if (options.watching !== false) {
|
|
167
|
-
lines.push(
|
|
168
|
-
`${bar} ${s.dim}watching — client types regenerate on save${s.reset}`,
|
|
169
|
-
);
|
|
153
|
+
lines.push(`${bar} ${s.dim}watching — client types regenerate on save${s.reset}`);
|
|
170
154
|
}
|
|
171
155
|
lines.push(formatDevHeroDetails(options).trimEnd());
|
|
172
156
|
lines.push(bar);
|
|
@@ -196,10 +180,7 @@ export function formatServiceLine(
|
|
|
196
180
|
* @param url - App base URL
|
|
197
181
|
* @param color - Color on/off
|
|
198
182
|
*/
|
|
199
|
-
export function formatAppReadyLine(
|
|
200
|
-
url: string,
|
|
201
|
-
color: boolean = termColorEnabled(),
|
|
202
|
-
): string {
|
|
183
|
+
export function formatAppReadyLine(url: string, color: boolean = termColorEnabled()): string {
|
|
203
184
|
const s = termStyle(color);
|
|
204
185
|
return `${s.green}●${s.reset} ${s.dim}App${s.reset} ${s.cyan}${url}${s.reset}\n`;
|
|
205
186
|
}
|
|
@@ -245,9 +226,7 @@ export function formatDevHero(
|
|
|
245
226
|
*
|
|
246
227
|
* @param color - Color on/off
|
|
247
228
|
*/
|
|
248
|
-
export function formatDevLogSeparator(
|
|
249
|
-
color: boolean = termColorEnabled(),
|
|
250
|
-
): string {
|
|
229
|
+
export function formatDevLogSeparator(color: boolean = termColorEnabled()): string {
|
|
251
230
|
const s = termStyle(color);
|
|
252
231
|
return (
|
|
253
232
|
`${s.dim}│${s.reset}\n` +
|
|
@@ -263,10 +242,7 @@ export function formatDevLogSeparator(
|
|
|
263
242
|
* @param message - Status text
|
|
264
243
|
* @param color - Color on/off
|
|
265
244
|
*/
|
|
266
|
-
export function formatStatusLine(
|
|
267
|
-
message: string,
|
|
268
|
-
color: boolean = termColorEnabled(),
|
|
269
|
-
): string {
|
|
245
|
+
export function formatStatusLine(message: string, color: boolean = termColorEnabled()): string {
|
|
270
246
|
const s = termStyle(color);
|
|
271
247
|
return `${s.dim}│${s.reset} ${s.dim}${message}${s.reset}\n`;
|
|
272
248
|
}
|
|
@@ -314,35 +290,24 @@ export function formatDevLogTime(at: Date = new Date()): string {
|
|
|
314
290
|
*
|
|
315
291
|
* @param options - Surface, method, path, flow, timing, status
|
|
316
292
|
*/
|
|
317
|
-
export function formatRequestLine(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
},
|
|
329
|
-
): string {
|
|
293
|
+
export function formatRequestLine(options: {
|
|
294
|
+
readonly surface: DevLogSurface;
|
|
295
|
+
readonly method: string;
|
|
296
|
+
readonly path: string;
|
|
297
|
+
readonly flow?: string;
|
|
298
|
+
readonly status: number;
|
|
299
|
+
readonly ms: number;
|
|
300
|
+
/** Instant for date/time columns (default now). */
|
|
301
|
+
readonly at?: Date;
|
|
302
|
+
readonly color?: boolean;
|
|
303
|
+
}): string {
|
|
330
304
|
const s = termStyle(options.color ?? termColorEnabled());
|
|
331
305
|
const at = options.at ?? new Date();
|
|
332
306
|
const date = formatDevLogDate(at);
|
|
333
307
|
const time = formatDevLogTime(at);
|
|
334
308
|
const surfaceColor =
|
|
335
|
-
options.surface === "App"
|
|
336
|
-
|
|
337
|
-
: options.surface === "Console"
|
|
338
|
-
? s.magenta
|
|
339
|
-
: s.cyan;
|
|
340
|
-
const statusColor =
|
|
341
|
-
options.status >= 500
|
|
342
|
-
? s.red
|
|
343
|
-
: options.status >= 400
|
|
344
|
-
? s.yellow
|
|
345
|
-
: s.green;
|
|
309
|
+
options.surface === "App" ? s.green : options.surface === "Console" ? s.magenta : s.cyan;
|
|
310
|
+
const statusColor = options.status >= 500 ? s.red : options.status >= 400 ? s.yellow : s.green;
|
|
346
311
|
const methodRaw = options.method.toUpperCase();
|
|
347
312
|
const methodColor =
|
|
348
313
|
methodRaw === "GET"
|
|
@@ -355,9 +320,7 @@ export function formatRequestLine(
|
|
|
355
320
|
? s.red
|
|
356
321
|
: s.cyan;
|
|
357
322
|
const method = methodRaw.padEnd(4);
|
|
358
|
-
const path = options.path.length > 28
|
|
359
|
-
? `${options.path.slice(0, 27)}…`
|
|
360
|
-
: options.path.padEnd(28);
|
|
323
|
+
const path = options.path.length > 28 ? `${options.path.slice(0, 27)}…` : options.path.padEnd(28);
|
|
361
324
|
const flow = (options.flow ?? "—").padEnd(22);
|
|
362
325
|
const ms = `${options.ms}ms`.padStart(6);
|
|
363
326
|
return (
|
|
@@ -378,34 +341,25 @@ export function formatRequestLine(
|
|
|
378
341
|
*
|
|
379
342
|
* @param options - Project name, services, driver labels
|
|
380
343
|
*/
|
|
381
|
-
export function formatStackSummary(
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
},
|
|
389
|
-
): string {
|
|
344
|
+
export function formatStackSummary(options: {
|
|
345
|
+
readonly project: string;
|
|
346
|
+
readonly services: readonly StackSummaryService[];
|
|
347
|
+
/** Drivers the host app will use (e.g. `postgres`, `redis`). */
|
|
348
|
+
readonly appDrivers?: readonly string[];
|
|
349
|
+
readonly color?: boolean;
|
|
350
|
+
}): string {
|
|
390
351
|
const s = termStyle(options.color ?? termColorEnabled());
|
|
391
352
|
const bar = `${s.dim}│${s.reset}`;
|
|
392
353
|
const pad = (label: string) => label.padEnd(8);
|
|
393
354
|
const lines: string[] = [
|
|
394
|
-
`${s.green}◇${s.reset} ${s.bold}
|
|
355
|
+
`${s.green}◇${s.reset} ${s.bold}Docker${s.reset} ${s.cyan}${options.project}${s.reset}`,
|
|
395
356
|
];
|
|
396
357
|
for (const svc of options.services) {
|
|
397
|
-
lines.push(
|
|
398
|
-
`${bar} ${s.dim}${pad(svc.label)}${s.reset} ${s.cyan}:${svc.hostPort}${s.reset}`,
|
|
399
|
-
);
|
|
358
|
+
lines.push(`${bar} ${s.dim}${pad(svc.label)}${s.reset} ${s.cyan}:${svc.hostPort}${s.reset}`);
|
|
400
359
|
}
|
|
401
360
|
const drivers = options.appDrivers ?? [];
|
|
402
|
-
const appDetail =
|
|
403
|
-
|
|
404
|
-
? `host Bun · ${drivers.join(" + ")}`
|
|
405
|
-
: "host Bun";
|
|
406
|
-
lines.push(
|
|
407
|
-
`${bar} ${s.dim}${pad("app")}${s.reset} ${s.dim}${appDetail}${s.reset}`,
|
|
408
|
-
);
|
|
361
|
+
const appDetail = drivers.length > 0 ? `host Bun · ${drivers.join(" + ")}` : "host Bun";
|
|
362
|
+
lines.push(`${bar} ${s.dim}${pad("app")}${s.reset} ${s.dim}${appDetail}${s.reset}`);
|
|
409
363
|
lines.push(bar);
|
|
410
364
|
return `${lines.join("\n")}\n`;
|
|
411
365
|
}
|
|
@@ -416,10 +370,7 @@ export function formatStackSummary(
|
|
|
416
370
|
* @param code - Hex claim code
|
|
417
371
|
* @param color - Color on/off
|
|
418
372
|
*/
|
|
419
|
-
export function formatClaimNote(
|
|
420
|
-
code: string,
|
|
421
|
-
color: boolean = termColorEnabled(),
|
|
422
|
-
): string {
|
|
373
|
+
export function formatClaimNote(code: string, color: boolean = termColorEnabled()): string {
|
|
423
374
|
const s = termStyle(color);
|
|
424
375
|
const bar = `${s.dim}│${s.reset}`;
|
|
425
376
|
const title = "Claim code";
|
|
@@ -96,19 +96,14 @@ describe("createTestApp — four-applications surface", () => {
|
|
|
96
96
|
const u = await t.auth.loginAs({ scopes: ["order:create"] });
|
|
97
97
|
expect(u.verified).toBe(true);
|
|
98
98
|
|
|
99
|
-
const { data, error } = await t.api.orders!.create!(
|
|
100
|
-
{ sku: "COFFEE", qty: 2 },
|
|
101
|
-
{ as: u },
|
|
102
|
-
);
|
|
99
|
+
const { data, error } = await t.api.orders!.create!({ sku: "COFFEE", qty: 2 }, { as: u });
|
|
103
100
|
expect(error).toBeNull();
|
|
104
101
|
expect(data).toMatchObject({ id: expect.any(String) });
|
|
105
102
|
|
|
106
103
|
await t.signals.drain();
|
|
107
104
|
const sent = t.channels.sent();
|
|
108
105
|
expect(sent.length).toBeGreaterThanOrEqual(1);
|
|
109
|
-
expect(
|
|
110
|
-
sent.some((s) => "template" in s && s.template === "order-confirmed"),
|
|
111
|
-
).toBe(true);
|
|
106
|
+
expect(sent.some((s) => "template" in s && s.template === "order-confirmed")).toBe(true);
|
|
112
107
|
|
|
113
108
|
await t.clock.advance("2m");
|
|
114
109
|
expect(await t.cron.run("expire-stale")).toBe(true);
|
|
@@ -116,9 +111,7 @@ describe("createTestApp — four-applications surface", () => {
|
|
|
116
111
|
const events = await t.runs();
|
|
117
112
|
expect(events.some((e) => e.flow === "orders.create")).toBe(true);
|
|
118
113
|
const createRun = events.find((e) => e.flow === "orders.create")!;
|
|
119
|
-
expect(t.effects.of(createRun.id).some((e) => e.kind === "emit")).toBe(
|
|
120
|
-
true,
|
|
121
|
-
);
|
|
114
|
+
expect(t.effects.of(createRun.id).some((e) => e.kind === "emit")).toBe(true);
|
|
122
115
|
|
|
123
116
|
await t.close();
|
|
124
117
|
});
|
|
@@ -142,10 +135,7 @@ describe("createTestApp — vault gaps still fail boot", () => {
|
|
|
142
135
|
|
|
143
136
|
try {
|
|
144
137
|
await createTestApp(app, {
|
|
145
|
-
secrets: [
|
|
146
|
-
vault("A", { description: "alpha" }),
|
|
147
|
-
vault("B", { description: "beta" }),
|
|
148
|
-
],
|
|
138
|
+
secrets: [vault("A", { description: "alpha" }), vault("B", { description: "beta" })],
|
|
149
139
|
boot: {
|
|
150
140
|
env: "prod",
|
|
151
141
|
vault: { allowDevFallbacks: false, chain: [] },
|
|
@@ -22,15 +22,8 @@ import {
|
|
|
22
22
|
type ChannelInbox,
|
|
23
23
|
type ChannelInboxEntry,
|
|
24
24
|
} from "../drivers/index.ts";
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
type AiPromptDecl,
|
|
28
|
-
type AiRuntime,
|
|
29
|
-
} from "../elements/ai.ts";
|
|
30
|
-
import {
|
|
31
|
-
createChannelRuntime,
|
|
32
|
-
type DeliveryReceipt,
|
|
33
|
-
} from "../elements/channel.ts";
|
|
25
|
+
import { createAiRuntime, type AiPromptDecl, type AiRuntime } from "../elements/ai.ts";
|
|
26
|
+
import { createChannelRuntime, type DeliveryReceipt } from "../elements/channel.ts";
|
|
34
27
|
import { createTestClockRuntime } from "../elements/clock.ts";
|
|
35
28
|
import type { GateDecl } from "../elements/gate.ts";
|
|
36
29
|
import type { SignalDecl } from "../elements/signal.ts";
|
|
@@ -199,16 +192,13 @@ export async function createTestApp<App extends OkeApp>(
|
|
|
199
192
|
defaultLocale: "ar",
|
|
200
193
|
...(appOpts.channel ?? {}),
|
|
201
194
|
...(options.boot?.channel ?? {}),
|
|
202
|
-
drivers: options.boot?.channel?.drivers ?? [
|
|
203
|
-
openConsoleChannel({ inbox }),
|
|
204
|
-
],
|
|
195
|
+
drivers: options.boot?.channel?.drivers ?? [openConsoleChannel({ inbox })],
|
|
205
196
|
now: () => clock.now(),
|
|
206
197
|
});
|
|
207
198
|
const ai = createAiRuntime({
|
|
208
199
|
...(appOpts.ai ?? {}),
|
|
209
200
|
...(options.boot?.ai ?? {}),
|
|
210
|
-
defaultDriver:
|
|
211
|
-
options.boot?.ai?.defaultDriver ?? createMockAiDriver(mockResponses),
|
|
201
|
+
defaultDriver: options.boot?.ai?.defaultDriver ?? createMockAiDriver(mockResponses),
|
|
212
202
|
now: () => clock.now(),
|
|
213
203
|
});
|
|
214
204
|
|
|
@@ -353,9 +343,7 @@ function createTestApi(app: OkeApp, now: () => number): TestApi {
|
|
|
353
343
|
opts?: TestCallOptions,
|
|
354
344
|
): Promise<{ data: unknown; error: FlowFailure["error"] | null }> => {
|
|
355
345
|
const flowDef =
|
|
356
|
-
app.flow(`${unit}.${flowName}`) ??
|
|
357
|
-
app.flow(flowName) ??
|
|
358
|
-
findFlowByUnit(app, unit, flowName);
|
|
346
|
+
app.flow(`${unit}.${flowName}`) ?? app.flow(flowName) ?? findFlowByUnit(app, unit, flowName);
|
|
359
347
|
if (!flowDef) {
|
|
360
348
|
return {
|
|
361
349
|
data: null,
|
|
@@ -369,9 +357,7 @@ function createTestApi(app: OkeApp, now: () => number): TestApi {
|
|
|
369
357
|
const principal = toPrincipal(opts?.as);
|
|
370
358
|
const httpTrigger = flowDef.triggers.find((t) => t.kind === "http");
|
|
371
359
|
const trigger: Trigger =
|
|
372
|
-
httpTrigger ??
|
|
373
|
-
flowDef.triggers[0] ??
|
|
374
|
-
({ kind: "internal" } satisfies InternalTrigger);
|
|
360
|
+
httpTrigger ?? flowDef.triggers[0] ?? ({ kind: "internal" } satisfies InternalTrigger);
|
|
375
361
|
|
|
376
362
|
const result = await app.execute(flowDef, input, trigger, {
|
|
377
363
|
principal,
|
|
@@ -400,8 +386,7 @@ function createTestApi(app: OkeApp, now: () => number): TestApi {
|
|
|
400
386
|
if (typeof flowName !== "string" || flowName === "then") {
|
|
401
387
|
return undefined;
|
|
402
388
|
}
|
|
403
|
-
return (input?: unknown, opts?: TestCallOptions) =>
|
|
404
|
-
call(unit, flowName, input, opts);
|
|
389
|
+
return (input?: unknown, opts?: TestCallOptions) => call(unit, flowName, input, opts);
|
|
405
390
|
},
|
|
406
391
|
},
|
|
407
392
|
);
|
|
@@ -409,11 +394,7 @@ function createTestApi(app: OkeApp, now: () => number): TestApi {
|
|
|
409
394
|
});
|
|
410
395
|
}
|
|
411
396
|
|
|
412
|
-
function findFlowByUnit(
|
|
413
|
-
app: OkeApp,
|
|
414
|
-
unit: string,
|
|
415
|
-
flowName: string,
|
|
416
|
-
): ReturnType<OkeApp["flow"]> {
|
|
397
|
+
function findFlowByUnit(app: OkeApp, unit: string, flowName: string): ReturnType<OkeApp["flow"]> {
|
|
417
398
|
// Prefer $routes unit.flow → full flow name from bindings.
|
|
418
399
|
const routes = app.$routes as Record<
|
|
419
400
|
string,
|
|
@@ -439,7 +420,10 @@ function findFlowByUnit(
|
|
|
439
420
|
}
|
|
440
421
|
}
|
|
441
422
|
for (const b of app.bindings) {
|
|
442
|
-
if (
|
|
423
|
+
if (
|
|
424
|
+
b.flow.unit === unit &&
|
|
425
|
+
(b.flow.name === flowName || b.flow.name.endsWith(`.${flowName}`))
|
|
426
|
+
) {
|
|
443
427
|
return b.flow;
|
|
444
428
|
}
|
|
445
429
|
// Auto-named flows: match export-style via name suffix after adopt.
|
|
@@ -515,9 +499,7 @@ function matchRestHeuristic(
|
|
|
515
499
|
return undefined;
|
|
516
500
|
}
|
|
517
501
|
|
|
518
|
-
function toPrincipal(
|
|
519
|
-
as: TestUser | ResolvedPrincipal | undefined,
|
|
520
|
-
): ResolvedPrincipal | undefined {
|
|
502
|
+
function toPrincipal(as: TestUser | ResolvedPrincipal | undefined): ResolvedPrincipal | undefined {
|
|
521
503
|
if (!as) return undefined;
|
|
522
504
|
if ("scopes" in as && as.scopes instanceof Set && "id" in as) {
|
|
523
505
|
const u = as as TestUser;
|
|
@@ -22,9 +22,7 @@ describe("Provisions integration", () => {
|
|
|
22
22
|
resetFlowSeq();
|
|
23
23
|
|
|
24
24
|
const member = gate.policy("member", ({ auth }) => !!auth.verified);
|
|
25
|
-
const canOrder = gate.policy("order:create", ({ auth }) =>
|
|
26
|
-
auth.scopes.has("order:create"),
|
|
27
|
-
);
|
|
25
|
+
const canOrder = gate.policy("order:create", ({ auth }) => auth.scopes.has("order:create"));
|
|
28
26
|
const stripeKey = vault("STRIPE_KEY", {
|
|
29
27
|
description: "Payments gateway key",
|
|
30
28
|
dev: "sk_test_local",
|
|
@@ -133,10 +131,7 @@ describe("Provisions integration", () => {
|
|
|
133
131
|
expect(denied.error?.code).toBe("Unauthorized");
|
|
134
132
|
|
|
135
133
|
const u = await t.auth.loginAs({ scopes: ["order:create"] });
|
|
136
|
-
const { data, error } = await t.api.orders!.create!(
|
|
137
|
-
{ sku: "COFFEE", qty: 2 },
|
|
138
|
-
{ as: u },
|
|
139
|
-
);
|
|
134
|
+
const { data, error } = await t.api.orders!.create!({ sku: "COFFEE", qty: 2 }, { as: u });
|
|
140
135
|
expect(error).toBeNull();
|
|
141
136
|
expect(data).toMatchObject({ id: expect.any(String) });
|
|
142
137
|
|
|
@@ -159,10 +154,7 @@ describe("Provisions integration", () => {
|
|
|
159
154
|
// First orders.create is the anonymous deny (stops at member); the
|
|
160
155
|
// authenticated success evaluates the full chain.
|
|
161
156
|
const createRun = events.find(
|
|
162
|
-
(e) =>
|
|
163
|
-
e.flow === "orders.create" &&
|
|
164
|
-
e.gates.includes("order:create") &&
|
|
165
|
-
e.error == null,
|
|
157
|
+
(e) => e.flow === "orders.create" && e.gates.includes("order:create") && e.error == null,
|
|
166
158
|
);
|
|
167
159
|
expect(createRun).toBeDefined();
|
|
168
160
|
expect(createRun!.gates).toEqual(["member", "order:create"]);
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
6
|
import {
|
|
7
7
|
CODEMODS,
|
|
8
|
+
rewriteConfigEnvKeys,
|
|
9
|
+
rewriteFromStackMarkers,
|
|
8
10
|
runCodemods,
|
|
9
11
|
validateCodemodRegistry,
|
|
10
12
|
type Codemod,
|
|
@@ -45,14 +47,31 @@ describe("codemod registry", () => {
|
|
|
45
47
|
from: "0.0.0",
|
|
46
48
|
to: "0.0.1",
|
|
47
49
|
description: "rename demo",
|
|
48
|
-
apply: async () => [
|
|
49
|
-
{ path: "src/x.ts", before: "old", after: "new" },
|
|
50
|
-
],
|
|
50
|
+
apply: async () => [{ path: "src/x.ts", before: "old", after: "new" }],
|
|
51
51
|
},
|
|
52
52
|
];
|
|
53
53
|
const changes = await runCodemods("/tmp", registry);
|
|
54
|
-
expect(changes).toEqual([
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
expect(changes).toEqual([{ path: "src/x.ts", before: "old", after: "new" }]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("rewriteConfigEnvKeys renames driver-map keys", () => {
|
|
58
|
+
const after = rewriteConfigEnvKeys(`sql: {
|
|
59
|
+
dev: "sqlite",
|
|
60
|
+
stack: "postgres",
|
|
61
|
+
prod: "postgres",
|
|
62
|
+
}`);
|
|
63
|
+
expect(after).toContain('local: "sqlite"');
|
|
64
|
+
expect(after).toContain('docker: "postgres"');
|
|
65
|
+
expect(after).not.toMatch(/(^|[^\w.])dev\s*:/);
|
|
66
|
+
expect(after).not.toMatch(/(^|[^\w.])stack\s*:/);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("rewriteFromStackMarkers renames vault helpers", () => {
|
|
70
|
+
const after = rewriteFromStackMarkers(
|
|
71
|
+
`dev: vault.fromStack("store.sql") // __oke_from_stack__`,
|
|
72
|
+
);
|
|
73
|
+
expect(after).toContain("fromDocker");
|
|
74
|
+
expect(after).toContain("__oke_from_docker__");
|
|
75
|
+
expect(after).not.toContain("fromStack");
|
|
57
76
|
});
|
|
58
77
|
});
|