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
|
@@ -69,34 +69,23 @@ export function AiPanel() {
|
|
|
69
69
|
);
|
|
70
70
|
const promptName = search.prompt ?? prompts[0]?.name;
|
|
71
71
|
const versions = useMemo(
|
|
72
|
-
() =>
|
|
73
|
-
promptName
|
|
74
|
-
? versionsForPrompt(data?.versions ?? [], promptName)
|
|
75
|
-
: [],
|
|
72
|
+
() => (promptName ? versionsForPrompt(data?.versions ?? [], promptName) : []),
|
|
76
73
|
[data?.versions, promptName],
|
|
77
74
|
);
|
|
78
75
|
const selectedVersion =
|
|
79
|
-
versions.find((v) => v.version === search.version) ??
|
|
80
|
-
|
|
81
|
-
const baseline =
|
|
82
|
-
versions.length >= 2
|
|
83
|
-
? versions[versions.length - 2]
|
|
84
|
-
: versions[0];
|
|
76
|
+
versions.find((v) => v.version === search.version) ?? versions[versions.length - 1];
|
|
77
|
+
const baseline = versions.length >= 2 ? versions[versions.length - 2] : versions[0];
|
|
85
78
|
const decision =
|
|
86
|
-
baseline &&
|
|
87
|
-
selectedVersion &&
|
|
88
|
-
baseline.version !== selectedVersion.version
|
|
79
|
+
baseline && selectedVersion && baseline.version !== selectedVersion.version
|
|
89
80
|
? promotionDecision(baseline, selectedVersion)
|
|
90
81
|
: null;
|
|
91
82
|
|
|
92
83
|
const agentName = search.agent ?? agents[0]?.name;
|
|
93
84
|
const agentRuns = useMemo(
|
|
94
|
-
() =>
|
|
95
|
-
agentName ? runsForAgent(data?.agentRuns ?? [], agentName) : [],
|
|
85
|
+
() => (agentName ? runsForAgent(data?.agentRuns ?? [], agentName) : []),
|
|
96
86
|
[data?.agentRuns, agentName],
|
|
97
87
|
);
|
|
98
|
-
const openRun =
|
|
99
|
-
agentRuns.find((r) => r.id === search.run) ?? agentRuns[0];
|
|
88
|
+
const openRun = agentRuns.find((r) => r.id === search.run) ?? agentRuns[0];
|
|
100
89
|
const pii = allowPiiStanding(data?.allowPii ?? []);
|
|
101
90
|
const cataloguePrompt = prompts.find((p) => p.name === promptName);
|
|
102
91
|
|
|
@@ -105,8 +94,8 @@ export function AiPanel() {
|
|
|
105
94
|
<header className="shrink-0 border-b border-[var(--oke-line)] px-4 py-3">
|
|
106
95
|
<h1 className="text-base font-medium text-[var(--oke-fg)]">AI</h1>
|
|
107
96
|
<p className="text-sm text-[var(--oke-muted)]">
|
|
108
|
-
Distributions per prompt version — cost, latency, eval score.
|
|
109
|
-
|
|
97
|
+
Distributions per prompt version — cost, latency, eval score. Schema-invalid is its own
|
|
98
|
+
class.
|
|
110
99
|
</p>
|
|
111
100
|
<label className="mt-2 flex max-w-sm flex-col gap-1 text-sm">
|
|
112
101
|
<span className="text-[var(--oke-muted)]">Filter</span>
|
|
@@ -140,21 +129,11 @@ export function AiPanel() {
|
|
|
140
129
|
? "bg-[var(--oke-line)] text-[var(--oke-fg)]"
|
|
141
130
|
: "text-[var(--oke-muted)]",
|
|
142
131
|
)}
|
|
143
|
-
onClick={() =>
|
|
144
|
-
setSearch(
|
|
145
|
-
openPromptVersion(
|
|
146
|
-
search,
|
|
147
|
-
p.name,
|
|
148
|
-
p.version ?? 0,
|
|
149
|
-
),
|
|
150
|
-
)
|
|
151
|
-
}
|
|
132
|
+
onClick={() => setSearch(openPromptVersion(search, p.name, p.version ?? 0))}
|
|
152
133
|
>
|
|
153
134
|
{p.name}
|
|
154
135
|
{p.version !== undefined ? (
|
|
155
|
-
<span className="ml-1 font-mono text-xs">
|
|
156
|
-
@{p.version}
|
|
157
|
-
</span>
|
|
136
|
+
<span className="ml-1 font-mono text-xs">@{p.version}</span>
|
|
158
137
|
) : null}
|
|
159
138
|
</button>
|
|
160
139
|
</li>
|
|
@@ -162,9 +141,7 @@ export function AiPanel() {
|
|
|
162
141
|
</ul>
|
|
163
142
|
</section>
|
|
164
143
|
<section aria-label="Agents" className="p-3">
|
|
165
|
-
<h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">
|
|
166
|
-
Agents
|
|
167
|
-
</h2>
|
|
144
|
+
<h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">Agents</h2>
|
|
168
145
|
<ul className="space-y-1">
|
|
169
146
|
{agents.map((a) => (
|
|
170
147
|
<li key={a.name}>
|
|
@@ -194,12 +171,8 @@ export function AiPanel() {
|
|
|
194
171
|
</aside>
|
|
195
172
|
|
|
196
173
|
<main id="ai-main" className="min-h-0 overflow-y-auto p-4">
|
|
197
|
-
{listQuery.isLoading ? (
|
|
198
|
-
|
|
199
|
-
) : null}
|
|
200
|
-
{listQuery.isError ? (
|
|
201
|
-
<p role="alert">Failed to load AI projection</p>
|
|
202
|
-
) : null}
|
|
174
|
+
{listQuery.isLoading ? <p className="text-[var(--oke-muted)]">Loading…</p> : null}
|
|
175
|
+
{listQuery.isError ? <p role="alert">Failed to load AI projection</p> : null}
|
|
203
176
|
|
|
204
177
|
{selectedVersion ? (
|
|
205
178
|
<VersionDistributions
|
|
@@ -209,23 +182,17 @@ export function AiPanel() {
|
|
|
209
182
|
setSearch(openPromptVersion(search, selectedVersion.prompt, v))
|
|
210
183
|
}
|
|
211
184
|
catalogueHref={
|
|
212
|
-
cataloguePrompt
|
|
213
|
-
? manifestDiffHref(cataloguePrompt.manifestDiffPath)
|
|
214
|
-
: null
|
|
185
|
+
cataloguePrompt ? manifestDiffHref(cataloguePrompt.manifestDiffPath) : null
|
|
215
186
|
}
|
|
216
187
|
decision={decision}
|
|
217
188
|
/>
|
|
218
189
|
) : (
|
|
219
|
-
<p className="text-[var(--oke-muted)]">
|
|
220
|
-
No prompt versions with samples yet.
|
|
221
|
-
</p>
|
|
190
|
+
<p className="text-[var(--oke-muted)]">No prompt versions with samples yet.</p>
|
|
222
191
|
)}
|
|
223
192
|
|
|
224
193
|
{openRun ? (
|
|
225
194
|
<section aria-label="Agent run trail" className="mt-8">
|
|
226
|
-
<h2 className="mb-2 text-sm font-medium">
|
|
227
|
-
Agent run · {openRun.agent}
|
|
228
|
-
</h2>
|
|
195
|
+
<h2 className="mb-2 text-sm font-medium">Agent run · {openRun.agent}</h2>
|
|
229
196
|
<div className="mb-2 flex flex-wrap gap-2">
|
|
230
197
|
{agentRuns.map((r) => (
|
|
231
198
|
<button
|
|
@@ -234,13 +201,9 @@ export function AiPanel() {
|
|
|
234
201
|
aria-pressed={r.id === openRun.id}
|
|
235
202
|
className={clsx(
|
|
236
203
|
"min-h-8 px-2 text-xs font-mono",
|
|
237
|
-
r.id === openRun.id
|
|
238
|
-
? "bg-[var(--oke-line)]"
|
|
239
|
-
: "text-[var(--oke-muted)]",
|
|
204
|
+
r.id === openRun.id ? "bg-[var(--oke-line)]" : "text-[var(--oke-muted)]",
|
|
240
205
|
)}
|
|
241
|
-
onClick={() =>
|
|
242
|
-
setSearch(openAgentRun(search, r.agent, r.id))
|
|
243
|
-
}
|
|
206
|
+
onClick={() => setSearch(openAgentRun(search, r.agent, r.id))}
|
|
244
207
|
>
|
|
245
208
|
{r.id}
|
|
246
209
|
</button>
|
|
@@ -265,22 +228,17 @@ export function AiPanel() {
|
|
|
265
228
|
{step.status === "denied" && step.denial ? (
|
|
266
229
|
<p role="status" className="mt-1 text-[var(--oke-muted)]">
|
|
267
230
|
DENIED by gate{" "}
|
|
268
|
-
<span className="font-mono text-[var(--oke-fg)]">
|
|
269
|
-
|
|
270
|
-
</span>
|
|
271
|
-
: {step.denial.reason}
|
|
231
|
+
<span className="font-mono text-[var(--oke-fg)]">{step.denial.gate}</span>:{" "}
|
|
232
|
+
{step.denial.reason}
|
|
272
233
|
</p>
|
|
273
234
|
) : null}
|
|
274
235
|
<ul className="mt-1 space-y-0.5 text-xs text-[var(--oke-muted)]">
|
|
275
236
|
{step.effects.map((e) => (
|
|
276
237
|
<li key={`${e.kind}:${e.resource}`}>
|
|
277
|
-
<span className="font-mono">{e.kind}</span>{
|
|
278
|
-
{e.resource}
|
|
238
|
+
<span className="font-mono">{e.kind}</span> {e.resource}
|
|
279
239
|
</li>
|
|
280
240
|
))}
|
|
281
|
-
{step.effects.length === 0 ?
|
|
282
|
-
<li>no declared effects</li>
|
|
283
|
-
) : null}
|
|
241
|
+
{step.effects.length === 0 ? <li>no declared effects</li> : null}
|
|
284
242
|
</ul>
|
|
285
243
|
</li>
|
|
286
244
|
))}
|
|
@@ -291,9 +249,7 @@ export function AiPanel() {
|
|
|
291
249
|
<section aria-label="Fallback chains" className="mt-8">
|
|
292
250
|
<h2 className="mb-2 text-sm font-medium">Fallback chains</h2>
|
|
293
251
|
{(data?.fallbackChains.length ?? 0) === 0 ? (
|
|
294
|
-
<p className="text-sm text-[var(--oke-muted)]">
|
|
295
|
-
No multi-model chains recorded.
|
|
296
|
-
</p>
|
|
252
|
+
<p className="text-sm text-[var(--oke-muted)]">No multi-model chains recorded.</p>
|
|
297
253
|
) : (
|
|
298
254
|
<ul className="space-y-2 text-sm">
|
|
299
255
|
{(data?.fallbackChains ?? []).map((chain, i) => (
|
|
@@ -311,16 +267,12 @@ export function AiPanel() {
|
|
|
311
267
|
{j > 0 ? " → " : ""}
|
|
312
268
|
<span
|
|
313
269
|
className={
|
|
314
|
-
a.ok
|
|
315
|
-
? "text-[var(--oke-fg)]"
|
|
316
|
-
: "text-[var(--oke-muted)] line-through"
|
|
270
|
+
a.ok ? "text-[var(--oke-fg)]" : "text-[var(--oke-muted)] line-through"
|
|
317
271
|
}
|
|
318
272
|
>
|
|
319
273
|
{a.model}
|
|
320
274
|
</span>
|
|
321
|
-
{a.cost !== undefined
|
|
322
|
-
? ` (${formatCost(a.cost)})`
|
|
323
|
-
: ""}
|
|
275
|
+
{a.cost !== undefined ? ` (${formatCost(a.cost)})` : ""}
|
|
324
276
|
</span>
|
|
325
277
|
))}
|
|
326
278
|
</div>
|
|
@@ -341,12 +293,9 @@ export function AiPanel() {
|
|
|
341
293
|
aria-label="allowPii security review"
|
|
342
294
|
className="min-h-0 overflow-y-auto border-t border-[var(--oke-line)] p-4 lg:border-l lg:border-t-0"
|
|
343
295
|
>
|
|
344
|
-
<h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">
|
|
345
|
-
allowPii
|
|
346
|
-
</h2>
|
|
296
|
+
<h2 className="mb-2 text-xs uppercase tracking-wide text-[var(--oke-muted)]">allowPii</h2>
|
|
347
297
|
<p className="mb-3 text-xs text-[var(--oke-muted)]">
|
|
348
|
-
Standing security review — flows that acknowledge PII egress to a
|
|
349
|
-
model.
|
|
298
|
+
Standing security review — flows that acknowledge PII egress to a model.
|
|
350
299
|
</p>
|
|
351
300
|
{pii.length === 0 ? (
|
|
352
301
|
<p className="text-sm text-[var(--oke-muted)]">None declared.</p>
|
|
@@ -368,9 +317,7 @@ export function AiPanel() {
|
|
|
368
317
|
<tbody>
|
|
369
318
|
{pii.map((row) => (
|
|
370
319
|
<tr key={row.flowId} className="align-top">
|
|
371
|
-
<td className="py-1 pr-2 font-mono text-[var(--oke-fg)]">
|
|
372
|
-
{row.flowId}
|
|
373
|
-
</td>
|
|
320
|
+
<td className="py-1 pr-2 font-mono text-[var(--oke-fg)]">{row.flowId}</td>
|
|
374
321
|
<td className="py-1 font-mono text-[var(--oke-muted)]">
|
|
375
322
|
{row.asks.join(", ") || "—"}
|
|
376
323
|
</td>
|
|
@@ -397,14 +344,10 @@ function VersionDistributions(props: {
|
|
|
397
344
|
<section aria-label="Version distributions" aria-live="polite">
|
|
398
345
|
<div className="mb-3 flex flex-wrap items-baseline gap-3">
|
|
399
346
|
<h2 className="text-sm font-medium">
|
|
400
|
-
{m.prompt}
|
|
401
|
-
<span className="font-mono text-[var(--oke-muted)]">@{m.version}</span>
|
|
347
|
+
{m.prompt} <span className="font-mono text-[var(--oke-muted)]">@{m.version}</span>
|
|
402
348
|
</h2>
|
|
403
349
|
{props.catalogueHref ? (
|
|
404
|
-
<a
|
|
405
|
-
href={props.catalogueHref}
|
|
406
|
-
className="text-xs text-[var(--oke-muted)] underline"
|
|
407
|
-
>
|
|
350
|
+
<a href={props.catalogueHref} className="text-xs text-[var(--oke-muted)] underline">
|
|
408
351
|
Manifest Diff — version bump is a deploy
|
|
409
352
|
</a>
|
|
410
353
|
) : null}
|
|
@@ -418,9 +361,7 @@ function VersionDistributions(props: {
|
|
|
418
361
|
aria-pressed={v.version === m.version}
|
|
419
362
|
className={clsx(
|
|
420
363
|
"min-h-8 px-2 font-mono text-xs",
|
|
421
|
-
v.version === m.version
|
|
422
|
-
? "bg-[var(--oke-line)]"
|
|
423
|
-
: "text-[var(--oke-muted)]",
|
|
364
|
+
v.version === m.version ? "bg-[var(--oke-line)]" : "text-[var(--oke-muted)]",
|
|
424
365
|
)}
|
|
425
366
|
onClick={() => props.onSelectVersion(v.version)}
|
|
426
367
|
>
|
|
@@ -431,13 +372,7 @@ function VersionDistributions(props: {
|
|
|
431
372
|
|
|
432
373
|
<DistributionBlock
|
|
433
374
|
label="Cost"
|
|
434
|
-
summary={distributionSummary(
|
|
435
|
-
"Cost",
|
|
436
|
-
m.cost.mean,
|
|
437
|
-
m.cost.p50,
|
|
438
|
-
m.cost.p95,
|
|
439
|
-
formatCost,
|
|
440
|
-
)}
|
|
375
|
+
summary={distributionSummary("Cost", m.cost.mean, m.cost.p50, m.cost.p95, formatCost)}
|
|
441
376
|
buckets={m.cost.buckets}
|
|
442
377
|
formatTick={formatCost}
|
|
443
378
|
/>
|
|
@@ -509,8 +444,7 @@ function VersionDistributions(props: {
|
|
|
509
444
|
aria-label="Promotion gate"
|
|
510
445
|
>
|
|
511
446
|
<p className="text-sm font-medium">
|
|
512
|
-
Promotion v{props.decision.from.version} → v
|
|
513
|
-
{props.decision.to.version} blocked
|
|
447
|
+
Promotion v{props.decision.from.version} → v{props.decision.to.version} blocked
|
|
514
448
|
</p>
|
|
515
449
|
<ul className="mt-1 list-disc pl-5 text-sm text-[var(--oke-muted)]">
|
|
516
450
|
{formatPromotionBlockers(props.decision).map((line) => (
|
|
@@ -520,8 +454,7 @@ function VersionDistributions(props: {
|
|
|
520
454
|
</div>
|
|
521
455
|
) : props.decision?.allowed ? (
|
|
522
456
|
<p className="mt-4 text-sm text-[var(--oke-muted)]" role="status">
|
|
523
|
-
Promotion v{props.decision.from.version} → v
|
|
524
|
-
{props.decision.to.version} allowed
|
|
457
|
+
Promotion v{props.decision.from.version} → v{props.decision.to.version} allowed
|
|
525
458
|
{props.decision.evalImproved ? " (eval improved)" : ""}.
|
|
526
459
|
</p>
|
|
527
460
|
) : null}
|
|
@@ -542,11 +475,7 @@ function DistributionBlock(props: {
|
|
|
542
475
|
{props.label} distribution
|
|
543
476
|
</h3>
|
|
544
477
|
<p className="mb-2 text-sm">{props.summary}</p>
|
|
545
|
-
<div
|
|
546
|
-
role="img"
|
|
547
|
-
aria-label={props.summary}
|
|
548
|
-
className="flex h-16 items-end gap-px"
|
|
549
|
-
>
|
|
478
|
+
<div role="img" aria-label={props.summary} className="flex h-16 items-end gap-px">
|
|
550
479
|
{props.buckets.map((b, i) => (
|
|
551
480
|
<div
|
|
552
481
|
key={i}
|
|
@@ -61,10 +61,7 @@ export function ArchitecturePanel() {
|
|
|
61
61
|
refetchInterval: 10_000,
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
const graph = useMemo(
|
|
65
|
-
() => buildCausalityGraph(manifestQuery.data),
|
|
66
|
-
[manifestQuery.data],
|
|
67
|
-
);
|
|
64
|
+
const graph = useMemo(() => buildCausalityGraph(manifestQuery.data), [manifestQuery.data]);
|
|
68
65
|
|
|
69
66
|
const layerFlags = layersOf(search);
|
|
70
67
|
const view = useMemo(
|
|
@@ -93,23 +90,15 @@ export function ArchitecturePanel() {
|
|
|
93
90
|
<div className="flex h-full min-h-0 flex-col">
|
|
94
91
|
<header className="flex shrink-0 flex-wrap items-end gap-4 border-b border-[var(--oke-line)] px-6 py-4">
|
|
95
92
|
<div className="flex flex-col gap-1">
|
|
96
|
-
<p className="text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]">
|
|
97
|
-
Architecture
|
|
98
|
-
</p>
|
|
93
|
+
<p className="text-xs uppercase tracking-[0.2em] text-[var(--oke-muted)]">Architecture</p>
|
|
99
94
|
<h1 className="text-xl font-semibold tracking-tight">System shape</h1>
|
|
100
95
|
<p className="text-sm text-[var(--oke-muted)]">
|
|
101
96
|
Clustered by unit · typed layers · traffic from Runs
|
|
102
97
|
</p>
|
|
103
98
|
</div>
|
|
104
|
-
<p
|
|
105
|
-
className="ml-auto font-mono text-sm"
|
|
106
|
-
role="status"
|
|
107
|
-
aria-live="polite"
|
|
108
|
-
>
|
|
99
|
+
<p className="ml-auto font-mono text-sm" role="status" aria-live="polite">
|
|
109
100
|
<span className="text-[var(--oke-muted)]">Boundary crossings</span>{" "}
|
|
110
|
-
<span className="text-lg font-semibold tabular-nums">
|
|
111
|
-
{view.boundaryCrossingCount}
|
|
112
|
-
</span>
|
|
101
|
+
<span className="text-lg font-semibold tabular-nums">{view.boundaryCrossingCount}</span>
|
|
113
102
|
</p>
|
|
114
103
|
</header>
|
|
115
104
|
|
|
@@ -129,11 +118,7 @@ export function ArchitecturePanel() {
|
|
|
129
118
|
<input
|
|
130
119
|
type="checkbox"
|
|
131
120
|
checked={layerFlags[layer]}
|
|
132
|
-
onChange={(e) =>
|
|
133
|
-
setSearch(
|
|
134
|
-
setLayerSearch(search, layer, e.target.checked),
|
|
135
|
-
)
|
|
136
|
-
}
|
|
121
|
+
onChange={(e) => setSearch(setLayerSearch(search, layer, e.target.checked))}
|
|
137
122
|
aria-label={`${LAYER_LABEL[layer]} layer`}
|
|
138
123
|
/>
|
|
139
124
|
{LAYER_LABEL[layer]}
|
|
@@ -161,33 +146,18 @@ export function ArchitecturePanel() {
|
|
|
161
146
|
</label>
|
|
162
147
|
))}
|
|
163
148
|
</fieldset>
|
|
164
|
-
<Button
|
|
165
|
-
type="button"
|
|
166
|
-
variant="ghost"
|
|
167
|
-
onClick={() => setSearch(clearFocus(search))}
|
|
168
|
-
>
|
|
149
|
+
<Button type="button" variant="ghost" onClick={() => setSearch(clearFocus(search))}>
|
|
169
150
|
Clear focus
|
|
170
151
|
</Button>
|
|
171
152
|
</div>
|
|
172
153
|
) : (
|
|
173
|
-
<p className="text-sm text-[var(--oke-muted)]">
|
|
174
|
-
Select a unit to focus at depth 1–2
|
|
175
|
-
</p>
|
|
154
|
+
<p className="text-sm text-[var(--oke-muted)]">Select a unit to focus at depth 1–2</p>
|
|
176
155
|
)}
|
|
177
156
|
</div>
|
|
178
157
|
|
|
179
|
-
<section
|
|
180
|
-
aria-
|
|
181
|
-
|
|
182
|
-
>
|
|
183
|
-
<div
|
|
184
|
-
aria-hidden="true"
|
|
185
|
-
className="mb-4 overflow-x-auto"
|
|
186
|
-
>
|
|
187
|
-
<svg
|
|
188
|
-
className="h-auto w-full max-w-5xl text-[var(--oke-fg)]"
|
|
189
|
-
viewBox="0 0 640 380"
|
|
190
|
-
>
|
|
158
|
+
<section aria-label="System diagram" className="min-h-0 flex-1 overflow-auto px-4 py-4">
|
|
159
|
+
<div aria-hidden="true" className="mb-4 overflow-x-auto">
|
|
160
|
+
<svg className="h-auto w-full max-w-5xl text-[var(--oke-fg)]" viewBox="0 0 640 380">
|
|
191
161
|
<rect
|
|
192
162
|
x={SYSTEM_BOUNDARY.x}
|
|
193
163
|
y={SYSTEM_BOUNDARY.y}
|
|
@@ -221,9 +191,7 @@ export function ArchitecturePanel() {
|
|
|
221
191
|
x2={to.x}
|
|
222
192
|
y2={to.y}
|
|
223
193
|
stroke={
|
|
224
|
-
edge.layer === "external"
|
|
225
|
-
? "var(--oke-external)"
|
|
226
|
-
: "var(--oke-muted)"
|
|
194
|
+
edge.layer === "external" ? "var(--oke-external)" : "var(--oke-muted)"
|
|
227
195
|
}
|
|
228
196
|
strokeWidth={edge.thickness}
|
|
229
197
|
strokeDasharray={edge.dashed ? "6 4" : undefined}
|
|
@@ -249,11 +217,7 @@ export function ArchitecturePanel() {
|
|
|
249
217
|
? "var(--oke-bg)"
|
|
250
218
|
: "color-mix(in oklab, var(--oke-external) 25%, var(--oke-bg))"
|
|
251
219
|
}
|
|
252
|
-
stroke={
|
|
253
|
-
node.insideBoundary
|
|
254
|
-
? "var(--oke-fg)"
|
|
255
|
-
: "var(--oke-external)"
|
|
256
|
-
}
|
|
220
|
+
stroke={node.insideBoundary ? "var(--oke-fg)" : "var(--oke-external)"}
|
|
257
221
|
strokeWidth={node.focused ? 2.5 : 1.25}
|
|
258
222
|
/>
|
|
259
223
|
<text
|
|
@@ -291,14 +255,10 @@ export function ArchitecturePanel() {
|
|
|
291
255
|
>
|
|
292
256
|
<span>{n.label}</span>
|
|
293
257
|
{n.kind === "unit" && n.flowCount !== undefined ? (
|
|
294
|
-
<span className="font-mono text-xs">
|
|
295
|
-
{n.flowCount}
|
|
296
|
-
</span>
|
|
258
|
+
<span className="font-mono text-xs">{n.flowCount}</span>
|
|
297
259
|
) : null}
|
|
298
260
|
{!n.insideBoundary ? (
|
|
299
|
-
<span className="text-xs text-[var(--oke-external)]">
|
|
300
|
-
external
|
|
301
|
-
</span>
|
|
261
|
+
<span className="text-xs text-[var(--oke-external)]">external</span>
|
|
302
262
|
) : null}
|
|
303
263
|
</button>
|
|
304
264
|
</li>
|
|
@@ -308,9 +268,7 @@ export function ArchitecturePanel() {
|
|
|
308
268
|
{view.edges.map((e) => (
|
|
309
269
|
<li key={e.id}>
|
|
310
270
|
{e.from} → {e.to}
|
|
311
|
-
{e.dashed
|
|
312
|
-
? " (declared, never traversed)"
|
|
313
|
-
: ` · ${e.traversals} traversals`}
|
|
271
|
+
{e.dashed ? " (declared, never traversed)" : ` · ${e.traversals} traversals`}
|
|
314
272
|
{` · ${e.layer}`}
|
|
315
273
|
</li>
|
|
316
274
|
))}
|
|
@@ -329,9 +287,7 @@ export function ArchitecturePanel() {
|
|
|
329
287
|
</p>
|
|
330
288
|
</div>
|
|
331
289
|
{view.findings.length === 0 ? (
|
|
332
|
-
<p className="px-5 pb-4 text-sm text-[var(--oke-muted)]">
|
|
333
|
-
No pathologies detected.
|
|
334
|
-
</p>
|
|
290
|
+
<p className="px-5 pb-4 text-sm text-[var(--oke-muted)]">No pathologies detected.</p>
|
|
335
291
|
) : (
|
|
336
292
|
<ul className="divide-y divide-[var(--oke-line)] border-t border-[var(--oke-line)]">
|
|
337
293
|
{view.findings.map((f, i) => (
|
|
@@ -348,16 +304,12 @@ export function ArchitecturePanel() {
|
|
|
348
304
|
/>
|
|
349
305
|
{f.title}
|
|
350
306
|
</p>
|
|
351
|
-
<p className="mt-1 text-sm text-[var(--oke-muted)]">
|
|
352
|
-
{f.detail}
|
|
353
|
-
</p>
|
|
307
|
+
<p className="mt-1 text-sm text-[var(--oke-muted)]">{f.detail}</p>
|
|
354
308
|
{f.nodeIds[0] ? (
|
|
355
309
|
<button
|
|
356
310
|
type="button"
|
|
357
311
|
className="mt-2 min-h-8 text-sm text-[var(--oke-accent)] underline-offset-2 hover:underline"
|
|
358
|
-
onClick={() =>
|
|
359
|
-
setSearch(focusNode(search, f.nodeIds[0]!))
|
|
360
|
-
}
|
|
312
|
+
onClick={() => setSearch(focusNode(search, f.nodeIds[0]!))}
|
|
361
313
|
>
|
|
362
314
|
Focus
|
|
363
315
|
</button>
|
|
@@ -61,18 +61,15 @@ export function ChannelsPanel() {
|
|
|
61
61
|
() => filterTemplates(list?.templates ?? [], search.q ?? ""),
|
|
62
62
|
[list?.templates, search.q],
|
|
63
63
|
);
|
|
64
|
-
const open =
|
|
64
|
+
const open =
|
|
65
|
+
templates.find((t) => t.name === search.template) ??
|
|
65
66
|
list?.templates.find((t) => t.name === search.template);
|
|
66
67
|
const outcomes = sortByConsequence(list?.outcomes ?? []);
|
|
67
68
|
const production = list?.production ?? true;
|
|
68
69
|
const sendConfirm = sendTestConfirmation({ production });
|
|
69
70
|
|
|
70
71
|
const previewQuery = useQuery({
|
|
71
|
-
queryKey: [
|
|
72
|
-
"console.channel.preview",
|
|
73
|
-
open?.name,
|
|
74
|
-
previewLocale || search.locale,
|
|
75
|
-
],
|
|
72
|
+
queryKey: ["console.channel.preview", open?.name, previewLocale || search.locale],
|
|
76
73
|
enabled: !!open,
|
|
77
74
|
queryFn: async () => {
|
|
78
75
|
if (!open) return null;
|
|
@@ -122,8 +119,7 @@ export function ChannelsPanel() {
|
|
|
122
119
|
template: open.name,
|
|
123
120
|
to: testTo,
|
|
124
121
|
locale: previewLocale || open.locales[0],
|
|
125
|
-
confirmation:
|
|
126
|
-
sendConfirm.kind === "typed" ? sendConfirm.phrase : undefined,
|
|
122
|
+
confirmation: sendConfirm.kind === "typed" ? sendConfirm.phrase : undefined,
|
|
127
123
|
reason: sendConfirm.kind === "typed" ? reason : undefined,
|
|
128
124
|
});
|
|
129
125
|
if (res.error) throw new Error(res.error.code);
|
|
@@ -169,9 +165,7 @@ export function ChannelsPanel() {
|
|
|
169
165
|
aria-label="Templates"
|
|
170
166
|
className="w-64 shrink-0 overflow-y-auto border-r border-[var(--oke-line)] p-3"
|
|
171
167
|
>
|
|
172
|
-
<h2 className="mb-2 text-xs tracking-wide text-[var(--oke-muted)]">
|
|
173
|
-
Templates
|
|
174
|
-
</h2>
|
|
168
|
+
<h2 className="mb-2 text-xs tracking-wide text-[var(--oke-muted)]">Templates</h2>
|
|
175
169
|
{listQuery.isLoading ? (
|
|
176
170
|
<p className="text-sm text-[var(--oke-muted)]">Loading…</p>
|
|
177
171
|
) : (
|
|
@@ -187,9 +181,7 @@ export function ChannelsPanel() {
|
|
|
187
181
|
? "bg-[var(--oke-line)] text-[var(--oke-fg)]"
|
|
188
182
|
: "text-[var(--oke-muted)]",
|
|
189
183
|
)}
|
|
190
|
-
onClick={() =>
|
|
191
|
-
setSearch(openTemplate(search, t.name))
|
|
192
|
-
}
|
|
184
|
+
onClick={() => setSearch(openTemplate(search, t.name))}
|
|
193
185
|
>
|
|
194
186
|
<span>{t.name}</span>
|
|
195
187
|
<span className="font-mono text-xs">{t.medium}</span>
|
|
@@ -200,33 +192,23 @@ export function ChannelsPanel() {
|
|
|
200
192
|
)}
|
|
201
193
|
</section>
|
|
202
194
|
|
|
203
|
-
<main
|
|
204
|
-
id="channels-main"
|
|
205
|
-
className="min-w-0 flex-1 overflow-y-auto p-4"
|
|
206
|
-
>
|
|
195
|
+
<main id="channels-main" className="min-w-0 flex-1 overflow-y-auto p-4">
|
|
207
196
|
{list?.face === "inbox" ? (
|
|
208
197
|
<section aria-label="Inbox" className="mb-8">
|
|
209
198
|
<h2 className="text-base text-[var(--oke-fg)]">Inbox</h2>
|
|
210
199
|
<ul className="mt-3 space-y-2">
|
|
211
200
|
{(list.inbox ?? []).map((e) => (
|
|
212
|
-
<li
|
|
213
|
-
key={e.id}
|
|
214
|
-
className="border-b border-[var(--oke-line)] pb-2 text-sm"
|
|
215
|
-
>
|
|
201
|
+
<li key={e.id} className="border-b border-[var(--oke-line)] pb-2 text-sm">
|
|
216
202
|
<div className="flex gap-2 text-[var(--oke-muted)]">
|
|
217
203
|
<span>{e.medium}</span>
|
|
218
204
|
<span>{e.toMasked}</span>
|
|
219
205
|
{e.template ? <span>{e.template}</span> : null}
|
|
220
206
|
</div>
|
|
221
|
-
<p className="mt-1 text-[var(--oke-fg)]">
|
|
222
|
-
{e.subject ?? e.text ?? "(empty)"}
|
|
223
|
-
</p>
|
|
207
|
+
<p className="mt-1 text-[var(--oke-fg)]">{e.subject ?? e.text ?? "(empty)"}</p>
|
|
224
208
|
</li>
|
|
225
209
|
))}
|
|
226
210
|
{(list.inbox ?? []).length === 0 ? (
|
|
227
|
-
<li className="text-sm text-[var(--oke-muted)]">
|
|
228
|
-
No messages yet
|
|
229
|
-
</li>
|
|
211
|
+
<li className="text-sm text-[var(--oke-muted)]">No messages yet</li>
|
|
230
212
|
) : null}
|
|
231
213
|
</ul>
|
|
232
214
|
</section>
|
|
@@ -235,9 +217,7 @@ export function ChannelsPanel() {
|
|
|
235
217
|
<section aria-label="Did not arrive" className="mb-8">
|
|
236
218
|
<h2 className="text-base text-[var(--oke-fg)]">Did not arrive</h2>
|
|
237
219
|
<table className="mt-3 w-full text-left text-sm">
|
|
238
|
-
<caption className="sr-only">
|
|
239
|
-
Seven-state taxonomy with verdicts
|
|
240
|
-
</caption>
|
|
220
|
+
<caption className="sr-only">Seven-state taxonomy with verdicts</caption>
|
|
241
221
|
<thead>
|
|
242
222
|
<tr className="text-[var(--oke-muted)]">
|
|
243
223
|
<th scope="col" className="py-1 font-normal">
|
|
@@ -282,28 +262,21 @@ export function ChannelsPanel() {
|
|
|
282
262
|
<section aria-label="Template detail" className="mb-8">
|
|
283
263
|
<h2 className="text-base text-[var(--oke-fg)]">{open.name}</h2>
|
|
284
264
|
<p className="mt-1 text-sm text-[var(--oke-muted)]">
|
|
285
|
-
From {open.from ?? "unset"} · Locales{" "}
|
|
286
|
-
{open.locales.join(", ") || "none"}
|
|
265
|
+
From {open.from ?? "unset"} · Locales {open.locales.join(", ") || "none"}
|
|
287
266
|
</p>
|
|
288
267
|
|
|
289
268
|
{open.from ? (
|
|
290
269
|
<section aria-label="Email authentication" className="mt-4">
|
|
291
|
-
<h3 className="text-sm text-[var(--oke-fg)]">
|
|
292
|
-
SPF / DKIM / DMARC
|
|
293
|
-
</h3>
|
|
270
|
+
<h3 className="text-sm text-[var(--oke-fg)]">SPF / DKIM / DMARC</h3>
|
|
294
271
|
{authQuery.data ? (
|
|
295
272
|
<ul className="mt-2 space-y-1 text-sm text-[var(--oke-muted)]">
|
|
296
273
|
<li>SPF: {authQuery.data.spf}</li>
|
|
297
274
|
<li>DKIM: {authQuery.data.dkim}</li>
|
|
298
275
|
<li>DMARC: {authQuery.data.dmarc}</li>
|
|
299
|
-
<li className="font-mono text-xs">
|
|
300
|
-
{authQuery.data.domain}
|
|
301
|
-
</li>
|
|
276
|
+
<li className="font-mono text-xs">{authQuery.data.domain}</li>
|
|
302
277
|
</ul>
|
|
303
278
|
) : (
|
|
304
|
-
<p className="mt-2 text-sm text-[var(--oke-muted)]">
|
|
305
|
-
Checking…
|
|
306
|
-
</p>
|
|
279
|
+
<p className="mt-2 text-sm text-[var(--oke-muted)]">Checking…</p>
|
|
307
280
|
)}
|
|
308
281
|
</section>
|
|
309
282
|
) : null}
|
|
@@ -318,10 +291,7 @@ export function ChannelsPanel() {
|
|
|
318
291
|
value={previewLocale || open.locales[0] || "en"}
|
|
319
292
|
onChange={(e) => setPreviewLocale(e.target.value)}
|
|
320
293
|
>
|
|
321
|
-
{(open.locales.length > 0
|
|
322
|
-
? open.locales
|
|
323
|
-
: ["en"]
|
|
324
|
-
).map((l) => (
|
|
294
|
+
{(open.locales.length > 0 ? open.locales : ["en"]).map((l) => (
|
|
325
295
|
<option key={l} value={l}>
|
|
326
296
|
{l}
|
|
327
297
|
</option>
|
|
@@ -331,8 +301,7 @@ export function ChannelsPanel() {
|
|
|
331
301
|
{previewQuery.data ? (
|
|
332
302
|
<>
|
|
333
303
|
<p className="mt-2 text-xs text-[var(--oke-muted)]">
|
|
334
|
-
Locale chain:{
|
|
335
|
-
{formatLocaleChainDisplay(previewQuery.data.localeChain)}
|
|
304
|
+
Locale chain: {formatLocaleChainDisplay(previewQuery.data.localeChain)}
|
|
336
305
|
</p>
|
|
337
306
|
<div
|
|
338
307
|
className="mt-2 max-w-prose border border-[var(--oke-line)] p-3 text-sm text-[var(--oke-fg)]"
|
|
@@ -340,9 +309,7 @@ export function ChannelsPanel() {
|
|
|
340
309
|
lang={previewQuery.data.locale}
|
|
341
310
|
>
|
|
342
311
|
{previewQuery.data.subject ? (
|
|
343
|
-
<p className="mb-2 font-medium">
|
|
344
|
-
{previewQuery.data.subject}
|
|
345
|
-
</p>
|
|
312
|
+
<p className="mb-2 font-medium">{previewQuery.data.subject}</p>
|
|
346
313
|
) : null}
|
|
347
314
|
<p>{previewQuery.data.text ?? previewQuery.data.html}</p>
|
|
348
315
|
</div>
|
|
@@ -417,9 +384,7 @@ export function ChannelsPanel() {
|
|
|
417
384
|
{s.subjectMasked} · {s.reason} · {s.medium}
|
|
418
385
|
</li>
|
|
419
386
|
))}
|
|
420
|
-
{(list?.suppression ?? []).length === 0 ?
|
|
421
|
-
<li>Empty</li>
|
|
422
|
-
) : null}
|
|
387
|
+
{(list?.suppression ?? []).length === 0 ? <li>Empty</li> : null}
|
|
423
388
|
</ul>
|
|
424
389
|
</section>
|
|
425
390
|
|
|
@@ -442,9 +407,7 @@ export function ChannelsPanel() {
|
|
|
442
407
|
) : null}
|
|
443
408
|
</li>
|
|
444
409
|
))}
|
|
445
|
-
{(list?.receipts ?? []).length === 0 ?
|
|
446
|
-
<li>No receipts yet</li>
|
|
447
|
-
) : null}
|
|
410
|
+
{(list?.receipts ?? []).length === 0 ? <li>No receipts yet</li> : null}
|
|
448
411
|
</ul>
|
|
449
412
|
</section>
|
|
450
413
|
</main>
|