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
|
@@ -3,18 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, expect, test } from "bun:test";
|
|
6
|
-
import {
|
|
7
|
-
createApiKeyStore,
|
|
8
|
-
createRoleStore,
|
|
9
|
-
setRoleGrants,
|
|
10
|
-
upsertRole,
|
|
11
|
-
} from "../../auth/index.ts";
|
|
6
|
+
import { createApiKeyStore, createRoleStore, setRoleGrants, upsertRole } from "../../auth/index.ts";
|
|
12
7
|
import { memoryKvDriver } from "../../drivers/memory.ts";
|
|
13
|
-
import {
|
|
14
|
-
createGateRuntime,
|
|
15
|
-
gate,
|
|
16
|
-
type GateRuntime,
|
|
17
|
-
} from "../../elements/gate.ts";
|
|
8
|
+
import { createGateRuntime, gate, type GateRuntime } from "../../elements/gate.ts";
|
|
18
9
|
import type { Manifest } from "../../manifest/types.ts";
|
|
19
10
|
import {
|
|
20
11
|
createDefaultGateAuthStores,
|
|
@@ -65,9 +56,7 @@ async function liveRuntime(): Promise<{
|
|
|
65
56
|
}> {
|
|
66
57
|
const kv = await memoryKvDriver.open({ name: "gates-test-live" });
|
|
67
58
|
const member = gate.policy("member", ({ auth }) => Boolean(auth.verified));
|
|
68
|
-
const canBook = gate.policy("booking:create", ({ auth }) =>
|
|
69
|
-
auth.scopes.has("booking:create"),
|
|
70
|
-
);
|
|
59
|
+
const canBook = gate.policy("booking:create", ({ auth }) => auth.scopes.has("booking:create"));
|
|
71
60
|
const staff = gate.policy("staff", ({ auth }) => auth.scopes.has("staff"));
|
|
72
61
|
const fair = gate.rate({
|
|
73
62
|
strategy: "sliding-window-counter",
|
|
@@ -100,10 +89,7 @@ describe("projectGatesPanel", () => {
|
|
|
100
89
|
test("two inquiry surfaces + continuous audit + plane violations", () => {
|
|
101
90
|
const auth = createDefaultGateAuthStores();
|
|
102
91
|
// Poison an operator role with an application scope.
|
|
103
|
-
setRoleGrants(auth.roles, "role_ops", [
|
|
104
|
-
"console:store.sql:read",
|
|
105
|
-
"booking:create",
|
|
106
|
-
]);
|
|
92
|
+
setRoleGrants(auth.roles, "role_ops", ["console:store.sql:read", "booking:create"]);
|
|
107
93
|
|
|
108
94
|
const projection = projectGatesPanel({
|
|
109
95
|
manifest: MANIFEST,
|
|
@@ -119,9 +105,7 @@ describe("projectGatesPanel", () => {
|
|
|
119
105
|
},
|
|
120
106
|
],
|
|
121
107
|
operatorRoles: new Map([["op_1", ["role_ops"]]]),
|
|
122
|
-
operators: new Map([
|
|
123
|
-
["op_1", { name: "Ops", email: "ops@example.com" }],
|
|
124
|
-
]),
|
|
108
|
+
operators: new Map([["op_1", { name: "Ops", email: "ops@example.com" }]]),
|
|
125
109
|
roleMembers: auth.roleMembers,
|
|
126
110
|
});
|
|
127
111
|
|
|
@@ -136,16 +120,10 @@ describe("projectGatesPanel", () => {
|
|
|
136
120
|
expect(projection.audit.emptyRoles).toContain("role_staff");
|
|
137
121
|
|
|
138
122
|
// Operator with application scope is a violation, never a principal row.
|
|
139
|
-
expect(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
).toBe(true);
|
|
144
|
-
expect(
|
|
145
|
-
projection.principals.some(
|
|
146
|
-
(p) => p.kind === "role" && p.id === "role_ops",
|
|
147
|
-
),
|
|
148
|
-
).toBe(false);
|
|
123
|
+
expect(projection.violations.some((v) => v.applicationScopes.includes("booking:create"))).toBe(
|
|
124
|
+
true,
|
|
125
|
+
);
|
|
126
|
+
expect(projection.principals.some((p) => p.kind === "role" && p.id === "role_ops")).toBe(false);
|
|
149
127
|
|
|
150
128
|
// Clean user principals remain rows.
|
|
151
129
|
expect(projection.principals.some((p) => p.kind === "user")).toBe(true);
|
|
@@ -201,10 +179,7 @@ describe("simulateGates — evaluate only", () => {
|
|
|
201
179
|
expect(denied.allowed).toBe(false);
|
|
202
180
|
// member passes (verified); first denial is booking:create — chain stops.
|
|
203
181
|
expect(denied.deniedAt).toBe("booking:create");
|
|
204
|
-
expect(denied.evaluations.map((e) => e.name)).toEqual([
|
|
205
|
-
"member",
|
|
206
|
-
"booking:create",
|
|
207
|
-
]);
|
|
182
|
+
expect(denied.evaluations.map((e) => e.name)).toEqual(["member", "booking:create"]);
|
|
208
183
|
expect(denied.denial?.code).toBe("Forbidden");
|
|
209
184
|
expect(denied.denial?.status).toBe(403);
|
|
210
185
|
expect(denied.denial?.data).toMatchObject({ gate: "booking:create" });
|
|
@@ -235,18 +210,9 @@ describe("simulateGates — evaluate only", () => {
|
|
|
235
210
|
meta: { userId: "user_demo" },
|
|
236
211
|
};
|
|
237
212
|
try {
|
|
238
|
-
await runtime.check(
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
);
|
|
242
|
-
await runtime.check(
|
|
243
|
-
["member", "booking:create", "rate:sliding-window-counter:2/1m"],
|
|
244
|
-
ctx,
|
|
245
|
-
);
|
|
246
|
-
const liveDenied = await runtime.check(
|
|
247
|
-
["rate:sliding-window-counter:2/1m"],
|
|
248
|
-
ctx,
|
|
249
|
-
);
|
|
213
|
+
await runtime.check(["member", "booking:create", "rate:sliding-window-counter:2/1m"], ctx);
|
|
214
|
+
await runtime.check(["member", "booking:create", "rate:sliding-window-counter:2/1m"], ctx);
|
|
215
|
+
const liveDenied = await runtime.check(["rate:sliding-window-counter:2/1m"], ctx);
|
|
250
216
|
expect(liveDenied[0]?.allowed).toBe(false);
|
|
251
217
|
|
|
252
218
|
// Simulate clones decls onto ephemeral KV — does not consume live budget.
|
|
@@ -319,9 +285,7 @@ describe("simulateGates — evaluate only", () => {
|
|
|
319
285
|
operator: ctx.operator,
|
|
320
286
|
});
|
|
321
287
|
expect(mapped.error.code).toBe("RateLimited");
|
|
322
|
-
expect(
|
|
323
|
-
(mapped.error.data as { retryAfterMs: number }).retryAfterMs,
|
|
324
|
-
).toBeGreaterThan(0);
|
|
288
|
+
expect((mapped.error.data as { retryAfterMs: number }).retryAfterMs).toBeGreaterThan(0);
|
|
325
289
|
await kv.close();
|
|
326
290
|
});
|
|
327
291
|
|
|
@@ -31,11 +31,7 @@ import {
|
|
|
31
31
|
import { statusForFailure } from "../../compiler/response.ts";
|
|
32
32
|
import { gateDenialFailure } from "../../kernel/index.ts";
|
|
33
33
|
import { diffManifest } from "../../manifest/diff.ts";
|
|
34
|
-
import type {
|
|
35
|
-
Gate as ManifestGate,
|
|
36
|
-
Manifest,
|
|
37
|
-
ManifestChange,
|
|
38
|
-
} from "../../manifest/types.ts";
|
|
34
|
+
import type { Gate as ManifestGate, Manifest, ManifestChange } from "../../manifest/types.ts";
|
|
39
35
|
|
|
40
36
|
/** Identity slice needed for Gates (avoids circular import with state). */
|
|
41
37
|
export interface GatesIdentity {
|
|
@@ -154,10 +150,7 @@ export interface ProjectGatesOptions {
|
|
|
154
150
|
/** operatorId → role ids. */
|
|
155
151
|
readonly operatorRoles: ReadonlyMap<string, readonly string[]>;
|
|
156
152
|
/** operatorId → { name, email }. */
|
|
157
|
-
readonly operators: ReadonlyMap<
|
|
158
|
-
string,
|
|
159
|
-
{ readonly name: string; readonly email: string }
|
|
160
|
-
>;
|
|
153
|
+
readonly operators: ReadonlyMap<string, { readonly name: string; readonly email: string }>;
|
|
161
154
|
/** roleId → member principal ids (users + operators). */
|
|
162
155
|
readonly roleMembers: ReadonlyMap<string, readonly string[]>;
|
|
163
156
|
/** Previous Manifest for deploy-diff widenings (optional). */
|
|
@@ -190,9 +183,7 @@ export function isApplicationScope(action: string): boolean {
|
|
|
190
183
|
*
|
|
191
184
|
* @param options - Manifest, roles, keys, identities, operators
|
|
192
185
|
*/
|
|
193
|
-
export function projectGatesPanel(
|
|
194
|
-
options: ProjectGatesOptions,
|
|
195
|
-
): GatesPanelProjection {
|
|
186
|
+
export function projectGatesPanel(options: ProjectGatesOptions): GatesPanelProjection {
|
|
196
187
|
const manifest = options.manifest;
|
|
197
188
|
const moduleActions = manifest ? deriveModuleActions(manifest) : [];
|
|
198
189
|
const flows = projectFlows(manifest);
|
|
@@ -205,10 +196,7 @@ export function projectGatesPanel(
|
|
|
205
196
|
roles: options.roles,
|
|
206
197
|
roleMembers: options.roleMembers,
|
|
207
198
|
});
|
|
208
|
-
const widenings = projectWidenings(
|
|
209
|
-
options.previousManifest ?? null,
|
|
210
|
-
manifest,
|
|
211
|
-
);
|
|
199
|
+
const widenings = projectWidenings(options.previousManifest ?? null, manifest);
|
|
212
200
|
|
|
213
201
|
return {
|
|
214
202
|
moduleActions,
|
|
@@ -228,9 +216,7 @@ export function projectGatesPanel(
|
|
|
228
216
|
*
|
|
229
217
|
* @param options - Flow, principal, runtime
|
|
230
218
|
*/
|
|
231
|
-
export async function simulateGates(
|
|
232
|
-
options: SimulateGatesOptions,
|
|
233
|
-
): Promise<SimulateGatesResult> {
|
|
219
|
+
export async function simulateGates(options: SimulateGatesOptions): Promise<SimulateGatesResult> {
|
|
234
220
|
const flow = options.manifest?.flows?.[options.flowId];
|
|
235
221
|
if (!flow) {
|
|
236
222
|
return {
|
|
@@ -337,9 +323,7 @@ export async function powersForPrincipal(options: {
|
|
|
337
323
|
const flows = projectFlows(options.manifest);
|
|
338
324
|
let scopes: string[] = [];
|
|
339
325
|
if (options.kind === "user") {
|
|
340
|
-
scopes = [
|
|
341
|
-
...(options.identities.find((u) => u.id === options.id)?.scopes ?? []),
|
|
342
|
-
];
|
|
326
|
+
scopes = [...(options.identities.find((u) => u.id === options.id)?.scopes ?? [])];
|
|
343
327
|
} else if (options.kind === "role") {
|
|
344
328
|
scopes = [...(options.roles.grants.get(options.id) ?? [])];
|
|
345
329
|
} else {
|
|
@@ -352,10 +336,7 @@ export async function powersForPrincipal(options: {
|
|
|
352
336
|
|
|
353
337
|
for (const flow of flows) {
|
|
354
338
|
// User/key inquiry is application power; skip operator-plane flows.
|
|
355
|
-
if (
|
|
356
|
-
flow.plane === "operator" &&
|
|
357
|
-
(options.kind === "user" || options.kind === "key")
|
|
358
|
-
) {
|
|
339
|
+
if (flow.plane === "operator" && (options.kind === "user" || options.kind === "key")) {
|
|
359
340
|
continue;
|
|
360
341
|
}
|
|
361
342
|
const result = await simulateGates({
|
|
@@ -426,12 +407,7 @@ export function createDefaultGateAuthStores(): {
|
|
|
426
407
|
description: "Console operators",
|
|
427
408
|
});
|
|
428
409
|
setRoleGrants(roles, "role_member", ["member", "booking:create"]);
|
|
429
|
-
setRoleGrants(roles, "role_staff", [
|
|
430
|
-
"member",
|
|
431
|
-
"booking:create",
|
|
432
|
-
"staff",
|
|
433
|
-
"reports:export",
|
|
434
|
-
]);
|
|
410
|
+
setRoleGrants(roles, "role_staff", ["member", "booking:create", "staff", "reports:export"]);
|
|
435
411
|
setRoleGrants(roles, "role_ops", [
|
|
436
412
|
"console:store.sql:read",
|
|
437
413
|
"console:store.sql:write",
|
|
@@ -508,9 +484,7 @@ function projectGateDefs(
|
|
|
508
484
|
max: def.max,
|
|
509
485
|
per: def.per,
|
|
510
486
|
keyBy: def.keyBy,
|
|
511
|
-
overridable: Boolean(
|
|
512
|
-
(def as ManifestGate & { overridable?: boolean }).overridable,
|
|
513
|
-
),
|
|
487
|
+
overridable: Boolean((def as ManifestGate & { overridable?: boolean }).overridable),
|
|
514
488
|
attachedTo: attached.get(name) ?? [],
|
|
515
489
|
});
|
|
516
490
|
}
|
|
@@ -603,9 +577,7 @@ function projectPrincipals(options: ProjectGatesOptions): {
|
|
|
603
577
|
// Operators: only those with clean console scopes appear… but Access owns
|
|
604
578
|
// operator listing. Gates only surfaces the violation when they hold app scopes.
|
|
605
579
|
for (const [operatorId, roleIds] of options.operatorRoles) {
|
|
606
|
-
const scopes = [
|
|
607
|
-
...scopesForRoles(options.roles, roleIds, "operator"),
|
|
608
|
-
].sort();
|
|
580
|
+
const scopes = [...scopesForRoles(options.roles, roleIds, "operator")].sort();
|
|
609
581
|
const appScopes = scopes.filter(isApplicationScope);
|
|
610
582
|
if (appScopes.length === 0) continue;
|
|
611
583
|
const op = options.operators.get(operatorId);
|
|
@@ -653,9 +625,7 @@ function buildAudit(options: {
|
|
|
653
625
|
.map((g) => g.name)
|
|
654
626
|
.sort((a, b) => a.localeCompare(b));
|
|
655
627
|
|
|
656
|
-
const unguardedFlows = options.flows
|
|
657
|
-
.filter((f) => f.unguarded)
|
|
658
|
-
.map((f) => f.flowId);
|
|
628
|
+
const unguardedFlows = options.flows.filter((f) => f.unguarded).map((f) => f.flowId);
|
|
659
629
|
|
|
660
630
|
return {
|
|
661
631
|
unguardedFlows,
|
|
@@ -665,10 +635,7 @@ function buildAudit(options: {
|
|
|
665
635
|
};
|
|
666
636
|
}
|
|
667
637
|
|
|
668
|
-
function projectWidenings(
|
|
669
|
-
before: Manifest | null,
|
|
670
|
-
after: Manifest | null,
|
|
671
|
-
): ManifestChange[] {
|
|
638
|
+
function projectWidenings(before: Manifest | null, after: Manifest | null): ManifestChange[] {
|
|
672
639
|
if (!before || !after) return [];
|
|
673
640
|
const diff = diffManifest(before, after);
|
|
674
641
|
return diff.changes.filter((c) => c.category === "permission-widening");
|
|
@@ -831,9 +798,7 @@ function declFromManifestGate(name: string, def: ManifestGate): GateDecl {
|
|
|
831
798
|
max: def.max ?? parsed.max,
|
|
832
799
|
per: def.per ?? parsed.per,
|
|
833
800
|
keyBy: def.keyBy,
|
|
834
|
-
overridable: Boolean(
|
|
835
|
-
(def as ManifestGate & { overridable?: boolean }).overridable,
|
|
836
|
-
),
|
|
801
|
+
overridable: Boolean((def as ManifestGate & { overridable?: boolean }).overridable),
|
|
837
802
|
};
|
|
838
803
|
}
|
|
839
804
|
|
|
@@ -76,16 +76,9 @@ export {
|
|
|
76
76
|
resolveConsoleSecret,
|
|
77
77
|
type ConsolePersistence,
|
|
78
78
|
} from "./operator-db.ts";
|
|
79
|
-
export {
|
|
80
|
-
createConsoleBindings,
|
|
81
|
-
} from "./flows.ts";
|
|
79
|
+
export { createConsoleBindings } from "./flows.ts";
|
|
82
80
|
export { PUBLIC_CONSOLE_FLOWS } from "./public-flows.ts";
|
|
83
|
-
export {
|
|
84
|
-
createLiveWebsocket,
|
|
85
|
-
feedManifest,
|
|
86
|
-
subscribeLive,
|
|
87
|
-
type ConsoleLiveData,
|
|
88
|
-
} from "./live.ts";
|
|
81
|
+
export { createLiveWebsocket, feedManifest, subscribeLive, type ConsoleLiveData } from "./live.ts";
|
|
89
82
|
export { consolePlugin } from "./plugin.ts";
|
|
90
83
|
export {
|
|
91
84
|
CONSOLE_COOKIES,
|
|
@@ -22,10 +22,7 @@ export interface ConsoleLiveData {
|
|
|
22
22
|
*/
|
|
23
23
|
export interface ConsoleServerWebSocket<T = undefined> {
|
|
24
24
|
readonly data: T;
|
|
25
|
-
send(
|
|
26
|
-
data: string | ArrayBuffer | Uint8Array,
|
|
27
|
-
compress?: boolean,
|
|
28
|
-
): number;
|
|
25
|
+
send(data: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
/**
|
|
@@ -52,16 +49,10 @@ export function subscribeLive(
|
|
|
52
49
|
*/
|
|
53
50
|
export function createLiveWebsocket(state: ConsoleState): {
|
|
54
51
|
readonly open: (ws: ConsoleServerWebSocket<ConsoleLiveData>) => void;
|
|
55
|
-
readonly message: (
|
|
56
|
-
ws: ConsoleServerWebSocket<ConsoleLiveData>,
|
|
57
|
-
message: string | Buffer,
|
|
58
|
-
) => void;
|
|
52
|
+
readonly message: (ws: ConsoleServerWebSocket<ConsoleLiveData>, message: string | Buffer) => void;
|
|
59
53
|
readonly close: (ws: ConsoleServerWebSocket<ConsoleLiveData>) => void;
|
|
60
54
|
} {
|
|
61
|
-
const unsubs = new WeakMap<
|
|
62
|
-
ConsoleServerWebSocket<ConsoleLiveData>,
|
|
63
|
-
() => void
|
|
64
|
-
>();
|
|
55
|
+
const unsubs = new WeakMap<ConsoleServerWebSocket<ConsoleLiveData>, () => void>();
|
|
65
56
|
|
|
66
57
|
return {
|
|
67
58
|
open(ws) {
|
|
@@ -9,18 +9,13 @@ import { join } from "node:path";
|
|
|
9
9
|
import { createOperator } from "../../auth/operator.ts";
|
|
10
10
|
import { issueSession, verifyAccess } from "../../auth/sessions.ts";
|
|
11
11
|
import { bootConsoleApp, createConsoleApp } from "./app.ts";
|
|
12
|
-
import {
|
|
13
|
-
openConsolePersistence,
|
|
14
|
-
resolveConsoleSecret,
|
|
15
|
-
} from "./operator-db.ts";
|
|
12
|
+
import { openConsolePersistence, resolveConsoleSecret } from "./operator-db.ts";
|
|
16
13
|
|
|
17
14
|
describe("console operator persistence", () => {
|
|
18
15
|
const dirs: string[] = [];
|
|
19
16
|
|
|
20
17
|
afterEach(async () => {
|
|
21
|
-
await Promise.all(
|
|
22
|
-
dirs.splice(0).map((d) => rm(d, { recursive: true, force: true })),
|
|
23
|
-
);
|
|
18
|
+
await Promise.all(dirs.splice(0).map((d) => rm(d, { recursive: true, force: true })));
|
|
24
19
|
});
|
|
25
20
|
|
|
26
21
|
test("secret is stable across resolveConsoleSecret calls", async () => {
|
|
@@ -48,9 +43,7 @@ describe("console operator persistence", () => {
|
|
|
48
43
|
|
|
49
44
|
const second = await openConsolePersistence(cwd);
|
|
50
45
|
expect(second.operators.operators.size).toBe(1);
|
|
51
|
-
expect(second.operators.operators.get(op.id)?.email).toBe(
|
|
52
|
-
"ops@example.com",
|
|
53
|
-
);
|
|
46
|
+
expect(second.operators.operators.get(op.id)?.email).toBe("ops@example.com");
|
|
54
47
|
expect(second.operators.credentials.has(op.id)).toBe(true);
|
|
55
48
|
|
|
56
49
|
const printed: string[] = [];
|
|
@@ -97,11 +90,7 @@ describe("console operator persistence", () => {
|
|
|
97
90
|
|
|
98
91
|
const second = await openConsolePersistence(cwd);
|
|
99
92
|
expect(second.sessions.sessions.size).toBe(1);
|
|
100
|
-
const claims = await verifyAccess(
|
|
101
|
-
second.sessions,
|
|
102
|
-
second.secret,
|
|
103
|
-
issued.accessToken,
|
|
104
|
-
);
|
|
93
|
+
const claims = await verifyAccess(second.sessions, second.secret, issued.accessToken);
|
|
105
94
|
expect(claims.sub).toBe(op.id);
|
|
106
95
|
second.close();
|
|
107
96
|
});
|
|
@@ -9,14 +9,8 @@
|
|
|
9
9
|
import { mkdirSync } from "node:fs";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { Database } from "bun:sqlite";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
type OperatorStore,
|
|
15
|
-
} from "../../auth/operator.ts";
|
|
16
|
-
import {
|
|
17
|
-
createSessionStore,
|
|
18
|
-
type SessionStore,
|
|
19
|
-
} from "../../auth/sessions.ts";
|
|
12
|
+
import { createOperatorStore, type OperatorStore } from "../../auth/operator.ts";
|
|
13
|
+
import { createSessionStore, type SessionStore } from "../../auth/sessions.ts";
|
|
20
14
|
import type {
|
|
21
15
|
OperatorCredentialRow,
|
|
22
16
|
OperatorRow,
|
|
@@ -72,10 +66,7 @@ export function consoleOkePaths(cwd: string): {
|
|
|
72
66
|
* @param cwd - Project root
|
|
73
67
|
* @param envSecret - Optional `OKE_CONSOLE_SECRET` override
|
|
74
68
|
*/
|
|
75
|
-
export async function resolveConsoleSecret(
|
|
76
|
-
cwd: string,
|
|
77
|
-
envSecret?: string,
|
|
78
|
-
): Promise<string> {
|
|
69
|
+
export async function resolveConsoleSecret(cwd: string, envSecret?: string): Promise<string> {
|
|
79
70
|
if (envSecret !== undefined && envSecret.length > 0) return envSecret;
|
|
80
71
|
const paths = consoleOkePaths(cwd);
|
|
81
72
|
const file = Bun.file(paths.secret);
|
|
@@ -85,9 +76,7 @@ export async function resolveConsoleSecret(
|
|
|
85
76
|
}
|
|
86
77
|
const bytes = new Uint8Array(32);
|
|
87
78
|
crypto.getRandomValues(bytes);
|
|
88
|
-
const secret = [...bytes]
|
|
89
|
-
.map((b) => b.toString(16).padStart(2, "0"))
|
|
90
|
-
.join("");
|
|
79
|
+
const secret = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
91
80
|
await Bun.write(paths.secret, `${secret}\n`);
|
|
92
81
|
return secret;
|
|
93
82
|
}
|
|
@@ -350,9 +339,7 @@ export function loadOperatorStore(db: Database): OperatorStore {
|
|
|
350
339
|
}
|
|
351
340
|
|
|
352
341
|
const ssoRows = db
|
|
353
|
-
.query(
|
|
354
|
-
`SELECT operator_id, provider, subject FROM ${AUTH_TABLES.operatorSsoLinks}`,
|
|
355
|
-
)
|
|
342
|
+
.query(`SELECT operator_id, provider, subject FROM ${AUTH_TABLES.operatorSsoLinks}`)
|
|
356
343
|
.all() as Array<{
|
|
357
344
|
operator_id: string;
|
|
358
345
|
provider: string;
|
|
@@ -371,9 +358,7 @@ export function loadOperatorStore(db: Database): OperatorStore {
|
|
|
371
358
|
}
|
|
372
359
|
|
|
373
360
|
const roleRows = db
|
|
374
|
-
.query(
|
|
375
|
-
`SELECT operator_id, role FROM ${AUTH_TABLES.operatorRoles}`,
|
|
376
|
-
)
|
|
361
|
+
.query(`SELECT operator_id, role FROM ${AUTH_TABLES.operatorRoles}`)
|
|
377
362
|
.all() as Array<{ operator_id: string; role: string }>;
|
|
378
363
|
|
|
379
364
|
for (const row of roleRows) {
|
|
@@ -392,11 +377,7 @@ export function loadOperatorStore(db: Database): OperatorStore {
|
|
|
392
377
|
* @param store - In-memory store
|
|
393
378
|
* @param operatorId - Operator id
|
|
394
379
|
*/
|
|
395
|
-
export function persistOperator(
|
|
396
|
-
db: Database,
|
|
397
|
-
store: OperatorStore,
|
|
398
|
-
operatorId: string,
|
|
399
|
-
): void {
|
|
380
|
+
export function persistOperator(db: Database, store: OperatorStore, operatorId: string): void {
|
|
400
381
|
const op = store.operators.get(operatorId);
|
|
401
382
|
if (!op) {
|
|
402
383
|
throw new Error(`oke console: unknown operator ${operatorId}`);
|
|
@@ -442,9 +423,9 @@ export function persistOperator(
|
|
|
442
423
|
$enabled: cred.loginEnabled ? 1 : 0,
|
|
443
424
|
});
|
|
444
425
|
|
|
445
|
-
db.query(
|
|
446
|
-
|
|
447
|
-
|
|
426
|
+
db.query(`DELETE FROM ${AUTH_TABLES.operatorSsoLinks} WHERE operator_id = $id`).run({
|
|
427
|
+
$id: operatorId,
|
|
428
|
+
});
|
|
448
429
|
const insertSso = db.query(
|
|
449
430
|
`INSERT INTO ${AUTH_TABLES.operatorSsoLinks} (operator_id, provider, subject)
|
|
450
431
|
VALUES ($id, $provider, $subject)`,
|
|
@@ -457,9 +438,9 @@ export function persistOperator(
|
|
|
457
438
|
});
|
|
458
439
|
}
|
|
459
440
|
|
|
460
|
-
db.query(
|
|
461
|
-
|
|
462
|
-
|
|
441
|
+
db.query(`DELETE FROM ${AUTH_TABLES.operatorRoles} WHERE operator_id = $id`).run({
|
|
442
|
+
$id: operatorId,
|
|
443
|
+
});
|
|
463
444
|
const insertRole = db.query(
|
|
464
445
|
`INSERT INTO ${AUTH_TABLES.operatorRoles} (operator_id, role)
|
|
465
446
|
VALUES ($id, $role)`,
|
|
@@ -4,12 +4,7 @@
|
|
|
4
4
|
* Uses only the public plugin API (unified-theory §14).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
fail,
|
|
9
|
-
plugin,
|
|
10
|
-
type Fx,
|
|
11
|
-
type PluginDef,
|
|
12
|
-
} from "../../kernel/index.ts";
|
|
7
|
+
import { fail, plugin, type Fx, type PluginDef } from "../../kernel/index.ts";
|
|
13
8
|
import { PUBLIC_CONSOLE_FLOWS } from "./public-flows.ts";
|
|
14
9
|
|
|
15
10
|
/**
|
|
@@ -18,53 +13,55 @@ import { PUBLIC_CONSOLE_FLOWS } from "./public-flows.ts";
|
|
|
18
13
|
* @returns Plugin definition
|
|
19
14
|
*/
|
|
20
15
|
export function consolePlugin(): PluginDef {
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
16
|
+
return (
|
|
17
|
+
plugin("console", { version: "0.0.1" })
|
|
18
|
+
.consolePanel({
|
|
19
|
+
id: "overview",
|
|
20
|
+
title: "Overview",
|
|
21
|
+
entry: "./panels/overview.js",
|
|
22
|
+
})
|
|
23
|
+
.consolePanel({
|
|
24
|
+
id: "traces",
|
|
25
|
+
title: "Traces",
|
|
26
|
+
entry: "./panels/traces.js",
|
|
27
|
+
})
|
|
28
|
+
.table("oke_console_prefs", undefined, { plane: "operator" })
|
|
29
|
+
// Public flows must not 401 when a stale Bearer/cookie is present —
|
|
30
|
+
// kernel onAuth verifies before beforeHandle's public-flow exemption.
|
|
31
|
+
// Rebuild from URL: `new Request(req, { headers })` re-copies Authorization.
|
|
32
|
+
.hook("onRequest", (ctx) => {
|
|
33
|
+
if (!PUBLIC_CONSOLE_FLOWS.has(ctx.flow.name) || !ctx.request) return;
|
|
34
|
+
const auth = ctx.request.headers.get("authorization");
|
|
35
|
+
if (!auth?.startsWith("Bearer ")) return;
|
|
36
|
+
const headers = new Headers();
|
|
37
|
+
for (const [key, value] of ctx.request.headers) {
|
|
38
|
+
if (key.toLowerCase() === "authorization") continue;
|
|
39
|
+
headers.set(key, value);
|
|
40
|
+
}
|
|
41
|
+
const method = ctx.request.method;
|
|
42
|
+
const init: RequestInit = { method, headers };
|
|
43
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
44
|
+
init.body = ctx.request.body;
|
|
45
|
+
(init as RequestInit & { duplex: "half" }).duplex = "half";
|
|
46
|
+
}
|
|
47
|
+
ctx.request = new Request(ctx.request.url, init);
|
|
48
|
+
})
|
|
49
|
+
.hook("beforeHandle", (ctx, fxOrErr) => {
|
|
50
|
+
const fx = fxOrErr as Fx;
|
|
51
|
+
const name = ctx.flow.name;
|
|
52
|
+
const plane = ctx.flow.plane ?? "user";
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
54
|
+
// Application principals never reach operator-plane flows.
|
|
55
|
+
if (plane === "operator" && fx.auth.userId && !fx.operator.id) {
|
|
56
|
+
return fail("Forbidden", {
|
|
57
|
+
reason: "application principal cannot reach a console flow",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
if (PUBLIC_CONSOLE_FLOWS.has(name)) return;
|
|
62
|
+
if (plane === "operator" && !fx.operator.id) {
|
|
63
|
+
return fail("Unauthorized", {});
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
);
|
|
70
67
|
}
|
|
@@ -88,9 +88,7 @@ describe("projectPluginsList", () => {
|
|
|
88
88
|
|
|
89
89
|
expect(byId.audit?.capabilityDiff[0]?.summary).toContain("widened");
|
|
90
90
|
expect(byId.auth?.supplyChain.lifecycleScripts.state).toBe("not-applicable");
|
|
91
|
-
expect(byId["oke-slack"]?.supplyChain.releaseCooldown.state).not.toBe(
|
|
92
|
-
"not-applicable",
|
|
93
|
-
);
|
|
91
|
+
expect(byId["oke-slack"]?.supplyChain.releaseCooldown.state).not.toBe("not-applicable");
|
|
94
92
|
});
|
|
95
93
|
|
|
96
94
|
test("privacy on from runs.redact", async () => {
|
|
@@ -124,8 +122,6 @@ describe("capability diff filter", () => {
|
|
|
124
122
|
},
|
|
125
123
|
]);
|
|
126
124
|
expect(grouped.audit).toHaveLength(1);
|
|
127
|
-
expect(
|
|
128
|
-
filterCapabilityDiffForPlugin(grouped.audit!, "audit"),
|
|
129
|
-
).toHaveLength(1);
|
|
125
|
+
expect(filterCapabilityDiffForPlugin(grouped.audit!, "audit")).toHaveLength(1);
|
|
130
126
|
});
|
|
131
127
|
});
|