okengine 0.2.8 → 0.3.4

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 (180) hide show
  1. package/AGENTS.md +17 -15
  2. package/README.md +59 -31
  3. package/package.json +11 -16
  4. package/site/content/docs/ai/llms-txt.mdx +54 -0
  5. package/site/content/docs/ai/mcp.mdx +123 -0
  6. package/site/content/docs/ai/meta.json +5 -0
  7. package/site/content/docs/ai/skills.mdx +53 -0
  8. package/site/content/docs/console/access.mdx +29 -0
  9. package/site/content/docs/console/ai.mdx +35 -0
  10. package/site/content/docs/console/architecture.mdx +35 -0
  11. package/site/content/docs/console/channels.mdx +37 -0
  12. package/site/content/docs/console/clock.mdx +31 -0
  13. package/site/content/docs/console/flows.mdx +31 -0
  14. package/site/content/docs/console/gates.mdx +35 -0
  15. package/site/content/docs/console/manifest-diff.mdx +34 -0
  16. package/site/content/docs/console/meta.json +23 -0
  17. package/site/content/docs/console/overview.mdx +40 -0
  18. package/site/content/docs/console/plugins.mdx +41 -0
  19. package/site/content/docs/console/privacy.mdx +32 -0
  20. package/site/content/docs/console/runs.mdx +40 -0
  21. package/site/content/docs/console/signals.mdx +31 -0
  22. package/site/content/docs/console/store.mdx +32 -0
  23. package/site/content/docs/console/tenancy.mdx +32 -0
  24. package/site/content/docs/console/traces.mdx +34 -0
  25. package/site/content/docs/console/vault.mdx +37 -0
  26. package/site/content/docs/elements/ai.mdx +180 -0
  27. package/site/content/docs/elements/channel.mdx +167 -0
  28. package/site/content/docs/elements/clock.mdx +182 -0
  29. package/site/content/docs/elements/flow.mdx +288 -0
  30. package/site/content/docs/elements/gate.mdx +171 -0
  31. package/site/content/docs/elements/meta.json +5 -0
  32. package/site/content/docs/elements/signal.mdx +171 -0
  33. package/site/content/docs/elements/store.mdx +320 -0
  34. package/site/content/docs/elements/vault.mdx +263 -0
  35. package/site/content/docs/get-started/basic-usage.mdx +124 -0
  36. package/site/content/docs/get-started/comparison.mdx +65 -0
  37. package/site/content/docs/get-started/installation.mdx +113 -0
  38. package/site/content/docs/get-started/introduction.mdx +123 -0
  39. package/site/content/docs/get-started/meta.json +5 -0
  40. package/site/content/docs/index.mdx +63 -0
  41. package/site/content/docs/meta.json +5 -0
  42. package/site/content/docs/plugins/compression.mdx +60 -0
  43. package/site/content/docs/plugins/cors.mdx +98 -0
  44. package/site/content/docs/plugins/csrf.mdx +96 -0
  45. package/site/content/docs/plugins/ip-allowlist.mdx +93 -0
  46. package/site/content/docs/plugins/maintenance-mode.mdx +101 -0
  47. package/site/content/docs/plugins/meta.json +15 -0
  48. package/site/content/docs/plugins/security-headers.mdx +136 -0
  49. package/site/content/docs/reference/cli.md +101 -0
  50. package/site/content/docs/reference/configuration.mdx +159 -0
  51. package/site/content/docs/reference/environment-variables.mdx +87 -0
  52. package/site/content/docs/reference/errors.mdx +80 -0
  53. package/site/content/docs/reference/fx.mdx +117 -0
  54. package/site/content/docs/reference/meta.json +5 -0
  55. package/site/content/docs/reference/plugins.mdx +249 -0
  56. package/site/content/docs/reference/security.md +63 -0
  57. package/src/auth/auth.test.ts +3 -0
  58. package/src/cli/ask-dev-mode.ts +1 -1
  59. package/src/cli/db.ts +87 -17
  60. package/src/cli/dev-db-push.test.ts +32 -2
  61. package/src/cli/dev-schema-sync.test.ts +66 -0
  62. package/src/cli/dev-schema-sync.ts +139 -0
  63. package/src/cli/dev.test.ts +123 -1
  64. package/src/cli/dev.ts +150 -8
  65. package/src/cli/doc-staleness.test.ts +4 -4
  66. package/src/cli/docker-cli.test.ts +20 -0
  67. package/src/cli/docker.ts +10 -0
  68. package/src/cli/drizzle-env.test.ts +67 -0
  69. package/src/cli/drizzle-env.ts +78 -0
  70. package/src/cli/ensure-drizzle-config.ts +50 -0
  71. package/src/cli/hero-meta.test.ts +1 -1
  72. package/src/cli/load-config.ts +6 -0
  73. package/src/cli/mode.ts +24 -4
  74. package/src/cli/openbao-bootstrap.test.ts +149 -0
  75. package/src/cli/openbao-bootstrap.ts +314 -0
  76. package/src/cli/openbao-restart.integration.test.ts +136 -0
  77. package/src/cli/ports.test.ts +7 -5
  78. package/src/cli/ports.ts +6 -2
  79. package/src/cli/resolve-dev-sql-env.test.ts +48 -0
  80. package/src/cli/resolve-dev-sql-env.ts +42 -0
  81. package/src/cli/stack.ts +7 -4
  82. package/src/cli/vault-cmd.ts +63 -0
  83. package/src/client/types.ts +7 -1
  84. package/src/compiler/extract.test.ts +40 -0
  85. package/src/compiler/extract.ts +123 -1
  86. package/src/compiler/fixtures/skyport/oke.config.ts +2 -2
  87. package/src/compiler/fixtures/skyport.expected.json +1 -1
  88. package/src/compiler/response.ts +12 -0
  89. package/src/config/define-config.test.ts +4 -6
  90. package/src/config/index.ts +2 -15
  91. package/src/console/server/app.ts +2 -0
  92. package/src/console/server/vault.ts +21 -6
  93. package/src/docker/compose.ts +112 -16
  94. package/src/docker/derive.ts +7 -1
  95. package/src/docker/docker.test.ts +103 -0
  96. package/src/docker/index.ts +11 -1
  97. package/src/docker/recipes/index.ts +3 -2
  98. package/src/docker/recipes/openbao.ts +47 -0
  99. package/src/docker/recipes/redis.ts +5 -1
  100. package/src/docker/recipes/rustfs.ts +2 -3
  101. package/src/docker/stack-id.test.ts +43 -8
  102. package/src/docker/stack-id.ts +99 -20
  103. package/src/docker/stack.ts +36 -4
  104. package/src/docker/types.ts +3 -0
  105. package/src/docs-origin.ts +4 -4
  106. package/src/drivers/drizzle-dialect.test.ts +20 -0
  107. package/src/drivers/drizzle-dialect.ts +37 -0
  108. package/src/drivers/index.ts +1 -2
  109. package/src/drivers/memory.ts +278 -39
  110. package/src/drivers/s3.ts +10 -1
  111. package/src/drivers/vault-driver-removal.test.ts +55 -0
  112. package/src/drivers/vault-openbao.test.ts +97 -0
  113. package/src/drivers/vault-openbao.ts +102 -35
  114. package/src/drivers/vault-types.ts +3 -10
  115. package/src/elements/store/declare.ts +4 -1
  116. package/src/elements/store/resource-list-docs.fixture.ts +56 -0
  117. package/src/elements/store/resource-list-docs.test.ts +79 -0
  118. package/src/elements/store/resource.test.ts +253 -0
  119. package/src/elements/store/resource.ts +786 -0
  120. package/src/elements/store/sql-condition.test.ts +132 -0
  121. package/src/elements/store/sql-condition.ts +284 -46
  122. package/src/elements/store/sql-session.test.ts +86 -1
  123. package/src/elements/store/sql-session.ts +187 -27
  124. package/src/elements/store/table.ts +34 -4
  125. package/src/elements/store.ts +16 -0
  126. package/src/elements/vault/runtime.ts +1 -1
  127. package/src/elements/vault.test.ts +1 -28
  128. package/src/elements/vault.ts +1 -1
  129. package/src/kernel/app.ts +59 -25
  130. package/src/kernel/boot-bind/channel.test.ts +60 -0
  131. package/src/kernel/boot-bind/channel.ts +64 -2
  132. package/src/kernel/boot-bind/store.test.ts +10 -1
  133. package/src/kernel/boot-bind/store.ts +49 -2
  134. package/src/kernel/boot.test.ts +0 -1
  135. package/src/kernel/boot.ts +1 -1
  136. package/src/kernel/edge.test.ts +68 -0
  137. package/src/kernel/errors.registry.test.ts +1 -1
  138. package/src/kernel/flow.ts +8 -0
  139. package/src/kernel/fx.test.ts +23 -3
  140. package/src/kernel/fx.ts +115 -18
  141. package/src/kernel/hooks.test.ts +33 -0
  142. package/src/kernel/hooks.ts +22 -0
  143. package/src/kernel/index.ts +7 -0
  144. package/src/kernel/on.ts +44 -3
  145. package/src/kernel/plugin.ts +33 -3
  146. package/src/kernel/registry-isolation.test.ts +74 -0
  147. package/src/kernel/registry.ts +22 -1
  148. package/src/kernel/triggers.ts +59 -0
  149. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  150. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  151. package/src/manifest/index.ts +1 -1
  152. package/src/manifest/types.ts +1 -1
  153. package/src/manifest/validate.ts +2 -2
  154. package/src/plugins/compression.test.ts +127 -0
  155. package/src/plugins/compression.ts +94 -0
  156. package/src/plugins/config-source.test.ts +204 -0
  157. package/src/plugins/config-source.ts +209 -0
  158. package/src/plugins/cors.test.ts +172 -0
  159. package/src/plugins/cors.ts +153 -0
  160. package/src/plugins/csrf.test.ts +102 -0
  161. package/src/plugins/csrf.ts +86 -0
  162. package/src/plugins/headers.ts +54 -0
  163. package/src/plugins/index.ts +26 -0
  164. package/src/plugins/ip-allowlist.test.ts +139 -0
  165. package/src/plugins/ip-allowlist.ts +129 -0
  166. package/src/plugins/maintenance-mode.test.ts +91 -0
  167. package/src/plugins/maintenance-mode.ts +85 -0
  168. package/src/plugins/security-headers.test.ts +243 -0
  169. package/src/plugins/security-headers.ts +255 -0
  170. package/src/release/measure.ts +1 -2
  171. package/src/test/create-test-app.ts +14 -2
  172. package/docs/spec/console.md +0 -762
  173. package/docs/spec/example.md +0 -1374
  174. package/docs/spec/four-applications.md +0 -1376
  175. package/docs/spec/unified-theory.md +0 -498
  176. package/src/cli/doc-drift.test.ts +0 -147
  177. package/src/cli/doc-drift.ts +0 -401
  178. package/src/cli/doctor-diff-examples.ts +0 -90
  179. package/src/drivers/vault-sops.ts +0 -246
  180. /package/{spec/manifest.v1.schema.json → manifest.v1.schema.json} +0 -0
@@ -1,246 +0,0 @@
1
- /**
2
- * `sops` vault driver — SOPS/age via Typage (`age-encryption`).
3
- *
4
- * Pure TypeScript, in-process. No Go `sops` / `age` binary.
5
- * Decrypts the SOPS data key with age, then AES-256-GCM value payloads.
6
- *
7
- * `age-encryption` is an optional peer — loaded only when this driver runs.
8
- */
9
-
10
- import type { VaultBag, VaultDriver, VaultOpenOptions } from "./vault-types.ts";
11
-
12
- /** Minimal Typage surface used by this driver. */
13
- type AgeModule = typeof import("age-encryption");
14
-
15
- /**
16
- * Lazy-load Typage so apps that never open a sops vault skip the dependency.
17
- */
18
- async function loadAge(): Promise<AgeModule> {
19
- try {
20
- return await import("age-encryption");
21
- } catch {
22
- throw new Error("sops vault: install optional peer `age-encryption` (bun add age-encryption)");
23
- }
24
- }
25
-
26
- /** SOPS metadata block. */
27
- interface SopsMeta {
28
- readonly age?: ReadonlyArray<{
29
- readonly recipient?: string;
30
- readonly enc?: string;
31
- }>;
32
- readonly mac?: string;
33
- }
34
-
35
- /** Encrypted value marker: `ENC[AES256_GCM,data:…,iv:…,tag:…,type:…]`. */
36
- const ENC_RE =
37
- /^ENC\[AES256_GCM,data:(?<data>[^,]+),iv:(?<iv>[^,]+),tag:(?<tag>[^,]+),type:(?<type>[^\]]+)\]$/;
38
-
39
- /**
40
- * Decode a URL-safe / standard base64 string to bytes.
41
- *
42
- * @param input - Base64 text
43
- */
44
- function b64(input: string): Uint8Array {
45
- const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
46
- const pad =
47
- normalized.length % 4 === 0 ? normalized : normalized + "=".repeat(4 - (normalized.length % 4));
48
- const bin = atob(pad);
49
- const out = new Uint8Array(bin.length);
50
- for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
51
- return out;
52
- }
53
-
54
- /**
55
- * Encode bytes as standard base64.
56
- *
57
- * @param bytes - Input
58
- */
59
- function b64encode(bytes: Uint8Array): string {
60
- let s = "";
61
- for (const b of bytes) s += String.fromCharCode(b);
62
- return btoa(s);
63
- }
64
-
65
- /**
66
- * Copy into a fresh `Uint8Array` so Web Crypto accepts it as `BufferSource`.
67
- *
68
- * @param bytes - Input
69
- */
70
- function asBufferSource(bytes: Uint8Array): Uint8Array<ArrayBuffer> {
71
- return new Uint8Array(bytes);
72
- }
73
-
74
- /**
75
- * Decrypt a SOPS AES-256-GCM value with the data key.
76
- *
77
- * @param enc - `ENC[AES256_GCM,…]` string
78
- * @param dataKey - 32-byte SOPS data key
79
- */
80
- async function decryptValue(enc: string, dataKey: Uint8Array): Promise<string> {
81
- const m = ENC_RE.exec(enc);
82
- const dataB64 = m?.groups?.data;
83
- const ivB64 = m?.groups?.iv;
84
- const tagB64 = m?.groups?.tag;
85
- if (!dataB64 || !ivB64 || !tagB64) {
86
- throw new Error(`sops: unrecognized ciphertext: ${enc.slice(0, 32)}…`);
87
- }
88
- const data = b64(dataB64);
89
- const iv = asBufferSource(b64(ivB64));
90
- const tag = b64(tagB64);
91
- const key = await crypto.subtle.importKey(
92
- "raw",
93
- asBufferSource(dataKey),
94
- { name: "AES-GCM" },
95
- false,
96
- ["decrypt"],
97
- );
98
- const cipher = new Uint8Array(data.length + tag.length);
99
- cipher.set(data, 0);
100
- cipher.set(tag, data.length);
101
- const plain = await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, asBufferSource(cipher));
102
- return new TextDecoder().decode(plain);
103
- }
104
-
105
- /**
106
- * Decrypt the SOPS data key from an age-encrypted stanza using Typage.
107
- *
108
- * @param identity - `AGE-SECRET-KEY-…`
109
- * @param encBlock - Armored age ciphertext from `sops.age[].enc`
110
- */
111
- async function decryptDataKey(identity: string, encBlock: string): Promise<Uint8Array> {
112
- const age = await loadAge();
113
- const d = new age.Decrypter();
114
- d.addIdentity(identity.trim());
115
- const trimmed = encBlock.trim();
116
- const file: Uint8Array = trimmed.includes("BEGIN AGE ENCRYPTED FILE")
117
- ? age.armor.decode(trimmed)
118
- : new TextEncoder().encode(trimmed);
119
- const bytes = await d.decrypt(file, "uint8array");
120
- return bytes;
121
- }
122
-
123
- /**
124
- * Parse a SOPS JSON document into a name→ciphertext map + metadata.
125
- *
126
- * @param text - File contents
127
- */
128
- function parseSopsJson(text: string): {
129
- values: Record<string, string>;
130
- meta: SopsMeta;
131
- } {
132
- const doc = JSON.parse(text) as Record<string, unknown>;
133
- const meta = (doc.sops ?? {}) as SopsMeta;
134
- const values: Record<string, string> = {};
135
- for (const [k, v] of Object.entries(doc)) {
136
- if (k === "sops") continue;
137
- if (typeof v === "string") values[k] = v;
138
- }
139
- return { values, meta };
140
- }
141
-
142
- /**
143
- * Encrypt a plaintext with AES-256-GCM into a SOPS-shaped `ENC[…]` string.
144
- * Exported for tests that build fixtures without the Go CLI.
145
- *
146
- * @param plaintext - Cleartext
147
- * @param dataKey - 32-byte key
148
- */
149
- export async function sopsEncryptValue(plaintext: string, dataKey: Uint8Array): Promise<string> {
150
- const iv = crypto.getRandomValues(new Uint8Array(12));
151
- const key = await crypto.subtle.importKey(
152
- "raw",
153
- asBufferSource(dataKey),
154
- { name: "AES-GCM" },
155
- false,
156
- ["encrypt"],
157
- );
158
- const cipher = new Uint8Array(
159
- await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, new TextEncoder().encode(plaintext)),
160
- );
161
- const tag = cipher.slice(cipher.length - 16);
162
- const data = cipher.slice(0, cipher.length - 16);
163
- return `ENC[AES256_GCM,data:${b64encode(data)},iv:${b64encode(iv)},tag:${b64encode(tag)},type:str]`;
164
- }
165
-
166
- /**
167
- * Build a minimal SOPS JSON document encrypted to an age recipient.
168
- * Test / fixture helper — not a full `sops` replacement.
169
- *
170
- * @param secrets - Cleartext map
171
- * @param recipient - `age1…` recipient
172
- * @param dataKey - Optional 32-byte data key (random when omitted)
173
- */
174
- export async function buildSopsFixture(
175
- secrets: Readonly<Record<string, string>>,
176
- recipient: string,
177
- dataKey?: Uint8Array,
178
- ): Promise<{ json: string; dataKey: Uint8Array }> {
179
- const age = await loadAge();
180
- const key = dataKey ?? crypto.getRandomValues(new Uint8Array(32));
181
- const e = new age.Encrypter();
182
- e.addRecipient(recipient);
183
- const encKey = await e.encrypt(key);
184
- const encBytes = typeof encKey === "string" ? new TextEncoder().encode(encKey) : encKey;
185
- const encArmored = age.armor.encode(encBytes);
186
- const out: Record<string, unknown> = {};
187
- for (const [name, value] of Object.entries(secrets)) {
188
- out[name] = await sopsEncryptValue(value, key);
189
- }
190
- out.sops = {
191
- age: [{ recipient, enc: encArmored }],
192
- lastmodified: new Date().toISOString(),
193
- version: "3.8.0",
194
- };
195
- return { json: JSON.stringify(out, null, 2), dataKey: key };
196
- }
197
-
198
- /**
199
- * SOPS/age vault driver (Typage).
200
- */
201
- export const sopsVaultDriver: VaultDriver = {
202
- id: "sops",
203
- async open(options: VaultOpenOptions = {}): Promise<VaultBag> {
204
- let text: string | undefined;
205
- if (typeof options.ciphertext === "string") {
206
- text = options.ciphertext;
207
- } else if (options.ciphertext instanceof Uint8Array) {
208
- text = new TextDecoder().decode(options.ciphertext);
209
- } else if (options.path) {
210
- text = await Bun.file(options.path).text();
211
- }
212
- if (!text) {
213
- throw new Error("sops vault: path or ciphertext is required");
214
- }
215
- if (!options.ageIdentity) {
216
- throw new Error(
217
- "sops vault: ageIdentity (AGE-SECRET-KEY-…) is required — Typage decrypts in-process",
218
- );
219
- }
220
-
221
- const { values, meta } = parseSopsJson(text);
222
- const stanza = meta.age?.[0]?.enc;
223
- if (!stanza) {
224
- throw new Error("sops vault: no age recipient stanza found");
225
- }
226
- const dataKey = await decryptDataKey(options.ageIdentity, stanza);
227
- const map = new Map<string, string>();
228
- for (const [name, enc] of Object.entries(values)) {
229
- if (enc.startsWith("ENC[")) {
230
- map.set(name, await decryptValue(enc, dataKey));
231
- } else {
232
- map.set(name, enc);
233
- }
234
- }
235
-
236
- return {
237
- driverId: "sops",
238
- get(name) {
239
- return map.get(name);
240
- },
241
- names() {
242
- return [...map.keys()];
243
- },
244
- };
245
- },
246
- };