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
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Key Rotation"
|
|
3
|
+
description: "Rotate secret versions under a fresh data key, rewrap the master key, and seal or unseal the builtin vault."
|
|
4
|
+
icon: "RefreshCw"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Key rotation keeps credentials and encryption keys moving without dropping the app. On the builtin
|
|
9
|
+
`vault` driver you rotate a **secret version** (fresh data key) or the **master key** (KEK rewrap).
|
|
10
|
+
Contract `rotate: "90d"` is a Console cadence hint — it does not rotate by itself.
|
|
11
|
+
|
|
12
|
+
For operators and Flows that must cut over keys safely — prefer CLI for master material; use
|
|
13
|
+
`fx.vault.rotate` for path versions inside privileged Flows.
|
|
14
|
+
|
|
15
|
+
<Callout title="The one rule">
|
|
16
|
+
Never pass master keys as CLI argv in shared shells — they land in history. Prefer `oke vault
|
|
17
|
+
unseal --key -`, the env `OKE_VAULT_MASTER_KEY`, or the hidden prompt.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Initialize and set a secret (builtin driver)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# drivers.vault = "vault" — SQL-backed AES-256-GCM
|
|
29
|
+
oke vault init # prints master key once — store out of band
|
|
30
|
+
export OKE_VAULT_MASTER_KEY=… # or --key - from stdin
|
|
31
|
+
|
|
32
|
+
oke vault set STRIPE_KEY
|
|
33
|
+
# prompts for value, or: oke vault set STRIPE_KEY sk_live_…
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
</Step>
|
|
37
|
+
|
|
38
|
+
<Step>
|
|
39
|
+
### Rotate to a new version
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
oke vault rotate STRIPE_KEY sk_live_new_key
|
|
43
|
+
# → oke vault: rotated STRIPE_KEY → v2 (fresh data key)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Omit the value to re-encrypt the current cleartext under a new data key (version bumps, readers
|
|
47
|
+
still see the same string until you change it).
|
|
48
|
+
|
|
49
|
+
</Step>
|
|
50
|
+
|
|
51
|
+
<Step>
|
|
52
|
+
### Confirm status
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
oke vault status
|
|
56
|
+
# initialized, unsealed, kek version, secret count
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
</Step>
|
|
60
|
+
|
|
61
|
+
</Steps>
|
|
62
|
+
|
|
63
|
+
## Progressive Patterns
|
|
64
|
+
|
|
65
|
+
From CLI path rotate to Flow mutations, cadence hints, and master rewrap:
|
|
66
|
+
|
|
67
|
+
<Tabs items={["CLI rotate", "fx.vault.rotate", "Cadence", "Master"]}>
|
|
68
|
+
|
|
69
|
+
<Tab value="CLI rotate">
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
oke vault rotate prod/api/stripe sk_live_new
|
|
73
|
+
oke vault rotate prod/api/stripe # same cleartext, fresh DEK
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Needs an unsealed builtin backend. Missing path:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
oke vault: no such secret: prod/api/stripe
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
</Tab>
|
|
83
|
+
|
|
84
|
+
<Tab value="fx.vault.rotate">
|
|
85
|
+
|
|
86
|
+
Privileged Flow — requires `drivers.vault = "vault"` (bound adapter):
|
|
87
|
+
|
|
88
|
+
```typescript title="src/flows/ops/rotate-stripe.ts"
|
|
89
|
+
import { on, flow, http } from "okengine";
|
|
90
|
+
import { z } from "zod";
|
|
91
|
+
import { gate } from "okengine";
|
|
92
|
+
|
|
93
|
+
const operator = gate.policy("operator", ({ operator: op }) => !!op);
|
|
94
|
+
|
|
95
|
+
export const rotateStripe = on(
|
|
96
|
+
http.post().gate(operator),
|
|
97
|
+
flow({
|
|
98
|
+
plane: "operator",
|
|
99
|
+
in: z.object({ value: z.string().min(1) }),
|
|
100
|
+
effects: { secrets: ["STRIPE_KEY"] },
|
|
101
|
+
do: async ({ value }, fx) => {
|
|
102
|
+
const result = await fx.vault.rotate("STRIPE_KEY", value);
|
|
103
|
+
return { path: result.path, version: result.version };
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`fx.vault.set` writes a new version without forcing a fresh DEK policy the same way; prefer
|
|
110
|
+
`rotate` when retiring the previous data key is the point.
|
|
111
|
+
|
|
112
|
+
Dry-run refuses both (`DryRunWriteIsolationError`).
|
|
113
|
+
|
|
114
|
+
</Tab>
|
|
115
|
+
|
|
116
|
+
<Tab value="Cadence">
|
|
117
|
+
|
|
118
|
+
Declare intent for Console posture — operators still run rotate:
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
export const stripeKey = vault.secret("STRIPE_KEY", {
|
|
122
|
+
description: "Stripe secret API key",
|
|
123
|
+
rotate: "90d",
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Omit or `"never"` when the secret must not rotate on a schedule.
|
|
128
|
+
|
|
129
|
+
</Tab>
|
|
130
|
+
|
|
131
|
+
<Tab value="Master">
|
|
132
|
+
|
|
133
|
+
Rewrap every DEK under a new KEK generation:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
oke vault rotate-master
|
|
137
|
+
# prints the new master key once — store it, then update OKE_VAULT_MASTER_KEY
|
|
138
|
+
|
|
139
|
+
# Resume an interrupted rewrap:
|
|
140
|
+
oke vault rotate-master --new-key -
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Overlapping batches surface `VaultRotateBusy`. Console rotate-master while sealed → `VaultSealed`.
|
|
144
|
+
|
|
145
|
+
</Tab>
|
|
146
|
+
|
|
147
|
+
</Tabs>
|
|
148
|
+
|
|
149
|
+
## Version physics
|
|
150
|
+
|
|
151
|
+
<VaultRotate />
|
|
152
|
+
|
|
153
|
+
Builtin storage encrypts each version with its own data key (DEK), wrapped by a KEK derived from
|
|
154
|
+
the master key:
|
|
155
|
+
|
|
156
|
+
| Operation | What changes | Readers see |
|
|
157
|
+
| ------------------------ | -------------------------------- | ------------------------------------ |
|
|
158
|
+
| `set` / `rotate` + value | New version + (rotate) fresh DEK | New cleartext on next `get` |
|
|
159
|
+
| `rotate` without value | New version + fresh DEK | Same cleartext |
|
|
160
|
+
| `rotate-master` | New KEK; DEKs re-wrapped | Same cleartexts; new master required |
|
|
161
|
+
| `delete` | Crypto-shred path | Subsequent `get` misses |
|
|
162
|
+
|
|
163
|
+
Paths are slash-separated with no leading slash (`prod/api/stripe`). Invalid paths throw
|
|
164
|
+
`VaultError` `INVALID_PATH`.
|
|
165
|
+
|
|
166
|
+
**Consequence:** secret access is not journaled — durable Flow replay re-reads live vault state
|
|
167
|
+
after a rotate instead of replaying a stale credential from the journal.
|
|
168
|
+
|
|
169
|
+
## Seal & unseal
|
|
170
|
+
|
|
171
|
+
| Command / state | Meaning |
|
|
172
|
+
| ------------------ | ------------------------------------------------------- |
|
|
173
|
+
| `oke vault init` | Create backend state; print master key **once** |
|
|
174
|
+
| `oke vault seal` | Drop in-memory master; reads fail with `SEALED` |
|
|
175
|
+
| `oke vault unseal` | Restore master from `--key` / env / prompt |
|
|
176
|
+
| `oke vault status` | `initialized`, sealed flag, `kekVersion`, `secretCount` |
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
oke vault unseal --key - # read base64 master from stdin
|
|
180
|
+
oke vault status --json
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## CLI reference
|
|
184
|
+
|
|
185
|
+
Env / dotenv bag loop:
|
|
186
|
+
|
|
187
|
+
| Command | Purpose |
|
|
188
|
+
| ------------------------------ | ------------------------- |
|
|
189
|
+
| `oke vault set <NAME> [value]` | Write / overwrite a name |
|
|
190
|
+
| `oke vault list` | List names (never values) |
|
|
191
|
+
| `oke vault import <file>` | Bulk import |
|
|
192
|
+
| `oke vault key rotate` | Env-loop key helper |
|
|
193
|
+
|
|
194
|
+
Builtin encrypted store:
|
|
195
|
+
|
|
196
|
+
| Command | Purpose |
|
|
197
|
+
| --------------------------------- | ---------------------------- |
|
|
198
|
+
| `oke vault init` | First-time initialize |
|
|
199
|
+
| `oke vault status [--json]` | Seal / KEK / counts |
|
|
200
|
+
| `oke vault seal` / `unseal` | Master lifecycle |
|
|
201
|
+
| `oke vault rotate <path> [value]` | Version + fresh DEK |
|
|
202
|
+
| `oke vault rotate-master` | KEK rewrap |
|
|
203
|
+
| `oke vault audit` … | Audit trail / verify / purge |
|
|
204
|
+
| `oke vault purge-expired` | Drop expired rows |
|
|
205
|
+
| `oke vault backup` / `restore` | File snapshot |
|
|
206
|
+
|
|
207
|
+
`--url` overrides the SQL URL (`DATABASE_URL` / `OKE_STORE_SQL_URL`).
|
|
208
|
+
|
|
209
|
+
## Troubleshooting
|
|
210
|
+
|
|
211
|
+
<Accordions>
|
|
212
|
+
|
|
213
|
+
<Accordion title="oke vault: no such secret">
|
|
214
|
+
Rotate/get targeted a path that was never set. `oke vault list` (or Console) for live paths;
|
|
215
|
+
remember per-tenant storage uses `{tenantId}/{name}`.
|
|
216
|
+
</Accordion>
|
|
217
|
+
|
|
218
|
+
<Accordion title="VaultSealed">
|
|
219
|
+
Process holds no master key. Export `OKE_VAULT_MASTER_KEY` or `oke vault unseal` before
|
|
220
|
+
rotate-master / reads that need the adapter.
|
|
221
|
+
</Accordion>
|
|
222
|
+
|
|
223
|
+
<Accordion title="VaultRotateBusy">
|
|
224
|
+
Another master-rotation lease or batch is in flight. Wait, or resume with `oke vault rotate-master
|
|
225
|
+
--new-key` (stdin `-` preferred).
|
|
226
|
+
</Accordion>
|
|
227
|
+
|
|
228
|
+
<Accordion title="VaultUnsupported / needs drivers.vault = vault">
|
|
229
|
+
Console or `fx.vault.rotate` hit a non-builtin bag (`env` / `memory` / `managed`). Pin
|
|
230
|
+
`drivers.vault` to `"vault"` and ensure SQL is available.
|
|
231
|
+
</Accordion>
|
|
232
|
+
|
|
233
|
+
<Accordion title="fx.vault.rotate needs a bound Vault backend">
|
|
234
|
+
Same as above — mutations need the encrypted adapter. `fx.vault.get` alone works on any driver.
|
|
235
|
+
</Accordion>
|
|
236
|
+
|
|
237
|
+
<Accordion title="DryRunWriteIsolationError on set / rotate">
|
|
238
|
+
Dry-run refuses vault writes so a live secret is never mutated. Use a real run for rotation.
|
|
239
|
+
</Accordion>
|
|
240
|
+
|
|
241
|
+
<Accordion title="VaultError EXPIRED">
|
|
242
|
+
A version’s absolute expiry passed on the builtin adapter. Rotate or set a new value; purge
|
|
243
|
+
expired rows with `oke vault purge-expired` when cleaning storage.
|
|
244
|
+
</Accordion>
|
|
245
|
+
|
|
246
|
+
</Accordions>
|
|
247
|
+
|
|
248
|
+
## Learn more
|
|
249
|
+
|
|
250
|
+
- [Secrets](/docs/elements/vault/secrets) — contracts and `fx.vault.get`
|
|
251
|
+
- [Vault overview](/docs/elements/vault) — drivers and resolution
|
|
252
|
+
- [Errors](/docs/reference/errors) — `VaultSealed` · `VaultRotateBusy` · `VaultUnsupported`
|
|
253
|
+
- [Environment variables](/docs/reference/environment-variables) — `OKE_VAULT_MASTER_KEY`
|
|
254
|
+
|
|
255
|
+
## Next
|
|
256
|
+
|
|
257
|
+
<Cards>
|
|
258
|
+
<Card
|
|
259
|
+
title="Channel Element"
|
|
260
|
+
description="Send email and other human reach through templates."
|
|
261
|
+
href="/docs/elements/channel"
|
|
262
|
+
/>
|
|
263
|
+
<Card
|
|
264
|
+
title="Secrets"
|
|
265
|
+
description="Declare contracts readers will rotate."
|
|
266
|
+
href="/docs/elements/vault/secrets"
|
|
267
|
+
/>
|
|
268
|
+
<Card
|
|
269
|
+
title="Vault Overview"
|
|
270
|
+
description="Resolution chain, Redacted, and drivers."
|
|
271
|
+
href="/docs/elements/vault"
|
|
272
|
+
/>
|
|
273
|
+
</Cards>
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Secrets"
|
|
3
|
+
description: "Typed vault.secret contracts, boot-time resolution, Redacted reads through fx.vault.get, and per-tenant paths."
|
|
4
|
+
icon: "Key"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Secret contracts (`vault.secret`) declare the credentials your backend requires — Stripe keys,
|
|
9
|
+
webhook HMACs, SMTP URLs. Values resolve at boot; Flows read them as `Redacted` through
|
|
10
|
+
`fx.vault.get`.
|
|
11
|
+
|
|
12
|
+
For developers who must never leak credentials into logs or HTTP bodies — declare the name,
|
|
13
|
+
resolve it, reveal only at the provider edge.
|
|
14
|
+
|
|
15
|
+
<Callout title="The one rule">
|
|
16
|
+
Touch secrets only through `fx.vault.get(contract)`. That records the `secret` effect and returns
|
|
17
|
+
`Redacted` — `.reveal()` belongs at the SDK / HMAC boundary, not in return values.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Declare the contract
|
|
26
|
+
|
|
27
|
+
```typescript title="src/core/vault.ts"
|
|
28
|
+
import { vault } from "okengine";
|
|
29
|
+
import { z } from "zod";
|
|
30
|
+
|
|
31
|
+
export const stripeKey = vault.secret("STRIPE_KEY", {
|
|
32
|
+
description: "Stripe secret API key",
|
|
33
|
+
schema: z.string().startsWith("sk_"),
|
|
34
|
+
rotate: "90d",
|
|
35
|
+
dev: "sk_test_local",
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Import this module before `oke()` so auto-registry can adopt the contract (or pass it in
|
|
40
|
+
`oke({ secrets: […] })`).
|
|
41
|
+
|
|
42
|
+
</Step>
|
|
43
|
+
|
|
44
|
+
<Step>
|
|
45
|
+
### Read inside `do`
|
|
46
|
+
|
|
47
|
+
```typescript title="src/flows/payments/charge.ts"
|
|
48
|
+
import { on, flow, http } from "okengine";
|
|
49
|
+
import { z } from "zod";
|
|
50
|
+
import { member } from "@/core/gate";
|
|
51
|
+
import { stripeKey } from "@/core/vault";
|
|
52
|
+
|
|
53
|
+
export const charge = on(
|
|
54
|
+
http.post().gate(member),
|
|
55
|
+
flow({
|
|
56
|
+
in: z.object({ amount: z.number().int().positive() }),
|
|
57
|
+
do: async ({ amount }, fx) => {
|
|
58
|
+
const key = await fx.vault.get(stripeKey);
|
|
59
|
+
const stripe = new Stripe(key.reveal());
|
|
60
|
+
const intent = await stripe.paymentIntents.create({ amount, currency: "usd" });
|
|
61
|
+
return { id: intent.id };
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
</Step>
|
|
68
|
+
|
|
69
|
+
<Step>
|
|
70
|
+
### Confirm the effect
|
|
71
|
+
|
|
72
|
+
Manifest / Console list `secrets: ["STRIPE_KEY"]` on `payments.charge`. Logs that stringify
|
|
73
|
+
`key` show `[redacted]`.
|
|
74
|
+
|
|
75
|
+
</Step>
|
|
76
|
+
|
|
77
|
+
</Steps>
|
|
78
|
+
|
|
79
|
+
## Progressive Patterns
|
|
80
|
+
|
|
81
|
+
From a bare name to schema, cadence, tenancy, and sensitivity overrides:
|
|
82
|
+
|
|
83
|
+
<Tabs items={["Minimal", "Schema", "Per-tenant", "Shared"]}>
|
|
84
|
+
|
|
85
|
+
<Tab value="Minimal">
|
|
86
|
+
|
|
87
|
+
Name only — description helps boot gaps and Console:
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
export const webhookSecret = vault.secret("APP_WEBHOOK_SECRET", {
|
|
91
|
+
description: "HMAC secret for outbound webhooks",
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
</Tab>
|
|
96
|
+
|
|
97
|
+
<Tab value="Schema">
|
|
98
|
+
|
|
99
|
+
Attach a schema for tooling and human contracts (Zod / Standard Schema). Prefer validating at the
|
|
100
|
+
provider edge when the remote value must match a prefix:
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
export const resendApiKey = vault.secret("RESEND_API_KEY", {
|
|
104
|
+
description: "Resend email delivery API key",
|
|
105
|
+
schema: z.string().startsWith("re_"),
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
</Tab>
|
|
110
|
+
|
|
111
|
+
<Tab value="Per-tenant">
|
|
112
|
+
|
|
113
|
+
When `gate.auth.tenant` is on, contracts default to request-time paths
|
|
114
|
+
`{tenantId}/{name}` — they are **not** boot-gap fatal (value appears per tenant):
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
export const tenantStripe = vault.secret("STRIPE_KEY", {
|
|
118
|
+
description: "Per-workspace Stripe key",
|
|
119
|
+
perTenant: true, // explicit; also the default when tenancy is on
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`fx.vault.get(tenantStripe)` resolves under the active `fx.tenant.id`. Missing tenant throws
|
|
124
|
+
`TENANT_REQUIRED`. Opt out of isolation with `perTenant: false`.
|
|
125
|
+
|
|
126
|
+
**Consequence:** seed or `set` the tenant path (`acme/STRIPE_KEY`), not only the bare contract
|
|
127
|
+
name.
|
|
128
|
+
|
|
129
|
+
</Tab>
|
|
130
|
+
|
|
131
|
+
<Tab value="Shared">
|
|
132
|
+
|
|
133
|
+
A secret shared across all tenants while tenancy is enabled:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
export const platformWebhook = vault.secret("PLATFORM_WEBHOOK", {
|
|
137
|
+
description: "Platform-wide webhook secret",
|
|
138
|
+
perTenant: false,
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Boot still requires a value for shared contracts.
|
|
143
|
+
|
|
144
|
+
</Tab>
|
|
145
|
+
|
|
146
|
+
</Tabs>
|
|
147
|
+
|
|
148
|
+
## Options Reference
|
|
149
|
+
|
|
150
|
+
Third argument shape is `VaultSecretOptions` on `vault.secret(name, options)`:
|
|
151
|
+
|
|
152
|
+
| Option | Type | Default | Meaning |
|
|
153
|
+
| ------------- | --------- | ---------------------- | -------------------------------------------------------------------- |
|
|
154
|
+
| `description` | `string` | — | Boot-gap and Console label |
|
|
155
|
+
| `rotate` | `string` | omit ≈ `"never"` | Cadence hint (`"90d"`) for Console posture — not automatic rotation |
|
|
156
|
+
| `schema` | Schema | — | Declared validator for docs / tooling |
|
|
157
|
+
| `dev` | `string` | — | Dev-only fallback (`vault.fromDocker(role)` allowed) |
|
|
158
|
+
| `sensitive` | `boolean` | `true` | Fingerprinted; Console never shows cleartext |
|
|
159
|
+
| `perTenant` | `boolean` | `true` when tenancy on | Storage path `{tenantId}/{name}`; skipped in boot-gap scan when true |
|
|
160
|
+
|
|
161
|
+
Empty name throws `TypeError: vault.secret: name is required`.
|
|
162
|
+
|
|
163
|
+
## Reading secrets
|
|
164
|
+
|
|
165
|
+
<VaultRedacted />
|
|
166
|
+
|
|
167
|
+
| Call | Returns | Notes |
|
|
168
|
+
| ---------------------------- | ------------------ | -------------------------------------- |
|
|
169
|
+
| `await fx.vault.get(handle)` | `Redacted<string>` | Preferred — capability from the handle |
|
|
170
|
+
| `await fx.vault.get("NAME")` | `Redacted<string>` | Same when the name is declared |
|
|
171
|
+
| `key.reveal()` | `string` | One explicit cleartext escape |
|
|
172
|
+
| `key.map(fn)` | `Redacted<U>` | Transform without exposing to callers |
|
|
173
|
+
| `String(key)` / `toJSON` | `"[redacted]"` | Safe for accidental serialization |
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
const key = await fx.vault.get(stripeKey);
|
|
177
|
+
|
|
178
|
+
fx.log.info(`using ${key}`); // message contains [redacted]
|
|
179
|
+
// JSON.stringify({ key }) → { "key": "[redacted]" }
|
|
180
|
+
|
|
181
|
+
const client = new Stripe(key.reveal());
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Secret access is **never journaled** — durable replay re-reads the live value so a rotated
|
|
185
|
+
credential is not resurrected from the journal.
|
|
186
|
+
|
|
187
|
+
## Effects & Manifest
|
|
188
|
+
|
|
189
|
+
Calling `fx.vault.get` records `effects.secrets` with the contract name. Declare the same list
|
|
190
|
+
explicitly when you want Manifest truth without inference:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
flow("payments.charge", {
|
|
194
|
+
effects: { secrets: ["STRIPE_KEY"] },
|
|
195
|
+
do: async (_, fx) => {
|
|
196
|
+
await fx.vault.get(stripeKey);
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Capability enforcement: reading a name not allowed by the Flow’s effects fails the `secret`
|
|
202
|
+
capability check.
|
|
203
|
+
|
|
204
|
+
## Boot gaps
|
|
205
|
+
|
|
206
|
+
Missing non-tenant contracts fail boot with every hole listed once:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
vault boot failed — 2 missing secret(s):
|
|
210
|
+
- STRIPE_KEY: Stripe secret API key
|
|
211
|
+
- APP_WEBHOOK_SECRET: HMAC secret for outbound webhooks
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Fill gaps with:
|
|
215
|
+
|
|
216
|
+
| Layer | How |
|
|
217
|
+
| ------------ | --------------------------------------------------------- |
|
|
218
|
+
| Driver | `oke vault set NAME`, managed provider write, memory seed |
|
|
219
|
+
| process.env | Export `NAME=…` in the host / CI |
|
|
220
|
+
| `.env.local` | Local override file (gitignored) |
|
|
221
|
+
| `dev:` | Contract fallback — only when dev fallbacks are allowed |
|
|
222
|
+
|
|
223
|
+
On a TTY, `oke dev` prompts for each gap before the app starts and writes values
|
|
224
|
+
into `.env.local` (same store as `oke vault set`). Non-interactive runs still
|
|
225
|
+
fail with `VaultBootError` listing every hole.
|
|
226
|
+
|
|
227
|
+
## Troubleshooting
|
|
228
|
+
|
|
229
|
+
<Accordions>
|
|
230
|
+
|
|
231
|
+
<Accordion title="VaultBootError lists this secret">
|
|
232
|
+
No resolution layer supplied a value. On a TTY, `oke dev` prompts into `.env.local`; otherwise use
|
|
233
|
+
`oke vault set` / env / managed, or a `dev:` fallback. Per-tenant contracts are skipped at boot —
|
|
234
|
+
seed the tenant path.
|
|
235
|
+
</Accordion>
|
|
236
|
+
|
|
237
|
+
<Accordion title='vault: secret "…" is not loaded'>
|
|
238
|
+
Boot succeeded but the name is absent from the merged bag (or you never declared it). Import the
|
|
239
|
+
declaring module; confirm auto-registry or `oke({ secrets: [handle] })`.
|
|
240
|
+
</Accordion>
|
|
241
|
+
|
|
242
|
+
<Accordion title="TENANT_REQUIRED on fx.vault.get">
|
|
243
|
+
Tenancy is on, the contract is per-tenant, and `fx.tenant.id` is null. Resolve a tenant on the
|
|
244
|
+
request, or set `perTenant: false` for a platform-wide secret.
|
|
245
|
+
</Accordion>
|
|
246
|
+
|
|
247
|
+
<Accordion title="Capability / secret effect denied">
|
|
248
|
+
The Flow’s `effects.secrets` (inferred or declared) must include the name you `get`. Touch the
|
|
249
|
+
handle inside `do`, or list the name explicitly.
|
|
250
|
+
</Accordion>
|
|
251
|
+
|
|
252
|
+
<Accordion title="Redacted still leaked through a third-party logger">
|
|
253
|
+
Vault scrubs `fx.log` and known substrings. Direct `console.log(key.reveal())` or foreign sinks
|
|
254
|
+
are outside the redactor — keep cleartext off those paths.
|
|
255
|
+
</Accordion>
|
|
256
|
+
|
|
257
|
+
</Accordions>
|
|
258
|
+
|
|
259
|
+
## Learn more
|
|
260
|
+
|
|
261
|
+
- [Vault overview](/docs/elements/vault) — resolution chain and drivers
|
|
262
|
+
- [Config](/docs/elements/vault/config) — cleartext contracts vs secrets
|
|
263
|
+
- [Key Rotation](/docs/elements/vault/rotation) — version and master-key rotate
|
|
264
|
+
- [Tenancy](/docs/elements/gate/tenancy) — `fx.tenant.id` for per-tenant paths
|
|
265
|
+
- [fx](/docs/reference/fx) — full `fx.vault` table
|
|
266
|
+
|
|
267
|
+
## Next
|
|
268
|
+
|
|
269
|
+
<Cards>
|
|
270
|
+
<Card
|
|
271
|
+
title="Config"
|
|
272
|
+
description="Non-sensitive vault.config and vault.env helpers."
|
|
273
|
+
href="/docs/elements/vault/config"
|
|
274
|
+
/>
|
|
275
|
+
<Card
|
|
276
|
+
title="Key Rotation"
|
|
277
|
+
description="Rotate secret versions and the master key."
|
|
278
|
+
href="/docs/elements/vault/rotation"
|
|
279
|
+
/>
|
|
280
|
+
<Card
|
|
281
|
+
title="Vault Overview"
|
|
282
|
+
description="Resolution chain, Redacted, and drivers."
|
|
283
|
+
href="/docs/elements/vault"
|
|
284
|
+
/>
|
|
285
|
+
</Cards>
|