okengine 0.18.4 → 0.19.0
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 +18 -10
- package/README.md +2 -2
- package/package.json +51 -50
- package/site/content/docs/ai/index.mdx +25 -6
- package/site/content/docs/ai/llms-txt.mdx +1 -1
- package/site/content/docs/ai/meta.json +1 -1
- package/site/content/docs/ai/skills.mdx +4 -1
- package/site/content/docs/ai/try-it.mdx +58 -0
- package/site/content/docs/client/auth.mdx +208 -0
- package/site/content/docs/client/calling.mdx +451 -0
- package/site/content/docs/client/index.mdx +209 -0
- package/site/content/docs/client/live.mdx +234 -0
- package/site/content/docs/client/meta.json +5 -0
- package/site/content/docs/client/react.mdx +249 -0
- package/site/content/docs/elements/ai/agents.mdx +232 -0
- package/site/content/docs/elements/ai/index.mdx +341 -0
- package/site/content/docs/elements/ai/mcp.mdx +275 -0
- package/site/content/docs/elements/ai/meta.json +5 -0
- package/site/content/docs/elements/ai/models.mdx +283 -0
- package/site/content/docs/elements/ai/prompts.mdx +256 -0
- package/site/content/docs/elements/channel/email.mdx +266 -0
- package/site/content/docs/elements/channel/index.mdx +344 -0
- package/site/content/docs/elements/channel/meta.json +5 -0
- package/site/content/docs/elements/channel/push.mdx +218 -0
- package/site/content/docs/elements/channel/receipts.mdx +206 -0
- package/site/content/docs/elements/channel/sms.mdx +264 -0
- package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
- package/site/content/docs/elements/clock/index.mdx +300 -0
- package/site/content/docs/elements/clock/meta.json +5 -0
- package/site/content/docs/elements/clock/schedules.mdx +508 -0
- package/site/content/docs/elements/clock/sleep.mdx +445 -0
- package/site/content/docs/elements/flow/consumers.mdx +707 -0
- package/site/content/docs/elements/flow/http.mdx +1080 -0
- package/site/content/docs/elements/flow/index.mdx +618 -0
- package/site/content/docs/elements/flow/meta.json +5 -0
- package/site/content/docs/elements/flow/routing.mdx +559 -0
- package/site/content/docs/elements/flow/workflows.mdx +640 -0
- package/site/content/docs/elements/gate/auth.mdx +371 -0
- package/site/content/docs/elements/gate/authorization.mdx +298 -0
- package/site/content/docs/elements/gate/index.mdx +418 -0
- package/site/content/docs/elements/gate/meta.json +5 -0
- package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
- package/site/content/docs/elements/gate/rls.mdx +303 -0
- package/site/content/docs/elements/gate/tenancy.mdx +372 -0
- package/site/content/docs/elements/index.mdx +52 -11
- package/site/content/docs/elements/signal/broadcast.mdx +517 -0
- package/site/content/docs/elements/signal/index.mdx +352 -0
- package/site/content/docs/elements/signal/live.mdx +590 -0
- package/site/content/docs/elements/signal/meta.json +5 -0
- package/site/content/docs/elements/signal/once.mdx +596 -0
- package/site/content/docs/elements/store/files.mdx +659 -0
- package/site/content/docs/elements/store/index.mdx +310 -0
- package/site/content/docs/elements/store/kv.mdx +629 -0
- package/site/content/docs/elements/store/meta.json +5 -0
- package/site/content/docs/elements/store/search.mdx +946 -0
- package/site/content/docs/elements/store/sql.mdx +937 -0
- package/site/content/docs/elements/vault/config.mdx +256 -0
- package/site/content/docs/elements/vault/index.mdx +356 -0
- package/site/content/docs/elements/vault/meta.json +5 -0
- package/site/content/docs/elements/vault/rotation.mdx +273 -0
- package/site/content/docs/elements/vault/secrets.mdx +285 -0
- package/site/content/docs/index.mdx +78 -30
- package/site/content/docs/meta.json +11 -8
- package/site/content/docs/plugins/cors.mdx +2 -1
- package/site/content/docs/plugins/csrf.mdx +4 -1
- package/site/content/docs/plugins/headers.mdx +2 -1
- package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
- package/site/content/docs/plugins/magic-link.mdx +6 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
- package/site/content/docs/plugins/oauth.mdx +1 -1
- package/site/content/docs/plugins/otp.mdx +12 -1
- package/site/content/docs/plugins/passkey.mdx +39 -15
- package/site/content/docs/plugins/two-factor.mdx +91 -34
- package/site/content/docs/plugins/username.mdx +1 -1
- package/site/content/docs/recipes/caddy.mdx +3 -3
- package/site/content/docs/recipes/index.mdx +18 -28
- package/site/content/docs/recipes/mailpit.mdx +1 -1
- package/site/content/docs/recipes/meilisearch.mdx +3 -3
- package/site/content/docs/recipes/meta.json +1 -4
- package/site/content/docs/recipes/nginx.mdx +2 -2
- package/site/content/docs/recipes/openrouter.mdx +283 -0
- package/site/content/docs/recipes/pgdog.mdx +3 -3
- package/site/content/docs/recipes/postgres.mdx +1 -2
- package/site/content/docs/recipes/rustfs.mdx +2 -2
- package/site/content/docs/recipes/traefik.mdx +3 -3
- package/site/content/docs/reference/cli.mdx +231 -0
- package/site/content/docs/reference/configuration.mdx +30 -10
- package/site/content/docs/reference/environment-variables.mdx +93 -20
- package/site/content/docs/reference/errors.mdx +132 -29
- package/site/content/docs/reference/fx.mdx +137 -73
- package/site/content/docs/reference/index.mdx +13 -21
- package/site/content/docs/reference/meta.json +4 -5
- package/site/content/docs/reference/okid.mdx +42 -17
- package/site/content/docs/reference/plugins.mdx +4 -3
- package/site/content/docs/reference/security.mdx +197 -0
- package/site/content/docs/understand/meta.json +5 -0
- package/site/content/docs/understand/the-anatomy.mdx +132 -0
- package/site/content/docs/understand/the-model.mdx +32 -0
- package/site/content/docs/understand/the-problem.mdx +74 -0
- package/site/content/docs/understand/the-vocabulary.mdx +26 -0
- package/src/auth/api-keys.ts +2 -1
- package/src/auth/bindings.ts +64 -16
- package/src/auth/gate-auth.test.ts +6 -1
- package/src/auth/identity.ts +152 -5
- package/src/auth/index.ts +29 -0
- package/src/auth/invites.ts +2 -1
- package/src/auth/method-context.ts +41 -0
- package/src/auth/oauth-as/crypto.ts +2 -1
- package/src/auth/oauth-as/stores.ts +2 -1
- package/src/auth/operator.ts +2 -1
- package/src/auth/sessions-jwt.test.ts +77 -0
- package/src/auth/sessions.ts +20 -4
- package/src/auth/tenants.ts +3 -2
- package/src/auth/two-factor-challenge.test.ts +61 -0
- package/src/auth/two-factor-challenge.ts +284 -0
- package/src/auth/verification.ts +5 -0
- package/src/bench/REPORT.md +49 -0
- package/src/bench/g03-signal-once.bench.ts +1 -1
- package/src/bench/g10-observability-contention.bench.ts +1 -1
- package/src/bench/g17-hybrid-search.bench.ts +572 -0
- package/src/bench/load-app.ts +2 -10
- package/src/cli/ai-setup/ai-setup.test.ts +331 -42
- package/src/cli/ai-setup/apply.ts +294 -52
- package/src/cli/ai-setup/catalog.ts +238 -1342
- package/src/cli/ai-setup/index.ts +14 -99
- package/src/cli/ai-setup/prompts.ts +60 -443
- package/src/cli/ask-seed.test.ts +96 -0
- package/src/cli/ask-seed.ts +82 -0
- package/src/cli/ask-vault-gaps.test.ts +84 -0
- package/src/cli/ask-vault-gaps.ts +146 -0
- package/src/cli/build.ts +2 -2
- package/src/cli/client-add.test.ts +26 -1
- package/src/cli/client-add.ts +106 -27
- package/src/cli/competitor-mention-removal.test.ts +1 -1
- package/src/cli/db-seed.ts +2 -0
- package/src/cli/db.ts +150 -11
- package/src/cli/dev.ts +119 -211
- package/src/cli/docker-clean.ts +2 -2
- package/src/cli/docker-cli.test.ts +1 -1
- package/src/cli/doctor-diff.ts +4 -2
- package/src/cli/doctor-pii.test.ts +1 -1
- package/src/cli/doctor.ts +14 -1
- package/src/cli/hero-meta.test.ts +4 -2
- package/src/cli/load-config.images.test.ts +8 -10
- package/src/cli/load-config.ts +1 -1
- package/src/cli/registry.ts +22 -10
- package/src/cli/replay.ts +3 -1
- package/src/cli/start.ts +1 -1
- package/src/cli/tui/keys.ts +2 -3
- package/src/client/auth/cookies.ts +74 -0
- package/src/client/auth/create-auth-client.ts +636 -0
- package/src/client/auth/denials.ts +99 -0
- package/src/client/auth/session.ts +283 -0
- package/src/client/auth.test.ts +251 -0
- package/src/client/auth.ts +39 -114
- package/src/client/create-with-session.ts +245 -0
- package/src/client/create.ts +51 -5
- package/src/client/index.ts +11 -1
- package/src/client/live.ts +11 -79
- package/src/client/notes-contract.test.ts +5 -10
- package/src/client/sse.ts +137 -0
- package/src/client/stream.ts +147 -0
- package/src/client/transport.test.ts +32 -0
- package/src/client/transport.ts +123 -26
- package/src/client/types.ts +118 -14
- package/src/client-react/index.ts +185 -24
- package/src/client-react/use-live-query.ts +13 -3
- package/src/compiler/aot.test.ts +7 -4
- package/src/compiler/effects-embed.test.ts +56 -0
- package/src/compiler/effects-fetch.test.ts +43 -0
- package/src/compiler/effects-infer.ts +58 -2
- package/src/compiler/extract.test.ts +258 -44
- package/src/compiler/extract.ts +566 -48
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
- package/src/compiler/fixtures/skyport.expected.json +4 -4
- package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
- package/src/compiler/response.ts +2 -2
- package/src/compiler/search-writer-isolation.test.ts +40 -0
- package/src/config/index.ts +11 -0
- package/src/console/server/app.ts +17 -23
- package/src/console/server/bind.ts +4 -0
- package/src/console/server/console.test.ts +2 -2
- package/src/console/server/flows-invoke.test.ts +50 -34
- package/src/console/server/flows.ts +436 -255
- package/src/console/server/runs-ingest.test.ts +6 -3
- package/src/console/server/serve.ts +1 -1
- package/src/console/server/signals.test.ts +1 -5
- package/src/console/server/signals.ts +8 -6
- package/src/console/server/state.ts +6 -1
- package/src/console/server/store.ts +1 -1
- package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
- package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
- package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
- package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
- package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
- package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
- package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
- package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
- package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
- package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
- package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
- package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
- package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
- package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
- package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
- package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
- package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
- package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
- package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
- package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
- package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
- package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
- package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
- package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
- package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
- package/src/console/ui-next/dist/index.html +6 -13
- package/src/console/ui-next/seed-invoke-host.ts +21 -18
- package/src/console/ui-next/src/client.ts +7 -2
- package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
- package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
- package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
- package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
- package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
- package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
- package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
- package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
- package/src/docker/ai-model-status.test.ts +1 -12
- package/src/docker/ai-model-status.ts +10 -38
- package/src/docker/compose-up.test.ts +100 -0
- package/src/docker/compose-up.ts +292 -0
- package/src/docker/compose.ts +4 -14
- package/src/docker/derive.ts +9 -34
- package/src/docker/docker.test.ts +16 -261
- package/src/docker/images-config.test.ts +13 -25
- package/src/docker/index.ts +1 -24
- package/src/docker/recipes/index.ts +0 -23
- package/src/docker/recipes/pgdog.ts +6 -4
- package/src/docker/stack-id.test.ts +2 -2
- package/src/docker/stack-id.ts +0 -1
- package/src/docker/types.ts +2 -2
- package/src/drivers/ai-anthropic.ts +10 -0
- package/src/drivers/ai-openai-compatible.ts +34 -7
- package/src/drivers/ai-providers.test.ts +0 -107
- package/src/drivers/ai-stream.test.ts +0 -34
- package/src/drivers/ai-types.ts +17 -8
- package/src/drivers/channel-fcm.ts +6 -1
- package/src/drivers/channel-msegat.ts +6 -1
- package/src/drivers/channel-resend.ts +5 -1
- package/src/drivers/channel-smtp.ts +5 -1
- package/src/drivers/channel-sndr.ts +10 -1
- package/src/drivers/channel-taqnyat-mail.ts +5 -1
- package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
- package/src/drivers/channel-taqnyat.ts +6 -1
- package/src/drivers/channel-types.ts +10 -0
- package/src/drivers/channel-unifonic.ts +6 -1
- package/src/drivers/channel-wa-cloud.ts +6 -1
- package/src/drivers/channel-webpush.ts +6 -1
- package/src/drivers/external.ts +33 -0
- package/src/drivers/index.ts +0 -10
- package/src/drivers/meilisearch.ts +6 -0
- package/src/drivers/oauth-types.ts +4 -0
- package/src/drivers/postgres.test.ts +74 -3
- package/src/drivers/postgres.ts +175 -6
- package/src/drivers/signal-types.ts +5 -5
- package/src/drivers/types.ts +7 -0
- package/src/drivers/vault-types.ts +5 -0
- package/src/elements/ai/declare.ts +17 -4
- package/src/elements/ai/eval.ts +1 -1
- package/src/elements/ai/mcp-http.ts +1 -1
- package/src/elements/ai/pii.ts +1 -1
- package/src/elements/ai/providers.test.ts +289 -0
- package/src/elements/ai/providers.ts +169 -0
- package/src/elements/ai/runtime.ts +68 -5
- package/src/elements/ai/schema.ts +2 -2
- package/src/elements/ai.test.ts +7 -7
- package/src/elements/ai.ts +17 -1
- package/src/elements/channel/runtime.ts +105 -12
- package/src/elements/clock/cron-fields.test.ts +144 -0
- package/src/elements/clock/cron-fields.ts +185 -0
- package/src/elements/clock/declare.ts +247 -3
- package/src/elements/clock.ts +21 -1
- package/src/elements/index.ts +15 -0
- package/src/elements/signal/chaos-child.ts +1 -2
- package/src/elements/signal/declare.ts +65 -37
- package/src/elements/signal/delivery-modes.test.ts +11 -31
- package/src/elements/signal/dry-run-replay.test.ts +1 -7
- package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
- package/src/elements/signal/key-ordering.test.ts +6 -26
- package/src/elements/signal/lease-reclaim.test.ts +2 -6
- package/src/elements/signal/optional-emit.test.ts +6 -9
- package/src/elements/signal/order-lifecycle.test.ts +4 -17
- package/src/elements/signal/orphan-messages.test.ts +4 -15
- package/src/elements/signal/reconcile.test.ts +2 -2
- package/src/elements/signal/runtime.ts +1 -1
- package/src/elements/signal/schema-emit.test.ts +4 -8
- package/src/elements/signal.test.ts +24 -49
- package/src/elements/signal.ts +9 -2
- package/src/elements/store/domain-ddl.test.ts +1 -1
- package/src/elements/store/live-http.test.ts +9 -4
- package/src/elements/store/prepare-row.test.ts +123 -0
- package/src/elements/store/resource.ts +43 -12
- package/src/elements/store/schema-decl.ts +117 -0
- package/src/elements/store/search-backfill.ts +205 -0
- package/src/elements/store/search-bind.ts +66 -0
- package/src/elements/store/search-bm25.ts +78 -0
- package/src/elements/store/search-ddl.ts +156 -0
- package/src/elements/store/search-embed-flow.ts +141 -0
- package/src/elements/store/search-errors.ts +34 -0
- package/src/elements/store/search-fusion.ts +112 -0
- package/src/elements/store/search-lsh.ts +179 -0
- package/src/elements/store/search-runtime.ts +300 -0
- package/src/elements/store/search.test.ts +144 -0
- package/src/elements/store/sql-session.test.ts +1 -0
- package/src/elements/store/sql-session.ts +83 -3
- package/src/elements/store/table.ts +23 -2
- package/src/elements/store/upsert-app.test.ts +1 -3
- package/src/elements/store.ts +50 -0
- package/src/full.ts +4 -2
- package/src/http.ts +4 -1
- package/src/i18n/catalogs/ar.ts +14 -6
- package/src/i18n/catalogs/en.ts +14 -6
- package/src/index.ts +6 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
- package/src/kernel/adopt-routes.ts +9 -1
- package/src/kernel/app-auth.ts +5 -0
- package/src/kernel/app.ts +102 -9
- package/src/kernel/auto-cache.test.ts +6 -12
- package/src/kernel/auto-registry.test.ts +3 -3
- package/src/kernel/boot-bind/ai.test.ts +22 -19
- package/src/kernel/boot-bind/ai.ts +5 -43
- package/src/kernel/boot-bind/clock.ts +23 -5
- package/src/kernel/boot-bind/honor-config.test.ts +4 -4
- package/src/kernel/boot.test.ts +11 -6
- package/src/kernel/boot.ts +66 -16
- package/src/kernel/boundary-contract.ts +93 -0
- package/src/kernel/budget.test.ts +1 -1
- package/src/kernel/call.ts +89 -0
- package/src/kernel/capability.ts +6 -0
- package/src/kernel/client-descriptor.ts +123 -0
- package/src/kernel/clock-timezone.test.ts +80 -0
- package/src/kernel/correlation.test.ts +1 -1
- package/src/kernel/dry-run.ts +11 -8
- package/src/kernel/effects-stamping.test.ts +42 -9
- package/src/kernel/effects.test.ts +4 -2
- package/src/kernel/effects.ts +51 -9
- package/src/kernel/errors-channel.ts +17 -0
- package/src/kernel/errors-live-resume.ts +3 -2
- package/src/kernel/errors-tenant.ts +7 -4
- package/src/kernel/errors.registry-helpers.ts +96 -0
- package/src/kernel/errors.registry.test.ts +139 -25
- package/src/kernel/errors.ts +102 -23
- package/src/kernel/external-effects.test.ts +196 -0
- package/src/kernel/flow.test.ts +13 -4
- package/src/kernel/flow.ts +69 -71
- package/src/kernel/fx-ask-telemetry.test.ts +2 -2
- package/src/kernel/fx-dead-letters.test.ts +3 -3
- package/src/kernel/fx-fetch.ts +55 -0
- package/src/kernel/fx-live-stream.ts +2 -2
- package/src/kernel/fx-live.test.ts +8 -8
- package/src/kernel/fx.test.ts +17 -11
- package/src/kernel/fx.ts +180 -57
- package/src/kernel/horizontal-child.ts +1 -1
- package/src/kernel/http-query.test.ts +3 -6
- package/src/kernel/index.ts +13 -3
- package/src/kernel/instance-id.ts +1 -1
- package/src/kernel/instances.test.ts +40 -0
- package/src/kernel/instances.ts +47 -9
- package/src/kernel/live-http.test.ts +6 -7
- package/src/kernel/live-http.ts +6 -2
- package/src/kernel/live-resume.test.ts +1 -1
- package/src/kernel/mcp-tool.test.ts +3 -3
- package/src/kernel/on.ts +98 -4
- package/src/kernel/pipeline.test.ts +12 -15
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/stamp-http.test.ts +3 -3
- package/src/kernel/triggers.ts +210 -95
- package/src/kernel-entry.ts +0 -1
- package/src/manifest/diff.ts +11 -1
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/types.ts +46 -2
- package/src/mcp/docs-index.ts +3 -3
- package/src/mcp/docs-mcp.test.ts +2 -2
- package/src/mcp/docs-tools.ts +1 -1
- package/src/okid.test.ts +56 -0
- package/src/okid.ts +55 -11
- package/src/plugins/anonymous.ts +8 -4
- package/src/plugins/auth/shared.ts +27 -3
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +561 -23
- package/src/plugins/config-source.ts +1 -1
- package/src/plugins/csrf.test.ts +65 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/magic-link.ts +36 -16
- package/src/plugins/oauth/shared.ts +3 -1
- package/src/plugins/oauth.ts +22 -14
- package/src/plugins/otp.ts +37 -21
- package/src/plugins/passkey-webauthn.ts +9 -6
- package/src/plugins/passkey.ts +98 -26
- package/src/plugins/pre-account-hijack.test.ts +223 -0
- package/src/plugins/two-factor.ts +466 -37
- package/src/plugins/username.ts +19 -7
- package/src/release/build-lib.ts +1 -0
- package/src/release/limits.ts +2 -2
- package/src/release/measure.ts +1 -1
- package/src/runs/collect.test.ts +0 -2
- package/src/runtime/json-code-block.test.ts +250 -20
- package/src/runtime/json-code-block.ts +1261 -41
- package/src/term.test.ts +1 -1
- package/src/test/create-test-app.test.ts +12 -12
- package/src/test/live-signals.test.ts +6 -6
- package/src/test/provisions.integration.test.ts +10 -14
- package/src/test/reset-element-registries.ts +1 -1
- package/src/test/tenant-isolation.test.ts +12 -6
- package/site/content/docs/deployment/docker-swarm.mdx +0 -164
- package/site/content/docs/deployment/docker.mdx +0 -227
- package/site/content/docs/deployment/index.mdx +0 -83
- package/site/content/docs/deployment/kubernetes.mdx +0 -176
- package/site/content/docs/deployment/meta.json +0 -5
- package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
- package/site/content/docs/elements/ai.mdx +0 -385
- package/site/content/docs/elements/channel.mdx +0 -346
- package/site/content/docs/elements/clock.mdx +0 -244
- package/site/content/docs/elements/flow.mdx +0 -420
- package/site/content/docs/elements/gate.mdx +0 -436
- package/site/content/docs/elements/signal.mdx +0 -380
- package/site/content/docs/elements/store.mdx +0 -1099
- package/site/content/docs/elements/vault.mdx +0 -405
- package/site/content/docs/get-started/basic-usage.mdx +0 -173
- package/site/content/docs/get-started/index.mdx +0 -43
- package/site/content/docs/get-started/installation.mdx +0 -220
- package/site/content/docs/get-started/introduction.mdx +0 -132
- package/site/content/docs/get-started/meta.json +0 -13
- package/site/content/docs/get-started/project-structure.mdx +0 -925
- package/site/content/docs/get-started/testing.mdx +0 -328
- package/site/content/docs/get-started/why.mdx +0 -162
- package/site/content/docs/recipes/llama-cpp.mdx +0 -151
- package/site/content/docs/recipes/ollama.mdx +0 -142
- package/site/content/docs/recipes/sglang.mdx +0 -105
- package/site/content/docs/recipes/vllm.mdx +0 -106
- package/site/content/docs/reference/cli.md +0 -232
- package/site/content/docs/reference/client.mdx +0 -469
- package/site/content/docs/reference/security.md +0 -74
- package/src/cli/ai-setup/detect-ollama.ts +0 -213
- package/src/cli/ai-setup/recommend.test.ts +0 -225
- package/src/cli/ai-setup/recommend.ts +0 -225
- package/src/cli/dev-controls.test.ts +0 -122
- package/src/cli/dev-controls.ts +0 -164
- package/src/cli/tui/DevLive.tsx +0 -126
- package/src/console/ui-next/dist/assets/access-page-De7Lc2JC.js +0 -4
- package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
- package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
- package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
- package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
- package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
- package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
- package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
- package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
- package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-RGy7VEA_.js +0 -1
- package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
- package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
- package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
- package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.js +0 -4
- package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
- package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
- package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
- package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
- package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
- package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
- package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
- package/src/console/ui-next/dist/assets/units-page-4rHOePuE.js +0 -1
- package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
- package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-DISPgxLM.js +0 -2
- package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
- package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
- package/src/docker/ollama-pull.ts +0 -232
- package/src/docker/recipes/llama-cpp.ts +0 -298
- package/src/docker/recipes/ollama.ts +0 -44
- package/src/docker/recipes/sglang.ts +0 -55
- package/src/docker/recipes/vllm.ts +0 -44
- package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
- package/src/drivers/ai-ollama.integration.test.ts +0 -184
- package/src/drivers/ai-ollama.ts +0 -389
- package/src/drivers/ollama.ts +0 -14
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Vault"
|
|
3
|
-
description: "Secrets, API keys, and config — declared once as typed contracts, resolved from a real vault in production, never leaked into logs."
|
|
4
|
-
icon: "KeyRound"
|
|
5
|
-
source: "docs/spec/unified-theory.md"
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Vault is where your app's **protected knowledge** lives: API keys, database URLs, tokens — plus non-secret config like a public app URL. This page shows how to declare a secret, give it a value, and read it in a Flow, then how OKE keeps it safe in production.
|
|
9
|
-
|
|
10
|
-
<Callout title="The one rule">
|
|
11
|
-
You declare **contracts**, never values, in code. Values come from the environment at boot — a
|
|
12
|
-
secret that has no value anywhere fails the boot loudly, with every gap listed at once.
|
|
13
|
-
</Callout>
|
|
14
|
-
|
|
15
|
-
## Quick start
|
|
16
|
-
|
|
17
|
-
<Steps>
|
|
18
|
-
|
|
19
|
-
<Step>
|
|
20
|
-
### Declare the contract
|
|
21
|
-
|
|
22
|
-
In `src/vault.ts`, declare what your app needs. This says "a secret named `STRIPE_KEY` exists" — it does **not** contain the key itself:
|
|
23
|
-
|
|
24
|
-
```typescript title="src/vault.ts"
|
|
25
|
-
import { vault } from "okengine";
|
|
26
|
-
import { z } from "zod";
|
|
27
|
-
|
|
28
|
-
export const stripeKey = vault.secret("STRIPE_KEY", {
|
|
29
|
-
description: "Payments gateway key",
|
|
30
|
-
rotate: "90d",
|
|
31
|
-
schema: z.string().startsWith("sk_"),
|
|
32
|
-
dev: "sk_test_local", // used only by `oke dev` (local) when nothing else provides a value
|
|
33
|
-
});
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
</Step>
|
|
37
|
-
|
|
38
|
-
<Step>
|
|
39
|
-
### Give it a value
|
|
40
|
-
|
|
41
|
-
For local development, put the real value in `.env.local` (gitignored):
|
|
42
|
-
|
|
43
|
-
```bash title=".env.local"
|
|
44
|
-
STRIPE_KEY=sk_test_your_key_here
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
Or set it from the CLI — it writes to the right place for the active mode:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
oke vault set STRIPE_KEY sk_test_your_key_here
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
</Step>
|
|
54
|
-
|
|
55
|
-
<Step>
|
|
56
|
-
### Read it in a Flow
|
|
57
|
-
|
|
58
|
-
Flows read secrets through `fx.vault.get` — never through `process.env`. It resolves to a
|
|
59
|
-
`Redacted<string>`: printing, logging, or serializing it yields a placeholder, never the value.
|
|
60
|
-
Call `.reveal()` once at the boundary that needs the real credential:
|
|
61
|
-
|
|
62
|
-
```typescript title="src/flows/billing/charge.ts"
|
|
63
|
-
export const charge = on(
|
|
64
|
-
http.post("/charge"),
|
|
65
|
-
flow("billing.charge", {
|
|
66
|
-
in: ChargeInput,
|
|
67
|
-
out: z.object({ id: z.string() }),
|
|
68
|
-
do: async (input, fx) => {
|
|
69
|
-
const key = await fx.vault.get(stripeKey); // Redacted — safe to pass to fx.log
|
|
70
|
-
const intent = await stripe(key.reveal()).create(input);
|
|
71
|
-
return { id: intent.id };
|
|
72
|
-
},
|
|
73
|
-
}),
|
|
74
|
-
);
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
`fx.log` masks any `Redacted` found in the logged data (nested included). A revealed string that
|
|
78
|
-
still reaches `fx.log` is scrubbed by the boot redactor as before.
|
|
79
|
-
|
|
80
|
-
</Step>
|
|
81
|
-
|
|
82
|
-
</Steps>
|
|
83
|
-
|
|
84
|
-
That's the whole loop: declare → set → read. Everything below is what OKE guarantees on top of it.
|
|
85
|
-
|
|
86
|
-
## Redacted until you reveal
|
|
87
|
-
|
|
88
|
-
<VaultRedacted />
|
|
89
|
-
|
|
90
|
-
Pass the wrapper freely — `fx.log`, `String()`, `JSON.stringify`, and
|
|
91
|
-
`console.log` / `util.inspect` all yield `[redacted]` (or a `Redacted<…>` label).
|
|
92
|
-
Call `.reveal()` once at the provider boundary that needs the credential.
|
|
93
|
-
|
|
94
|
-
## Two kinds of contracts
|
|
95
|
-
|
|
96
|
-
| Declaration | Sensitive? | Console shows | Use for |
|
|
97
|
-
| ----------------------------------- | ---------- | ----------------------------------- | --------------------------- |
|
|
98
|
-
| `vault.secret("STRIPE_KEY", …)` | yes | fingerprint only | API keys, tokens, passwords |
|
|
99
|
-
| `vault.config("PUBLIC_APP_URL", …)` | no | **Config** band, value in the clear | Public URLs, feature flags |
|
|
100
|
-
|
|
101
|
-
`vault(name, …)` is shorthand for `vault.secret(name, …)`.
|
|
102
|
-
|
|
103
|
-
<Callout title="Config is the one place for non-secret variables">
|
|
104
|
-
`vault.config()` is the contract the Console **Config** band lists and edits. Declare it once; set
|
|
105
|
-
the value from Console, `oke vault set`, or the resolution chain. Do not use `vault.env` for
|
|
106
|
-
values you want to see or change on `/vault`.
|
|
107
|
-
</Callout>
|
|
108
|
-
|
|
109
|
-
```typescript title="src/vault.ts"
|
|
110
|
-
export const publicAppUrl = vault.config("PUBLIC_APP_URL", {
|
|
111
|
-
description: "Public site origin",
|
|
112
|
-
dev: "http://127.0.0.1:6530",
|
|
113
|
-
});
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
```bash title=".env.local"
|
|
117
|
-
PUBLIC_APP_URL=https://app.example.com
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
```typescript title="src/flows/site/render.ts"
|
|
121
|
-
do: async (_input, fx) => {
|
|
122
|
-
const origin = (await fx.vault.get(publicAppUrl)).reveal();
|
|
123
|
-
return { canonical: `${origin}/` };
|
|
124
|
-
},
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
**Consequence:** `/vault` lists this under **Config** in the clear. `fx.vault.get` still
|
|
128
|
-
returns `Redacted` — `.reveal()` is the read. `vault.env("PUBLIC_APP_URL")` never appears
|
|
129
|
-
on that page.
|
|
130
|
-
|
|
131
|
-
### Plain environment variables
|
|
132
|
-
|
|
133
|
-
`vault.env` reads `process.env` synchronously for values that need no contract — a port, a feature flag, a log level. It never joins the resolution chain, never appears in the Console, never gets a fingerprint, and never gets redacted.
|
|
134
|
-
|
|
135
|
-
| Call | Returns | On a missing value |
|
|
136
|
-
| -------------------------------- | --------------------- | -------------------------------------- |
|
|
137
|
-
| `vault.env("LOG_LEVEL")` | `string \| undefined` | `undefined` (empty counts as missing) |
|
|
138
|
-
| `vault.env.required("REGION")` | `string` | Throws, and boot lists it as a gap |
|
|
139
|
-
| `vault.env.int("PORT", 3000)` | `number` | The default; throws when none is given |
|
|
140
|
-
| `vault.env.bool("DEBUG", false)` | `boolean` | The default; throws when none is given |
|
|
141
|
-
| `vault.env.json("FLAGS")` | `T \| undefined` | `undefined`; throws on malformed JSON |
|
|
142
|
-
|
|
143
|
-
Every name passed to `vault.env.required` is registered, so boot reports missing variables in the same `VaultBootError` as missing secrets — before it opens a database connection.
|
|
144
|
-
|
|
145
|
-
### Contract options
|
|
146
|
-
|
|
147
|
-
| Option | Type | Meaning |
|
|
148
|
-
| ------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
149
|
-
| `description` | string | Human title in boot-gap listings and the Console (falls back to the key) |
|
|
150
|
-
| `rotate` | string | Cadence (`"90d"`) or `"never"` when the secret must not rotate. Omit is the same as `"never"`. Console shows `no rotate` and skips `is:overdue`. |
|
|
151
|
-
| `schema` | zod / Standard Schema | Validated at boot; a bad value fails boot like a missing one |
|
|
152
|
-
| `dev` | string | Local-only fallback when no source provides a value (never used in prod) |
|
|
153
|
-
| `sensitive` | boolean | Override the default (`true` for secrets, `false` for config) |
|
|
154
|
-
| `perTenant` | boolean | Resolve at request time under `{tenantId}/{contract}`. Default `true` when `gate.auth.tenant` is on. Boot skips these contracts. |
|
|
155
|
-
|
|
156
|
-
### Zero-setup Compose fallback
|
|
157
|
-
|
|
158
|
-
`dev: vault.fromDocker("store.sql")` resolves the connection URL that `oke dev` generated for that role — no manual copying of Postgres URLs:
|
|
159
|
-
|
|
160
|
-
```typescript
|
|
161
|
-
export const dbUrl = vault.secret("DATABASE_URL", {
|
|
162
|
-
dev: vault.fromDocker("store.sql"),
|
|
163
|
-
});
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
## Where values come from
|
|
167
|
-
|
|
168
|
-
At boot, each contract is resolved through this chain — **first hit wins**.
|
|
169
|
-
A value already in the vault / managed backend wins over a leftover env pin.
|
|
170
|
-
|
|
171
|
-
<VaultResolution />
|
|
172
|
-
|
|
173
|
-
If every layer misses a contract, boot **fails** before any request is served:
|
|
174
|
-
|
|
175
|
-
```text
|
|
176
|
-
vault boot failed — 1 missing secret(s):
|
|
177
|
-
- STRIPE_KEY: Payments gateway key
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
<Callout title="Good to know">
|
|
181
|
-
This is the fail-loud contract: an app with a missing secret **never** boots halfway and fails
|
|
182
|
-
later at request time. All gaps are listed in one error, not one at a time.
|
|
183
|
-
</Callout>
|
|
184
|
-
|
|
185
|
-
## Setting and rotating values
|
|
186
|
-
|
|
187
|
-
| Command | What it does |
|
|
188
|
-
| -------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
189
|
-
| `oke vault set NAME value` | Write a value to the env file (`.env.local` by default) |
|
|
190
|
-
| `oke vault list` | List names present in the active store |
|
|
191
|
-
| `oke vault import <file>` | Bulk-import names from a dotenv file |
|
|
192
|
-
| `oke vault init` | Initialize the built-in encrypted store (prints the master key once) |
|
|
193
|
-
| `oke vault status` / `seal` / `unseal` | Built-in seal lifecycle |
|
|
194
|
-
| `oke vault rotate <path>` / `rotate-master` | Re-encrypt a secret, or rewrap every DEK under a new master (exclusive lease) |
|
|
195
|
-
| `oke vault audit` / `audit verify` / `audit purge` | Hash-chained audit (serialized appends; no secret values) |
|
|
196
|
-
| `oke vault purge-expired [--dry-run] [--before]` | Hard-delete secret rows past `expires_at` (operator cleanup) |
|
|
197
|
-
| `oke vault backup` / `restore` | Encrypted backup (atomic write + end marker; separate backup KEK) |
|
|
198
|
-
|
|
199
|
-
Flows can write too, through the same capability gate as reads: `fx.vault.set(path, value, { ttlMs?, metadata? })`, `fx.vault.rotate(path, value)`, `fx.vault.delete(path)`, plus `fx.vault.list(prefix?)` and `fx.vault.status()`. These need the encrypted-at-rest backend (`drivers.vault = "vault"`) and throw without it; `fx.vault.get` works on every app.
|
|
200
|
-
|
|
201
|
-
The **Console** (`:6533`) **Vault** page (`/vault`) groups **Secrets** and
|
|
202
|
-
**Config**. Secrets are write-only: a salted fingerprint (`sha256:…`), never
|
|
203
|
-
the cleartext. Config rows show the value — that is `vault.config()`.
|
|
204
|
-
|
|
205
|
-
API keys are principals — mint them on **Access** (`/access`), not Vault.
|
|
206
|
-
See [Gate](/docs/elements/gate#api-keys).
|
|
207
|
-
|
|
208
|
-
Add (`+`) creates a contract from Console as well as from source. Those rows
|
|
209
|
-
show `console` until you declare the same name in the Manifest.
|
|
210
|
-
|
|
211
|
-
Search matches name, description, fingerprint, reader, and winner. Operators
|
|
212
|
-
AND together. `/` focuses the field.
|
|
213
|
-
|
|
214
|
-
| Token | Matches |
|
|
215
|
-
| ------------------------------------------------------ | ------------------------------- |
|
|
216
|
-
| `is:unset` / `is:set` / `is:healthy` | Value present or not |
|
|
217
|
-
| `is:blast` / `is:shared` / `is:dormant` / `is:overdue` | Posture |
|
|
218
|
-
| `kind:secret` / `kind:config` | Contract kind |
|
|
219
|
-
| `from:.env.local` | Resolution winner |
|
|
220
|
-
| `reader:payments` / `fp:sha256` | Flow id / fingerprint |
|
|
221
|
-
| `has:readers` / `has:rotate` | Declared readers or rotate hint |
|
|
222
|
-
|
|
223
|
-
The empty pane is a posture board (unset, blast, shared, dormant, overdue).
|
|
224
|
-
Rotate shows **blast radius** — in-flight durable runs that will wake holding
|
|
225
|
-
the new value.
|
|
226
|
-
|
|
227
|
-
Verify, rotate-master, fingerprint export, and CLI copy live in the security
|
|
228
|
-
sheet.
|
|
229
|
-
|
|
230
|
-
| Action | Confirm | HTTP |
|
|
231
|
-
| -------------------- | ---------------------------- | -------------------------------------------------------------------------- |
|
|
232
|
-
| Add a contract | review dialog | `POST /console/vault/create` — lists as `console` until declared in source |
|
|
233
|
-
| Set / rotate a value | reason + review dialog | `POST /console/vault/set` · `/rotate` |
|
|
234
|
-
| Rotate master key | `ROTATE_MASTER` + reason ≥ 3 | `POST /console/vault/rotate-master` — one batch; `remaining` is honest |
|
|
235
|
-
| Verify audit chain | session only | `GET /console/vault/audit/verify` → `{ ok, brokenAt, reason, row }` |
|
|
236
|
-
|
|
237
|
-
Master rotation is process-global: any operator in the same Console process may
|
|
238
|
-
continue. Overlapping batches return `VaultRotateBusy`. A generated master key
|
|
239
|
-
is shown once and never logged.
|
|
240
|
-
|
|
241
|
-
Backup stays on the CLI (`oke vault backup` / `restore`). The Console never
|
|
242
|
-
accepts a master key in the HTTP body — unseal via `OKE_VAULT_MASTER_KEY`.
|
|
243
|
-
|
|
244
|
-
<Callout title="Builtin concurrency (rotate / audit / backup)">
|
|
245
|
-
`rotate-master` holds a lease (`FOR UPDATE` + lease TTL) so exactly one batch runs at a time; a
|
|
246
|
-
busy audit append briefly waits rather than being misread as "lease held". Audit appends serialize
|
|
247
|
-
under a transactional write lock; backups use temp → fsync → rename with end marker + checksum.
|
|
248
|
-
</Callout>
|
|
249
|
-
|
|
250
|
-
<Callout title="Builtin master keys and expired rows">
|
|
251
|
-
Resolve the master key with `--key -` (stdin), `OKE_VAULT_MASTER_KEY`, or a hidden TTY prompt —
|
|
252
|
-
never put keys on argv in shared shells (history risk). Expired rows stay until `oke vault
|
|
253
|
-
purge-expired` (use `--dry-run` first, or schedule via cron).
|
|
254
|
-
</Callout>
|
|
255
|
-
|
|
256
|
-
<Callout title="Secrets never reach logs">
|
|
257
|
-
`fx.vault.get` returns `Redacted` — `fx.log` shows `[redacted]`. A revealed string that still
|
|
258
|
-
reaches a log is scrubbed by the boot redactor to `[redacted:secret]`. Traces and the Console get
|
|
259
|
-
fingerprints, never cleartext.
|
|
260
|
-
</Callout>
|
|
261
|
-
|
|
262
|
-
## Per-environment drivers
|
|
263
|
-
|
|
264
|
-
Which backend holds your values depends on the environment — configured once in `oke.config.ts`.
|
|
265
|
-
App boot and the Console share the same chain: **backend first**, then env files:
|
|
266
|
-
|
|
267
|
-
```typescript title="oke.config.ts"
|
|
268
|
-
drivers: {
|
|
269
|
-
vault: {
|
|
270
|
-
dev: "env", // process env / .env.local
|
|
271
|
-
test: "memory",
|
|
272
|
-
prod: "vault", // built-in encrypted store (Postgres you already run)
|
|
273
|
-
},
|
|
274
|
-
},
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Defaults are `env` / `memory` / `vault`. create-oke templates pin the built-in store for prod.
|
|
278
|
-
|
|
279
|
-
| Driver | Backend | Best for |
|
|
280
|
-
| --------- | ----------------------------------------------------------- | ---------------------------------- |
|
|
281
|
-
| `env` | process env | Local pins — no encryption at rest |
|
|
282
|
-
| `vault` | Postgres/PGlite envelope (AES-256-GCM) | Default prod — no extra container |
|
|
283
|
-
| `managed` | Official SM (`OKE_VAULT_PROVIDER`) or platform-injected env | Cloud SM / Fly / Railway / K8s |
|
|
284
|
-
| `memory` | in-process map | Tests |
|
|
285
|
-
|
|
286
|
-
### Threat model (honest)
|
|
287
|
-
|
|
288
|
-
Built-in Vault protects a **database dump** (ciphertext + wrapped DEKs). It does **not** equal a separate process-isolated vault:
|
|
289
|
-
|
|
290
|
-
| Threat | Built-in `vault` | Managed remote vault |
|
|
291
|
-
| --------------------------------------------- | ---------------------------------- | --------------------------- |
|
|
292
|
-
| Postgres dump / backup leak | Protected (need master/KEK) | Protected |
|
|
293
|
-
| App RCE / memory dump | Game over (same process) | Better if vault is isolated |
|
|
294
|
-
| Master key only in `.env` next to app secrets | Weak — use KMS auto-unseal in prod | Prefer non-exportable KEK |
|
|
295
|
-
| JS `Buffer.fill(0)` vs remote `mlock` | Hygiene only — not claimed | Stronger outside the app |
|
|
296
|
-
|
|
297
|
-
For production built-in stores, set `vault.encryption.masterKey` to a KMS source (optional peer
|
|
298
|
-
`@aws-sdk/client-kms`) or use `managed` with a provider below. `oke doctor` warns when prod would
|
|
299
|
-
take the master key from the environment.
|
|
300
|
-
|
|
301
|
-
## Tenant isolation (built-in store)
|
|
302
|
-
|
|
303
|
-
When `gate.auth.tenant` is on, `perTenant` contracts resolve at request time under
|
|
304
|
-
`{tenantId}/{contract}`. Boot skips those contracts.
|
|
305
|
-
|
|
306
|
-
The built-in Postgres table `oke_vault_secrets` carries `tenant_id` and the same
|
|
307
|
-
`oke.tenant()` helper as domain tables — not a second GUC.
|
|
308
|
-
|
|
309
|
-
<Callout title="RLS on ciphertext rows">
|
|
310
|
-
`tenant_id = oke.tenant() OR tenant_id IS NULL`. ENABLE without FORCE: the adapter (owner) still
|
|
311
|
-
sees every row; Console / `oke_app` cannot list another tenant's ciphertext. Global `NULL` rows
|
|
312
|
-
stay visible to every stamped tenant.
|
|
313
|
-
</Callout>
|
|
314
|
-
|
|
315
|
-
## Managed providers (official)
|
|
316
|
-
|
|
317
|
-
Set `drivers.vault` to `"managed"` and `OKE_VAULT_PROVIDER` to an id below. Omit the provider when
|
|
318
|
-
the platform already injects secrets as env vars (Fly, Railway, Kubernetes).
|
|
319
|
-
|
|
320
|
-
| Provider | `OKE_VAULT_PROVIDER` | Connection | Optional peer |
|
|
321
|
-
| ------------------- | --------------------- | --------------------------------------------------------------------------------- | --------------------------------------------- |
|
|
322
|
-
| AWS Secrets Manager | `aws-secrets-manager` | `OKE_VAULT_REGION`, `OKE_VAULT_MOUNT` (name prefix) | `@aws-sdk/client-secrets-manager` |
|
|
323
|
-
| Azure Key Vault | `azure-key-vault` | `OKE_VAULT_URL` (vault URI), `OKE_VAULT_MOUNT` (prefix) | `@azure/keyvault-secrets` + `@azure/identity` |
|
|
324
|
-
| GCP Secret Manager | `gcp-secret-manager` | `OKE_VAULT_MOUNT` (`project` or `project/prefix`) | `@google-cloud/secret-manager` |
|
|
325
|
-
| Doppler | `doppler` | `OKE_VAULT_TOKEN`; `OKE_VAULT_MOUNT` as `project/config` for personal tokens | — |
|
|
326
|
-
| 1Password Connect | `1password` | `OKE_VAULT_URL` (Connect host), `OKE_VAULT_TOKEN`, `OKE_VAULT_MOUNT` (vault name) | — |
|
|
327
|
-
|
|
328
|
-
AWS, Azure, and GCP use that cloud's default credential chain. Azure names allow only letters,
|
|
329
|
-
numbers, and hyphens — OKE maps `_` in the contract name to `-` on the wire.
|
|
330
|
-
|
|
331
|
-
## Community / plugin
|
|
332
|
-
|
|
333
|
-
OpenBao and HashiCorp Vault are not shipped in core. Implement a community adapter for the
|
|
334
|
-
`managed` driver surface, or keep using built-in `vault` / `env`.
|
|
335
|
-
|
|
336
|
-
## Troubleshooting
|
|
337
|
-
|
|
338
|
-
<Accordions>
|
|
339
|
-
<Accordion title="Boot fails with VaultBootError listing missing secrets">
|
|
340
|
-
|
|
341
|
-
A contract has no value in any layer of the chain. Fix by providing it in exactly one place:
|
|
342
|
-
|
|
343
|
-
- locally: add `NAME=value` to `.env.local` (or run `oke vault set NAME value`)
|
|
344
|
-
- built-in store: `oke vault init` then unseal, or set via Console (write-only)
|
|
345
|
-
- CI / hosting: set a real environment variable (or the managed provider when `managed`)
|
|
346
|
-
|
|
347
|
-
</Accordion>
|
|
348
|
-
<Accordion title="Does the keel example put secrets in Vault?">
|
|
349
|
-
|
|
350
|
-
Yes — this example only (prod posture). `oke db seed` (dev) writes the keel
|
|
351
|
-
stubs and copies minted stack URLs into the built-in store. `.env.local` keeps
|
|
352
|
-
`OKE_VAULT_MASTER_KEY` and `PORT`; other apps leave Vault empty.
|
|
353
|
-
|
|
354
|
-
</Accordion>
|
|
355
|
-
<Accordion title="How do I rotate a key safely?">
|
|
356
|
-
|
|
357
|
-
Set the new value (`oke vault set` or the Console). The Console shows blast
|
|
358
|
-
radius before you rotate, and `is:overdue` when a secret is past its
|
|
359
|
-
`rotate: "90d"` hint. `rotate: "never"` (or omit `rotate`) shows `no rotate`.
|
|
360
|
-
|
|
361
|
-
</Accordion>
|
|
362
|
-
<Accordion title="How do I pass the builtin master key without shell history?">
|
|
363
|
-
|
|
364
|
-
Prefer `oke vault unseal --key -` and pipe the key on stdin, or omit `--key` on a
|
|
365
|
-
TTY and type it at the hidden prompt. Avoid `--key <base64>` on shared hosts.
|
|
366
|
-
|
|
367
|
-
</Accordion>
|
|
368
|
-
<Accordion title="Console SQL lists another tenant's vault rows">
|
|
369
|
-
|
|
370
|
-
User-plane SQL is stamped `oke.tenant()`. The policy hides other tenants' ciphertext
|
|
371
|
-
and keeps global `NULL` rows. The Vault adapter is table owner, so ENABLE (not FORCE)
|
|
372
|
-
does not hide rows from itself.
|
|
373
|
-
|
|
374
|
-
</Accordion>
|
|
375
|
-
<Accordion title="Expired secrets still take space in Postgres">
|
|
376
|
-
|
|
377
|
-
`expires_at` fails closed on read, but rows stay until you hard-delete them:
|
|
378
|
-
|
|
379
|
-
```bash
|
|
380
|
-
oke vault purge-expired --dry-run
|
|
381
|
-
oke vault purge-expired
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
Schedule the live command with cron when you want automatic cleanup.
|
|
385
|
-
|
|
386
|
-
</Accordion>
|
|
387
|
-
</Accordions>
|
|
388
|
-
|
|
389
|
-
## Learn more
|
|
390
|
-
|
|
391
|
-
- [Project structure](/docs/get-started/project-structure) — `flow({…})` names as `unit.export`; `flow("billing.charge")` still wins
|
|
392
|
-
- [Flow](/docs/elements/flow) — how `fx.vault.get` reads secrets inside `do`
|
|
393
|
-
- [Gate](/docs/elements/gate) — `perTenant` contracts when `gate.auth.tenant` is on
|
|
394
|
-
- [CLI Reference](/docs/reference/cli) — `oke vault set` · `list` · `import`
|
|
395
|
-
|
|
396
|
-
## Next
|
|
397
|
-
|
|
398
|
-
<Cards>
|
|
399
|
-
<Card title="Channel" description="Continue to Channel." href="/docs/elements/channel" />
|
|
400
|
-
<Card
|
|
401
|
-
title="Introduction"
|
|
402
|
-
description="Eight elements overview."
|
|
403
|
-
href="/docs/get-started/introduction"
|
|
404
|
-
/>
|
|
405
|
-
</Cards>
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Basic Usage
|
|
3
|
-
description: Scaffold the standard Notes starter, call health and notes Flows, and inspect them in the Console.
|
|
4
|
-
source: packages/create-oke/templates/standard
|
|
5
|
-
icon: SquareTerminal
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Write your first Flow, call it from a typed client, and prove it with
|
|
9
|
-
`bun:test` — using the same standard Notes starter `create-oke` scaffolds.
|
|
10
|
-
|
|
11
|
-
<Callout title="The one rule">
|
|
12
|
-
All reads, writes, emits, sends, and external calls belong behind `fx`. That is what makes effects
|
|
13
|
-
inspectable and tests deterministic.
|
|
14
|
-
</Callout>
|
|
15
|
-
|
|
16
|
-
## Quick start
|
|
17
|
-
|
|
18
|
-
<Steps>
|
|
19
|
-
|
|
20
|
-
<Step>
|
|
21
|
-
### Scaffold and run
|
|
22
|
-
|
|
23
|
-
```bash title="Terminal"
|
|
24
|
-
bunx create-oke@latest my-app
|
|
25
|
-
cd my-app
|
|
26
|
-
oke dev
|
|
27
|
-
bun run web
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Use `--template advanced` for the same Notes domain with files attach, a daily
|
|
31
|
-
digest Clock, and an AI summarize stub.
|
|
32
|
-
|
|
33
|
-
To exercise Docker with a larger domain, run `examples/keel` from the okengine
|
|
34
|
-
repo (`bun run dev:keel`) — not a create-oke template.
|
|
35
|
-
|
|
36
|
-
Open **6530** in a browser to read the envelope in a code block. The right rail
|
|
37
|
-
lists HTTP routes — static GET paths are links. `curl` still gets `{ data, error }`.
|
|
38
|
-
|
|
39
|
-
<Surfaces />
|
|
40
|
-
|
|
41
|
-
</Step>
|
|
42
|
-
|
|
43
|
-
<Step>
|
|
44
|
-
### Read the health Flow
|
|
45
|
-
|
|
46
|
-
The standard starter already exports a named health Flow:
|
|
47
|
-
|
|
48
|
-
```typescript title="flows/main/health.ts"
|
|
49
|
-
import { on, flow, http } from "okengine/http";
|
|
50
|
-
|
|
51
|
-
export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
`main` omits the URL prefix, so this file is `GET /health` named `main.health`. See [Project structure](/docs/get-started/project-structure).
|
|
55
|
-
|
|
56
|
-
Named flows show up as `main.health` (not `flow_1`) in `oke dev` logs, with the run id after the timestamp.
|
|
57
|
-
Change the route or output and save — App and Console update together from the
|
|
58
|
-
same Manifest.
|
|
59
|
-
|
|
60
|
-
</Step>
|
|
61
|
-
|
|
62
|
-
<Step>
|
|
63
|
-
### Call it from a typed client
|
|
64
|
-
|
|
65
|
-
Generated units become namespaces on the client:
|
|
66
|
-
|
|
67
|
-
```typescript title="app"
|
|
68
|
-
import "@/core";
|
|
69
|
-
import "@/flows/generated";
|
|
70
|
-
import { oke } from "okengine/http";
|
|
71
|
-
|
|
72
|
-
export const app = oke({ name: "notes" });
|
|
73
|
-
export type App = typeof app;
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
`import "@/core"` loads stores, secrets, gates, clocks, channels, and
|
|
77
|
-
message catalogs (via `locales/index.ts`) so they auto-register before `oke()`.
|
|
78
|
-
|
|
79
|
-
```typescript title="client"
|
|
80
|
-
import { createClient } from "okengine/client";
|
|
81
|
-
import type { App } from "./app";
|
|
82
|
-
|
|
83
|
-
const api = createClient<App>("http://localhost:6530");
|
|
84
|
-
const { data, error } = await api.main.health({});
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
`data` and `error` are inferred from the Flow contracts.
|
|
88
|
-
|
|
89
|
-
The starter `web/` app uses `createClient("")` so Vite proxies `/notes` and
|
|
90
|
-
`/health` to the app. Bearer: `auth: { getToken, refresh }`. See [Client](/docs/reference/client).
|
|
91
|
-
|
|
92
|
-
</Step>
|
|
93
|
-
|
|
94
|
-
</Steps>
|
|
95
|
-
|
|
96
|
-
## Mental model
|
|
97
|
-
|
|
98
|
-
Every backend behavior has one shape:
|
|
99
|
-
|
|
100
|
-
<FlowShape />
|
|
101
|
-
|
|
102
|
-
## From Flow to client
|
|
103
|
-
|
|
104
|
-
Export → generated barrel → call or test. Same App type — no separate codegen project.
|
|
105
|
-
|
|
106
|
-
<ClientLoop />
|
|
107
|
-
|
|
108
|
-
## Test
|
|
109
|
-
|
|
110
|
-
Boot the same app with test drivers:
|
|
111
|
-
|
|
112
|
-
```typescript title="tests/standard.test.ts"
|
|
113
|
-
import { expect, test } from "bun:test";
|
|
114
|
-
import { createTestApp } from "okengine/test";
|
|
115
|
-
import { app } from "../src/app";
|
|
116
|
-
|
|
117
|
-
test("boots — health flow", async () => {
|
|
118
|
-
const t = await createTestApp(app);
|
|
119
|
-
const { data, error } = await t.api.main.health({});
|
|
120
|
-
expect(error).toBeNull();
|
|
121
|
-
expect(data).toEqual({ ok: true });
|
|
122
|
-
});
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
```bash title="Terminal"
|
|
126
|
-
bun test
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Troubleshooting
|
|
130
|
-
|
|
131
|
-
<Accordions>
|
|
132
|
-
|
|
133
|
-
<Accordion title="api.main.health is not a function / type error">
|
|
134
|
-
Confirm the Flow is `export`ed from a generated unit (`import "@/flows/generated"` then `oke({ name })`), or from a module you still `.adopt({ main })`.
|
|
135
|
-
|
|
136
|
-
Type `createClient` with your `App` type. Restart `oke dev` after renaming exports so the Manifest refreshes.
|
|
137
|
-
|
|
138
|
-
</Accordion>
|
|
139
|
-
|
|
140
|
-
<Accordion title="createTestApp fails to boot">
|
|
141
|
-
The starter patches test env and stores on the app options. Keep the template's side-imports
|
|
142
|
-
(vault, gates, channels, core db) — removing them can leave Vault or Store unresolved under test
|
|
143
|
-
drivers.
|
|
144
|
-
</Accordion>
|
|
145
|
-
|
|
146
|
-
</Accordions>
|
|
147
|
-
|
|
148
|
-
## Learn more
|
|
149
|
-
|
|
150
|
-
- [Project structure](/docs/get-started/project-structure) — folders are the URL
|
|
151
|
-
- [Flow](/docs/elements/flow) — triggers, contracts, effects, and composition
|
|
152
|
-
- [Store](/docs/elements/store) — SQL, KV, files, index, and the preferred list envelope
|
|
153
|
-
- [fx](/docs/reference/fx) — the full effect surface
|
|
154
|
-
|
|
155
|
-
## Next
|
|
156
|
-
|
|
157
|
-
<Cards>
|
|
158
|
-
<Card
|
|
159
|
-
title="Project structure"
|
|
160
|
-
description="Folders are the URL; unit plus export is the name."
|
|
161
|
-
href="/docs/get-started/project-structure"
|
|
162
|
-
/>
|
|
163
|
-
<Card
|
|
164
|
-
title="Flow"
|
|
165
|
-
description="Triggers, contracts, effects, and composition."
|
|
166
|
-
href="/docs/elements/flow"
|
|
167
|
-
/>
|
|
168
|
-
<Card
|
|
169
|
-
title="Store"
|
|
170
|
-
description="SQL, KV, files, index, and declarative resources."
|
|
171
|
-
href="/docs/elements/store"
|
|
172
|
-
/>
|
|
173
|
-
</Cards>
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: "Get Started"
|
|
3
|
-
description: "From the one law to a running app — introduction, why OKE, install, and first flows."
|
|
4
|
-
icon: "Rocket"
|
|
5
|
-
source: "docs/spec/unified-theory.md"
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
Learn the shape once, install on Bun, then write your first Flow from the standard starter.
|
|
9
|
-
|
|
10
|
-
## Pages
|
|
11
|
-
|
|
12
|
-
<Cards>
|
|
13
|
-
<Card
|
|
14
|
-
title="Introduction"
|
|
15
|
-
description="One law, eight elements, one contract."
|
|
16
|
-
href="/docs/get-started/introduction"
|
|
17
|
-
/>
|
|
18
|
-
<Card
|
|
19
|
-
title="Why OKE"
|
|
20
|
-
description="Six seams every backend maintains by hand."
|
|
21
|
-
href="/docs/get-started/why"
|
|
22
|
-
/>
|
|
23
|
-
<Card
|
|
24
|
-
title="Installation"
|
|
25
|
-
description="Scaffold with create-oke and open the Console."
|
|
26
|
-
href="/docs/get-started/installation"
|
|
27
|
-
/>
|
|
28
|
-
<Card
|
|
29
|
-
title="Basic Usage"
|
|
30
|
-
description="Health Flow, typed client, Console proof."
|
|
31
|
-
href="/docs/get-started/basic-usage"
|
|
32
|
-
/>
|
|
33
|
-
<Card
|
|
34
|
-
title="Project structure"
|
|
35
|
-
description="Folder and file conventions — URL, name, and the generated barrel."
|
|
36
|
-
href="/docs/get-started/project-structure"
|
|
37
|
-
/>
|
|
38
|
-
<Card
|
|
39
|
-
title="Deployment"
|
|
40
|
-
description="Compose, Swarm, Kubernetes, and reverse proxy."
|
|
41
|
-
href="/docs/deployment"
|
|
42
|
-
/>
|
|
43
|
-
</Cards>
|