okengine 0.9.1 → 0.10.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.
Files changed (166) hide show
  1. package/AGENTS.md +1 -1
  2. package/manifest.v1.schema.json +9 -1
  3. package/package.json +3 -3
  4. package/site/content/docs/console/runs.mdx +10 -0
  5. package/site/content/docs/console/traces.mdx +4 -0
  6. package/site/content/docs/elements/ai.mdx +54 -32
  7. package/site/content/docs/elements/channel.mdx +97 -9
  8. package/site/content/docs/elements/clock.mdx +1 -0
  9. package/site/content/docs/elements/flow.mdx +42 -8
  10. package/site/content/docs/get-started/basic-usage.mdx +5 -1
  11. package/site/content/docs/get-started/installation.mdx +9 -5
  12. package/site/content/docs/meta.json +2 -0
  13. package/site/content/docs/providers/azure-redis.mdx +85 -0
  14. package/site/content/docs/providers/cockroachdb.mdx +86 -0
  15. package/site/content/docs/providers/digitalocean-caching.mdx +88 -0
  16. package/site/content/docs/providers/dragonfly-cloud.mdx +82 -0
  17. package/site/content/docs/providers/elasticache.mdx +92 -0
  18. package/site/content/docs/providers/index.mdx +101 -0
  19. package/site/content/docs/providers/memorystore.mdx +89 -0
  20. package/site/content/docs/providers/meta.json +20 -0
  21. package/site/content/docs/providers/neon.mdx +115 -0
  22. package/site/content/docs/providers/redis-cloud.mdx +93 -0
  23. package/site/content/docs/providers/supabase.mdx +117 -0
  24. package/site/content/docs/providers/upstash.mdx +91 -0
  25. package/site/content/docs/providers/yugabytedb.mdx +95 -0
  26. package/site/content/docs/recipes/caddy.mdx +128 -0
  27. package/site/content/docs/recipes/cockroachdb.mdx +127 -0
  28. package/site/content/docs/recipes/dragonfly.mdx +125 -0
  29. package/site/content/docs/recipes/index.mdx +146 -0
  30. package/site/content/docs/recipes/llama-cpp.mdx +153 -0
  31. package/site/content/docs/recipes/mailpit.mdx +136 -0
  32. package/site/content/docs/recipes/meilisearch.mdx +139 -0
  33. package/site/content/docs/recipes/meta.json +31 -0
  34. package/site/content/docs/recipes/ollama.mdx +142 -0
  35. package/site/content/docs/recipes/openbao.mdx +141 -0
  36. package/site/content/docs/recipes/pgdog.mdx +137 -0
  37. package/site/content/docs/recipes/postgres.mdx +136 -0
  38. package/site/content/docs/recipes/redis.mdx +130 -0
  39. package/site/content/docs/recipes/rustfs.mdx +148 -0
  40. package/site/content/docs/recipes/sglang.mdx +105 -0
  41. package/site/content/docs/recipes/supabase-docker.mdx +145 -0
  42. package/site/content/docs/recipes/timescale.mdx +129 -0
  43. package/site/content/docs/recipes/traefik.mdx +136 -0
  44. package/site/content/docs/recipes/valkey.mdx +121 -0
  45. package/site/content/docs/recipes/vllm.mdx +106 -0
  46. package/site/content/docs/recipes/yugabytedb.mdx +135 -0
  47. package/site/content/docs/reference/cli.md +42 -6
  48. package/site/content/docs/reference/configuration.mdx +5 -3
  49. package/site/content/docs/reference/environment-variables.mdx +12 -12
  50. package/site/content/docs/reference/fx.mdx +38 -4
  51. package/src/cli/ai-setup/ai-setup.test.ts +32 -12
  52. package/src/cli/ai-setup/apply.ts +65 -23
  53. package/src/cli/ai-setup/catalog.ts +1316 -35
  54. package/src/cli/ai-setup/detect-ollama.ts +47 -0
  55. package/src/cli/ai-setup/index.ts +44 -7
  56. package/src/cli/ai-setup/prompts.ts +430 -486
  57. package/src/cli/ai-setup/recommend.test.ts +150 -50
  58. package/src/cli/ai-setup/recommend.ts +118 -101
  59. package/src/cli/ask-seed.test.ts +68 -0
  60. package/src/cli/ask-seed.ts +79 -0
  61. package/src/cli/db-seed-redact.test.ts +25 -0
  62. package/src/cli/db-seed.ts +36 -7
  63. package/src/cli/db.test.ts +1 -1
  64. package/src/cli/db.ts +2 -2
  65. package/src/cli/dev-controls.test.ts +107 -0
  66. package/src/cli/dev-controls.ts +354 -0
  67. package/src/cli/dev-schema-sync.ts +12 -4
  68. package/src/cli/dev.test.ts +50 -30
  69. package/src/cli/dev.ts +607 -66
  70. package/src/cli/drizzle-env.test.ts +40 -6
  71. package/src/cli/drizzle-env.ts +22 -1
  72. package/src/cli/ensure-drizzle-config.ts +6 -4
  73. package/src/cli/hero-meta.test.ts +13 -1
  74. package/src/cli/hero-meta.ts +28 -6
  75. package/src/cli/index.ts +5 -0
  76. package/src/cli/registry.ts +24 -0
  77. package/src/cli/replay.test.ts +105 -0
  78. package/src/cli/replay.ts +206 -0
  79. package/src/compiler/extract.ts +3 -3
  80. package/src/config/index.ts +3 -3
  81. package/src/console/server/claim.ts +3 -1
  82. package/src/console/ui/dist/assets/{index-ClX0ZCe5.js → index-D-9KFce5.js} +2 -2
  83. package/src/console/ui/dist/assets/panel-overview-CW0CQEc2.js +1 -0
  84. package/src/console/ui/dist/assets/panel-runs-BxuyDI3x.js +1 -0
  85. package/src/console/ui/dist/assets/{panel-signals-Dsxdu_AR.js → panel-signals-BXofbj7v.js} +1 -1
  86. package/src/console/ui/dist/assets/{panel-store-hy7O8HOs.js → panel-store-B8mH-arU.js} +1 -1
  87. package/src/console/ui/dist/assets/{panel-traces-CBiAe5go.js → panel-traces-DSA-ZWnf.js} +1 -1
  88. package/src/console/ui/dist/index.html +1 -1
  89. package/src/console/ui/overview/slo.ts +31 -3
  90. package/src/console/ui/overview/types.ts +6 -0
  91. package/src/console/ui/runs/errors.test.ts +53 -0
  92. package/src/console/ui/runs/errors.ts +88 -0
  93. package/src/console/ui/runs/index.ts +8 -0
  94. package/src/console/ui/runs/search.ts +16 -0
  95. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +72 -1
  96. package/src/docker/ai-model-status.test.ts +101 -0
  97. package/src/docker/ai-model-status.ts +276 -0
  98. package/src/docker/compose-health.test.ts +115 -0
  99. package/src/docker/compose-health.ts +234 -0
  100. package/src/docker/compose.ts +24 -8
  101. package/src/docker/derive.ts +35 -9
  102. package/src/docker/docker.test.ts +304 -12
  103. package/src/docker/helpers.ts +56 -0
  104. package/src/docker/index.ts +52 -0
  105. package/src/docker/ollama-pull.ts +232 -0
  106. package/src/docker/recipes/cockroach.ts +24 -0
  107. package/src/docker/recipes/index.ts +32 -0
  108. package/src/docker/recipes/llama-cpp.ts +273 -0
  109. package/src/docker/recipes/ollama.ts +19 -23
  110. package/src/docker/recipes/pgdog.ts +4 -1
  111. package/src/docker/recipes/postgres.ts +5 -18
  112. package/src/docker/recipes/sglang.ts +55 -0
  113. package/src/docker/recipes/supabase.ts +21 -0
  114. package/src/docker/recipes/timescale.ts +18 -0
  115. package/src/docker/recipes/vllm.ts +44 -0
  116. package/src/docker/recipes/yugabyte.ts +23 -0
  117. package/src/docker/stack-id.test.ts +22 -0
  118. package/src/docker/stack-id.ts +38 -4
  119. package/src/docker/types.ts +15 -0
  120. package/src/drivers/ai-ollama.integration.test.ts +7 -4
  121. package/src/drivers/signal-engine.ts +10 -0
  122. package/src/drivers/signal-postgres.ts +24 -2
  123. package/src/drivers/signal-types.ts +10 -0
  124. package/src/elements/channel/fallback.test.ts +91 -0
  125. package/src/elements/channel/hard-bounce.test.ts +82 -0
  126. package/src/elements/channel/injection.test.ts +153 -0
  127. package/src/elements/channel/locale-ar.test.ts +102 -0
  128. package/src/elements/channel/otp-delivery.ts +5 -2
  129. package/src/elements/channel/receipts-ledger.test.ts +100 -0
  130. package/src/elements/channel/runtime.ts +24 -1
  131. package/src/elements/channel/test-helpers.ts +60 -0
  132. package/src/elements/channel/whatsapp-compliance.test.ts +124 -0
  133. package/src/elements/store/cache.ts +1 -1
  134. package/src/elements/store/emit-drizzle.ts +43 -9
  135. package/src/elements/store/runtime.ts +1 -1
  136. package/src/elements/store/schema-decl.test.ts +2 -0
  137. package/src/elements/store/schema-decl.ts +15 -0
  138. package/src/elements/store/seed.ts +1 -1
  139. package/src/index.ts +1 -0
  140. package/src/kernel/app.ts +117 -10
  141. package/src/kernel/boot-bind/signal.ts +6 -2
  142. package/src/kernel/boot-bind/store.ts +2 -1
  143. package/src/kernel/boot.test.ts +6 -5
  144. package/src/kernel/boot.ts +8 -3
  145. package/src/kernel/compensate.test.ts +131 -0
  146. package/src/kernel/correlation.test.ts +108 -0
  147. package/src/kernel/effect-timing.test.ts +82 -0
  148. package/src/kernel/flow.ts +38 -0
  149. package/src/kernel/fx-runs.test.ts +49 -0
  150. package/src/kernel/fx.test.ts +14 -0
  151. package/src/kernel/fx.ts +111 -1
  152. package/src/manifest/types.ts +8 -2
  153. package/src/runs/collect.ts +3 -0
  154. package/src/runs/export-otlp.ts +64 -0
  155. package/src/runs/index.ts +16 -0
  156. package/src/runs/parquet.ts +9 -0
  157. package/src/runs/types.ts +5 -0
  158. package/src/runs/window.test.ts +68 -0
  159. package/src/runs/window.ts +148 -0
  160. package/src/runtime/boot-warn.test.ts +45 -0
  161. package/src/runtime/boot-warn.ts +17 -0
  162. package/src/runtime/dev-request-log.ts +5 -5
  163. package/src/term.test.ts +95 -10
  164. package/src/term.ts +369 -14
  165. package/src/console/ui/dist/assets/panel-overview-DONDzBd2.js +0 -1
  166. package/src/console/ui/dist/assets/panel-runs-D5zf-D9c.js +0 -1
@@ -0,0 +1,136 @@
1
+ ---
2
+ title: "Postgres"
3
+ description: "Default store.sql image — POSTGRES_* env, PGDATA path, and when DATABASE_URL points at PgDog instead."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Postgres is the default `store.sql` image in docker and prod. `oke docker` matches
9
+ any image whose reference contains `postgres` or `pgvector` (after more specific
10
+ recipes), then derives env, healthcheck, and connection URL.
11
+
12
+ <Callout title="The one rule">
13
+ The driver id stays `postgres` no matter which Postgres-wire image you pin — vendor choice lives
14
+ in `images["store.sql"]`, not in `drivers.store.sql`.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin the image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ images: {
26
+ "store.sql": "postgres:18-alpine", // any Postgres / pgvector image
27
+ },
28
+ ```
29
+
30
+ </Step>
31
+
32
+ <Step>
33
+ ### Bring the stack up
34
+
35
+ ```bash
36
+ oke dev --docker
37
+ ```
38
+
39
+ `oke docker` writes `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB` into
40
+ `docker/.env.docker` as `${OKE_STORE_SQL_USER}` / `${OKE_STORE_SQL_PASSWORD}` /
41
+ `${OKE_STORE_SQL_DB}` refs — never literal secrets in compose YAML.
42
+
43
+ </Step>
44
+
45
+ <Step>
46
+ ### Connect
47
+
48
+ ```bash
49
+ # App reads this (also accepts OKE_STORE_SQL_URL)
50
+ echo "$DATABASE_URL"
51
+ # postgres://oke:…@127.0.0.1:5432/oke
52
+ ```
53
+
54
+ When PgDog is pinned, `DATABASE_URL` points at `:6432` instead — see
55
+ [PgDog](/docs/recipes/pgdog).
56
+
57
+ </Step>
58
+
59
+ </Steps>
60
+
61
+ ## Required env
62
+
63
+ | Variable | Who sets it | Meaning |
64
+ | ------------------------ | ---------------------- | ------------------------------------ |
65
+ | `OKE_STORE_SQL_USER` | `oke docker` → compose | Injected as `POSTGRES_USER` |
66
+ | `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | Injected as `POSTGRES_PASSWORD` |
67
+ | `OKE_STORE_SQL_DB` | `oke docker` → compose | Injected as `POSTGRES_DB` |
68
+ | `DATABASE_URL` | stack env for the app | What Bun.SQL / Drizzle actually open |
69
+ | `PGDATA` | stack default | `/var/lib/postgresql/data/pgdata` |
70
+ | `POSTGRES_INITDB_ARGS` | stack default | `--data-checksums` |
71
+
72
+ ## Data and backup
73
+
74
+ | Path | What lives there |
75
+ | --------------------------------------------- | ---------------------------------------------------- |
76
+ | `$PGDATA` (`/var/lib/postgresql/data/pgdata`) | Cluster data directory |
77
+ | Image `VOLUME` `/var/lib/postgresql/data` | Official image mount — Docker attaches a volume here |
78
+
79
+ The recipe does **not** declare a named compose volume. Persistence rides the image's
80
+ `VOLUME` (anonymous unless you add a named mount in `compose.override.yml`).
81
+
82
+ **Backup means:** `pg_dump` / `pg_dumpall`, or a Docker volume backup of
83
+ `/var/lib/postgresql/data`. Losing that volume loses the cluster.
84
+
85
+ ## Production note
86
+
87
+ For multi-replica apps, keep SQL on a shared Postgres — Clock CronStore and durable
88
+ journal need one backend. See [Clock](/docs/elements/clock#what-the-runtime-guarantees) ·
89
+ [Docker](/docs/deployment/docker#share-backing-services).
90
+
91
+ Scale out with [PgDog](/docs/recipes/pgdog) so `N × Bun.SQL pool` does not exhaust
92
+ `max_connections`. Do not also stack a managed provider's pooler on the same URL.
93
+
94
+ ## What the recipe configures
95
+
96
+ | Field | Value |
97
+ | -------------- | ---------------------------------------------------- |
98
+ | Container port | `5432` |
99
+ | Healthcheck | `pg_isready -U $POSTGRES_USER`, every 5s, 10 retries |
100
+ | Connection URL | `postgres://user:pass@host:5432/db` |
101
+
102
+ ## Troubleshooting
103
+
104
+ <Accordions>
105
+ <Accordion title="oke boot: postgres driver needs DATABASE_URL">
106
+
107
+ The `postgres` driver fails boot when neither `DATABASE_URL` nor `OKE_STORE_SQL_URL` is
108
+ set. Re-run `oke dev --docker` so the stack writes `docker/.env.docker`, or export
109
+ `DATABASE_URL` yourself when pointing at a managed host.
110
+
111
+ </Accordion>
112
+ <Accordion title="pg_isready fails / store-sql unhealthy">
113
+
114
+ Wrong `POSTGRES_USER` or the container is still initializing. Check
115
+ `docker compose … logs store-sql` for `database system is ready to accept connections`.
116
+
117
+ Credential refs must resolve in `.env.docker` — empty `${OKE_STORE_SQL_PASSWORD}` leaves
118
+ Postgres refusing auth.
119
+
120
+ </Accordion>
121
+ </Accordions>
122
+
123
+ ## Learn more
124
+
125
+ - [PgDog](/docs/recipes/pgdog) — transaction pooling in front of this recipe
126
+ - [Store · SQL](/docs/elements/store#sql) — schema push / generate / migrate
127
+ - [Environment variables](/docs/reference/environment-variables) — `DATABASE_URL` precedence
128
+ - [Neon](/docs/providers/neon) · [Supabase](/docs/providers/supabase) — managed alternatives
129
+
130
+ ## Next
131
+
132
+ <Cards>
133
+ <Card title="PgDog" description="Add pooling in front of Postgres." href="/docs/recipes/pgdog" />
134
+ <Card title="Neon" description="A managed alternative." href="/docs/providers/neon" />
135
+ <Card title="Redis" description="The default store.kv image." href="/docs/recipes/redis" />
136
+ </Cards>
@@ -0,0 +1,130 @@
1
+ ---
2
+ title: "Redis"
3
+ description: "Default store.kv image — OKE_STORE_KV_PASSWORD, maxmemory policy, ephemeral data, REDIS_URL."
4
+ icon: "Zap"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Redis is the default `store.kv` image in docker and prod. `oke docker` matches image
9
+ references containing `redis` or `keydb` and derives a password-required server — no
10
+ unauthenticated instance.
11
+
12
+ <Callout title="The one rule">
13
+ The driver id stays `redis` for every Redis-wire image — Redis, Valkey, Dragonfly, or a managed
14
+ provider. Vendor choice lives in `images["store.kv"]`, never in `drivers.store.kv`.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin the image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ images: {
26
+ "store.kv": "redis:8-alpine",
27
+ },
28
+ ```
29
+
30
+ </Step>
31
+
32
+ <Step>
33
+ ### Required password
34
+
35
+ ```bash title="docker/.env.docker (written by oke docker)"
36
+ OKE_STORE_KV_PASSWORD=…
37
+ REDIS_URL=redis://:…@127.0.0.1:6379
38
+ ```
39
+
40
+ The recipe runs:
41
+
42
+ `redis-server --requirepass "$OKE_STORE_KV_PASSWORD" --maxmemory … --maxmemory-policy …`
43
+
44
+ </Step>
45
+
46
+ <Step>
47
+ ### Optional memory caps
48
+
49
+ | Variable | Default in recipe | Meaning |
50
+ | ------------------------------- | ------------------------------------------------------- | -------- |
51
+ | `OKE_STORE_KV_MAXMEMORY` | `0` (unlimited) in command; stack often sets `256mb` | Max RSS |
52
+ | `OKE_STORE_KV_MAXMEMORY_POLICY` | `noeviction` in command; stack often sets `allkeys-lru` | Eviction |
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Required? | Meaning |
61
+ | ------------------------------- | ------------- | ------------------------------------------------------------------ |
62
+ | `OKE_STORE_KV_PASSWORD` | **Yes** | `--requirepass` — empty password is not a valid production posture |
63
+ | `REDIS_URL` | **Yes** (app) | What the `redis` driver opens (`OKE_STORE_KV_URL` also works) |
64
+ | `OKE_STORE_KV_MAXMEMORY` | Optional | Cap memory |
65
+ | `OKE_STORE_KV_MAXMEMORY_POLICY` | Optional | Eviction when at cap |
66
+
67
+ ## Data and backup
68
+
69
+ The Redis recipe declares **no named volume**. Process memory is the source of truth;
70
+ a container recreate loses keys unless you add persistence yourself
71
+ (`compose.override.yml` + Redis AOF/RDB).
72
+
73
+ **Backup means (default recipe):** treat KV as a cache — rebuild from SQL / files, or
74
+ add an explicit volume + `SAVE`/`BGSAVE` policy before you rely on durability.
75
+
76
+ ## Production note
77
+
78
+ <Callout title="License note" type="warn">
79
+ Redis ≥8 is dual-licensed RSALv2 / SSPLv1 / AGPLv3. Those terms restrict offering Redis itself as
80
+ a managed service to third parties — running it for your own app is unaffected. Prefer
81
+ [Valkey](/docs/recipes/valkey) when the managed-service restriction matters.
82
+ </Callout>
83
+
84
+ Multi-replica Gate rate counters and Signal need a **shared** Redis URL — an in-process
85
+ `memory` driver is per instance. Same shared-store idea as
86
+ [Clock](/docs/elements/clock#what-the-runtime-guarantees) for cron exclusivity.
87
+
88
+ ## What the recipe configures
89
+
90
+ | Field | Value |
91
+ | -------------- | ---------------------------------------------------- |
92
+ | Container port | `6379` |
93
+ | Healthcheck | `redis-cli -a <password> ping`, every 5s, 10 retries |
94
+ | Connection URL | `redis://:pass@host:6379` |
95
+
96
+ ## Troubleshooting
97
+
98
+ <Accordions>
99
+ <Accordion title="oke boot: redis driver needs REDIS_URL">
100
+
101
+ Missing `REDIS_URL` fails boot loudly — never a silent fallback to `memory`. Re-run
102
+ `oke dev --docker` or export `REDIS_URL` when using a managed host. In docker mode the
103
+ message asks whether `oke dev -d` wrote `docker/.env.docker`.
104
+
105
+ </Accordion>
106
+ <Accordion title="NOAUTH Authentication required">
107
+
108
+ `REDIS_URL` is missing the password, or it does not match `OKE_STORE_KV_PASSWORD`.
109
+ Format must be `redis://:PASSWORD@host:6379` (colon before the password, empty username).
110
+
111
+ </Accordion>
112
+ </Accordions>
113
+
114
+ ## Learn more
115
+
116
+ - [Store · KV](/docs/elements/store#kv) — TTL physics, per-driver behavior, license table
117
+ - [Valkey](/docs/recipes/valkey) · [Dragonfly](/docs/recipes/dragonfly) — Redis-wire peers
118
+ - [Environment variables](/docs/reference/environment-variables) — `REDIS_URL` precedence
119
+
120
+ ## Next
121
+
122
+ <Cards>
123
+ <Card title="Valkey" description="Permissive-licensed alternative." href="/docs/recipes/valkey" />
124
+ <Card title="Redis Cloud" description="Managed Redis." href="/docs/providers/redis-cloud" />
125
+ <Card
126
+ title="Upstash"
127
+ description="Serverless Redis-protocol option."
128
+ href="/docs/providers/upstash"
129
+ />
130
+ </Cards>
@@ -0,0 +1,148 @@
1
+ ---
2
+ title: "RustFS"
3
+ description: "S3-compatible object store — S3_ACCESS_KEY_ID / S3_SECRET_ACCESS_KEY, /data volume, console on :9001."
4
+ icon: "HardDrive"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ RustFS is the default docker `store.files` image — an Apache-2.0 S3-compatible object
9
+ store (MinIO alternative). Driver id stays `s3`; Bun binds `Bun.S3Client` against the
10
+ endpoint.
11
+
12
+ <Callout title="The one rule">
13
+ Protocol name is `s3` — vendor choice is the image pin (`rustfs/rustfs:…`) plus `S3_ENDPOINT`.
14
+ Never invent a `rustfs` driver id.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin driver + image (templates already do)
23
+
24
+ ```typescript title="oke.config.ts"
25
+ drivers: {
26
+ store: {
27
+ files: { local: "fs", docker: "s3", test: "memory", prod: "s3" },
28
+ },
29
+ },
30
+ images: {
31
+ "store.files": "rustfs/rustfs:1.0.0-beta.11",
32
+ },
33
+ ```
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Credentials and endpoint
39
+
40
+ ```bash title="docker/.env.docker (written by oke docker)"
41
+ S3_ACCESS_KEY_ID=…
42
+ S3_SECRET_ACCESS_KEY=…
43
+ S3_BUCKET=oke
44
+ S3_ENDPOINT=http://127.0.0.1:9000
45
+ S3_URL=http://…@127.0.0.1:9000/oke
46
+ S3_REGION=us-east-1
47
+ S3_CONSOLE_URL=http://127.0.0.1:9001
48
+ ```
49
+
50
+ Recipe maps:
51
+
52
+ - `RUSTFS_ACCESS_KEY=${S3_ACCESS_KEY_ID}`
53
+ - `RUSTFS_SECRET_KEY=${S3_SECRET_ACCESS_KEY}`
54
+ - `RUSTFS_CONSOLE_ENABLE=true`
55
+ - `RUSTFS_ADDRESS=:9000`
56
+ - command: `/data`
57
+
58
+ </Step>
59
+
60
+ <Step>
61
+ ### Put an object
62
+
63
+ Any flow using `fx.store` files (`put` / `get`) against the `s3` driver talks to this
64
+ endpoint. Open `S3_CONSOLE_URL` for a browser console on port **9001**.
65
+
66
+ </Step>
67
+
68
+ </Steps>
69
+
70
+ ## Required env
71
+
72
+ | Variable | Required? | Meaning |
73
+ | ---------------------- | ----------------- | ------------------------------------------ |
74
+ | `S3_ACCESS_KEY_ID` | **Yes** | Access key → `RUSTFS_ACCESS_KEY` |
75
+ | `S3_SECRET_ACCESS_KEY` | **Yes** | Secret key → `RUSTFS_SECRET_KEY` |
76
+ | `S3_BUCKET` | **Yes** (app) | Bucket name the driver opens |
77
+ | `S3_ENDPOINT` | **Yes** (non-AWS) | Origin `http://host:9000` |
78
+ | `S3_REGION` | Optional | Default `us-east-1` in stack env |
79
+ | `S3_SESSION_TOKEN` | Optional | Temporary creds |
80
+ | `S3_CONSOLE_URL` | Written by stack | UI on `:9001` — not required by the driver |
81
+ | `S3_URL` | Written by stack | Credentialed URL form |
82
+
83
+ ## Data and backup
84
+
85
+ | Volume | Path | What it stores |
86
+ | ------------------ | ------- | ------------------------------ |
87
+ | `store-files-data` | `/data` | Object bytes + RustFS metadata |
88
+
89
+ **Backup means:** snapshot that named volume (or `aws s3 sync` against the API).
90
+ Deleting the volume deletes every object.
91
+
92
+ Credentials live in `.env.docker`, not in `/data` — rotate keys without wiping objects.
93
+ Losing both volume and keys means full restore from backup only.
94
+
95
+ ## Production note
96
+
97
+ For cloud prod, point the same `s3` driver at real S3 / R2 / GCS interop by changing
98
+ `S3_ENDPOINT` + keys — keep the driver id. Self-hosted RustFS on a single node is a
99
+ durability SPOF: put the `/data` volume on reliable disks and back it up.
100
+
101
+ Do not publish `:9000` / `:9001` on the public internet without TLS and network policy —
102
+ the recipe enables the console for local ops.
103
+
104
+ ## What the recipe configures
105
+
106
+ | Field | Value |
107
+ | -------------- | ----------------------------------------------------------------------- |
108
+ | API port | `9000` |
109
+ | Extra port | `9001` → console |
110
+ | Healthcheck | `curl -f http://127.0.0.1:9000/health`, every 5s, 12 retries, 10s start |
111
+ | Connection URL | `http://user:pass@host:9000/bucket` |
112
+
113
+ ## Troubleshooting
114
+
115
+ <Accordions>
116
+ <Accordion title="oke boot: redis / meilisearch / S3 URL missing — S3_BUCKET">
117
+
118
+ Files on the `s3` driver need `S3_BUCKET` (or `OKE_STORE_FILES_DB`). Without it the
119
+ facet cannot open. Re-run `oke dev --docker` so stack env fills `S3_*`, or export them
120
+ for a managed bucket.
121
+
122
+ </Accordion>
123
+ <Accordion title="Access Denied / signature errors against :9000">
124
+
125
+ `S3_ACCESS_KEY_ID` / `S3_SECRET_ACCESS_KEY` do not match `RUSTFS_*` inside the
126
+ container, or `S3_ENDPOINT` points at the wrong host/port. Align `.env.docker` with the
127
+ running service; confirm health at `/health` before debugging client signatures.
128
+
129
+ </Accordion>
130
+ </Accordions>
131
+
132
+ ## Learn more
133
+
134
+ - [Store · Files](/docs/elements/store#files) — facet API and drivers
135
+ - [Environment variables](/docs/reference/environment-variables) — full `S3_*` map
136
+ - [Installation](/docs/get-started/installation) — docker env cheat sheet
137
+
138
+ ## Next
139
+
140
+ <Cards>
141
+ <Card
142
+ title="Mailpit"
143
+ description="SMTP catcher for the same stack."
144
+ href="/docs/recipes/mailpit"
145
+ />
146
+ <Card title="OpenBao" description="Vault for secrets." href="/docs/recipes/openbao" />
147
+ <Card title="Store" description="Files facet details." href="/docs/elements/store" />
148
+ </Cards>
@@ -0,0 +1,105 @@
1
+ ---
2
+ title: "SGLang"
3
+ description: "Production-tier self-hosted inference for structured and agent workloads on GPU."
4
+ icon: "Cpu"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ SGLang is for **structured generation and agent-heavy workloads on real GPU
9
+ hardware** when you self-host inference. Prefer a managed provider for most
10
+ production apps. For general multi-user serving, prefer [vLLM](/docs/recipes/vllm).
11
+
12
+ <Callout title="The one rule">
13
+ Pin an explicit runtime tag (never `latest`), publish only on loopback, and pick SGLang only when
14
+ structured / agent throughput is the reason you self-host.
15
+ </Callout>
16
+
17
+ ## Quick start
18
+
19
+ <Steps>
20
+
21
+ <Step>
22
+ ### Pin driver + image
23
+
24
+ ```typescript title="oke.config.ts"
25
+ drivers: {
26
+ ai: { docker: "openai-compatible", prod: "openai-compatible", test: "mock" },
27
+ },
28
+ images: {
29
+ ai: "lmsysorg/sglang:v0.5.16-runtime", // never :latest
30
+ },
31
+ ```
32
+
33
+ Or `oke ai setup --provider sglang --yes`.
34
+
35
+ </Step>
36
+
37
+ <Step>
38
+ ### Env + GPU
39
+
40
+ ```bash title="docker/.env.docker"
41
+ OKE_AI_URL=http://127.0.0.1:30000/v1
42
+ OKE_AI_MODEL=Qwen/Qwen3-0.6B
43
+ ```
44
+
45
+ Same NVIDIA reservation pattern as vLLM (`ipc: host` + device reservation).
46
+
47
+ </Step>
48
+
49
+ <Step>
50
+ ### Decision matrix
51
+
52
+ | Workload | Recipe |
53
+ | -------------------------------- | -------------------------------------------------------------------------------- |
54
+ | Single-user / dev | [llama.cpp](/docs/recipes/llama-cpp) (default) or [Ollama](/docs/recipes/ollama) |
55
+ | Multi-user GPU serving | [vLLM](/docs/recipes/vllm) |
56
+ | Structured / agent GPU workloads | **SGLang** (this recipe) |
57
+ | Managed cloud | Anthropic / OpenAI / … |
58
+
59
+ </Step>
60
+
61
+ </Steps>
62
+
63
+ ## Security
64
+
65
+ | Control | Requirement |
66
+ | ------------ | ---------------------------------------------- |
67
+ | Host publish | `127.0.0.1:30000:30000` only — never `0.0.0.0` |
68
+ | Image pin | Explicit version tag — never `latest` |
69
+ | Model source | Trusted Hugging Face repos / your own weights |
70
+
71
+ ## What the recipe configures
72
+
73
+ | Field | Value |
74
+ | -------------- | ----------------------------------------------------- |
75
+ | Container port | `30000` |
76
+ | Host publish | `127.0.0.1:30000:30000` |
77
+ | `ipc` | `host` |
78
+ | GPU | `deploy.resources.reservations.devices` (nvidia, all) |
79
+ | Healthcheck | `GET /health`, long start period for model load |
80
+ | Connection URL | `http://host:30000/v1` |
81
+
82
+ ## Troubleshooting
83
+
84
+ <Accordions>
85
+ <Accordion title="GPU not visible / container exits">
86
+
87
+ Install the NVIDIA Container Toolkit. Without a GPU, use
88
+ [llama.cpp](/docs/recipes/llama-cpp) for local smoke tests.
89
+
90
+ </Accordion>
91
+ </Accordions>
92
+
93
+ ## Learn more
94
+
95
+ - [vLLM](/docs/recipes/vllm) — general production GPU serving
96
+ - [llama.cpp](/docs/recipes/llama-cpp) — default local AI
97
+ - [AI](/docs/elements/ai) — drivers and `fx.ask`
98
+
99
+ ## Next
100
+
101
+ <Cards>
102
+ <Card title="vLLM" description="General multi-user GPU serving." href="/docs/recipes/vllm" />
103
+ <Card title="llama.cpp" description="Default local AI." href="/docs/recipes/llama-cpp" />
104
+ <Card title="AI" description="Prompts and guardrails." href="/docs/elements/ai" />
105
+ </Cards>
@@ -0,0 +1,145 @@
1
+ ---
2
+ title: "Supabase"
3
+ description: "Pin supabase/postgres as store.sql — extension bundle (pgvector, …) without Auth, Storage, Realtime, or Studio."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Supabase publishes `supabase/postgres` — plain Postgres with a bundled extension set
9
+ (`pgvector`, `pg_graphql`, `pg_cron`, `wrappers`, and more). `oke docker` matches that
10
+ image ahead of the generic Postgres recipe.
11
+
12
+ <Callout title="Not the full Supabase platform">
13
+ This recipe does **not** start GoTrue, PostgREST, Kong, Realtime, Storage, or Studio. Auth, files,
14
+ and realtime delivery are already covered by [Vault](/docs/elements/vault), [Store ·
15
+ files](/docs/elements/store#files), and [Signal](/docs/elements/signal).
16
+ </Callout>
17
+
18
+ ## Quick start
19
+
20
+ <Steps>
21
+
22
+ <Step>
23
+ ### Pin the image
24
+
25
+ ```typescript title="oke.config.ts"
26
+ images: {
27
+ "store.sql": "supabase/postgres:15.8.1.049", // pin a real tag from Supabase's registry
28
+ },
29
+ ```
30
+
31
+ </Step>
32
+
33
+ <Step>
34
+ ### Same env shape as Postgres
35
+
36
+ `oke docker` injects the same `POSTGRES_USER` / `POSTGRES_PASSWORD` / `POSTGRES_DB`
37
+ refs from `OKE_STORE_SQL_*`. Driver id stays `postgres`.
38
+
39
+ </Step>
40
+
41
+ <Step>
42
+ ### Use pgvector when you need it
43
+
44
+ ```typescript
45
+ drivers: {
46
+ store: {
47
+ index: { local: "memory", docker: "pgvector", prod: "pgvector" },
48
+ },
49
+ },
50
+ ```
51
+
52
+ `CREATE EXTENSION IF NOT EXISTS vector` runs when the `pgvector` index driver opens —
53
+ the extension ships in this image.
54
+
55
+ </Step>
56
+
57
+ </Steps>
58
+
59
+ ## Required env
60
+
61
+ | Variable | Meaning |
62
+ | ------------------------ | ----------------------------------------- |
63
+ | `OKE_STORE_SQL_USER` | → `POSTGRES_USER` |
64
+ | `OKE_STORE_SQL_PASSWORD` | → `POSTGRES_PASSWORD` |
65
+ | `OKE_STORE_SQL_DB` | → `POSTGRES_DB` |
66
+ | `DATABASE_URL` | App connection (`postgres://…:5432/…`) |
67
+ | `PGDATA` | Default `/var/lib/postgresql/data/pgdata` |
68
+
69
+ Identical credential contract to [Postgres](/docs/recipes/postgres) — only the image
70
+ (and its extension bundle) differs.
71
+
72
+ ## Data and backup
73
+
74
+ | Path | What lives there |
75
+ | ----------------------------------------- | ------------------------------------------ |
76
+ | `$PGDATA` | Cluster data, including extension catalogs |
77
+ | Image `VOLUME` `/var/lib/postgresql/data` | Persistence mount |
78
+
79
+ Same backup story as plain Postgres: `pg_dump` or volume backup of
80
+ `/var/lib/postgresql/data`. Losing that volume loses tables **and** which extensions
81
+ were created.
82
+
83
+ ## Production note
84
+
85
+ Want managed Supabase (Auth / Storage / Realtime included)? Use the
86
+ [Supabase provider](/docs/providers/supabase) and set `DATABASE_URL` — do not run this
87
+ image and the cloud project as if they were the same deployment.
88
+
89
+ For self-hosted production, prefer a pinned tag (not `latest`) and the same
90
+ shared-store guidance as [Postgres](/docs/recipes/postgres#production-note). Free-tier
91
+ cloud pausing does not apply to this Docker image — you own uptime.
92
+
93
+ ## What the recipe configures
94
+
95
+ | Field | Value |
96
+ | -------------- | ---------------------------------------------------- |
97
+ | Match | `supabase/postgres` before generic `postgres` |
98
+ | Container port | `5432` |
99
+ | Healthcheck | `pg_isready -U $POSTGRES_USER`, every 5s, 10 retries |
100
+ | Connection URL | `postgres://user:pass@host:5432/db` |
101
+
102
+ ## Troubleshooting
103
+
104
+ <Accordions>
105
+ <Accordion title='Extension "vector" is not available'>
106
+
107
+ You pinned a plain `postgres:` image, not `supabase/postgres`, or the tag predates the
108
+ bundle. Confirm the image reference contains `supabase/postgres`, then re-derive.
109
+ With the right image, `CREATE EXTENSION vector` succeeds without a separate install.
110
+
111
+ </Accordion>
112
+ <Accordion title="Looking for Studio / the REST API">
113
+
114
+ Those services are not part of this recipe. Use the
115
+ [managed Supabase provider](/docs/providers/supabase) for the full platform, or oke's
116
+ own Vault / Store · files / Signal for those concerns.
117
+
118
+ </Accordion>
119
+ </Accordions>
120
+
121
+ ## Learn more
122
+
123
+ - [Supabase (provider)](/docs/providers/supabase) — managed cloud alternative
124
+ - [Postgres](/docs/recipes/postgres) — generic recipe this one takes precedence over
125
+ - [Store · Index](/docs/elements/store#index) — `pgvector`-backed vector search
126
+
127
+ ## Next
128
+
129
+ <Cards>
130
+ <Card
131
+ title="Supabase"
132
+ description="Managed cloud, same wire protocol."
133
+ href="/docs/providers/supabase"
134
+ />
135
+ <Card
136
+ title="PgDog"
137
+ description="Add pooling in front of this recipe too."
138
+ href="/docs/recipes/pgdog"
139
+ />
140
+ <Card
141
+ title="Postgres"
142
+ description="The plain image this specializes."
143
+ href="/docs/recipes/postgres"
144
+ />
145
+ </Cards>