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,93 @@
1
+ ---
2
+ title: "Redis Cloud"
3
+ description: "Redis Ltd. managed Redis — Configuration tab endpoints, Connect wizard, rediss://, dynamic vs static endpoints."
4
+ icon: "Zap"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Redis Cloud is Redis Ltd.'s first-party managed service — RESP over TCP/TLS, no separate
9
+ REST layer. `drivers.store.kv` stays `redis`.
10
+
11
+ <Callout title="The one rule">
12
+ Use `rediss://` (double **s**) with the endpoint from **Configuration** or the **Connect** wizard.
13
+ Prefer **dynamic** endpoints when both are offered.
14
+ </Callout>
15
+
16
+ ## Find credentials (current console)
17
+
18
+ 1. Open Redis Cloud → your **database**.
19
+ 2. Open the **Configuration** tab:
20
+ - **Essentials:** endpoint under **Access**
21
+ - **Pro:** endpoint under **General** (expand **Dynamic endpoints** if shown)
22
+ 3. Credentials:
23
+ - **Essentials:** **Default user → Configure** → eye icon for password (`default`)
24
+ - **Pro:** **Security** section on Configuration → eye icon for default user password
25
+ 4. Or click **Connect** → connection wizard → copy the ready-made client / `redis-cli`
26
+ snippet (fills host, port, user, password).
27
+
28
+ ```bash title="process env"
29
+ REDIS_URL=rediss://default:PASSWORD@redis-12345.c1.region.cloud.redislabs.com:12345
30
+ # or dynamic: …@horse-battery-staple-12345.db.redis.io:…
31
+ ```
32
+
33
+ Port is a **per-database high port**, not always `6379` — copy it from the panel.
34
+
35
+ ## Production guidance
36
+
37
+ | Topic | Guidance |
38
+ | ------------- | --------------------------------------------------------------------------------- |
39
+ | TLS | Public endpoints expect TLS → `rediss://` |
40
+ | Endpoint type | **Dynamic** (`*.db.redis.io`) can be redirected later; static `redis-….c…` cannot |
41
+ | Private | Pro private endpoint needs VPC peering / PrivateLink / PSC first |
42
+ | Modules | RediSearch / RedisJSON optional — unused by oke's KV driver |
43
+ | Port | Per-database high port from Configuration — never assume `6379` |
44
+
45
+ Essentials vs Pro panels differ (Access vs General), but **Connect** always opens the
46
+ wizard with a filled client snippet — prefer that when the Configuration layout feels
47
+ unfamiliar after a UI refresh.
48
+
49
+ ## Real gotcha — dynamic vs static
50
+
51
+ Apps hard-coded to a **static** `redis-….c…` host cannot follow a later “redirect
52
+ dynamic endpoint” migration. Copy the **dynamic** endpoint from Configuration when both
53
+ exist so you can repoint without code changes.
54
+
55
+ ## Troubleshooting
56
+
57
+ <Accordions>
58
+ <Accordion title="NOAUTH / WRONGPASS">
59
+
60
+ Password not in the URL, or default user disabled under RBAC. Format:
61
+ `rediss://default:PASSWORD@host:port`. If default user is off, use a data-access role
62
+ username/password from Access Control.
63
+
64
+ </Accordion>
65
+ <Accordion title="Connection timeout to public endpoint">
66
+
67
+ Pro databases can block public endpoints. Use the private endpoint after peering, or
68
+ re-enable public access in security settings.
69
+
70
+ </Accordion>
71
+ </Accordions>
72
+
73
+ ## Learn more
74
+
75
+ - [Redis (image)](/docs/recipes/redis) — self-hosted peer
76
+ - [Store · KV](/docs/elements/store#kv) — TTL physics
77
+ - [Upstash](/docs/providers/upstash) — serverless alternative
78
+
79
+ ## Next
80
+
81
+ <Cards>
82
+ <Card
83
+ title="Upstash"
84
+ description="Serverless-friendly alternative."
85
+ href="/docs/providers/upstash"
86
+ />
87
+ <Card
88
+ title="ElastiCache"
89
+ description="AWS-native alternative."
90
+ href="/docs/providers/elasticache"
91
+ />
92
+ <Card title="Neon" description="Managed SQL-side pair." href="/docs/providers/neon" />
93
+ </Cards>
@@ -0,0 +1,117 @@
1
+ ---
2
+ title: "Supabase"
3
+ description: "Managed Postgres — Connect button modes, transaction :6543 vs direct :5432, IPv6, free-tier pause."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Supabase wraps Postgres with Auth, Storage, Realtime, and generated APIs. oke only needs
9
+ the Postgres connection underneath — `drivers.store.sql` stays `postgres`.
10
+
11
+ <Callout title="The one rule">
12
+ Use the dashboard **Connect** button and pick the mode that matches your runtime — Transaction
13
+ pooler for serverless, Direct for migrations. Do not guess ports.
14
+ </Callout>
15
+
16
+ ## Find credentials (current dashboard)
17
+
18
+ 1. Open your project in [supabase.com/dashboard](https://supabase.com/dashboard).
19
+ 2. Click **Connect** in the project top bar
20
+ (`?showConnect=true` on the project URL).
21
+ 3. Choose a method:
22
+ - **Transaction pooler** — `aws-[region].pooler.supabase.com:6543` (Supavisor
23
+ transaction mode)
24
+ - **Session pooler** — same host, port **5432** (IPv4-friendly persistent clients)
25
+ - **Direct connection** — `db.[project-ref].supabase.co:5432`
26
+ 4. Copy the URI; substitute the database password from **Project Settings → Database**
27
+ if the string still shows a placeholder.
28
+
29
+ Alternate path: **Project Settings → Database** → connection string / connection info
30
+ panels (same values as Connect).
31
+
32
+ ```bash title="process env"
33
+ # Serverless / many short-lived clients
34
+ DATABASE_URL=postgres://postgres.[ref]:…@aws-0-[region].pooler.supabase.com:6543/postgres
35
+
36
+ # Migrations / pg_dump / long session features
37
+ # Direct (IPv6 by default on Free unless IPv4 add-on):
38
+ # DATABASE_URL=postgres://postgres:…@db.[ref].supabase.co:5432/postgres
39
+ ```
40
+
41
+ ## Pooled vs direct
42
+
43
+ | Mode | Host:port | Best for |
44
+ | -------------------------- | --------------------------- | ---------------------------------------------- |
45
+ | Transaction (Supavisor) | `…pooler.supabase.com:6543` | Serverless / edge — default app `DATABASE_URL` |
46
+ | Session (Supavisor) | `…pooler.supabase.com:5432` | Persistent backends on **IPv4-only** networks |
47
+ | Direct | `db.[ref].supabase.co:5432` | Migrations, `pg_dump`, replication |
48
+ | Dedicated PgBouncer (paid) | `db.[ref].supabase.co:6543` | High-performance pooled traffic on paid tiers |
49
+
50
+ **Do not stack** [PgDog](/docs/recipes/pgdog) on top of Supavisor. Transaction mode does
51
+ not support prepared statements — turn them off in the client if you see related errors.
52
+
53
+ **IPv6 gotcha:** Direct (and dedicated pooler) are IPv6 unless you buy the IPv4 add-on.
54
+ IPv4-only app hosts must use the shared pooler hostnames.
55
+
56
+ ## pgvector
57
+
58
+ Available on every plan. Enable from the dashboard **Database → Extensions** (or
59
+ `CREATE EXTENSION vector;`). Same `store.index` + `pgvector` driver path as self-hosted
60
+ Postgres.
61
+
62
+ ## Free tier — breaks real production
63
+
64
+ | Limit | Free |
65
+ | -------------------------- | ------------------------------------------------------ |
66
+ | Inactivity pause | **7 days** without enough DB activity → project paused |
67
+ | Active projects | **2** |
68
+ | DB size | **500 MB** |
69
+ | Restore window after pause | Finite (platform retention) |
70
+
71
+ Paused projects wake slowly and will fail uptime checks. Paid plans do not auto-pause.
72
+ Do not run user-facing production on Free.
73
+
74
+ ## Real gotcha — Connect port mix-ups
75
+
76
+ Since Feb 2025, **6543 is transaction-only** on the shared pooler; session mode is
77
+ **5432** on the pooler host. An old snippet that assumed “6543 = session” will break
78
+ session features or auth in subtle ways — re-copy from **Connect** today.
79
+
80
+ ## Troubleshooting
81
+
82
+ <Accordions>
83
+ <Accordion title="Connection refused / timeout to db.[ref].supabase.co">
84
+
85
+ Often IPv4 client → IPv6-only direct endpoint. Switch `DATABASE_URL` to the **Session**
86
+ or **Transaction** pooler host (`pooler.supabase.com`), or enable the IPv4 add-on.
87
+
88
+ </Accordion>
89
+ <Accordion title="Project paused after a quiet week">
90
+
91
+ Free-tier inactivity pause. Restore from the dashboard, then upgrade or keep real DB
92
+ traffic above the pause threshold. Dashboard page views alone may not count.
93
+
94
+ </Accordion>
95
+ </Accordions>
96
+
97
+ ## Learn more
98
+
99
+ - [Supabase recipe](/docs/recipes/supabase-docker) — Postgres image only, no platform
100
+ - [Store · Index](/docs/elements/store#index) — `pgvector`
101
+ - [Environment variables](/docs/reference/environment-variables) — `DATABASE_URL`
102
+
103
+ ## Next
104
+
105
+ <Cards>
106
+ <Card
107
+ title="Supabase (image)"
108
+ description="Run just the Postgres image."
109
+ href="/docs/recipes/supabase-docker"
110
+ />
111
+ <Card title="Neon" description="Serverless alternative." href="/docs/providers/neon" />
112
+ <Card
113
+ title="YugabyteDB"
114
+ description="Distributed Apache-2.0 option."
115
+ href="/docs/providers/yugabytedb"
116
+ />
117
+ </Cards>
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: "Upstash"
3
+ description: "Serverless Redis — Details tab TCP endpoint vs REST URL/token; oke needs rediss:// only."
4
+ icon: "Zap"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Upstash exposes the **same database** two ways: Redis protocol over TLS (TCP) and a
9
+ separate HTTP REST API. oke's `redis` driver speaks **TCP only**.
10
+
11
+ <Callout title="The one rule">
12
+ From the database **Details** / **Connect** panel, copy the **Redis** / TCP connection
13
+ (`rediss://…`), never `UPSTASH_REDIS_REST_URL` / `UPSTASH_REDIS_REST_TOKEN`.
14
+ </Callout>
15
+
16
+ ## Find credentials (current console)
17
+
18
+ 1. Open [console.upstash.com](https://console.upstash.com) → **Redis** → your database.
19
+ 2. On the database page (**Details**):
20
+ - **Endpoint**, **Port**, **Password** (token) for TCP clients
21
+ - Ready-made `redis-cli` / `rediss://` snippets under **Connect** / **Redis**
22
+ 3. Ignore the **REST** tab values (`UPSTASH_REDIS_REST_URL`,
23
+ `UPSTASH_REDIS_REST_TOKEN`) for oke — those are for `@upstash/redis` / HTTP only.
24
+
25
+ ```bash title="process env"
26
+ REDIS_URL=rediss://default:PASSWORD@usw1-example-12345.upstash.io:6379
27
+ ```
28
+
29
+ TLS is mandatory — `redis://` without TLS fails.
30
+
31
+ ## Production guidance
32
+
33
+ | Topic | Guidance |
34
+ | ----------- | --------------------------------------------------------------------------- |
35
+ | Transport | TCP `rediss://` for Bun / long-running servers |
36
+ | REST | Edge/serverless SDKs only — **not** wired to `fx.store` |
37
+ | Pricing | Per-request — watch command fan-out in hot KV paths |
38
+ | Eviction | Plan max size / eviction; serverless still has quotas |
39
+ | Consistency | Global replication options are product-specific — confirm region in Details |
40
+
41
+ Do not put [PgDog](/docs/recipes/pgdog)-style thinking on Redis: there is no separate
42
+ “pooled hostname” toggle. Connection count pressure shows up as Upstash plan limits /
43
+ timeouts, not a Neon-style `-pooler` suffix.
44
+
45
+ When debugging, open **Details** and confirm you are reading the **Redis** column, not
46
+ the REST env var block that sits beside it on the same page.
47
+
48
+ ## Real gotcha — REST token ≠ Redis password
49
+
50
+ Using `UPSTASH_REDIS_REST_TOKEN` inside a `rediss://` URL (or the reverse) yields
51
+ `WRONGPASS` / `NOAUTH`. REST token and TCP password are different credentials on the
52
+ same console page — copy from the **Redis/TCP** section.
53
+
54
+ ## Troubleshooting
55
+
56
+ <Accordions>
57
+ <Accordion title="WRONGPASS invalid or missing auth token">
58
+
59
+ Often a REST token pasted into a TCP client. Re-copy **Password** from Details for
60
+ Redis protocol, build `rediss://:PASSWORD@ENDPOINT:PORT`.
61
+
62
+ </Accordion>
63
+ <Accordion title="NOAUTH Authentication required">
64
+
65
+ Password missing from the URL. ioredis-style URLs need the colon before the password:
66
+ `rediss://:PASSWORD@host:port`.
67
+
68
+ </Accordion>
69
+ </Accordions>
70
+
71
+ ## Learn more
72
+
73
+ - [Redis (image)](/docs/recipes/redis)
74
+ - [Redis Cloud](/docs/providers/redis-cloud) — fixed-instance alternative
75
+ - [Store · KV](/docs/elements/store#kv)
76
+
77
+ ## Next
78
+
79
+ <Cards>
80
+ <Card
81
+ title="Redis Cloud"
82
+ description="Fixed-instance alternative."
83
+ href="/docs/providers/redis-cloud"
84
+ />
85
+ <Card
86
+ title="Dragonfly Cloud"
87
+ description="Another managed option."
88
+ href="/docs/providers/dragonfly-cloud"
89
+ />
90
+ <Card title="Neon" description="Managed SQL-side pair." href="/docs/providers/neon" />
91
+ </Cards>
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: "YugabyteDB"
3
+ description: "Distributed SQL (YSQL) — Connect → Application, port 5433, CA cert, YSQL vs YCQL."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ YugabyteDB Aeon exposes a Postgres-compatible query layer (**YSQL**). That is the only
9
+ API oke's `postgres` driver targets — not YCQL.
10
+
11
+ <Callout title="The one rule">
12
+ In **Connect → Connect to your Application**, choose **YSQL** and download the CA cert. Port
13
+ **5433** is the YSQL default — not Postgres's 5432.
14
+ </Callout>
15
+
16
+ ## Find credentials (current console)
17
+
18
+ 1. YugabyteDB Aeon → **Clusters** → select the cluster.
19
+ 2. Click **Connect**.
20
+ 3. Click **Connect to your Application**.
21
+ 4. Click **Download CA Cert** and install it where the app can read it.
22
+ 5. Select API **YSQL** (not YCQL).
23
+ 6. Pick address mode: **Private Address** / **Private Service Endpoint** if VPC-peered;
24
+ **Public Address** only if **Settings → Network Access → Public Access** is enabled
25
+ (not recommended for production).
26
+ 7. Copy **Connection String** (or Parameters) into `DATABASE_URL`.
27
+
28
+ ```bash title="process env"
29
+ DATABASE_URL=postgresql://admin:…@….aws.yugabyte.cloud:5433/yugabyte?ssl=true&sslmode=verify-full&sslrootcert=/path/to/root.crt
30
+ ```
31
+
32
+ Also add your app's IPs (or peered VPC) to the cluster **IP allow list** before
33
+ connecting.
34
+
35
+ ## Production guidance
36
+
37
+ | Topic | Guidance |
38
+ | ------- | ----------------------------------------------------------------------------- |
39
+ | API | **YSQL only** — YCQL is Cassandra-wire, useless to `postgres` |
40
+ | TLS | `sslmode=verify-full` + downloaded CA |
41
+ | Network | Prefer private / PSE; public access is an explicit opt-in |
42
+ | License | Core is **Apache 2.0** (including once-enterprise features in the core build) |
43
+
44
+ No Neon-style pooled hostname toggle — connection limits and load balancing are
45
+ cluster/VPC topology concerns. Smart drivers want a peered VPC; otherwise they probe
46
+ unreachable nodes first and add latency.
47
+
48
+ ## Real gotcha — wrong API tab
49
+
50
+ Copying **YCQL** parameters (port **9042**) into `DATABASE_URL` fails immediately —
51
+ different protocol. Always confirm the Connect dialog shows **YSQL** and port **5433**.
52
+
53
+ ## Troubleshooting
54
+
55
+ <Accordions>
56
+ <Accordion title="Connection timed out / could not connect to server">
57
+
58
+ IP allow list or Public Access. Add the client IP under network settings, or use the
59
+ private address from a peered VPC. Public hostname stays dark until Public Access is on.
60
+
61
+ </Accordion>
62
+ <Accordion title="SSL error with verify-full">
63
+
64
+ CA not downloaded or `sslrootcert` path wrong. Re-run **Download CA Cert** from the
65
+ Connect dialog and point the URI at that file.
66
+
67
+ </Accordion>
68
+ </Accordions>
69
+
70
+ ## Learn more
71
+
72
+ - [CockroachDB](/docs/providers/cockroachdb) — license / feature comparison
73
+ - [YugabyteDB (self-hosted)](/docs/recipes/yugabytedb) — single-node Docker recipe
74
+ - [Postgres (image)](/docs/recipes/postgres) — driver this backs
75
+ - [Store · SQL](/docs/elements/store#sql) — schema workflows
76
+
77
+ ## Next
78
+
79
+ <Cards>
80
+ <Card
81
+ title="CockroachDB"
82
+ description="Compare licensing and features."
83
+ href="/docs/providers/cockroachdb"
84
+ />
85
+ <Card
86
+ title="Supabase"
87
+ description="Managed single-node option."
88
+ href="/docs/providers/supabase"
89
+ />
90
+ <Card
91
+ title="Redis Cloud"
92
+ description="Managed Redis-side pair."
93
+ href="/docs/providers/redis-cloud"
94
+ />
95
+ </Cards>
@@ -0,0 +1,128 @@
1
+ ---
2
+ title: "Caddy"
3
+ description: "Automatic-HTTPS reverse proxy — OKE_PROXY_HOST, Caddyfile, /data certificate volume, single-instance compose."
4
+ icon: "Lock"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ Caddy is the simplest TLS path — automatic HTTPS from a generated `Caddyfile`, no
9
+ certificate management by hand. Right choice for a single app instance without `--scale`.
10
+
11
+ <Callout title="The one rule">
12
+ Leave `images.proxy` unset until you need HTTPS at the edge or `--scale app=N`. Once set, `app`
13
+ stops publishing its host port directly — Caddy (or Traefik) does.
14
+ </Callout>
15
+
16
+ ## Quick start
17
+
18
+ <Steps>
19
+
20
+ <Step>
21
+ ### Pin the proxy
22
+
23
+ ```typescript title="oke.config.ts"
24
+ images: {
25
+ proxy: "caddy:2-alpine",
26
+ },
27
+ ```
28
+
29
+ </Step>
30
+
31
+ <Step>
32
+ ### Set the public hostname
33
+
34
+ ```bash title="docker/.env.docker"
35
+ OKE_PROXY_HOST=app.example.com
36
+ ```
37
+
38
+ Unset defaults to `localhost` — Caddy issues a **local** TLS cert instead of Let's Encrypt.
39
+
40
+ </Step>
41
+
42
+ <Step>
43
+ ### Include the proxy layer
44
+
45
+ ```bash
46
+ docker compose -f compose.yml -f compose.proxy.yml … up -d
47
+ ```
48
+
49
+ Generated `Caddyfile`: `{$OKE_PROXY_HOST:localhost} { reverse_proxy app:6530 }`.
50
+
51
+ </Step>
52
+
53
+ </Steps>
54
+
55
+ ## Required env
56
+
57
+ | Variable | Required? | Meaning |
58
+ | ----------------------- | ----------- | --------------------------------------------------------------------------- |
59
+ | `OKE_PROXY_HOST` | Recommended | Public hostname for ACME; default `localhost` → local TLS only |
60
+ | `allowedHosts` (config) | Production | Must include the public hostname — see [Security](/docs/reference/security) |
61
+
62
+ Caddy has no separate ACME email env in this recipe (unlike Traefik's
63
+ `OKE_PROXY_ACME_EMAIL`).
64
+
65
+ ## Data and backup
66
+
67
+ | Volume | Path | What it stores |
68
+ | -------------- | ----------------------------------------- | ------------------------------- |
69
+ | `proxy-data` | `/data` | ACME certificates, account keys |
70
+ | `proxy-config` | `/config` | Caddy runtime config |
71
+ | Bind mount | `./Caddyfile` → `/etc/caddy/Caddyfile:ro` | Generated site block |
72
+
73
+ **Backup means:** preserve the `proxy-data` named volume (and ideally `proxy-config`) so
74
+ Let's Encrypt rate limits and cert renewals survive recreates. Losing `/data` forces
75
+ re-issuance. The `Caddyfile` is regenerated by `oke docker`.
76
+
77
+ ## Production note
78
+
79
+ Caddy has **no** service-discovery story for multiple `app` replicas. Once you run
80
+ `docker compose up --scale app=N`, switch to [Traefik](/docs/recipes/traefik) — it
81
+ discovers replicas from Docker labels instead of a static `reverse_proxy` target.
82
+
83
+ Also set `allowedHosts` to your public hostname before exposing the edge — see
84
+ [Reverse proxy](/docs/deployment/reverse-proxy).
85
+
86
+ ## What the recipe configures
87
+
88
+ | Field | Value |
89
+ | -------------- | -------------------------------------------- |
90
+ | Ports | `80` + `443` published; `app` stays internal |
91
+ | Healthcheck | `caddy version`, every 10s, 5 retries |
92
+ | Connection URL | `https://<host>` |
93
+
94
+ ## Troubleshooting
95
+
96
+ <Accordions>
97
+ <Accordion title="ACME fails — connection refused / challenge timeout">
98
+
99
+ `OKE_PROXY_HOST` must be a DNS name that resolves to this host on ports 80/443. Localhost
100
+ never gets a public Let's Encrypt cert — that path uses Caddy's local CA. Check firewall
101
+ and that nothing else binds `:80`.
102
+
103
+ </Accordion>
104
+ <Accordion title="Browser trust errors on localhost">
105
+
106
+ Expected with the local CA. Install Caddy's local root for that machine, or set a real
107
+ `OKE_PROXY_HOST` with public DNS when you need a public cert.
108
+
109
+ </Accordion>
110
+ </Accordions>
111
+
112
+ ## Learn more
113
+
114
+ - [Reverse proxy](/docs/deployment/reverse-proxy) — Caddy vs Traefik rationale
115
+ - [Docker · Reverse proxy](/docs/deployment/docker#reverse-proxy) — compose layer order
116
+ - [Security](/docs/reference/security) — `allowedHosts`
117
+
118
+ ## Next
119
+
120
+ <Cards>
121
+ <Card title="Traefik" description="Multi-replica alternative." href="/docs/recipes/traefik" />
122
+ <Card
123
+ title="PgDog"
124
+ description="Pool Postgres behind the same stack."
125
+ href="/docs/recipes/pgdog"
126
+ />
127
+ <Card title="Redis" description="The default store.kv image." href="/docs/recipes/redis" />
128
+ </Cards>
@@ -0,0 +1,127 @@
1
+ ---
2
+ title: "CockroachDB"
3
+ description: "Self-hosted single-node Cockroach — COCKROACH_* env, port 26257, DB Console on :8080, driver stays postgres."
4
+ icon: "Database"
5
+ source: "docs/spec/unified-theory.md"
6
+ ---
7
+
8
+ CockroachDB speaks Postgres wire closely enough that `drivers.store.sql` stays
9
+ `postgres`. Pin `cockroachdb/cockroach` as `store.sql` and `oke docker` derives a
10
+ single-node compose service — credentials, healthcheck, and `DATABASE_URL`.
11
+
12
+ <Callout title="The one rule">
13
+ The driver id stays `postgres` — vendor choice lives in `images["store.sql"]`, not in
14
+ `drivers.store.sql`. Host maps `:5432` → container `:26257` so local apps keep the usual Postgres
15
+ port.
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": "cockroachdb/cockroach:v25.2.0", // pin a real tag
28
+ },
29
+ ```
30
+
31
+ </Step>
32
+
33
+ <Step>
34
+ ### Bring the stack up
35
+
36
+ ```bash
37
+ oke dev --docker
38
+ ```
39
+
40
+ `oke docker` injects `COCKROACH_USER` / `COCKROACH_PASSWORD` / `COCKROACH_DATABASE`
41
+ from `OKE_STORE_SQL_*`, starts `start-single-node --accept-sql-without-tls`, and
42
+ publishes SQL on host `:5432` plus the DB Console on `:8080`.
43
+
44
+ </Step>
45
+
46
+ <Step>
47
+ ### Connect
48
+
49
+ ```bash
50
+ echo "$DATABASE_URL"
51
+ # postgres://oke:…@127.0.0.1:5432/oke?sslmode=require
52
+ ```
53
+
54
+ </Step>
55
+
56
+ </Steps>
57
+
58
+ ## Required env
59
+
60
+ | Variable | Who sets it | Meaning |
61
+ | ------------------------ | ---------------------- | ------------------------------------ |
62
+ | `OKE_STORE_SQL_USER` | `oke docker` → compose | → `COCKROACH_USER` (first boot only) |
63
+ | `OKE_STORE_SQL_PASSWORD` | `oke docker` → compose | → `COCKROACH_PASSWORD` |
64
+ | `OKE_STORE_SQL_DB` | `oke docker` → compose | → `COCKROACH_DATABASE` |
65
+ | `DATABASE_URL` | stack env for the app | Includes `sslmode=require` |
66
+
67
+ ## Data and backup
68
+
69
+ | Path | What lives there |
70
+ | --------------------------- | --------------------------------------------- |
71
+ | `/cockroach/cockroach-data` | Named volume `store-sql-data` — cluster store |
72
+
73
+ **Backup means:** volume backup of `store-sql-data`, or Cockroach's backup tooling
74
+ against a running node. Losing that volume loses the cluster.
75
+
76
+ ## Production note
77
+
78
+ This recipe is a **single-node** cluster — fine for local and small self-hosted apps,
79
+ not multi-region HA. For managed multi-region, use the
80
+ [CockroachDB provider](/docs/providers/cockroachdb). Prefer a pinned tag, not `latest`.
81
+
82
+ ## What the recipe configures
83
+
84
+ | Field | Value |
85
+ | -------------- | -------------------------------------------- |
86
+ | Container port | `26257` (host publishes `5432`) |
87
+ | Extra port | `8080` — DB Console |
88
+ | Command | `start-single-node --accept-sql-without-tls` |
89
+ | Healthcheck | `GET /health?ready=1` on `:8080` |
90
+ | Connection URL | `postgres://…?sslmode=require` |
91
+
92
+ ## Troubleshooting
93
+
94
+ <Accordions>
95
+ <Accordion title="oke boot: postgres driver needs DATABASE_URL">
96
+
97
+ Re-run `oke dev --docker` so the stack writes `docker/.env.docker`, or export
98
+ `DATABASE_URL` yourself when pointing at a remote Cockroach host.
99
+
100
+ </Accordion>
101
+ <Accordion title="store-sql unhealthy / healthcheck never ready">
102
+
103
+ First boot can take longer than Postgres. Check
104
+ `docker compose … logs store-sql` for SQL ready. Empty `${OKE_STORE_SQL_PASSWORD}`
105
+ in `.env.docker` leaves the init user broken — regenerate the stack env.
106
+
107
+ </Accordion>
108
+ </Accordions>
109
+
110
+ ## Learn more
111
+
112
+ - [CockroachDB (provider)](/docs/providers/cockroachdb) — managed Cloud Connect flow
113
+ - [YugabyteDB](/docs/recipes/yugabytedb) — Apache-2.0 self-hosted alternative
114
+ - [Postgres](/docs/recipes/postgres) — default SQL recipe
115
+ - [Store · SQL](/docs/elements/store#sql) — schema push / generate / migrate
116
+
117
+ ## Next
118
+
119
+ <Cards>
120
+ <Card
121
+ title="CockroachDB Cloud"
122
+ description="Managed multi-region alternative."
123
+ href="/docs/providers/cockroachdb"
124
+ />
125
+ <Card title="YugabyteDB" description="Self-hosted YSQL peer." href="/docs/recipes/yugabytedb" />
126
+ <Card title="Postgres" description="The default store.sql image." href="/docs/recipes/postgres" />
127
+ </Cards>