okengine 0.10.3 → 0.11.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 (318) hide show
  1. package/package.json +76 -10
  2. package/site/content/docs/deployment/docker-swarm.mdx +48 -111
  3. package/site/content/docs/deployment/docker.mdx +43 -36
  4. package/site/content/docs/deployment/index.mdx +9 -9
  5. package/site/content/docs/deployment/kubernetes.mdx +4 -4
  6. package/site/content/docs/elements/ai.mdx +7 -7
  7. package/site/content/docs/elements/channel.mdx +9 -7
  8. package/site/content/docs/elements/clock.mdx +8 -8
  9. package/site/content/docs/elements/flow.mdx +46 -47
  10. package/site/content/docs/elements/gate.mdx +6 -5
  11. package/site/content/docs/elements/signal.mdx +2 -2
  12. package/site/content/docs/elements/store.mdx +71 -78
  13. package/site/content/docs/elements/vault.mdx +89 -70
  14. package/site/content/docs/get-started/basic-usage.mdx +8 -8
  15. package/site/content/docs/get-started/installation.mdx +36 -36
  16. package/site/content/docs/get-started/introduction.mdx +11 -0
  17. package/site/content/docs/get-started/why.mdx +2 -2
  18. package/site/content/docs/plugins/anonymous.mdx +1 -1
  19. package/site/content/docs/plugins/magic-link.mdx +11 -11
  20. package/site/content/docs/plugins/otp.mdx +2 -2
  21. package/site/content/docs/plugins/passkey.mdx +1 -1
  22. package/site/content/docs/plugins/two-factor.mdx +1 -1
  23. package/site/content/docs/plugins/username.mdx +1 -1
  24. package/site/content/docs/recipes/caddy.mdx +1 -1
  25. package/site/content/docs/recipes/cockroachdb.mdx +2 -2
  26. package/site/content/docs/recipes/dragonfly.mdx +1 -1
  27. package/site/content/docs/recipes/index.mdx +1 -2
  28. package/site/content/docs/recipes/llama-cpp.mdx +21 -23
  29. package/site/content/docs/recipes/mailpit.mdx +11 -11
  30. package/site/content/docs/recipes/meilisearch.mdx +10 -10
  31. package/site/content/docs/recipes/meta.json +0 -1
  32. package/site/content/docs/recipes/ollama.mdx +1 -1
  33. package/site/content/docs/recipes/pgdog.mdx +12 -9
  34. package/site/content/docs/recipes/postgres.mdx +3 -3
  35. package/site/content/docs/recipes/redis.mdx +2 -2
  36. package/site/content/docs/recipes/rustfs.mdx +10 -7
  37. package/site/content/docs/recipes/sglang.mdx +1 -1
  38. package/site/content/docs/recipes/supabase-docker.mdx +1 -1
  39. package/site/content/docs/recipes/timescale.mdx +2 -2
  40. package/site/content/docs/recipes/valkey.mdx +1 -1
  41. package/site/content/docs/recipes/vllm.mdx +1 -1
  42. package/site/content/docs/recipes/yugabytedb.mdx +2 -2
  43. package/site/content/docs/reference/cli.md +61 -38
  44. package/site/content/docs/reference/configuration.mdx +145 -70
  45. package/site/content/docs/reference/environment-variables.mdx +36 -28
  46. package/site/content/docs/reference/errors.mdx +28 -29
  47. package/site/content/docs/reference/fx.mdx +11 -4
  48. package/site/content/docs/reference/i18n.mdx +17 -6
  49. package/site/content/docs/reference/index.mdx +5 -0
  50. package/site/content/docs/reference/meta.json +1 -0
  51. package/site/content/docs/reference/migrating-environments.mdx +158 -0
  52. package/site/content/docs/reference/plugins.mdx +2 -2
  53. package/src/auth/gate-auth.test.ts +12 -10
  54. package/src/cli/ai-setup/ai-setup.test.ts +27 -15
  55. package/src/cli/ai-setup/apply.ts +111 -15
  56. package/src/cli/ai-setup/catalog.ts +3 -3
  57. package/src/cli/ai-setup/index.ts +1 -1
  58. package/src/cli/ai-setup/prompts.ts +1 -1
  59. package/src/cli/ai-setup/recommend.test.ts +1 -1
  60. package/src/cli/ask-seed.test.ts +3 -3
  61. package/src/cli/build.ts +1 -1
  62. package/src/cli/db-auto-push.test.ts +6 -3
  63. package/src/cli/db-auto-push.ts +7 -5
  64. package/src/cli/db-seed.ts +7 -8
  65. package/src/cli/db.test.ts +70 -71
  66. package/src/cli/db.ts +86 -12
  67. package/src/cli/dev-controller.test.ts +35 -0
  68. package/src/cli/dev-controller.ts +298 -0
  69. package/src/cli/dev-controls.ts +11 -65
  70. package/src/cli/dev-db-push.test.ts +47 -15
  71. package/src/cli/dev-schema-sync.test.ts +11 -11
  72. package/src/cli/dev-schema-sync.ts +10 -10
  73. package/src/cli/dev-session-lock.test.ts +106 -0
  74. package/src/cli/dev-session-lock.ts +209 -0
  75. package/src/cli/dev.test.ts +166 -121
  76. package/src/cli/dev.ts +138 -192
  77. package/src/cli/doc-staleness.test.ts +3 -6
  78. package/src/cli/docker-clean.test.ts +33 -1
  79. package/src/cli/docker-clean.ts +28 -33
  80. package/src/cli/docker-cli.test.ts +12 -11
  81. package/src/cli/docker.ts +95 -20
  82. package/src/cli/doctor.test.ts +40 -0
  83. package/src/cli/doctor.ts +55 -15
  84. package/src/cli/drizzle-env.test.ts +11 -13
  85. package/src/cli/drizzle-env.ts +18 -11
  86. package/src/cli/ensure-drizzle-config.ts +11 -14
  87. package/src/cli/hero-meta.test.ts +15 -15
  88. package/src/cli/hero-meta.ts +10 -9
  89. package/src/cli/index.ts +36 -6
  90. package/src/cli/load-config.images.test.ts +16 -12
  91. package/src/cli/load-config.source.test.ts +50 -0
  92. package/src/cli/load-config.ts +34 -28
  93. package/src/cli/meilisearch-local.ts +1 -2
  94. package/src/cli/mode.ts +7 -58
  95. package/src/cli/registry.ts +175 -19
  96. package/src/cli/resolve-dev-sql-env.test.ts +8 -16
  97. package/src/cli/resolve-dev-sql-env.ts +13 -15
  98. package/src/cli/safe-defaults.test.ts +28 -10
  99. package/src/cli/schema.ts +65 -16
  100. package/src/cli/test.ts +58 -0
  101. package/src/cli/tui/App.tsx +252 -0
  102. package/src/cli/tui/DevLive.tsx +116 -0
  103. package/src/cli/tui/components/ConfirmDialog.tsx +48 -0
  104. package/src/cli/tui/components/HeaderBar.tsx +67 -0
  105. package/src/cli/tui/components/LogStream.tsx +47 -0
  106. package/src/cli/tui/components/PanelCard.tsx +39 -0
  107. package/src/cli/tui/components/SelectRow.tsx +37 -0
  108. package/src/cli/tui/components/SlashPalette.tsx +172 -0
  109. package/src/cli/tui/components/Spinner.tsx +32 -0
  110. package/src/cli/tui/components/StatusBar.tsx +51 -0
  111. package/src/cli/tui/components/StatusDot.tsx +37 -0
  112. package/src/cli/tui/components/TabBar.tsx +49 -0
  113. package/src/cli/tui/components/Wordmark.tsx +43 -0
  114. package/src/cli/tui/format.ts +38 -0
  115. package/src/cli/tui/keys.test.ts +18 -0
  116. package/src/cli/tui/keys.ts +26 -0
  117. package/src/cli/tui/launch.test.ts +18 -0
  118. package/src/cli/tui/launch.ts +57 -0
  119. package/src/cli/tui/panels/Dashboard.tsx +201 -0
  120. package/src/cli/tui/panels/Database.tsx +198 -0
  121. package/src/cli/tui/panels/Dev.tsx +257 -0
  122. package/src/cli/tui/panels/Docker.tsx +357 -0
  123. package/src/cli/tui/panels/Navigator.test.ts +22 -0
  124. package/src/cli/tui/panels/Navigator.tsx +213 -0
  125. package/src/cli/tui/slash-catalog.test.ts +31 -0
  126. package/src/cli/tui/slash-catalog.ts +184 -0
  127. package/src/cli/tui/slash-run.ts +54 -0
  128. package/src/cli/tui/state/ports.ts +95 -0
  129. package/src/cli/tui/theme.ts +24 -0
  130. package/src/cli/vault-cmd.test.ts +402 -0
  131. package/src/cli/vault-cmd.ts +727 -69
  132. package/src/cli/vault-secure-input.test.ts +56 -0
  133. package/src/cli/vault-secure-input.ts +124 -0
  134. package/src/compiler/effects-infer.ts +7 -0
  135. package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
  136. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
  137. package/src/compiler/fixtures/skyport.expected.json +1 -1
  138. package/src/compiler-entry.ts +7 -0
  139. package/src/config/define-config.test.ts +111 -47
  140. package/src/config/driver-defaults.test.ts +16 -23
  141. package/src/config/driver-defaults.ts +33 -63
  142. package/src/config/index.ts +169 -144
  143. package/src/config/resolve-driver.test.ts +14 -19
  144. package/src/console/server/app.ts +4 -2
  145. package/src/console/server/console.test.ts +58 -1
  146. package/src/console/server/flows.ts +22 -2
  147. package/src/console/server/index.ts +3 -0
  148. package/src/console/server/operator-db.test.ts +55 -13
  149. package/src/console/server/operator-db.ts +305 -263
  150. package/src/console/server/serve.ts +16 -7
  151. package/src/console/server/state.ts +31 -9
  152. package/src/console/server/vault.test.ts +120 -5
  153. package/src/console/server/vault.ts +208 -12
  154. package/src/console/ui/dist/assets/{index-D-9KFce5.js → index--Y0Uaz-m.js} +2 -2
  155. package/src/console/ui/dist/assets/panel-vault-BkZdJPX8.js +1 -0
  156. package/src/console/ui/dist/assets/style-C3L349iZ.css +3 -0
  157. package/src/console/ui/dist/index.html +2 -2
  158. package/src/console/ui/shell/client.ts +16 -0
  159. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +54 -1
  160. package/src/console/ui/vault/VaultA11yView.tsx +33 -1
  161. package/src/console/ui/vault/backend.test.ts +75 -0
  162. package/src/console/ui/vault/backend.ts +117 -0
  163. package/src/console/ui/vault/fixture.ts +21 -2
  164. package/src/console/ui/vault/index.ts +11 -1
  165. package/src/console/ui/vault/types.ts +26 -0
  166. package/src/docker/compose.ts +164 -61
  167. package/src/docker/derive.ts +106 -12
  168. package/src/docker/docker.test.ts +156 -110
  169. package/src/docker/helpers.ts +98 -0
  170. package/src/docker/images-config.test.ts +3 -8
  171. package/src/docker/index.ts +30 -5
  172. package/src/docker/recipes/index.ts +0 -3
  173. package/src/docker/recipes/llama-cpp.ts +4 -4
  174. package/src/docker/recipes/pgdog.ts +9 -2
  175. package/src/docker/resources.test.ts +71 -0
  176. package/src/docker/resources.ts +176 -0
  177. package/src/docker/stack-id.test.ts +11 -4
  178. package/src/docker/stack-id.ts +42 -32
  179. package/src/docker/stack.integration.test.ts +4 -15
  180. package/src/docker/types.ts +35 -3
  181. package/src/drivers/ai-ollama.integration.test.ts +2 -2
  182. package/src/drivers/conformance.test.ts +11 -12
  183. package/src/drivers/drizzle-dialect.test.ts +0 -4
  184. package/src/drivers/drizzle-dialect.ts +7 -13
  185. package/src/drivers/index.ts +24 -7
  186. package/src/drivers/journal-postgres.test.ts +3 -1
  187. package/src/drivers/journal-postgres.ts +4 -2
  188. package/src/drivers/meilisearch.ts +1 -1
  189. package/src/drivers/pglite.ts +28 -5
  190. package/src/drivers/types.ts +9 -11
  191. package/src/drivers/vault-aws-secrets-manager.test.ts +159 -0
  192. package/src/drivers/vault-aws-secrets-manager.ts +333 -0
  193. package/src/drivers/vault-builtin.test.ts +110 -0
  194. package/src/drivers/vault-builtin.ts +184 -0
  195. package/src/drivers/vault-driver-removal.test.ts +13 -0
  196. package/src/drivers/vault-managed.test.ts +95 -0
  197. package/src/drivers/vault-managed.ts +101 -25
  198. package/src/drivers/vault-types.ts +25 -5
  199. package/src/elements/ai/runtime.ts +1 -1
  200. package/src/elements/clock/chaos.test.ts +4 -1
  201. package/src/elements/clock/durable.ts +57 -4
  202. package/src/elements/clock.test.ts +13 -14
  203. package/src/elements/gate/constants.ts +18 -0
  204. package/src/elements/gate.test.ts +1 -1
  205. package/src/elements/gate.ts +2 -2
  206. package/src/elements/store/domain-ddl.test.ts +5 -12
  207. package/src/elements/store/emit-drizzle.ts +44 -19
  208. package/src/elements/store/index-boot.test.ts +15 -116
  209. package/src/elements/store/load-plugin-tables.ts +1 -1
  210. package/src/elements/store/resource-list-docs.fixture.ts +12 -6
  211. package/src/elements/store/resource-list-docs.test.ts +64 -44
  212. package/src/elements/store/resource.test.ts +17 -10
  213. package/src/elements/store/runtime.ts +9 -12
  214. package/src/elements/store/schema-decl.test.ts +16 -32
  215. package/src/elements/store/seed.test.ts +1 -2
  216. package/src/elements/store/seed.ts +7 -8
  217. package/src/elements/store/sql-condition.test.ts +2 -2
  218. package/src/elements/store/sql-session.test.ts +8 -10
  219. package/src/elements/store/sql-session.ts +10 -2
  220. package/src/elements/store.test.ts +13 -13
  221. package/src/elements/vault/audit.ts +233 -0
  222. package/src/elements/vault/boot-chain.test.ts +78 -0
  223. package/src/elements/vault/boot-chain.ts +43 -39
  224. package/src/elements/vault/builtin-adapter.test.ts +479 -0
  225. package/src/elements/vault/builtin-adapter.ts +1184 -0
  226. package/src/elements/vault/crypto.test.ts +237 -0
  227. package/src/elements/vault/crypto.ts +431 -0
  228. package/src/elements/vault/declare.ts +164 -3
  229. package/src/elements/vault/errors.ts +56 -0
  230. package/src/elements/vault/kms-unseal.test.ts +76 -0
  231. package/src/elements/vault/kms-unseal.ts +181 -0
  232. package/src/elements/vault/path.ts +90 -0
  233. package/src/elements/vault/resilience.test.ts +102 -0
  234. package/src/elements/vault/resilience.ts +107 -0
  235. package/src/elements/vault/runtime.ts +36 -4
  236. package/src/elements/vault/security-checklist.test.ts +130 -0
  237. package/src/elements/vault/storage.ts +448 -0
  238. package/src/elements/vault/types.ts +288 -0
  239. package/src/elements/vault/unseal.ts +150 -0
  240. package/src/elements/vault.test.ts +72 -4
  241. package/src/elements/vault.ts +91 -2
  242. package/src/full.ts +248 -0
  243. package/src/http.ts +41 -0
  244. package/src/i18n/interpolate-simple.ts +37 -0
  245. package/src/i18n/messages.ts +51 -4
  246. package/src/i18n-entry.ts +7 -0
  247. package/src/index.ts +35 -145
  248. package/src/journal-entry.ts +20 -0
  249. package/src/kernel/adopt-barrel-fresh.test.ts +25 -10
  250. package/src/kernel/app.ts +40 -42
  251. package/src/kernel/auto-registry.test.ts +2 -2
  252. package/src/kernel/boot-bind/ai.test.ts +5 -5
  253. package/src/kernel/boot-bind/ai.ts +2 -1
  254. package/src/kernel/boot-bind/channel.test.ts +6 -6
  255. package/src/kernel/boot-bind/channel.ts +3 -10
  256. package/src/kernel/boot-bind/clock.ts +2 -2
  257. package/src/kernel/boot-bind/gate.ts +5 -9
  258. package/src/kernel/boot-bind/honor-config.test.ts +42 -42
  259. package/src/kernel/boot-bind/journal.ts +2 -2
  260. package/src/kernel/boot-bind/store.test.ts +43 -44
  261. package/src/kernel/boot-bind/store.ts +16 -41
  262. package/src/kernel/boot-bind/vault.ts +16 -1
  263. package/src/kernel/boot.test.ts +12 -4
  264. package/src/kernel/boot.ts +31 -19
  265. package/src/kernel/budget-entry.ts +1 -1
  266. package/src/kernel/compensate.test.ts +288 -1
  267. package/src/kernel/compensate.ts +126 -0
  268. package/src/kernel/concurrency.test.ts +10 -9
  269. package/src/kernel/effects-stamping.test.ts +27 -2
  270. package/src/kernel/element-registries.ts +5 -3
  271. package/src/kernel/flow.ts +4 -2
  272. package/src/kernel/fx.test.ts +119 -3
  273. package/src/kernel/fx.ts +215 -40
  274. package/src/kernel/index.ts +14 -0
  275. package/src/kernel/journal.ts +130 -7
  276. package/src/kernel/pipeline.test.ts +20 -6
  277. package/src/kernel/redacted.test.ts +35 -0
  278. package/src/kernel/redacted.ts +24 -2
  279. package/src/kernel/router/create-default.ts +16 -0
  280. package/src/kernel/router/create-edge.ts +18 -0
  281. package/src/kernel/router/create.ts +23 -0
  282. package/src/kernel/router/index.ts +23 -0
  283. package/src/kernel/router/linear.ts +88 -0
  284. package/src/kernel/router/regexp.ts +188 -0
  285. package/src/kernel/router/smart.ts +120 -0
  286. package/src/kernel/router/trie.ts +108 -0
  287. package/src/kernel/router/types.ts +56 -0
  288. package/src/kernel/router.ts +18 -532
  289. package/src/kernel-entry.ts +43 -0
  290. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  291. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  292. package/src/plugins/config-source.test.ts +7 -7
  293. package/src/release/build-lib.ts +58 -0
  294. package/src/release/exports.test.ts +4 -2
  295. package/src/release/exports.ts +30 -4
  296. package/src/release/measure.ts +101 -22
  297. package/src/runs/duckdb.ts +7 -2
  298. package/src/shared/optional-peer.ts +41 -0
  299. package/src/term.test.ts +3 -44
  300. package/src/test/create-test-app.ts +12 -0
  301. package/src/test/provisions.integration.test.ts +1 -1
  302. package/src/test/reset-element-registries.ts +2 -0
  303. package/src/upgrade/codemods.test.ts +7 -20
  304. package/src/upgrade/codemods.ts +93 -60
  305. package/site/content/docs/recipes/openbao.mdx +0 -141
  306. package/src/cli/ask-dev-mode.ts +0 -40
  307. package/src/cli/dev-mode.test.ts +0 -45
  308. package/src/cli/dev-mode.ts +0 -78
  309. package/src/cli/openbao-bootstrap.test.ts +0 -150
  310. package/src/cli/openbao-bootstrap.ts +0 -321
  311. package/src/cli/openbao-restart.integration.test.ts +0 -145
  312. package/src/console/ui/dist/assets/panel-vault-Za1GyJfM.js +0 -1
  313. package/src/console/ui/dist/assets/style-C8MxEWPd.css +0 -3
  314. package/src/docker/recipes/openbao.ts +0 -47
  315. package/src/drivers/libsql.ts +0 -179
  316. package/src/drivers/sqlite.ts +0 -44
  317. package/src/drivers/vault-openbao.test.ts +0 -97
  318. package/src/drivers/vault-openbao.ts +0 -143
@@ -84,6 +84,27 @@ const HELP: CliFlag = {
84
84
  summary: "Show help",
85
85
  };
86
86
 
87
+ const VAULT_KEY: CliFlag = {
88
+ long: "--key",
89
+ takesValue: true,
90
+ valueName: "base64|-",
91
+ summary: "Master key (`-` = stdin; else env / interactive prompt)",
92
+ };
93
+
94
+ const VAULT_NEW_KEY: CliFlag = {
95
+ long: "--new-key",
96
+ takesValue: true,
97
+ valueName: "base64|-",
98
+ summary: "New master key for resume (`-` = stdin)",
99
+ };
100
+
101
+ const VAULT_URL: CliFlag = {
102
+ long: "--url",
103
+ takesValue: true,
104
+ valueName: "url",
105
+ summary: "SQL URL (else DATABASE_URL)",
106
+ };
107
+
87
108
  /**
88
109
  * Canonical `oke` command catalogue.
89
110
  *
@@ -93,24 +114,19 @@ const HELP: CliFlag = {
93
114
  export const OKE_COMMANDS: readonly CliCommand[] = [
94
115
  {
95
116
  name: "dev",
96
- summary: "watch · hot reload · Console · client types",
117
+ summary: "watch · hot reload · Console · client types (Docker Compose)",
97
118
  leaf: true,
98
119
  flags: [
99
- {
100
- long: "--local",
101
- short: "-l",
102
- summary: "Session-only local mode (in-memory; no compose)",
103
- },
104
120
  {
105
121
  long: "--docker",
106
122
  short: "-d",
107
123
  takesValue: true,
108
124
  valueName: "roles",
109
- summary: "Session-only docker compose (optional role list)",
125
+ summary: "Optional compose role filter (default: all roles)",
110
126
  },
111
127
  {
112
128
  long: "--no-db-push",
113
- summary: "Disable auto `oke db push` on schema change (local)",
129
+ summary: "Disable auto `oke db push` on schema change",
114
130
  },
115
131
  ENTRY,
116
132
  HELP,
@@ -118,7 +134,13 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
118
134
  },
119
135
  {
120
136
  name: "mode",
121
- summary: "get/set default oke dev mode (local|docker)",
137
+ summary: "deprecated oke dev always uses Docker Compose",
138
+ leaf: true,
139
+ flags: [HELP],
140
+ },
141
+ {
142
+ name: "test",
143
+ summary: "run bun test with PGLite test posture",
122
144
  leaf: true,
123
145
  flags: [HELP],
124
146
  },
@@ -182,11 +204,11 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
182
204
  },
183
205
  {
184
206
  name: "schema",
185
- summary: "core + plugin tables → schema/oke.ts",
207
+ summary: "core + plugin tables → .oke/schema/oke.ts",
186
208
  subcommands: [
187
209
  {
188
210
  name: "generate",
189
- summary: "Emit schema/oke.ts",
211
+ summary: "Emit .oke/schema/oke.ts",
190
212
  flags: [
191
213
  {
192
214
  long: "--check",
@@ -202,7 +224,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
202
224
  },
203
225
  {
204
226
  name: "db",
205
- summary: "domain schema — push · generate · migrate · seed",
227
+ summary: "domain schema — push · generate · migrate · seed · studio",
206
228
  subcommands: [
207
229
  {
208
230
  name: "push",
@@ -219,7 +241,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
219
241
  long: "--env",
220
242
  takesValue: true,
221
243
  valueName: "name",
222
- summary: "Config env (local|docker|test|prod)",
244
+ summary: "Config env (dev|test|prod)",
223
245
  },
224
246
  HELP,
225
247
  ],
@@ -239,7 +261,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
239
261
  long: "--env",
240
262
  takesValue: true,
241
263
  valueName: "name",
242
- summary: "Config env (local|docker|test|prod)",
264
+ summary: "Config env (dev|test|prod)",
243
265
  },
244
266
  HELP,
245
267
  ],
@@ -259,7 +281,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
259
281
  long: "--env",
260
282
  takesValue: true,
261
283
  valueName: "name",
262
- summary: "Config env (local|docker|test|prod)",
284
+ summary: "Config env (dev|test|prod)",
263
285
  },
264
286
  HELP,
265
287
  ],
@@ -272,7 +294,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
272
294
  long: "--env",
273
295
  takesValue: true,
274
296
  valueName: "name",
275
- summary: "Config env (local|docker|test|prod)",
297
+ summary: "Config env (dev|test|prod)",
276
298
  },
277
299
  {
278
300
  long: "--force",
@@ -282,6 +304,26 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
282
304
  HELP,
283
305
  ],
284
306
  },
307
+ {
308
+ name: "studio",
309
+ summary: "Open drizzle-kit Studio (long-running)",
310
+ flags: [
311
+ {
312
+ long: "--config",
313
+ short: "-c",
314
+ takesValue: true,
315
+ valueName: "path",
316
+ summary: "drizzle.config.ts path",
317
+ },
318
+ {
319
+ long: "--env",
320
+ takesValue: true,
321
+ valueName: "name",
322
+ summary: "Config env (dev|test|prod)",
323
+ },
324
+ HELP,
325
+ ],
326
+ },
285
327
  ],
286
328
  },
287
329
  {
@@ -298,7 +340,7 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
298
340
  },
299
341
  {
300
342
  name: "vault",
301
- summary: "set · list · import · key rotate",
343
+ summary: "secrets — set · list · seal/unseal · rotate · audit · backup",
302
344
  subcommands: [
303
345
  {
304
346
  name: "set",
@@ -319,6 +361,96 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
319
361
  positionals: "rotate",
320
362
  flags: [HELP],
321
363
  },
364
+ {
365
+ name: "init",
366
+ summary: "Create the builtin vault; print the master key once",
367
+ flags: [VAULT_URL, HELP],
368
+ },
369
+ {
370
+ name: "status",
371
+ summary: "Seal state · KEK generation · secret count",
372
+ flags: [VAULT_KEY, VAULT_URL, JSON_FLAG, HELP],
373
+ },
374
+ {
375
+ name: "seal",
376
+ summary: "Drop the master key; reads fail until unsealed",
377
+ flags: [VAULT_URL, HELP],
378
+ },
379
+ {
380
+ name: "unseal",
381
+ summary: "Verify the master key and clear the sealed flag",
382
+ flags: [VAULT_KEY, VAULT_URL, HELP],
383
+ },
384
+ {
385
+ name: "rotate",
386
+ summary: "New version of a secret under a fresh data key",
387
+ positionals: "<path> [value]",
388
+ flags: [VAULT_KEY, VAULT_URL, HELP],
389
+ },
390
+ {
391
+ name: "rotate-master",
392
+ summary: "New master key; re-wrap every data key",
393
+ flags: [VAULT_KEY, VAULT_NEW_KEY, VAULT_URL, HELP],
394
+ },
395
+ {
396
+ name: "audit",
397
+ summary: "Read · verify · purge the tamper-evident chain",
398
+ positionals: "[verify|purge]",
399
+ flags: [
400
+ {
401
+ long: "--limit",
402
+ takesValue: true,
403
+ valueName: "n",
404
+ summary: "Rows to show (default 50)",
405
+ },
406
+ {
407
+ long: "--path",
408
+ takesValue: true,
409
+ valueName: "path",
410
+ summary: "Restrict to one secret path",
411
+ },
412
+ {
413
+ long: "--before",
414
+ takesValue: true,
415
+ valueName: "iso",
416
+ summary: "Purge rows older than this instant",
417
+ },
418
+ VAULT_URL,
419
+ JSON_FLAG,
420
+ HELP,
421
+ ],
422
+ },
423
+ {
424
+ name: "purge-expired",
425
+ summary: "Hard-delete secret rows past expires_at",
426
+ flags: [
427
+ VAULT_KEY,
428
+ VAULT_URL,
429
+ {
430
+ long: "--dry-run",
431
+ summary: "Count expired rows without deleting",
432
+ },
433
+ {
434
+ long: "--before",
435
+ takesValue: true,
436
+ valueName: "iso",
437
+ summary: "Exclusive upper bound (default: now)",
438
+ },
439
+ HELP,
440
+ ],
441
+ },
442
+ {
443
+ name: "backup",
444
+ summary: "Write every live secret as one encrypted bundle",
445
+ positionals: "<file>",
446
+ flags: [VAULT_KEY, VAULT_URL, HELP],
447
+ },
448
+ {
449
+ name: "restore",
450
+ summary: "Replay a bundle as new versions",
451
+ positionals: "<file>",
452
+ flags: [VAULT_KEY, VAULT_URL, HELP],
453
+ },
322
454
  ],
323
455
  },
324
456
  {
@@ -549,7 +681,15 @@ export const OKE_COMMANDS: readonly CliCommand[] = [
549
681
  * @returns Help text (no trailing exit-code block)
550
682
  */
551
683
  export function formatOkeHelp(): string {
552
- const lines = ["oke — okengine CLI", "", "Commands:"];
684
+ const lines = [
685
+ "oke — okengine CLI",
686
+ "",
687
+ " oke Interactive TUI (TTY). Non-TTY prints this help.",
688
+ " oke --tui Force the interactive TUI",
689
+ " oke --help This command list",
690
+ "",
691
+ "Commands:",
692
+ ];
553
693
  for (const cmd of OKE_COMMANDS) {
554
694
  const usage = formatCommandUsage(cmd);
555
695
  lines.push(` ${pad(usage, 34)} ${cmd.summary}`);
@@ -608,7 +748,7 @@ function formatCommandUsage(cmd: CliCommand): string {
608
748
  return `oke ${cmd.name} ${sub.name}${pos}${flagHint ? ` ${flagHint}` : ""}`;
609
749
  }
610
750
  if (cmd.subcommands && cmd.subcommands.length > 1) {
611
- const subs = cmd.subcommands.map((s) => s.name).join("|");
751
+ const subs = summarizeSubcommands(cmd.subcommands);
612
752
  // Prefer shared JSON flag hint when every list-like sub supports it.
613
753
  const jsonHint = cmd.subcommands.some((s) => s.flags?.some((f) => f.long === "--json"))
614
754
  ? " [--json|-j]"
@@ -624,6 +764,22 @@ function formatCommandUsage(cmd: CliCommand): string {
624
764
  return `oke ${cmd.name}${pos}${flagHint ? ` ${flagHint}` : ""}`;
625
765
  }
626
766
 
767
+ /** Longest `a|b|c` sub list the one-line help layout can carry. */
768
+ const MAX_SUBCOMMAND_HINTS = 4;
769
+
770
+ /**
771
+ * Join subcommand names for the one-line usage, eliding a long tail.
772
+ *
773
+ * Commands with a large surface (`vault`) would otherwise push the summary
774
+ * column off screen; the full list still reaches completion and `--help`.
775
+ *
776
+ * @param subs - Subcommands in registry order
777
+ */
778
+ function summarizeSubcommands(subs: readonly CliSubcommand[]): string {
779
+ const shown = subs.slice(0, MAX_SUBCOMMAND_HINTS).map((s) => s.name);
780
+ return subs.length > MAX_SUBCOMMAND_HINTS ? `${shown.join("|")}|…` : shown.join("|");
781
+ }
782
+
627
783
  function formatFlagHint(f: CliFlag): string {
628
784
  const name = f.short ? `${f.long}|${f.short}` : f.long;
629
785
  if (f.takesValue) {
@@ -1,12 +1,11 @@
1
1
  /**
2
- * Active SQL env resolution from `.oke/mode` / session overrides.
2
+ * Active SQL env resolution Docker-first (`dev` default).
3
3
  */
4
4
 
5
5
  import { afterEach, describe, expect, test } from "bun:test";
6
6
  import { mkdtemp, rm } from "node:fs/promises";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
- import { writeDevMode } from "./dev-mode.ts";
10
9
  import { resolveDevSqlEnv } from "./resolve-dev-sql-env.ts";
11
10
 
12
11
  const dirs: string[] = [];
@@ -22,27 +21,20 @@ async function tempDir(): Promise<string> {
22
21
  }
23
22
 
24
23
  describe("resolveDevSqlEnv", () => {
25
- test("defaults to local when nothing set", async () => {
24
+ test("defaults to dev (Docker-first)", async () => {
26
25
  const dir = await tempDir();
27
- expect(await resolveDevSqlEnv(dir)).toBe("local");
26
+ expect(await resolveDevSqlEnv(dir)).toBe("dev");
28
27
  });
29
28
 
30
29
  test("explicit env override wins", async () => {
31
30
  const dir = await tempDir();
32
- await writeDevMode(dir, "local");
33
- expect(await resolveDevSqlEnv(dir, { env: "docker" })).toBe("docker");
31
+ expect(await resolveDevSqlEnv(dir, { env: "test" })).toBe("test");
32
+ expect(await resolveDevSqlEnv(dir, { env: "dev" })).toBe("dev");
34
33
  });
35
34
 
36
- test("session docker flag wins over saved mode", async () => {
35
+ test("docker flag is ignored (always dev unless env set)", async () => {
37
36
  const dir = await tempDir();
38
- await writeDevMode(dir, "local");
39
- expect(await resolveDevSqlEnv(dir, { docker: true })).toBe("docker");
40
- expect(await resolveDevSqlEnv(dir, { docker: false })).toBe("local");
41
- });
42
-
43
- test("reads saved .oke/mode", async () => {
44
- const dir = await tempDir();
45
- await writeDevMode(dir, "docker");
46
- expect(await resolveDevSqlEnv(dir)).toBe("docker");
37
+ expect(await resolveDevSqlEnv(dir, { docker: true })).toBe("dev");
38
+ expect(await resolveDevSqlEnv(dir, { docker: false })).toBe("dev");
47
39
  });
48
40
  });
@@ -1,42 +1,40 @@
1
1
  /**
2
- * Resolve the active SQL env for schema tooling (`oke db`, `oke mode`,
3
- * `oke dev` one-shot sync) from session overrides and the saved dev mode.
2
+ * Resolve the active SQL env for schema tooling (`oke db`, `oke dev`
3
+ * one-shot sync). Docker-first: `oke dev` always uses `dev`.
4
4
  */
5
5
 
6
6
  import type { ConfigEnv } from "../config/index.ts";
7
- import { readDevMode } from "./dev-mode.ts";
8
7
 
9
8
  /** Options for {@link resolveDevSqlEnv}. */
10
9
  export interface ResolveDevSqlEnvOptions {
11
10
  /**
12
- * Session override — `true` means docker (e.g. `OKE_DOCKER=1` or
13
- * `oke dev --docker`). `false` means local. `undefined` auto-resolve.
11
+ * Session override — `true` means compose infra is up. Ignored for env
12
+ * selection (always `dev` unless `options.env` is set); kept for call-site
13
+ * compatibility.
14
14
  */
15
15
  readonly docker?: boolean;
16
16
  /**
17
- * Explicit env override (e.g. `oke db --env docker`). Wins over `.oke/mode`.
17
+ * Explicit env override (e.g. `oke db --env test`). Wins over the default.
18
18
  */
19
19
  readonly env?: ConfigEnv;
20
20
  }
21
21
 
22
22
  /**
23
- * Resolve the SQL env (`local` | `docker` for dev tooling) without prompting.
23
+ * Resolve the SQL {@link ConfigEnv} for tooling without prompting.
24
24
  *
25
25
  * Order:
26
26
  * 1. Explicit `options.env` (CLI flag)
27
- * 2. Session docker flag (`options.docker`)
28
- * 3. `.oke/mode` persisted preference
29
- * 4. Default `local`
27
+ * 2. Default `dev` (Docker-first local development)
30
28
  *
31
- * @param cwd - Project root
29
+ * @param _cwd - Project root (unused; kept for call-site compatibility)
32
30
  * @param options - Session / CLI overrides
33
31
  */
34
32
  export async function resolveDevSqlEnv(
35
- cwd: string,
33
+ _cwd: string,
36
34
  options: ResolveDevSqlEnvOptions = {},
37
35
  ): Promise<ConfigEnv> {
36
+ void _cwd;
37
+ void options.docker;
38
38
  if (options.env !== undefined) return options.env;
39
- if (options.docker !== undefined) return options.docker ? "docker" : "local";
40
- const saved = await readDevMode(cwd);
41
- return saved ?? "local";
39
+ return "dev";
42
40
  }
@@ -12,36 +12,54 @@ import { runImagesPin } from "./images.ts";
12
12
  import { upgradeCli } from "./upgrade.ts";
13
13
 
14
14
  describe("oke safe-default overrides", () => {
15
- test("docker --prod is off unless --prod|-p is passed", async () => {
15
+ test("docker prod overlays are on by default; --no-prod opts out", async () => {
16
16
  const dir = await mkdtemp(join(tmpdir(), "oke-safe-docker-"));
17
17
  await Bun.write(
18
18
  join(dir, "oke.config.ts"),
19
19
  `export default { images: { store: { sql: "postgres:18-alpine" } } }\n`,
20
20
  );
21
- // Without --prod, derive still runs but prod overlays are not requested.
22
- // We assert the parser default by calling runDockerDerive via dockerCli
23
- // with a dry path: inspect that -p flips prod on.
24
21
  const { runDockerDerive } = await import("./docker.ts");
25
- const off = await runDockerDerive({
22
+
23
+ // Default layout is single: prod readiness/deploy folds into docker-compose.yml
24
+ // (no separate compose.prod.yml). Assert production-grade content is present.
25
+ const defaults = await runDockerDerive({
26
+ cwd: dir,
27
+ outDir: dir,
28
+ images: { "store.sql": "postgres:18-alpine" },
29
+ dryRun: true,
30
+ write: () => {},
31
+ });
32
+ expect(defaults.code).toBe(0);
33
+ const defaultCompose = defaults.result?.files.find((f) => f.path === "docker-compose.yml");
34
+ expect(defaultCompose).toBeDefined();
35
+ expect(defaultCompose!.content).toContain("/_/ready");
36
+ expect(defaults.result?.files.some((f) => f.path.includes("prod"))).toBe(false);
37
+
38
+ const noProd = await runDockerDerive({
26
39
  cwd: dir,
27
40
  outDir: dir,
28
41
  images: { "store.sql": "postgres:18-alpine" },
42
+ prod: false,
29
43
  dryRun: true,
30
44
  write: () => {},
31
45
  });
32
- expect(off.code).toBe(0);
33
- expect(off.result?.files.some((f) => f.path.includes("prod"))).toBe(false);
46
+ expect(noProd.code).toBe(0);
47
+ const noProdCompose = noProd.result?.files.find((f) => f.path === "docker-compose.yml");
48
+ expect(noProdCompose).toBeDefined();
49
+ expect(noProdCompose!.content).not.toContain("/_/ready");
34
50
 
35
- const on = await runDockerDerive({
51
+ // Split layout still emits a separate compose.prod.yml when prod is on.
52
+ const splitProd = await runDockerDerive({
36
53
  cwd: dir,
37
54
  outDir: dir,
38
55
  images: { "store.sql": "postgres:18-alpine" },
39
56
  prod: true,
57
+ layout: "split",
40
58
  dryRun: true,
41
59
  write: () => {},
42
60
  });
43
- expect(on.code).toBe(0);
44
- expect(on.result?.files.some((f) => f.path.includes("prod"))).toBe(true);
61
+ expect(splitProd.code).toBe(0);
62
+ expect(splitProd.result?.files.some((f) => f.path === "compose.prod.yml")).toBe(true);
45
63
 
46
64
  expect(await dockerCli(["--help"])).toBe(0);
47
65
  });
package/src/cli/schema.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  /**
2
- * `oke schema generate` — core + auth + plugin tables → `schema/oke.ts`.
2
+ * `oke schema generate` — core + auth + plugin tables → `.oke/schema/oke.ts`.
3
+ *
4
+ * Domain Drizzle lives under `src/db/` (`oke db …`). This file is the
5
+ * generated system/stub catalogue — kept under `.oke/` so it never lands
6
+ * at the project root next to app source.
3
7
  */
4
8
 
5
9
  import { createHash } from "node:crypto";
@@ -15,10 +19,16 @@ import type { Manifest } from "../manifest/types.ts";
15
19
  import { loadManifest } from "./load-config.ts";
16
20
 
17
21
  /** Fingerprint file written beside generated schema. */
18
- export const SCHEMA_FINGERPRINT_FILE = "schema/.oke-schema.sha256";
22
+ export const SCHEMA_FINGERPRINT_FILE = ".oke/schema/.oke-schema.sha256";
23
+
24
+ /** Default generated system schema path (under `.oke/`, not project root). */
25
+ export const SCHEMA_OUT = ".oke/schema/oke.ts";
19
26
 
20
- /** Default generated schema path. */
21
- export const SCHEMA_OUT = "schema/oke.ts";
27
+ /** Pre-0.10.4 path still read for doctor / --check soft-compat. */
28
+ export const LEGACY_SCHEMA_OUT = "schema/oke.ts";
29
+
30
+ /** Pre-0.10.4 fingerprint path. */
31
+ export const LEGACY_SCHEMA_FINGERPRINT_FILE = "schema/.oke-schema.sha256";
22
32
 
23
33
  /** Options for {@link runSchemaGenerate}. */
24
34
  export interface SchemaGenerateOptions {
@@ -36,7 +46,7 @@ export interface SchemaGenerateOptions {
36
46
  }
37
47
 
38
48
  /**
39
- * Generate `schema/oke.ts` from Manifest store tables + core auth columns.
49
+ * Generate `.oke/schema/oke.ts` from Manifest store tables + core auth columns.
40
50
  *
41
51
  * @param options - Manifest / check flag
42
52
  */
@@ -60,6 +70,11 @@ export async function runSchemaGenerate(options: SchemaGenerateOptions = {}): Pr
60
70
  "oke_crons",
61
71
  "oke_signal_config",
62
72
  "oke_console_prefs",
73
+ "oke_vault_secrets",
74
+ "oke_vault_keys",
75
+ "oke_vault_audit",
76
+ "oke_vault_master",
77
+ "oke_vault_status",
63
78
  ...(options.extraTables ?? []),
64
79
  ]);
65
80
  if (authSchema) {
@@ -85,13 +100,31 @@ export async function runSchemaGenerate(options: SchemaGenerateOptions = {}): Pr
85
100
  }
86
101
 
87
102
  const source = emitSchemaSource([...tables].sort(), authSchema);
88
- const out = resolve(cwd, options.out ?? SCHEMA_OUT);
103
+ const outRel = options.out ?? SCHEMA_OUT;
104
+ const out = resolve(cwd, outRel);
89
105
  const fp = hashSource(source);
106
+ const fpRel = options.out
107
+ ? `${dirname(outRel)}/.oke-schema.sha256`.replace(/^\.\//, "")
108
+ : SCHEMA_FINGERPRINT_FILE;
90
109
 
91
110
  if (options.check) {
92
111
  const existing = Bun.file(out);
93
112
  if (!(await existing.exists())) {
94
- write("oke schema generate --check: schema/oke.ts missing\n");
113
+ // Soft-compat: accept a correct legacy root `schema/oke.ts` during migrate.
114
+ if (!options.out) {
115
+ const legacy = Bun.file(resolve(cwd, LEGACY_SCHEMA_OUT));
116
+ if (await legacy.exists()) {
117
+ if (hashSource(await legacy.text()) === fp) {
118
+ write(
119
+ "oke schema generate --check: ok (legacy schema/oke.ts — re-run without --check to move under .oke/schema/)\n",
120
+ );
121
+ return 0;
122
+ }
123
+ write("oke schema generate --check: schema drift\n");
124
+ return 1;
125
+ }
126
+ }
127
+ write(`oke schema generate --check: ${outRel} missing\n`);
95
128
  return 1;
96
129
  }
97
130
  const current = await existing.text();
@@ -105,7 +138,7 @@ export async function runSchemaGenerate(options: SchemaGenerateOptions = {}): Pr
105
138
 
106
139
  await mkdir(dirname(out), { recursive: true });
107
140
  await Bun.write(out, source);
108
- await Bun.write(resolve(cwd, SCHEMA_FINGERPRINT_FILE), `${fp}\n`);
141
+ await Bun.write(resolve(cwd, fpRel), `${fp}\n`);
109
142
  write(`oke schema generate: wrote ${out} (${tables.size} table(s))\n`);
110
143
  return 0;
111
144
  }
@@ -128,6 +161,11 @@ export async function schemaFingerprint(cwd: string, manifest?: Manifest): Promi
128
161
  "oke_crons",
129
162
  "oke_signal_config",
130
163
  "oke_console_prefs",
164
+ "oke_vault_secrets",
165
+ "oke_vault_keys",
166
+ "oke_vault_audit",
167
+ "oke_vault_master",
168
+ "oke_vault_status",
131
169
  ...authSchema.tableNames,
132
170
  ]);
133
171
  if (m?.stores) {
@@ -141,16 +179,24 @@ export async function schemaFingerprint(cwd: string, manifest?: Manifest): Promi
141
179
  /**
142
180
  * Read the on-disk schema fingerprint, if any.
143
181
  *
182
+ * Prefers `.oke/schema/`, then legacy root `schema/`.
183
+ *
144
184
  * @param cwd - Project root
145
185
  */
146
186
  export async function readSchemaFingerprint(cwd: string): Promise<string | null> {
147
- const fpFile = Bun.file(resolve(cwd, SCHEMA_FINGERPRINT_FILE));
148
- if (await fpFile.exists()) {
149
- return (await fpFile.text()).trim();
187
+ for (const rel of [SCHEMA_FINGERPRINT_FILE, LEGACY_SCHEMA_FINGERPRINT_FILE] as const) {
188
+ const fpFile = Bun.file(resolve(cwd, rel));
189
+ if (await fpFile.exists()) {
190
+ return (await fpFile.text()).trim();
191
+ }
192
+ }
193
+ for (const rel of [SCHEMA_OUT, LEGACY_SCHEMA_OUT] as const) {
194
+ const schema = Bun.file(resolve(cwd, rel));
195
+ if (await schema.exists()) {
196
+ return hashSource(await schema.text());
197
+ }
150
198
  }
151
- const schema = Bun.file(resolve(cwd, SCHEMA_OUT));
152
- if (!(await schema.exists())) return null;
153
- return hashSource(await schema.text());
199
+ return null;
154
200
  }
155
201
 
156
202
  /**
@@ -173,9 +219,11 @@ export async function schemaCli(args: readonly string[]): Promise<number> {
173
219
  else if (a === "--manifest" || a === "-m") manifestPath = rest[++i];
174
220
  else if (a === "--out" || a === "-o") out = rest[++i];
175
221
  else if (a === "--help" || a === "-h") {
176
- console.log(`oke schema generate [--check|-c] [--out|-o schema/oke.ts]
222
+ console.log(`oke schema generate [--check|-c] [--out|-o .oke/schema/oke.ts]
177
223
 
178
- Emit core auth columns + Manifest store tables. Use --check in CI to fail on drift.
224
+ Emit core auth columns + Manifest store tables into \`.oke/schema/oke.ts\`
225
+ (system stubs — not domain Drizzle under src/db/). Use --check in CI to fail on drift.
226
+ Re-run after adding plugins / auth tables so the stub catalogue stays current.
179
227
  `);
180
228
  return 0;
181
229
  }
@@ -211,6 +259,7 @@ export function emitSchemaSource(
211
259
  return `/**
212
260
  * Generated by \`oke schema generate\` — do not edit.
213
261
  * Core Gate auth tables + Manifest store tables.
262
+ * Path: \`.oke/schema/oke.ts\` (system stubs; domain schema lives under \`src/db/\`).
214
263
  */
215
264
 
216
265
  ${decls}