okengine 0.2.5 → 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 +46 -38
- 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/cli/doc-drift.ts
CHANGED
|
@@ -81,13 +81,12 @@ async function loadMermaid(): Promise<typeof import("mermaid").default> {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/** App section heading → example package directory name. */
|
|
84
|
-
const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }> =
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
];
|
|
84
|
+
const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }> = [
|
|
85
|
+
{ re: /^# 1 · BASIC — Notes\b/m, app: "notes" },
|
|
86
|
+
{ re: /^# 2 · INTERMEDIATE — Linkly\b/m, app: "linkly" },
|
|
87
|
+
{ re: /^# 3 · ADVANCED — Provisions\b/m, app: "provisions" },
|
|
88
|
+
{ re: /^# 4 · COMPLEX — Skyport\b/m, app: "skyport" },
|
|
89
|
+
];
|
|
91
90
|
|
|
92
91
|
/**
|
|
93
92
|
* Normalize TypeScript source for containment comparison.
|
|
@@ -95,12 +94,9 @@ const APP_SECTIONS: ReadonlyArray<{ readonly re: RegExp; readonly app: string }>
|
|
|
95
94
|
* @param text - Raw source
|
|
96
95
|
*/
|
|
97
96
|
export function normalizeTs(text: string): string {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
.map((line) => line.replace(/[ \t]+$/g, ""))
|
|
102
|
-
.join("\n")
|
|
103
|
-
.trim();
|
|
97
|
+
// Collapse all whitespace so claimed fences match sources regardless of
|
|
98
|
+
// indent (e.g. oxfmt-formatted bodies inside `test(...)` callbacks).
|
|
99
|
+
return text.replace(/\s+/g, " ").trim();
|
|
104
100
|
}
|
|
105
101
|
|
|
106
102
|
/** One claimed fence extracted from a markdown document. */
|
|
@@ -136,9 +132,7 @@ export function parseMermaidFences(markdown: string): MermaidFence[] {
|
|
|
136
132
|
i++;
|
|
137
133
|
}
|
|
138
134
|
if (i >= lines.length || !lines[i]!.startsWith("```")) {
|
|
139
|
-
throw new Error(
|
|
140
|
-
`doc-drift: unclosed mermaid fence (line ${startLine})`,
|
|
141
|
-
);
|
|
135
|
+
throw new Error(`doc-drift: unclosed mermaid fence (line ${startLine})`);
|
|
142
136
|
}
|
|
143
137
|
fences.push({ body: bodyLines.join("\n").trim(), startLine });
|
|
144
138
|
}
|
|
@@ -165,15 +159,11 @@ export async function checkMermaidSyntax(
|
|
|
165
159
|
try {
|
|
166
160
|
const result = await mermaid.parse(fence.body);
|
|
167
161
|
if (!result) {
|
|
168
|
-
failures.push(
|
|
169
|
-
`mermaid: parse returned false (line ${fence.startLine})`,
|
|
170
|
-
);
|
|
162
|
+
failures.push(`mermaid: parse returned false (line ${fence.startLine})`);
|
|
171
163
|
}
|
|
172
164
|
} catch (err) {
|
|
173
165
|
const detail = err instanceof Error ? err.message : String(err);
|
|
174
|
-
failures.push(
|
|
175
|
-
`mermaid: invalid syntax (line ${fence.startLine}): ${detail.split("\n")[0]}`,
|
|
176
|
-
);
|
|
166
|
+
failures.push(`mermaid: invalid syntax (line ${fence.startLine}): ${detail.split("\n")[0]}`);
|
|
177
167
|
}
|
|
178
168
|
}
|
|
179
169
|
|
|
@@ -280,10 +270,7 @@ export function parseClaimedFences(markdown: string): ClaimedFence[] {
|
|
|
280
270
|
* @param targetPath - File or directory (`tests/`)
|
|
281
271
|
* @param expected - Normalized fence body
|
|
282
272
|
*/
|
|
283
|
-
async function containsFence(
|
|
284
|
-
targetPath: string,
|
|
285
|
-
expected: string,
|
|
286
|
-
): Promise<boolean> {
|
|
273
|
+
async function containsFence(targetPath: string, expected: string): Promise<boolean> {
|
|
287
274
|
const direct = Bun.file(targetPath);
|
|
288
275
|
if (await direct.exists()) {
|
|
289
276
|
const st = await direct.stat();
|
|
@@ -293,9 +280,7 @@ async function containsFence(
|
|
|
293
280
|
}
|
|
294
281
|
|
|
295
282
|
// Directory claim (`### \`tests/\``) — any nested file may contain the fence.
|
|
296
|
-
const dirPath = targetPath.endsWith("/")
|
|
297
|
-
? targetPath.slice(0, -1)
|
|
298
|
-
: targetPath;
|
|
283
|
+
const dirPath = targetPath.endsWith("/") ? targetPath.slice(0, -1) : targetPath;
|
|
299
284
|
try {
|
|
300
285
|
const glob = new Bun.Glob("**/*.{ts,tsx,js,jsx}");
|
|
301
286
|
for await (const rel of glob.scan({ cwd: dirPath, onlyFiles: true })) {
|
|
@@ -354,9 +339,7 @@ export async function runDocDrift(
|
|
|
354
339
|
|
|
355
340
|
for (const path of paths) {
|
|
356
341
|
const abs = resolve(ROOT, path);
|
|
357
|
-
const label = abs.startsWith(ROOT + "/")
|
|
358
|
-
? abs.slice(ROOT.length + 1)
|
|
359
|
-
: abs;
|
|
342
|
+
const label = abs.startsWith(ROOT + "/") ? abs.slice(ROOT.length + 1) : abs;
|
|
360
343
|
const requireClaimed = !label.startsWith("site/");
|
|
361
344
|
const markdown = await Bun.file(abs).text();
|
|
362
345
|
const fences = parseClaimedFences(markdown);
|
|
@@ -371,14 +354,10 @@ export async function runDocDrift(
|
|
|
371
354
|
total += fences.length;
|
|
372
355
|
if (!result.ok) {
|
|
373
356
|
ok = false;
|
|
374
|
-
messages.push(
|
|
375
|
-
`doc-drift: ${result.failures.length} failure(s) in ${label}`,
|
|
376
|
-
);
|
|
357
|
+
messages.push(`doc-drift: ${result.failures.length} failure(s) in ${label}`);
|
|
377
358
|
for (const f of result.failures) messages.push(` · ${f}`);
|
|
378
359
|
} else {
|
|
379
|
-
messages.push(
|
|
380
|
-
`doc-drift: ok — ${fences.length} claimed fence(s) in ${label}`,
|
|
381
|
-
);
|
|
360
|
+
messages.push(`doc-drift: ok — ${fences.length} claimed fence(s) in ${label}`);
|
|
382
361
|
}
|
|
383
362
|
}
|
|
384
363
|
|
|
@@ -388,21 +367,16 @@ export async function runDocDrift(
|
|
|
388
367
|
const mermaidResult = await checkMermaidSyntax(mermaidFences);
|
|
389
368
|
if (!mermaidResult.ok) {
|
|
390
369
|
ok = false;
|
|
391
|
-
messages.push(
|
|
392
|
-
`doc-drift: ${mermaidResult.failures.length} mermaid failure(s) in ${label}`,
|
|
393
|
-
);
|
|
370
|
+
messages.push(`doc-drift: ${mermaidResult.failures.length} mermaid failure(s) in ${label}`);
|
|
394
371
|
for (const f of mermaidResult.failures) messages.push(` · ${f}`);
|
|
395
372
|
} else {
|
|
396
|
-
messages.push(
|
|
397
|
-
`doc-drift: ok — ${mermaidFences.length} mermaid fence(s) in ${label}`,
|
|
398
|
-
);
|
|
373
|
+
messages.push(`doc-drift: ok — ${mermaidFences.length} mermaid fence(s) in ${label}`);
|
|
399
374
|
}
|
|
400
375
|
}
|
|
401
376
|
}
|
|
402
377
|
|
|
403
378
|
if (ok && checkedFiles > 1) {
|
|
404
|
-
const mermaidNote =
|
|
405
|
-
mermaidTotal > 0 ? ` · ${mermaidTotal} mermaid fence(s)` : "";
|
|
379
|
+
const mermaidNote = mermaidTotal > 0 ? ` · ${mermaidTotal} mermaid fence(s)` : "";
|
|
406
380
|
messages.push(
|
|
407
381
|
`doc-drift: ok — ${total} claimed fence(s) across ${checkedFiles} file(s)${mermaidNote}`,
|
|
408
382
|
);
|
|
@@ -413,10 +387,7 @@ export async function runDocDrift(
|
|
|
413
387
|
|
|
414
388
|
async function main(): Promise<number> {
|
|
415
389
|
const args = process.argv.slice(2);
|
|
416
|
-
const paths =
|
|
417
|
-
args.length > 0
|
|
418
|
-
? args
|
|
419
|
-
: [...REQUIRED_DOCS, ...(await discoverSiteDocs(ROOT))];
|
|
390
|
+
const paths = args.length > 0 ? args : [...REQUIRED_DOCS, ...(await discoverSiteDocs(ROOT))];
|
|
420
391
|
const { ok, messages } = await runDocDrift(paths);
|
|
421
392
|
for (const m of messages) {
|
|
422
393
|
if (ok) console.log(m);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate: removed legacy stack-mode soft-compat stays gone.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors {@link ../drivers/vault-driver-removal.test.ts} — `git grep` over the
|
|
5
|
+
* tracked tree must find zero hits (changelog history may still document the
|
|
6
|
+
* rename; upgrade codemods may still rewrite the old tokens).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, expect, test } from "bun:test";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
|
|
12
|
+
const ROOT = join(import.meta.dir, "../..");
|
|
13
|
+
|
|
14
|
+
/** Forbidden CLI flag, split so this file does not match itself. */
|
|
15
|
+
const FORBIDDEN_STACK_FLAG = ["--", "stack"].join("");
|
|
16
|
+
/** Forbidden compose env filename. */
|
|
17
|
+
const FORBIDDEN_ENV_STACK = [".env.", "stack"].join("");
|
|
18
|
+
/** Forbidden env var — name avoids the contiguous token so this file is clean. */
|
|
19
|
+
const FORBIDDEN_LEGACY_ENV = ["OKE_", "STACK"].join("");
|
|
20
|
+
/** Forbidden vault helper. */
|
|
21
|
+
const FORBIDDEN_FROM_STACK = ["from", "Stack"].join("");
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Run `git grep -F` and assert zero matches after ignoring allow-listed paths.
|
|
25
|
+
*
|
|
26
|
+
* @param pattern - Fixed-string pattern
|
|
27
|
+
* @param ignorePrefixes - Path prefixes to ignore (`path:line:` hits)
|
|
28
|
+
*/
|
|
29
|
+
function assertZeroGitGrep(pattern: string, ignorePrefixes: readonly string[] = []): void {
|
|
30
|
+
const proc = Bun.spawnSync(["git", "grep", "-F", "-n", "-e", pattern, "--"], {
|
|
31
|
+
cwd: ROOT,
|
|
32
|
+
stdout: "pipe",
|
|
33
|
+
stderr: "pipe",
|
|
34
|
+
});
|
|
35
|
+
// git grep exits 1 when there are no matches.
|
|
36
|
+
if (proc.exitCode === 1) {
|
|
37
|
+
expect(proc.stdout.toString()).toBe("");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const hits = proc.stdout
|
|
41
|
+
.toString()
|
|
42
|
+
.trim()
|
|
43
|
+
.split("\n")
|
|
44
|
+
.filter((line) => line.length > 0)
|
|
45
|
+
.filter((line) => !ignorePrefixes.some((prefix) => line.startsWith(prefix)));
|
|
46
|
+
expect(hits.join("\n")).toBe("");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
describe("legacy stack-mode removal gate", () => {
|
|
50
|
+
test("tracked tree has zero legacy docker-mode flag outside changelog", () => {
|
|
51
|
+
assertZeroGitGrep(FORBIDDEN_STACK_FLAG, ["docs/changelog.md:"]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("tracked tree has zero legacy compose env filename outside changelog", () => {
|
|
55
|
+
assertZeroGitGrep(FORBIDDEN_ENV_STACK, ["docs/changelog.md:"]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("tracked tree has zero legacy OKE env outside changelog", () => {
|
|
59
|
+
assertZeroGitGrep(FORBIDDEN_LEGACY_ENV, ["docs/changelog.md:"]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("tracked tree has zero legacy vault helper outside changelog + upgrade", () => {
|
|
63
|
+
assertZeroGitGrep(FORBIDDEN_FROM_STACK, [
|
|
64
|
+
"docs/changelog.md:",
|
|
65
|
+
"src/upgrade/codemods.ts:",
|
|
66
|
+
"src/upgrade/codemods.test.ts:",
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `oke docker` / `oke stack` / `oke images pin` / `oke schema` / `oke dev --
|
|
2
|
+
* `oke docker` / `oke stack` / `oke images pin` / `oke schema` / `oke dev --docker`.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
@@ -39,12 +39,10 @@ describe("oke docker CLI", () => {
|
|
|
39
39
|
expect(code).toBe(0);
|
|
40
40
|
expect(result).toBeDefined();
|
|
41
41
|
expect(await Bun.file(join(dir, "docker/Dockerfile")).exists()).toBe(true);
|
|
42
|
-
expect(
|
|
43
|
-
await Bun.file(join(dir, "docker/compose.store.sql.yml")).exists(),
|
|
44
|
-
).toBe(true);
|
|
42
|
+
expect(await Bun.file(join(dir, "docker/compose.store.sql.yml")).exists()).toBe(true);
|
|
45
43
|
const yml = await Bun.file(join(dir, "docker/compose.store.sql.yml")).text();
|
|
46
44
|
expect(yml).not.toContain("test-password-not-in-yaml");
|
|
47
|
-
expect(yml).toContain("
|
|
45
|
+
expect(yml).toContain(".env.docker");
|
|
48
46
|
expect(logs.join("")).toContain("docker/compose.override.yml");
|
|
49
47
|
});
|
|
50
48
|
});
|
|
@@ -149,13 +147,14 @@ describe("oke schema generate", () => {
|
|
|
149
147
|
});
|
|
150
148
|
});
|
|
151
149
|
|
|
152
|
-
describe("oke dev --
|
|
153
|
-
test("plans
|
|
150
|
+
describe("oke dev --docker", () => {
|
|
151
|
+
test("plans docker with postgres and writes nothing on dryRun", async () => {
|
|
154
152
|
const dir = await mkdtemp(join(tmpdir(), "oke-cli-dev-dry-"));
|
|
155
153
|
await Bun.write(join(dir, "src/app.ts"), "export {}\n");
|
|
156
154
|
const { code, plan } = await runDev({
|
|
155
|
+
stdinIsTTY: false,
|
|
157
156
|
cwd: dir,
|
|
158
|
-
|
|
157
|
+
docker: ["store.sql"],
|
|
159
158
|
images,
|
|
160
159
|
credentials,
|
|
161
160
|
dryRun: true,
|
package/src/cli/docker.ts
CHANGED
|
@@ -93,9 +93,7 @@ export async function runDockerDerive(
|
|
|
93
93
|
write(
|
|
94
94
|
`compose merge order (cwd ${composeDir}/):\n${result.composeFiles.map((f) => ` -f ${f}`).join("\n")}\n`,
|
|
95
95
|
);
|
|
96
|
-
write(
|
|
97
|
-
`(${composeDir}/compose.override.yml is layer 4 — user-owned, never written by oke)\n`,
|
|
98
|
-
);
|
|
96
|
+
write(`(${composeDir}/compose.override.yml is layer 4 — user-owned, never written by oke)\n`);
|
|
99
97
|
return { code: 0, result };
|
|
100
98
|
} catch (err) {
|
|
101
99
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -47,9 +47,7 @@ export async function runDoctorDiffExamples(): Promise<number> {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (failed > 0) {
|
|
50
|
-
console.log(
|
|
51
|
-
"Acknowledge intentional breaks with `breaking: true` on the owning flow.",
|
|
52
|
-
);
|
|
50
|
+
console.log("Acknowledge intentional breaks with `breaking: true` on the owning flow.");
|
|
53
51
|
}
|
|
54
52
|
return failed > 0 ? 1 : 0;
|
|
55
53
|
}
|
|
@@ -9,10 +9,7 @@ import type { Manifest } from "../manifest/types.ts";
|
|
|
9
9
|
import { parseManifest } from "../manifest/validate.ts";
|
|
10
10
|
import { runDoctorDiff } from "./doctor-diff.ts";
|
|
11
11
|
|
|
12
|
-
const baseUrl = new URL(
|
|
13
|
-
"../manifest/fixtures/base.manifest.json",
|
|
14
|
-
import.meta.url,
|
|
15
|
-
);
|
|
12
|
+
const baseUrl = new URL("../manifest/fixtures/base.manifest.json", import.meta.url);
|
|
16
13
|
|
|
17
14
|
async function loadBase(): Promise<Manifest> {
|
|
18
15
|
return parseManifest(await Bun.file(baseUrl).text());
|
|
@@ -88,4 +85,3 @@ describe("oke doctor --diff", () => {
|
|
|
88
85
|
}
|
|
89
86
|
});
|
|
90
87
|
});
|
|
91
|
-
|
package/src/cli/doctor-diff.ts
CHANGED
|
@@ -34,10 +34,7 @@ export interface DoctorDiffOptions {
|
|
|
34
34
|
* @param cwd - Repo root
|
|
35
35
|
* @param baseBranch - Preferred base
|
|
36
36
|
*/
|
|
37
|
-
readonly resolveMergeBase?: (
|
|
38
|
-
cwd: string,
|
|
39
|
-
baseBranch?: string,
|
|
40
|
-
) => Promise<string | null>;
|
|
37
|
+
readonly resolveMergeBase?: (cwd: string, baseBranch?: string) => Promise<string | null>;
|
|
41
38
|
/**
|
|
42
39
|
* Read a file at a git revision (tests).
|
|
43
40
|
*
|
|
@@ -45,11 +42,7 @@ export interface DoctorDiffOptions {
|
|
|
45
42
|
* @param rev - Commit-ish
|
|
46
43
|
* @param path - Path relative to repo root
|
|
47
44
|
*/
|
|
48
|
-
readonly readAtRevision?: (
|
|
49
|
-
cwd: string,
|
|
50
|
-
rev: string,
|
|
51
|
-
path: string,
|
|
52
|
-
) => Promise<string | null>;
|
|
45
|
+
readonly readAtRevision?: (cwd: string, rev: string, path: string) => Promise<string | null>;
|
|
53
46
|
/** Manifest relative path when using git (default: auto-detect). */
|
|
54
47
|
readonly manifestPath?: string;
|
|
55
48
|
readonly write?: (text: string) => void;
|
|
@@ -67,9 +60,7 @@ export interface DoctorDiffResult {
|
|
|
67
60
|
*
|
|
68
61
|
* @param options - Paths / injections / git helpers
|
|
69
62
|
*/
|
|
70
|
-
export async function runDoctorDiff(
|
|
71
|
-
options: DoctorDiffOptions = {},
|
|
72
|
-
): Promise<DoctorDiffResult> {
|
|
63
|
+
export async function runDoctorDiff(options: DoctorDiffOptions = {}): Promise<DoctorDiffResult> {
|
|
73
64
|
const write = options.write ?? ((t) => process.stdout.write(t));
|
|
74
65
|
const cwd = options.cwd ?? process.cwd();
|
|
75
66
|
|
|
@@ -86,15 +77,11 @@ export async function runDoctorDiff(
|
|
|
86
77
|
return { code: EXIT_OK, undeclared, allChanges: all };
|
|
87
78
|
}
|
|
88
79
|
|
|
89
|
-
write(
|
|
90
|
-
`oke doctor --diff: ${undeclared.length} undeclared contract-breaking change(s)\n`,
|
|
91
|
-
);
|
|
80
|
+
write(`oke doctor --diff: ${undeclared.length} undeclared contract-breaking change(s)\n`);
|
|
92
81
|
for (const c of undeclared) {
|
|
93
82
|
write(` [contract-breaking] ${c.path}: ${c.summary}\n`);
|
|
94
83
|
}
|
|
95
|
-
write(
|
|
96
|
-
"Acknowledge intentional breaks with `breaking: true` on the owning flow.\n",
|
|
97
|
-
);
|
|
84
|
+
write("Acknowledge intentional breaks with `breaking: true` on the owning flow.\n");
|
|
98
85
|
return { code: EXIT_RUNTIME, undeclared, allChanges: all };
|
|
99
86
|
}
|
|
100
87
|
|
|
@@ -125,20 +112,16 @@ async function resolveManifests(
|
|
|
125
112
|
);
|
|
126
113
|
}
|
|
127
114
|
|
|
128
|
-
const rel =
|
|
129
|
-
options.manifestPath ??
|
|
130
|
-
(await detectManifestRel(cwd));
|
|
115
|
+
const rel = options.manifestPath ?? (await detectManifestRel(cwd));
|
|
131
116
|
if (!rel) {
|
|
132
117
|
throw new Error(
|
|
133
118
|
"oke doctor --diff: no oke.manifest.json or manifest.oke.json in cwd — pass --before/--after",
|
|
134
119
|
);
|
|
135
120
|
}
|
|
136
121
|
|
|
137
|
-
const after =
|
|
138
|
-
options.after ?? (await loadManifest(resolve(cwd, rel)));
|
|
122
|
+
const after = options.after ?? (await loadManifest(resolve(cwd, rel)));
|
|
139
123
|
|
|
140
|
-
const resolveBase =
|
|
141
|
-
options.resolveMergeBase ?? gitMergeBase;
|
|
124
|
+
const resolveBase = options.resolveMergeBase ?? gitMergeBase;
|
|
142
125
|
const readAt = options.readAtRevision ?? gitShow;
|
|
143
126
|
const mergeBase = await resolveBase(cwd, options.baseBranch);
|
|
144
127
|
if (!mergeBase) {
|
|
@@ -177,23 +160,18 @@ async function detectManifestRel(cwd: string): Promise<string | null> {
|
|
|
177
160
|
* @param cwd - Repo root
|
|
178
161
|
* @param baseBranch - Preferred base
|
|
179
162
|
*/
|
|
180
|
-
export async function gitMergeBase(
|
|
181
|
-
cwd: string,
|
|
182
|
-
baseBranch?: string,
|
|
183
|
-
): Promise<string | null> {
|
|
163
|
+
export async function gitMergeBase(cwd: string, baseBranch?: string): Promise<string | null> {
|
|
184
164
|
const candidates = baseBranch
|
|
185
165
|
? [baseBranch, ...BASE_BRANCH_CANDIDATES.filter((b) => b !== baseBranch)]
|
|
186
166
|
: [...BASE_BRANCH_CANDIDATES];
|
|
187
167
|
|
|
188
168
|
for (const base of candidates) {
|
|
189
|
-
const proc = Bun.spawn(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
proc.exited,
|
|
196
|
-
]);
|
|
169
|
+
const proc = Bun.spawn(["git", "merge-base", "HEAD", base], {
|
|
170
|
+
cwd,
|
|
171
|
+
stdout: "pipe",
|
|
172
|
+
stderr: "pipe",
|
|
173
|
+
});
|
|
174
|
+
const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
197
175
|
if (exitCode === 0) {
|
|
198
176
|
const rev = stdout.trim();
|
|
199
177
|
if (rev.length > 0) return rev;
|
|
@@ -209,20 +187,13 @@ export async function gitMergeBase(
|
|
|
209
187
|
* @param rev - Commit-ish
|
|
210
188
|
* @param path - Path relative to repo root
|
|
211
189
|
*/
|
|
212
|
-
export async function gitShow(
|
|
213
|
-
cwd: string,
|
|
214
|
-
rev: string,
|
|
215
|
-
path: string,
|
|
216
|
-
): Promise<string | null> {
|
|
190
|
+
export async function gitShow(cwd: string, rev: string, path: string): Promise<string | null> {
|
|
217
191
|
const proc = Bun.spawn(["git", "show", `${rev}:${path}`], {
|
|
218
192
|
cwd,
|
|
219
193
|
stdout: "pipe",
|
|
220
194
|
stderr: "pipe",
|
|
221
195
|
});
|
|
222
|
-
const [stdout, exitCode] = await Promise.all([
|
|
223
|
-
new Response(proc.stdout).text(),
|
|
224
|
-
proc.exited,
|
|
225
|
-
]);
|
|
196
|
+
const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
226
197
|
if (exitCode !== 0) return null;
|
|
227
198
|
return stdout;
|
|
228
199
|
}
|
package/src/cli/doctor-pii.ts
CHANGED
|
@@ -4,10 +4,7 @@
|
|
|
4
4
|
* Reuses {@link assertAllowPiiForAsk} — does not reimplement matching.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
AiPiiBuildError,
|
|
9
|
-
assertAllowPiiForAsk,
|
|
10
|
-
} from "../elements/ai/pii.ts";
|
|
7
|
+
import { AiPiiBuildError, assertAllowPiiForAsk } from "../elements/ai/pii.ts";
|
|
11
8
|
import type {
|
|
12
9
|
AiPrompt,
|
|
13
10
|
ClassificationValue,
|
|
@@ -23,9 +20,7 @@ import type { DoctorFinding } from "./doctor.ts";
|
|
|
23
20
|
*
|
|
24
21
|
* @param manifest - Extracted Manifest
|
|
25
22
|
*/
|
|
26
|
-
export function checkManifestPiiAsks(
|
|
27
|
-
manifest: Manifest,
|
|
28
|
-
): readonly DoctorFinding[] {
|
|
23
|
+
export function checkManifestPiiAsks(manifest: Manifest): readonly DoctorFinding[] {
|
|
29
24
|
const findings: DoctorFinding[] = [];
|
|
30
25
|
const classifications = collectClassifications(manifest);
|
|
31
26
|
const flows = manifest.flows ?? {};
|
package/src/cli/doctor.test.ts
CHANGED
|
@@ -14,13 +14,12 @@ describe("oke doctor", () => {
|
|
|
14
14
|
ports: [],
|
|
15
15
|
currentSchemaFingerprint: null,
|
|
16
16
|
expectedSchemaFingerprint: undefined,
|
|
17
|
+
skipDbDrift: true,
|
|
17
18
|
write: () => {},
|
|
18
19
|
});
|
|
19
20
|
expect(code).toBe(2);
|
|
20
21
|
expect(findings.some((f) => f.code === "missing_secret")).toBe(true);
|
|
21
|
-
expect(
|
|
22
|
-
findings.find((f) => f.message.includes("STRIPE_KEY")),
|
|
23
|
-
).toBeDefined();
|
|
22
|
+
expect(findings.find((f) => f.message.includes("STRIPE_KEY"))).toBeDefined();
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
test("catches a port conflict", async () => {
|
|
@@ -30,6 +29,7 @@ describe("oke doctor", () => {
|
|
|
30
29
|
isPortInUse: async (p) => p === 6530,
|
|
31
30
|
currentSchemaFingerprint: "abc",
|
|
32
31
|
expectedSchemaFingerprint: "abc",
|
|
32
|
+
skipDbDrift: true,
|
|
33
33
|
write: () => {},
|
|
34
34
|
});
|
|
35
35
|
expect(code).toBe(2);
|
|
@@ -37,17 +37,36 @@ describe("oke doctor", () => {
|
|
|
37
37
|
expect(findings[0]!.message).toContain("6530");
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
test("catches schema drift", async () => {
|
|
40
|
+
test("catches core stub schema drift", async () => {
|
|
41
41
|
const { code, findings } = await runDoctor({
|
|
42
42
|
secrets: [],
|
|
43
43
|
ports: [],
|
|
44
44
|
isPortInUse: async () => false,
|
|
45
45
|
expectedSchemaFingerprint: "aaa",
|
|
46
46
|
currentSchemaFingerprint: "bbb",
|
|
47
|
+
skipDbDrift: true,
|
|
47
48
|
write: () => {},
|
|
48
49
|
});
|
|
49
50
|
expect(code).toBe(2);
|
|
50
51
|
expect(findings.some((f) => f.code === "schema_drift")).toBe(true);
|
|
52
|
+
expect(findings.find((f) => f.code === "schema_drift")?.message).toContain(
|
|
53
|
+
"oke schema generate",
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("catches domain db_drift from drizzle-kit probe", async () => {
|
|
58
|
+
const { code, findings } = await runDoctor({
|
|
59
|
+
secrets: [],
|
|
60
|
+
ports: [],
|
|
61
|
+
isPortInUse: async () => false,
|
|
62
|
+
currentSchemaFingerprint: null,
|
|
63
|
+
skipDbDrift: false,
|
|
64
|
+
detectDbDrift: async () => ({ drifted: true, detail: "pending migrations" }),
|
|
65
|
+
write: () => {},
|
|
66
|
+
});
|
|
67
|
+
expect(code).toBe(2);
|
|
68
|
+
expect(findings.some((f) => f.code === "db_drift")).toBe(true);
|
|
69
|
+
expect(findings.find((f) => f.code === "db_drift")?.message).toContain("pending");
|
|
51
70
|
});
|
|
52
71
|
|
|
53
72
|
test("ok when secrets present, ports free, schema matches", async () => {
|
|
@@ -58,6 +77,7 @@ describe("oke doctor", () => {
|
|
|
58
77
|
isPortInUse: async () => false,
|
|
59
78
|
expectedSchemaFingerprint: "same",
|
|
60
79
|
currentSchemaFingerprint: "same",
|
|
80
|
+
skipDbDrift: true,
|
|
61
81
|
write: () => {},
|
|
62
82
|
});
|
|
63
83
|
expect(code).toBe(0);
|
|
@@ -99,6 +119,7 @@ describe("oke doctor", () => {
|
|
|
99
119
|
secrets: [],
|
|
100
120
|
ports: [],
|
|
101
121
|
currentSchemaFingerprint: null,
|
|
122
|
+
skipDbDrift: true,
|
|
102
123
|
write: () => {},
|
|
103
124
|
});
|
|
104
125
|
|
|
@@ -142,6 +163,7 @@ describe("oke doctor", () => {
|
|
|
142
163
|
ports: [],
|
|
143
164
|
expectedSchemaFingerprint: "same",
|
|
144
165
|
currentSchemaFingerprint: "same",
|
|
166
|
+
skipDbDrift: true,
|
|
145
167
|
write: () => {},
|
|
146
168
|
});
|
|
147
169
|
expect(code).toBe(0);
|
package/src/cli/doctor.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface DoctorFinding {
|
|
|
20
20
|
| "missing_secret"
|
|
21
21
|
| "port_conflict"
|
|
22
22
|
| "schema_drift"
|
|
23
|
+
| "db_drift"
|
|
23
24
|
| "tenancy"
|
|
24
25
|
| "driver"
|
|
25
26
|
| "pii_ask";
|
|
@@ -44,6 +45,16 @@ export interface DoctorOptions {
|
|
|
44
45
|
readonly expectedSchemaFingerprint?: string;
|
|
45
46
|
/** Current schema fingerprint (tests). */
|
|
46
47
|
readonly currentSchemaFingerprint?: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Inject domain DB drift probe (tests). When unset, runs drizzle-kit
|
|
50
|
+
* push explain when `drizzle.config.ts` exists.
|
|
51
|
+
*/
|
|
52
|
+
readonly detectDbDrift?: () => Promise<{
|
|
53
|
+
readonly drifted: boolean;
|
|
54
|
+
readonly detail?: string;
|
|
55
|
+
}>;
|
|
56
|
+
/** Skip live DB drift probe (default false). */
|
|
57
|
+
readonly skipDbDrift?: boolean;
|
|
47
58
|
readonly write?: (text: string) => void;
|
|
48
59
|
/** Write hints / progress (defaults to stderr). */
|
|
49
60
|
readonly writeErr?: (text: string) => void;
|
|
@@ -79,9 +90,7 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
|
|
|
79
90
|
}
|
|
80
91
|
|
|
81
92
|
const env = options.env ?? ((k) => Bun.env[k] ?? process.env[k]);
|
|
82
|
-
const secretNames =
|
|
83
|
-
options.secrets ??
|
|
84
|
-
(manifest?.vault ? Object.keys(manifest.vault) : []);
|
|
93
|
+
const secretNames = options.secrets ?? (manifest?.vault ? Object.keys(manifest.vault) : []);
|
|
85
94
|
|
|
86
95
|
for (const name of secretNames) {
|
|
87
96
|
const value = env(name);
|
|
@@ -90,9 +99,7 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
|
|
|
90
99
|
findings.push({
|
|
91
100
|
code: "missing_secret",
|
|
92
101
|
severity: "error",
|
|
93
|
-
message: description
|
|
94
|
-
? `missing secret ${name}: ${description}`
|
|
95
|
-
: `missing secret ${name}`,
|
|
102
|
+
message: description ? `missing secret ${name}: ${description}` : `missing secret ${name}`,
|
|
96
103
|
});
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -120,24 +127,42 @@ export async function runDoctor(options: DoctorOptions = {}): Promise<{
|
|
|
120
127
|
options.currentSchemaFingerprint !== undefined
|
|
121
128
|
) {
|
|
122
129
|
const expected =
|
|
123
|
-
options.expectedSchemaFingerprint ??
|
|
124
|
-
(await schemaFingerprint(cwd).catch(() => null));
|
|
130
|
+
options.expectedSchemaFingerprint ?? (await schemaFingerprint(cwd).catch(() => null));
|
|
125
131
|
if (expected !== null && current !== null && expected !== current) {
|
|
126
132
|
findings.push({
|
|
127
133
|
code: "schema_drift",
|
|
128
134
|
severity: "error",
|
|
129
135
|
message:
|
|
130
|
-
"schema drift
|
|
136
|
+
"core stub schema drift — run `oke schema generate` (schema/oke.ts; not domain migrations)",
|
|
131
137
|
});
|
|
132
138
|
} else if (expected !== null && current === null) {
|
|
133
139
|
findings.push({
|
|
134
140
|
code: "schema_drift",
|
|
135
141
|
severity: "error",
|
|
136
|
-
message: "schema/oke.ts missing — run `oke schema generate`",
|
|
142
|
+
message: "schema/oke.ts missing — run `oke schema generate` (core/plugin stubs)",
|
|
137
143
|
});
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
|
|
147
|
+
// Domain schema ↔ live DB — drizzle-kit is the single source of truth.
|
|
148
|
+
if (!options.skipDbDrift) {
|
|
149
|
+
const drizzleConfig = Bun.file(resolve(cwd, "drizzle.config.ts"));
|
|
150
|
+
if (options.detectDbDrift || (await drizzleConfig.exists())) {
|
|
151
|
+
const { detectDbDrift } = await import("./db.ts");
|
|
152
|
+
const probe = options.detectDbDrift ?? (() => detectDbDrift({ cwd }));
|
|
153
|
+
const drift = await probe();
|
|
154
|
+
if (drift.drifted) {
|
|
155
|
+
findings.push({
|
|
156
|
+
code: "db_drift",
|
|
157
|
+
severity: "error",
|
|
158
|
+
message:
|
|
159
|
+
drift.detail ??
|
|
160
|
+
"domain schema differs from the database — run `oke db generate` then `oke db migrate` (or `oke db push` in local)",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
141
166
|
if (manifest?.tenancy?.isolation) {
|
|
142
167
|
// Structural tenancy check is compile-time; doctor warns when isolation
|
|
143
168
|
// is set but no tenant resolver string is recorded on the Manifest.
|
|
@@ -205,4 +230,3 @@ Verify secrets, ports, schema drift, and PII→model egress before serving.
|
|
|
205
230
|
const { code } = await runDoctor({ manifestPath, json });
|
|
206
231
|
return code;
|
|
207
232
|
}
|
|
208
|
-
|