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,372 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Tenancy"
|
|
3
|
+
description: "Opt into gate.auth.tenant so requests resolve fx.tenant.id from claim, header, or subdomain."
|
|
4
|
+
icon: "Building2"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Tenancy is an identity **dimension** under `gate.auth.tenant`, not a separate gate you attach with
|
|
9
|
+
`.gate(...)`. When enabled, the runtime resolves a tenant for the request and exposes it as
|
|
10
|
+
`fx.tenant.id`. Your SQL / KV / files code (and optional RLS) use that id for isolation.
|
|
11
|
+
|
|
12
|
+
For developers shipping B2B or mixed B2C+B2B apps on okengine — enable the dimension, filter every
|
|
13
|
+
store access by `fx.tenant.id`.
|
|
14
|
+
|
|
15
|
+
<Callout title="The one rule">
|
|
16
|
+
Enable `gate.auth.tenant`, keep membership checks on — then filter every store access by
|
|
17
|
+
`fx.tenant.id`. Do not invent a `gate.auth.tenant` trigger handle.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Turn tenancy on
|
|
26
|
+
|
|
27
|
+
```typescript title="src/app.ts"
|
|
28
|
+
import { oke } from "okengine";
|
|
29
|
+
|
|
30
|
+
export const app = oke({
|
|
31
|
+
name: "shop",
|
|
32
|
+
env: "dev",
|
|
33
|
+
gate: {
|
|
34
|
+
auth: {
|
|
35
|
+
tenant: true, // claim source · header x-oke-tenant · required: false
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or pass options:
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
tenant: {
|
|
45
|
+
required: true, // every user-plane request needs a tenant
|
|
46
|
+
source: "header", // "claim" | "header" | "subdomain" | "resolve"
|
|
47
|
+
header: "x-oke-tenant",
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
</Step>
|
|
52
|
+
|
|
53
|
+
<Step>
|
|
54
|
+
### Protect the route and scope data
|
|
55
|
+
|
|
56
|
+
```typescript title="src/flows/invoices/list.ts"
|
|
57
|
+
import { on, flow, http } from "okengine";
|
|
58
|
+
import { eq } from "drizzle-orm";
|
|
59
|
+
import { member } from "@/core/gate";
|
|
60
|
+
import { db, invoices } from "@/schema";
|
|
61
|
+
|
|
62
|
+
export const list = on(
|
|
63
|
+
http.get().gate(member),
|
|
64
|
+
flow({
|
|
65
|
+
do: async (_, fx) => {
|
|
66
|
+
const tenantId = fx.tenant.id;
|
|
67
|
+
if (!tenantId) return fx.fail("Forbidden", { reason: "tenant_required" });
|
|
68
|
+
return await fx.store(db).select().from(invoices).where(eq(invoices.tenantId, tenantId));
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
</Step>
|
|
75
|
+
|
|
76
|
+
<Step>
|
|
77
|
+
### Switch tenant (session)
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
// Session-only
|
|
81
|
+
const session = await fx.auth.switchTenant("ten_acme");
|
|
82
|
+
// New access token carries tid; subsequent requests resolve fx.tenant.id
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
</Step>
|
|
86
|
+
|
|
87
|
+
</Steps>
|
|
88
|
+
|
|
89
|
+
## Progressive Patterns
|
|
90
|
+
|
|
91
|
+
From claim-based B2C+B2B to pure B2B, custom resolve, and Flow opt-out:
|
|
92
|
+
|
|
93
|
+
<Tabs items={["Claim", "Required", "Resolve", "Opt-out"]}>
|
|
94
|
+
|
|
95
|
+
<Tab value="Claim">
|
|
96
|
+
|
|
97
|
+
Default when `tenant: true`: `source: "claim"`, `required: false`, header name `x-oke-tenant`
|
|
98
|
+
(unused until you switch source).
|
|
99
|
+
|
|
100
|
+
The signed session / key claim supplies `tid`. Membership is still checked unless
|
|
101
|
+
`authoritative: true` on a custom `resolve`.
|
|
102
|
+
|
|
103
|
+
</Tab>
|
|
104
|
+
|
|
105
|
+
<Tab value="Required">
|
|
106
|
+
|
|
107
|
+
Pure B2B — every user-plane request must resolve a tenant:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
tenant: {
|
|
111
|
+
required: true,
|
|
112
|
+
source: "header",
|
|
113
|
+
header: "x-oke-tenant",
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Consequence:** missing tenant fails before `do` with
|
|
118
|
+
`Forbidden` · `reason: "tenant_required"`. Operator-plane Flows are not forced through the
|
|
119
|
+
same required path.
|
|
120
|
+
|
|
121
|
+
</Tab>
|
|
122
|
+
|
|
123
|
+
<Tab value="Resolve">
|
|
124
|
+
|
|
125
|
+
Custom resolver (tier-3 escape hatch). Membership is still checked unless `authoritative`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
tenant: {
|
|
129
|
+
source: "resolve",
|
|
130
|
+
resolve: ({ auth, request, claimTenantId }) => {
|
|
131
|
+
if (claimTenantId) return claimTenantId;
|
|
132
|
+
return request?.headers.get("x-workspace") ?? null;
|
|
133
|
+
},
|
|
134
|
+
// authoritative: true // trust resolve without membership query (fail-open — rare)
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
</Tab>
|
|
139
|
+
|
|
140
|
+
<Tab value="Opt-out">
|
|
141
|
+
|
|
142
|
+
When tenancy is on, Flows default to tenant-scoped (role scopes may union into `fx.auth.scopes`).
|
|
143
|
+
Opt a Flow out with `tenantScoped: false`:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
flow("billing.globalReport", {
|
|
147
|
+
plane: "operator",
|
|
148
|
+
tenantScoped: false,
|
|
149
|
+
do: async (_, fx) => {
|
|
150
|
+
// No tenant-role scope union; fx.tenant.id may still be set from the request
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
</Tab>
|
|
156
|
+
|
|
157
|
+
</Tabs>
|
|
158
|
+
|
|
159
|
+
## Resolution Sources
|
|
160
|
+
|
|
161
|
+
<Callout title="Detailed section">
|
|
162
|
+
Three tiers: signed claim (no membership query), client-supplied header/subdomain (membership
|
|
163
|
+
required), and custom `resolve` (membership unless `authoritative`).
|
|
164
|
+
</Callout>
|
|
165
|
+
|
|
166
|
+
<Tabs items={["claim", "header", "subdomain", "resolve"]}>
|
|
167
|
+
|
|
168
|
+
<Tab value="claim">
|
|
169
|
+
|
|
170
|
+
Signed `tid` on the session / API key. Fast path — no membership query:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
tenant: true;
|
|
174
|
+
// expands to source: "claim", required: false, header: "x-oke-tenant"
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
After `fx.auth.switchTenant(id)`, new access tokens carry `tid` for this source.
|
|
178
|
+
|
|
179
|
+
</Tab>
|
|
180
|
+
|
|
181
|
+
<Tab value="header">
|
|
182
|
+
|
|
183
|
+
Client sends the configured header; membership is required:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
tenant: {
|
|
187
|
+
source: "header",
|
|
188
|
+
header: "x-oke-tenant", // default name
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
curl -X GET http://localhost:6530/invoices \
|
|
194
|
+
-H "authorization: Bearer …" \
|
|
195
|
+
-H "x-oke-tenant: ten_acme"
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Not a member → `Forbidden` · `reason: "not_member"`. Anonymous with a header →
|
|
199
|
+
`Unauthorized`.
|
|
200
|
+
|
|
201
|
+
</Tab>
|
|
202
|
+
|
|
203
|
+
<Tab value="subdomain">
|
|
204
|
+
|
|
205
|
+
First Host label is the tenant id (`acme.example.com` → `acme`). Needs at least three
|
|
206
|
+
labels; membership is required:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
tenant: {
|
|
210
|
+
source: "subdomain";
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Internal / cron calls without an HTTP request keep the stamped claim when present.
|
|
215
|
+
|
|
216
|
+
</Tab>
|
|
217
|
+
|
|
218
|
+
<Tab value="resolve">
|
|
219
|
+
|
|
220
|
+
Callback receives `{ auth, request, claimTenantId }`. Membership still runs unless
|
|
221
|
+
`authoritative: true`:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
tenant: {
|
|
225
|
+
source: "resolve",
|
|
226
|
+
resolve: ({ claimTenantId, request }) =>
|
|
227
|
+
claimTenantId ?? request?.headers.get("x-workspace") ?? null,
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Consequence:** `authoritative: true` is fail-open — use only when you own the resolver’s
|
|
232
|
+
trust boundary.
|
|
233
|
+
|
|
234
|
+
</Tab>
|
|
235
|
+
|
|
236
|
+
</Tabs>
|
|
237
|
+
|
|
238
|
+
## Options
|
|
239
|
+
|
|
240
|
+
| Option | Type | Default | Meaning |
|
|
241
|
+
| --------------- | ------------------------------------------------------- | -------------- | ------------------------------------------- |
|
|
242
|
+
| `required` | `boolean` | `false` | Reject user-plane requests without a tenant |
|
|
243
|
+
| `source` | `"claim"` \| `"header"` \| `"subdomain"` \| `"resolve"` | `"claim"` | Where the tenant id comes from |
|
|
244
|
+
| `header` | `string` | `x-oke-tenant` | Header name when `source: "header"` |
|
|
245
|
+
| `resolve` | `(ctx) => string \| null \| undefined` | — | Custom resolver; membership still checked |
|
|
246
|
+
| `authoritative` | `boolean` | `false` | Trust `resolve` without a membership query |
|
|
247
|
+
|
|
248
|
+
`tenant: true` expands to `{ required: false, source: "claim", header: "x-oke-tenant", authoritative: false }`.
|
|
249
|
+
|
|
250
|
+
## `fx.auth` tenant methods
|
|
251
|
+
|
|
252
|
+
Session-only. API keys get `Forbidden` with `reason: "session_only"`:
|
|
253
|
+
|
|
254
|
+
| Method | Meaning |
|
|
255
|
+
| -------------------------------------------------- | ------------------------------------ |
|
|
256
|
+
| `listTenants()` | Tenants the user belongs to |
|
|
257
|
+
| `switchTenant(id)` | Mint a new session family with `tid` |
|
|
258
|
+
| `createTenant({ name, slug?, id? })` | Create + add caller as member |
|
|
259
|
+
| `deleteTenant(id)` | Remove tenant |
|
|
260
|
+
| `addMember` / `removeMember` | Membership |
|
|
261
|
+
| `listMembers(tenantId)` | Members of a tenant |
|
|
262
|
+
| `upsertTenantRole({ tenantId, roleName, scopes })` | Role → scopes (unioned when scoped) |
|
|
263
|
+
|
|
264
|
+
```typescript title="src/flows/tenants/switch.ts"
|
|
265
|
+
import { on, flow, http } from "okengine";
|
|
266
|
+
import { z } from "zod";
|
|
267
|
+
import { member } from "@/core/gate";
|
|
268
|
+
|
|
269
|
+
export const switchTenant = on(
|
|
270
|
+
http.post().gate(member),
|
|
271
|
+
flow({
|
|
272
|
+
in: z.object({ tenantId: z.string() }),
|
|
273
|
+
do: async ({ tenantId }, fx) => fx.auth.switchTenant(tenantId),
|
|
274
|
+
}),
|
|
275
|
+
);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Store isolation
|
|
279
|
+
|
|
280
|
+
| Facet | Pattern |
|
|
281
|
+
| ----- | ------------------------------------------------------------------------ |
|
|
282
|
+
| SQL | Filter / RLS by `fx.tenant.id` (and table tenant policies when declared) |
|
|
283
|
+
| KV | Optional `{tenantId}:` key prefix when the namespace is tenant-scoped |
|
|
284
|
+
| Files | Path / ACL under the active tenant |
|
|
285
|
+
|
|
286
|
+
RLS helper for a tenant column:
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
import { store, field } from "okengine";
|
|
290
|
+
|
|
291
|
+
export const invoices = store.schema.table(
|
|
292
|
+
"invoices",
|
|
293
|
+
{
|
|
294
|
+
id: field.text().primaryKey(),
|
|
295
|
+
tenantId: field.text(),
|
|
296
|
+
total: field.integer(),
|
|
297
|
+
},
|
|
298
|
+
[store.schema.policy.tenant("tenantId"), store.schema.rls()],
|
|
299
|
+
);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Globally shared tables when tenancy is on need an explicit opt-out:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
store.schema.table("plans", { id: field.text().primaryKey() }, [store.schema.unscoped()]);
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**Consequence:** Gate resolves identity; your Flow still owns the filter. A missing `where
|
|
309
|
+
tenant_id = …` is a data leak, not a Gate bug.
|
|
310
|
+
|
|
311
|
+
## Denial Mapping
|
|
312
|
+
|
|
313
|
+
| Situation | Code | `error.data.reason` |
|
|
314
|
+
| ------------------------------------------ | -------------- | ------------------- |
|
|
315
|
+
| `required: true`, authenticated, no tenant | `Forbidden` | `tenant_required` |
|
|
316
|
+
| Header / subdomain / resolve, not a member | `Forbidden` | `not_member` |
|
|
317
|
+
| Header / subdomain without session | `Unauthorized` | — |
|
|
318
|
+
| Tenant admin from API key | `Forbidden` | `session_only` |
|
|
319
|
+
|
|
320
|
+
## Troubleshooting
|
|
321
|
+
|
|
322
|
+
<Accordions>
|
|
323
|
+
|
|
324
|
+
<Accordion title="fx.tenant.id is null on every request">
|
|
325
|
+
Tenancy off, `required: false` with no claim/header, or membership failed. Enable
|
|
326
|
+
`gate.auth.tenant`, send the claim / header, and confirm the user is a member.
|
|
327
|
+
</Accordion>
|
|
328
|
+
|
|
329
|
+
<Accordion title="Forbidden · session_only on listTenants / switchTenant">
|
|
330
|
+
Tenant admin methods refuse API-key principals. Use a user session.
|
|
331
|
+
</Accordion>
|
|
332
|
+
|
|
333
|
+
<Accordion title="Tenant-granted scope does not authorize a route">
|
|
334
|
+
The Flow set `tenantScoped: false`, or the role was never upserted. Tenant-role union only applies
|
|
335
|
+
when the Flow is tenant-scoped (default when tenancy is on).
|
|
336
|
+
</Accordion>
|
|
337
|
+
|
|
338
|
+
<Accordion title="required: true rejects browser calls">
|
|
339
|
+
Pure B2B needs a tenant on every user-plane request — send `tid` (claim) or the configured header
|
|
340
|
+
before calling gated APIs.
|
|
341
|
+
</Accordion>
|
|
342
|
+
|
|
343
|
+
<Accordion title="Forbidden · not_member on header / subdomain">
|
|
344
|
+
The supplied tenant id is not in the user’s membership set. Add the member, or switch to `source:
|
|
345
|
+
"claim"` after `switchTenant` so the signed `tid` is trusted.
|
|
346
|
+
</Accordion>
|
|
347
|
+
|
|
348
|
+
</Accordions>
|
|
349
|
+
|
|
350
|
+
## Learn more
|
|
351
|
+
|
|
352
|
+
- [Authentication](/docs/elements/gate/auth) — `gate.auth` and `fx.auth`
|
|
353
|
+
- [Authorization](/docs/elements/gate/authorization) — scopes after tenant-role union
|
|
354
|
+
- [RLS](/docs/elements/gate/rls) — `policy.tenant` and the SQL stamp
|
|
355
|
+
- [Store](/docs/elements/store) — SQL / KV / files facets
|
|
356
|
+
- [HTTP](/docs/elements/flow/http) — gated routes that read `fx.tenant`
|
|
357
|
+
|
|
358
|
+
## Next
|
|
359
|
+
|
|
360
|
+
<Cards>
|
|
361
|
+
<Card
|
|
362
|
+
title="RLS"
|
|
363
|
+
description="policy.tenant and the SQL identity stamp."
|
|
364
|
+
href="/docs/elements/gate/rls"
|
|
365
|
+
/>
|
|
366
|
+
<Card
|
|
367
|
+
title="Vault Element"
|
|
368
|
+
description="Secrets and protected configuration."
|
|
369
|
+
href="/docs/elements/vault"
|
|
370
|
+
/>
|
|
371
|
+
<Card title="Gate Overview" description="Return to Gate overview." href="/docs/elements/gate" />
|
|
372
|
+
</Cards>
|
|
@@ -1,45 +1,86 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "Elements"
|
|
3
|
-
description: "The
|
|
3
|
+
description: "The closed set of eight semantic primitives forming the entire OKEngine backend model."
|
|
4
4
|
icon: "Boxes"
|
|
5
5
|
source: "docs/spec/unified-theory.md"
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Forty backend concerns collapse into eight semantic primitives. An element earns its place only with **irreducible physics**.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
<Callout title="Closed primitive set">
|
|
11
|
+
There is no ninth element. Every backend capability belongs to one of the eight elements. New
|
|
12
|
+
infrastructure creates a protocol driver or plugin, preserving a small mental model.
|
|
13
|
+
</Callout>
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
Elements define the model.
|
|
17
|
+
Plugins extend the model's capabilities.
|
|
18
|
+
Drivers connect the model to infrastructure.
|
|
19
|
+
Providers and Recipes choose where that infrastructure runs.
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## The Structural Anatomy
|
|
23
|
+
|
|
24
|
+
Every backend concern is mapped across three conceptual tiers:
|
|
25
|
+
|
|
26
|
+
| Tier | Question Answered | Definition & Scope |
|
|
27
|
+
| ---------------- | ----------------------------------- | --------------------------------------------------------------------------- |
|
|
28
|
+
| **Elements** | _What is the thing?_ | The 8 closed primitives representing irreducible backend physics. |
|
|
29
|
+
| **Capabilities** | _What can it do?_ | Explicit facets, triggers, and execution mechanics within each element. |
|
|
30
|
+
| **Composition** | _What happens when they cooperate?_ | Emergent system properties (Realtime, Live Queries, Multi-Tenancy, Agents). |
|
|
31
|
+
|
|
32
|
+
## The Eight Primitives
|
|
11
33
|
|
|
12
34
|
<Cards>
|
|
13
|
-
<Card
|
|
35
|
+
<Card
|
|
36
|
+
title="Flow"
|
|
37
|
+
description="Behavior — on(Trigger) → Effects via fx. Unified endpoints, jobs, consumers, and durable sagas."
|
|
38
|
+
href="/docs/elements/flow"
|
|
39
|
+
/>
|
|
14
40
|
<Card
|
|
15
41
|
title="Signal"
|
|
16
|
-
description="Data in motion —
|
|
42
|
+
description="Data in motion — once, broadcast, and live with mandatory delivery physics."
|
|
17
43
|
href="/docs/elements/signal"
|
|
18
44
|
/>
|
|
19
45
|
<Card
|
|
20
46
|
title="Store"
|
|
21
|
-
description="Data at rest —
|
|
47
|
+
description="Data at rest — SQL, KV, files with image transforms, and search behind one handle."
|
|
22
48
|
href="/docs/elements/store"
|
|
23
49
|
/>
|
|
24
50
|
<Card
|
|
25
51
|
title="Clock"
|
|
26
|
-
description="Time — schedules, intervals, durable
|
|
52
|
+
description="Time — schedules, intervals, durable sleep, and deterministic time travel."
|
|
27
53
|
href="/docs/elements/clock"
|
|
28
54
|
/>
|
|
29
55
|
<Card
|
|
30
56
|
title="Gate"
|
|
31
|
-
description="Permission to act — auth and rate limits."
|
|
57
|
+
description="Permission to act — auth, tenancy, ABAC/RBAC, and rate limits at the trigger."
|
|
32
58
|
href="/docs/elements/gate"
|
|
33
59
|
/>
|
|
34
60
|
<Card
|
|
35
61
|
title="Vault"
|
|
36
|
-
description="Protected knowledge —
|
|
62
|
+
description="Protected knowledge — fail-loud secret contracts, dynamic config, and redacted values."
|
|
37
63
|
href="/docs/elements/vault"
|
|
38
64
|
/>
|
|
39
65
|
<Card
|
|
40
66
|
title="Channel"
|
|
41
|
-
description="Reaching humans — email, SMS, push."
|
|
67
|
+
description="Reaching humans — email, SMS, WhatsApp, and push with built-in consent."
|
|
42
68
|
href="/docs/elements/channel"
|
|
43
69
|
/>
|
|
44
|
-
<Card
|
|
70
|
+
<Card
|
|
71
|
+
title="AI"
|
|
72
|
+
description="Reaching machine intelligence — models, prompts, agents, and MCP tool boundaries."
|
|
73
|
+
href="/docs/elements/ai"
|
|
74
|
+
/>
|
|
45
75
|
</Cards>
|
|
76
|
+
|
|
77
|
+
## See How They Compose
|
|
78
|
+
|
|
79
|
+
The closed elements compose into full backend capabilities:
|
|
80
|
+
|
|
81
|
+
| Composition Target | Formula | How It Works |
|
|
82
|
+
| ------------------ | ----------------------------------------------- | --------------------------------------------------------- |
|
|
83
|
+
| **Realtime** | Store + Gate + Signal + Flow → Live Query | CDC changes re-checked against Gate RLS, streamed as SSE |
|
|
84
|
+
| **Security** | Gate + Store/RLS + Tenant + fx → Secure runtime | Tenant-isolated queries with least-privilege capability |
|
|
85
|
+
| **Agents** | MCP + Gate + OAuth + Flow → Agent-ready backend | Declared Flows exposed on :6535 behind auth confirmation |
|
|
86
|
+
| **Operations** | Manifest + Effects + Runs → Inspectable backend | Inferred effects feed Console (:6533) and wide-event logs |
|