okengine 0.18.3 → 0.18.5

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 (31) hide show
  1. package/AGENTS.md +5 -3
  2. package/README.md +5 -5
  3. package/package.json +2 -2
  4. package/site/content/docs/ai/index.mdx +25 -6
  5. package/site/content/docs/ai/mcp.mdx +10 -1
  6. package/site/content/docs/ai/skills.mdx +9 -9
  7. package/site/content/docs/elements/ai.mdx +1 -1
  8. package/site/content/docs/elements/gate.mdx +3 -2
  9. package/site/content/docs/elements/index.mdx +42 -11
  10. package/site/content/docs/elements/store.mdx +2 -0
  11. package/site/content/docs/get-started/basic-usage.mdx +3 -10
  12. package/site/content/docs/get-started/index.mdx +1 -1
  13. package/site/content/docs/get-started/installation.mdx +1 -1
  14. package/site/content/docs/get-started/introduction.mdx +69 -64
  15. package/site/content/docs/get-started/meta.json +1 -1
  16. package/site/content/docs/get-started/project-structure.mdx +4 -11
  17. package/site/content/docs/get-started/why.mdx +64 -114
  18. package/site/content/docs/index.mdx +69 -15
  19. package/site/content/docs/meta.json +10 -5
  20. package/site/content/docs/providers/index.mdx +2 -0
  21. package/site/content/docs/recipes/index.mdx +2 -0
  22. package/src/cli/competitor-mention-removal.test.ts +1 -1
  23. package/src/compiler/extract.test.ts +1 -1
  24. package/src/console/ui-next/dist/assets/{access-page-DY4N6nnk.js → access-page-3-EFj-2G.js} +1 -1
  25. package/src/console/ui-next/dist/assets/{flows-page-CsPDMrVM.js → flows-page-cVFnA4HH.js} +1 -1
  26. package/src/console/ui-next/dist/assets/{index-CcTDXHuz.js → index-CMIgUbD0.js} +3 -3
  27. package/src/console/ui-next/dist/assets/{observability-page-CKR595wP.js → observability-page-CQ3p34ip.js} +1 -1
  28. package/src/console/ui-next/dist/assets/{units-page-CpPFFKyE.js → units-page-l8FeKfnP.js} +1 -1
  29. package/src/console/ui-next/dist/assets/{vault-page-BsMf-9_W.js → vault-page-CL-d_mLE.js} +1 -1
  30. package/src/console/ui-next/dist/index.html +1 -1
  31. package/src/index.ts +1 -1
package/AGENTS.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # OKE — Agent Contract
2
2
 
3
+ One law. Eight elements. One contract. The backend model stays small; operational surfaces are derived from it instead of maintained separately.
4
+
3
5
  This file is loaded by every later session. It prevents drift. Product documentation lives in `site/content/docs/`. **If the documentation is silent, stop and ask.**
4
6
 
5
7
  ## The one law
@@ -27,13 +29,13 @@ There are no separate species called endpoints, handlers, consumers, jobs, subsc
27
29
 
28
30
  An element earns its place only if it has irreducible physics. New infrastructure becomes a new **driver** for an existing element — never a ninth element.
29
31
 
30
- ## The ten exports
32
+ ## Core programming vocabulary
31
33
 
32
34
  ```typescript
33
35
  import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";
34
36
  ```
35
37
 
36
- That is the entire public vocabulary. Everything else is derived.
38
+ That is the core programming vocabulary. Everything else is derived.
37
39
 
38
40
  ## Governing rule
39
41
 
@@ -80,7 +82,7 @@ Published packages:
80
82
  - `okengine` — framework. Subpath exports: `.`, `./client`, `./test`, `./config`, `./auth`, `./plugins`, `./drivers/*`. `"sideEffects": false`. CLI binary: `oke`.
81
83
  - `create-oke` — scaffold CLI (`bunx create-oke@latest <name>`). Lives in `packages/create-oke` and ships Notes starters from `packages/create-oke/templates/{standard,advanced}`.
82
84
 
83
- Engine: Bun `>=1.3.14`.
85
+ Engine: Bun `>=1.4.0`.
84
86
 
85
87
  ## Documentation authority
86
88
 
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
  <picture>
3
3
  <source
4
4
  media="(prefers-color-scheme: dark)"
5
- srcset="https://shieldcn.dev/header/grid.svg?title=okengine&subtitle=One+law.+Eight+elements.+Ten+exports.&logo=https://raw.githubusercontent.com/omqkhafi/okengine/main/site/public/logo/OKE-W.svg&theme=zinc&size=banner&mode=dark&font=geist&align=left"
5
+ srcset="https://shieldcn.dev/header/grid.svg?title=okengine&subtitle=One+law.+Eight+elements.+One+contract.&logo=https://raw.githubusercontent.com/omqkhafi/okengine/main/site/public/logo/OKE-W.svg&theme=zinc&size=banner&mode=dark&font=geist&align=left"
6
6
  />
7
7
  <img
8
- alt="okengine — One law. Eight elements. Ten exports."
9
- src="https://shieldcn.dev/header/grid.svg?title=okengine&subtitle=One+law.+Eight+elements.+Ten+exports.&logo=https://raw.githubusercontent.com/omqkhafi/okengine/main/site/public/logo/OKE-B.svg&theme=zinc&size=banner&mode=light&font=geist&align=left"
8
+ alt="okengine — One law. Eight elements. One contract."
9
+ src="https://shieldcn.dev/header/grid.svg?title=okengine&subtitle=One+law.+Eight+elements.+One+contract.&logo=https://raw.githubusercontent.com/omqkhafi/okengine/main/site/public/logo/OKE-B.svg&theme=zinc&size=banner&mode=light&font=geist&align=left"
10
10
  width="750"
11
11
  />
12
12
  </picture>
@@ -22,7 +22,7 @@
22
22
  </p>
23
23
 
24
24
  <p align="center">
25
- <em>Stop gluing APIs, jobs, and queues into one backend. One law collapses them — client, Console, and infra come free. Yours to host.</em>
25
+ <em>Modern backends became a pile of disconnected systems. One law collapses them — client, Console, and infra derived from one contract. Yours to host.</em>
26
26
  </p>
27
27
 
28
28
  <p align="center">
@@ -104,7 +104,7 @@ Every backend behavior is a Flow: `on(Trigger) → Effects`. Endpoints, jobs, co
104
104
  import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";
105
105
  ```
106
106
 
107
- That is the entire public vocabulary. World access goes through `fx` — effects are inferred, so the Manifest can derive the typed client, Console, and MCP without a second source of truth.
107
+ That is the core programming vocabulary. World access goes through `fx` — effects are inferred, so the Manifest can derive the typed client, Console, and MCP without a second source of truth.
108
108
 
109
109
  | Element | Essence |
110
110
  | ----------- | ----------------------------- |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "okengine",
3
- "version": "0.18.3",
4
- "description": "One law. Eight elements. Ten exports. One package. One manifest. Every backend need is derived, never added.",
3
+ "version": "0.18.5",
4
+ "description": "One law. Eight elements. One contract. The backend model stays small; operational surfaces are derived from it instead of maintained separately.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -5,20 +5,39 @@ icon: "Bot"
5
5
  source: "docs/spec/unified-theory.md"
6
6
  ---
7
7
 
8
- Resources for AI agents that read or operate an OKE app — not the `ai` element itself.
8
+ Resources for AI agents that inspect, understand, or operate an OKEngine application.
9
9
 
10
- ## Pages
10
+ <Callout title="Two directions, one model">
11
+ **MCP is a surface of the model, not the model itself.** Gate governs agents calling in; the AI
12
+ element governs applications calling out to models.
13
+ </Callout>
14
+
15
+ ```text
16
+ External Agents → MCP (:6535) → Gate Check → Flow (inbound)
17
+ Flow → fx.ask / fx.stream → AI Runtime → Models & External Tools (outbound)
18
+ ```
19
+
20
+ ## AI & Agent Surfaces
11
21
 
12
22
  <Cards>
13
- <Card title="MCP" description="Runtime MCP on :6535; docs MCP on :6536." href="/docs/ai/mcp" />
14
23
  <Card
15
- title="Skills"
16
- description="AGENTS.md contract and installable skills."
24
+ title="MCP"
25
+ description="Runtime MCP on :6535 for running apps; Docs MCP on :6536 for handbook search."
26
+ href="/docs/ai/mcp"
27
+ />
28
+ <Card
29
+ title="Agent Skills"
30
+ description="AGENTS.md contract and autonomous maintenance skills."
17
31
  href="/docs/ai/skills"
18
32
  />
19
33
  <Card
20
34
  title="llms.txt"
21
- description="Index, JSON catalogue, full dump, per-page markdown."
35
+ description="Standardized machine-readable feeds: /llms.txt, /llms.json, /llms-full.txt, and markdown twins."
22
36
  href="/docs/ai/llms-txt"
23
37
  />
38
+ <Card
39
+ title="AI Element"
40
+ description="Calling out: models, prompts, agents, and RAG inside your application."
41
+ href="/docs/elements/ai"
42
+ />
24
43
  </Cards>
@@ -5,7 +5,16 @@ icon: "Plug"
5
5
  source: "docs/spec/unified-theory.md"
6
6
  ---
7
7
 
8
- Two directions, same protocol. **Serve:** OKE exposes your running app on port **6535** so an agent can read the Manifest and take confirmed actions. **Consume:** your Flows call _external_ MCP servers as tools — declared on `ai.mcpServer`, dispatched through `fx.call`.
8
+ ## Two directions, same execution model
9
+
10
+ > **MCP is a surface of the model, not the model itself.**
11
+
12
+ Two genuinely distinct things share the protocol in OKE:
13
+
14
+ 1. **Gate Element (MCP Provider role):** Your app exposes Flows as MCP tools on port **6535** (or via `mcp.tool()` + OAuth 2.1 Authorization Server) so external AI agents (Claude, ChatGPT) can read the Manifest and call declared Flows.
15
+ 2. **AI Element (MCP Client role):** Your app consumes _external_ MCP tool servers via `ai.mcpServer(...)`, routing tool calls through `fx.call` inside prompts and agents.
16
+
17
+ OKE does not create separate security models for users, operators, and agents. They enter the same execution model through different triggers and planes.
9
18
 
10
19
  The server on **6535** speaks JSON-RPC over HTTP (MCP protocol `2024-11-05`), requires a Bearer token **even on localhost**, and never forwards that token upstream — adapters receive structured operator ids instead.
11
20
 
@@ -9,18 +9,18 @@ Tools alone don't make a good operator — an agent also needs to know the _voca
9
9
 
10
10
  ## The layers
11
11
 
12
- | Layer | Path | Loaded when | Teaches |
13
- | ------------------ | ---------------------------- | ------------------------------------------------- | --------------------------------------------------------------------- |
14
- | **Agent contract** | `AGENTS.md` (repo root) | Every agent session, automatically | The one law, eight elements, ten exports, the fx rule, ports, budgets |
15
- | **Element skill** | `.agents/skills/oke/` | Building or changing an okengine app | The element contract in depth — declaration patterns per element |
16
- | **Docs skill** | `.agents/skills/oke-docs/` | Writing or editing docs under `site/content/docs` | The documentation information-architecture standard and its gates |
17
- | **Ship skill** | `.agents/skills/oke-ship/` | After any implementation, before claiming done | Changelog under `## Unreleased` + docs sync via `oke-docs` |
18
- | **Deps skill** | `.agents/skills/oke-deps/` | Updating `package.json` dependencies | Scoped bumps, Bun install, pins (Drizzle RC, fumadocs alias, …) |
19
- | **Images skill** | `.agents/skills/oke-images/` | Updating Compose image pins | Registry probe, pin style, catalog + recipes + Keel + docs lockstep |
12
+ | Layer | Path | Loaded when | Teaches |
13
+ | ------------------ | ---------------------------- | ------------------------------------------------- | ---------------------------------------------------------------------- |
14
+ | **Agent contract** | `AGENTS.md` (repo root) | Every agent session, automatically | The one law, eight elements, one contract, the fx rule, ports, budgets |
15
+ | **Element skill** | `.agents/skills/oke/` | Building or changing an okengine app | The element contract in depth — declaration patterns per element |
16
+ | **Docs skill** | `.agents/skills/oke-docs/` | Writing or editing docs under `site/content/docs` | The documentation information-architecture standard and its gates |
17
+ | **Ship skill** | `.agents/skills/oke-ship/` | After any implementation, before claiming done | Changelog under `## Unreleased` + docs sync via `oke-docs` |
18
+ | **Deps skill** | `.agents/skills/oke-deps/` | Updating `package.json` dependencies | Scoped bumps, Bun install, pins (Drizzle RC, fumadocs alias, …) |
19
+ | **Images skill** | `.agents/skills/oke-images/` | Updating Compose image pins | Registry probe, pin style, catalog + recipes + Keel + docs lockstep |
20
20
 
21
21
  ## AGENTS.md — the root contract
22
22
 
23
- Every OKE app's repo carries an `AGENTS.md` that agents (Cursor, Claude Code, and peers) read at session start. It is deliberately short and absolute: every backend behavior is a Flow (`on(Trigger) → Effects`), there are eight elements and ten exports, all world access goes through `fx`, drivers are named after protocols, and the ports/budgets are fixed. Its closing rule is the one that keeps agents honest: **if the documentation is silent, stop and ask** — never invent the API.
23
+ Every OKE app's repo carries an `AGENTS.md` that agents (Cursor, Claude Code, and peers) read at session start. It is deliberately short and absolute: every backend behavior is a Flow (`on(Trigger) → Effects`), there are eight elements bound to one contract, all world access goes through `fx`, drivers are named after protocols, and the ports/budgets are fixed. Its closing rule is the one that keeps agents honest: **if the documentation is silent, stop and ask** — never invent the API.
24
24
 
25
25
  ## Skills — installable know-how
26
26
 
@@ -129,7 +129,7 @@ const result = await fx.ask(triage, input, {
129
129
  });
130
130
  ```
131
131
 
132
- External MCP tools take the same path. Declare a server with a **required** allowlist, then pass `server.tool("…")` — never whatever `tools/list` happens to expose:
132
+ External MCP tools take the same path. In OKE, **MCP is a surface of the model, not the model itself** — `ai.mcpServer` models the client role (consuming external tools), while `mcp.tool()` + Gate models the provider role (exposing your flows to agents). Declare a server with a **required** allowlist, then pass `server.tool("…")` — never whatever `tools/list` happens to expose:
133
133
 
134
134
  ```typescript
135
135
  export const github = ai.mcpServer("github", {
@@ -9,6 +9,8 @@ Gate answers **"may this happen?"** before it happens: is this a verified member
9
9
  burned its minute quota? Attach gates to the HTTP trigger — the pipeline checks them before a
10
10
  store write, emit, or channel send runs.
11
11
 
12
+ > **Same Semantics Across Planes:** OKE does not create separate security models for users, operators, and agents. They enter the same execution model through different triggers and planes: users via sessions, operators via Console policies, and agents via `mcp.tool()` + OAuth 2.1 AS.
13
+
12
14
  <Callout title="The one rule">
13
15
  Every HTTP trigger declares posture: attach a real gate, or attach `.public()`. Omitting both
14
16
  fails boot. Denial is a typed error value — never a thrown exception mid-`do`.
@@ -63,8 +65,7 @@ import { member, canBook, fair } from "../../gates";
63
65
  export const health = on(
64
66
  http.get("/health").public(),
65
67
  flow("health.check", {
66
- out: HealthOut,
67
- do: () => ({ ok: true as const }),
68
+ do: () => ({ ok: true }),
68
69
  }),
69
70
  );
70
71
 
@@ -1,45 +1,76 @@
1
1
  ---
2
2
  title: "Elements"
3
- description: "The eight irreducible parts of an OKE backend — Flow through AI, one page each."
3
+ description: "The eight closed semantic primitives of the OKEngine backend model."
4
4
  icon: "Boxes"
5
5
  source: "docs/spec/unified-theory.md"
6
6
  ---
7
7
 
8
- Every backend concern collapses to one of these eight. Pick the element you need.
8
+ Forty backend concerns collapse into eight semantic primitives. An element earns its place only with **irreducible physics**.
9
9
 
10
- ## Pages
10
+ <Callout title="Closed primitive set">
11
+ There is no ninth element. New infrastructure creates a protocol driver or plugin, preserving a
12
+ small mental model.
13
+ </Callout>
14
+
15
+ ```text
16
+ Elements define the model.
17
+ Plugins extend the model's capabilities.
18
+ Drivers connect the model to infrastructure.
19
+ Providers and Recipes choose where that infrastructure runs.
20
+ ```
21
+
22
+ ## The Eight Primitives
11
23
 
12
24
  <Cards>
13
- <Card title="Flow" description="Behavior — on(Trigger) → Effects." href="/docs/elements/flow" />
25
+ <Card
26
+ title="Flow"
27
+ description="Behavior — on(Trigger) → Effects via fx."
28
+ href="/docs/elements/flow"
29
+ />
14
30
  <Card
15
31
  title="Signal"
16
- description="Data in motion — queues, pub/sub, streams."
32
+ description="Data in motion — delivery physics as a property (once, broadcast, live)."
17
33
  href="/docs/elements/signal"
18
34
  />
19
35
  <Card
20
36
  title="Store"
21
- description="Data at rest — sql, kv, files, index."
37
+ description="Data at rest — SQL, KV, files with image transforms, and search."
22
38
  href="/docs/elements/store"
23
39
  />
24
40
  <Card
25
41
  title="Clock"
26
- description="Time — schedules, intervals, durable sleeps."
42
+ description="Time — schedules, intervals, durable sleeps, and time travel."
27
43
  href="/docs/elements/clock"
28
44
  />
29
45
  <Card
30
46
  title="Gate"
31
- description="Permission to act — auth and rate limits."
47
+ description="Permission to act — auth, tenancy, ABAC, and rate limits at the trigger."
32
48
  href="/docs/elements/gate"
33
49
  />
34
50
  <Card
35
51
  title="Vault"
36
- description="Protected knowledge — secrets and keys."
52
+ description="Protected knowledge — fail-loud secret contracts and redacted values."
37
53
  href="/docs/elements/vault"
38
54
  />
39
55
  <Card
40
56
  title="Channel"
41
- description="Reaching humans — email, SMS, push."
57
+ description="Reaching humans — email, SMS, WhatsApp, and push with built-in consent."
42
58
  href="/docs/elements/channel"
43
59
  />
44
- <Card title="AI" description="Reaching machine intelligence." href="/docs/elements/ai" />
60
+ <Card
61
+ title="AI"
62
+ description="Reaching machine intelligence — models, prompts, agents, and RAG."
63
+ href="/docs/elements/ai"
64
+ />
45
65
  </Cards>
66
+
67
+ ## See How They Compose
68
+
69
+ The closed elements compose into full backend capabilities:
70
+
71
+ | Composition Target | Formula | How It Works |
72
+ | ------------------ | ----------------------------------------------- | --------------------------------------------------------- |
73
+ | **Realtime** | Store + Gate + Signal + Flow → Live Query | CDC changes re-checked against Gate RLS, streamed as SSE |
74
+ | **Security** | Gate + Store/RLS + Tenant + fx → Secure runtime | Tenant-isolated queries with least-privilege capability |
75
+ | **Agents** | MCP + Gate + OAuth + Flow → Agent-ready backend | Declared Flows exposed on :6535 behind auth confirmation |
76
+ | **Operations** | Manifest + Effects + Runs → Inspectable backend | Inferred effects feed Console (:6533) and wide-event logs |
@@ -129,6 +129,8 @@ A request that filters on a forbidden column — `?secret=eq.x` — fails with *
129
129
 
130
130
  ### Live queries — `live: true` and `.live(table)`
131
131
 
132
+ > **Realtime did not introduce a new subsystem. It composed existing Store, Signal, Gate/RLS, Flow, and Manifest semantics.**
133
+
132
134
  Pass `live: true` to also mount `GET <path>/live` — an SSE feed of per-subscriber classified events (`upsert` / `revoked` / `delete`), gated the same way as the CRUD verbs:
133
135
 
134
136
  ```typescript
@@ -46,16 +46,9 @@ lists HTTP routes — static GET paths are links. `curl` still gets `{ data, err
46
46
  The standard starter already exports a named health Flow:
47
47
 
48
48
  ```typescript title="flows/main/health.ts"
49
- import { on, flow, http } from "okengine";
50
- import { z } from "zod";
51
-
52
- export const health = on(
53
- http.get().public(),
54
- flow({
55
- out: z.object({ ok: z.literal(true) }),
56
- do: () => ({ ok: true as const }),
57
- }),
58
- );
49
+ import { on, flow, http } from "okengine/http";
50
+
51
+ export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
59
52
  ```
60
53
 
61
54
  `main` omits the URL prefix, so this file is `GET /health` named `main.health`. See [Project structure](/docs/get-started/project-structure).
@@ -12,7 +12,7 @@ Learn the shape once, install on Bun, then write your first Flow from the standa
12
12
  <Cards>
13
13
  <Card
14
14
  title="Introduction"
15
- description="One law, eight elements, ten exports."
15
+ description="One law, eight elements, one contract."
16
16
  href="/docs/get-started/introduction"
17
17
  />
18
18
  <Card
@@ -209,7 +209,7 @@ Rename the env keys in `oke.config.ts` to `dev` / `test` / `prod`.
209
209
  />
210
210
  <Card
211
211
  title="Introduction"
212
- description="The one law, eight elements, ten exports."
212
+ description="The one law, eight elements, one contract."
213
213
  href="/docs/get-started/introduction"
214
214
  />
215
215
  <Card
@@ -1,41 +1,25 @@
1
1
  ---
2
2
  title: Introduction
3
- description: Learn the one idea behind okengine — then the eight elements and ten exports you will use everywhere.
3
+ description: The Law, the eight elements, the fx rule, and the compiled Manifest contract.
4
4
  source: docs/spec/unified-theory.md
5
5
  icon: BookOpen
6
6
  ---
7
7
 
8
- ## The One Idea
8
+ ## The One Law
9
9
 
10
- A booking API, a nightly cleanup job, a receipt email, a row-change hook — in most stacks those are four frameworks. In OKE they are **one species** with one shape. Learn the shape once; only the trigger changes.
11
-
12
- > **The one rule**
13
- > Every backend behavior is a **Flow**: `on(Trigger) → Effects`. There are no separate species called endpoints, handlers, consumers, jobs, or workflows.
14
-
15
- ## Quick Start
16
-
17
- ### Write One Flow
18
-
19
- Four contracts plus a `do`. This is the standard starter's health check:
10
+ Every backend behavior is a Flow: `on(Trigger) Effects`.
20
11
 
21
12
  ```typescript
22
- import { on, flow, http } from "okengine";
23
- import { z } from "zod";
13
+ import { on, flow, http } from "okengine/http";
24
14
 
25
- export const health = on(
26
- http.get().public(),
27
- flow({
28
- out: z.object({ ok: z.literal(true) }),
29
- do: () => ({ ok: true as const }),
30
- }),
31
- );
15
+ export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
32
16
  ```
33
17
 
34
- `main` omits the URL prefix, so this file is `GET /health` named `main.health`. See [Project structure](/docs/get-started/project-structure). Explicit `http.get("/health")` and `flow("main.health")` still win.
18
+ An endpoint, a nightly cleanup cron, a queue consumer, a row-change CDC hook these are not four frameworks. They are **one species** with one shape. Only the trigger changes.
35
19
 
36
- ### Change Only the Trigger
20
+ ## Changing Only the Trigger
37
21
 
38
- Triggers define what starts the flow. Changing the trigger replaces the entire behavior while keeping the same structure:
22
+ Triggers determine what starts the flow while preserving identical anatomy and effect tracking:
39
23
 
40
24
  | Trigger | Starts when | Replaces |
41
25
  | ---------------------------------- | ------------------ | ------------------ |
@@ -53,9 +37,9 @@ on(orderPlaced, sendReceipt);
53
37
  on(db.table(users).changed("email"), reverify);
54
38
  ```
55
39
 
56
- ## Anatomy
40
+ ## Anatomy of a Flow
57
41
 
58
- One pipeline. Only the trigger changes between an endpoint, a job, a consumer, and a row hook.
42
+ Every Flow consists of four clear sections:
59
43
 
60
44
  | Piece | Role |
61
45
  | ------------- | -------------------------------------------------------------- |
@@ -64,35 +48,53 @@ One pipeline. Only the trigger changes between an endpoint, a job, a consumer, a
64
48
  | **`do`** | The body — every read, write, emit, and call goes through `fx` |
65
49
  | **Effects** | Inferred from those `fx` calls — not hand-annotated |
66
50
 
67
- Consequence: One documentation path, one trace shape, one Flow model, one thing for an AI agent to learn.
51
+ ```typescript
52
+ export const createOrder = on(
53
+ http.post("/orders"),
54
+ flow("orders.create", {
55
+ in: OrderInput,
56
+ out: OrderResult,
57
+ do: async (input, fx) => {
58
+ const order = await fx.store(db).insert(orders).values(input);
59
+ await fx.emit(orderPlaced, { orderId: order.id });
60
+ return order;
61
+ },
62
+ }),
63
+ );
64
+ ```
68
65
 
69
66
  ## The `fx` Rule
70
67
 
71
- **All world access goes through `fx`.** A Flow that imports `node:fs`, calls `fetch` directly, or uses `Date.now()` is a defect.
68
+ **All world access goes through `fx`.**
69
+
70
+ <Callout title="Single door to the world">
71
+ Nothing in user flows imports `node:fs`, calls global `fetch`, or calls `Date.now()`. Every effect
72
+ is recorded on the effect ledger.
73
+ </Callout>
72
74
 
73
- | Inferred From | With `fx` |
74
- | ----------------------- | --------- |
75
- | Cache invalidation keys | Yes |
76
- | Live queries | Yes |
77
- | Least-privilege tokens | Yes |
78
- | Deterministic tests | Yes |
79
- | Manifest Diff | Yes |
75
+ | Inferred from `fx` | What it powers |
76
+ | ----------------------- | ------------------------------------ |
77
+ | Cache invalidation keys | Invalidation follows the flow writes |
78
+ | Live queries | Realtime CDC subscriptions |
79
+ | Least-privilege tokens | Compiler-derived capability matrix |
80
+ | Deterministic tests | Injected time, clock, and stores |
81
+ | Manifest Diff | Blast-radius checks on every save |
80
82
 
81
- ## What the Manifest Derives
83
+ ## The Compiled Manifest
82
84
 
83
- At build time OKE extracts a **Manifest** a machine-readable description of your system. You do not maintain a second source of truth.
85
+ The source of truth is the backend model expressed in code. The **Manifest** is the compiled, versioned contract representing that model.
84
86
 
85
- | Surface | Port / Place | You Maintain? |
87
+ | Surface | Port | You Maintain? |
86
88
  | --------------------------------- | ------------------ | ----------------------------- |
87
- | Typed client (`okengine/client`) | your app code | No separate codegen |
88
- | Console panels, traces, explorers | `:6533` | No |
89
- | MCP for agents | `:6535` | No |
89
+ | Typed client (`okengine/client`) | your app code | No derived from Manifest |
90
+ | Console panels, traces, explorers | `:6533` | No — reads the Manifest |
91
+ | MCP for agents | `:6535` | No — reads the Manifest |
90
92
  | Architecture diagram | Console | No — it _is_ the effect graph |
91
- | Capability matrix + cache keys | compiler / runtime | No — from `fx` |
93
+ | Capability matrix + cache keys | compiler / runtime | No — inferred from `fx` |
92
94
 
93
95
  ## The Eight Elements
94
96
 
95
- An element earns its place only if it has **irreducible physics**. New infrastructure becomes a new **driver** — never a ninth element.
97
+ An element earns its place only if it has **irreducible physics**.
96
98
 
97
99
  | Element | Essence | Replaces the Zoo |
98
100
  | ----------- | ----------------------------- | --------------------------------------------------------- |
@@ -105,35 +107,38 @@ An element earns its place only if it has **irreducible physics**. New infrastru
105
107
  | **Channel** | Reaching humans | email · SMS · WhatsApp · push |
106
108
  | **AI** | Reaching machine intelligence | model calls · prompts · embeddings · agents · RAG |
107
109
 
108
- ## Ten Exports
110
+ New infrastructure becomes a **driver** for an existing element, never a ninth.
109
111
 
110
- The entire public vocabulary fits in one import. Everything else in the docs is derived from these ten names:
112
+ ## Core Programming Vocabulary
111
113
 
112
- ```ts
114
+ The core programming vocabulary is ten exported names:
115
+
116
+ ```typescript
113
117
  import { on, flow, signal, store, clock, gate, vault, channel, ai, plugin } from "okengine";
114
118
  ```
115
119
 
116
- For HTTP-only apps, prefer the slim entry so the cold graph stays on the edge:
120
+ For HTTP runtime essentials, use the slim entry `okengine/http`:
117
121
 
118
- ```ts
122
+ ```typescript
119
123
  import { on, flow, http, gate, oke, createBunRuntime } from "okengine/http";
120
124
  ```
121
125
 
122
- Heavy surfaces (runs, journal factories, compiler extract, the legacy mega-barrel) live on `okengine/runs`, `okengine/journal`, `okengine/compiler`, and `okengine/full`.
123
-
124
- ## Learn More
125
-
126
- | Topic | Page |
127
- | ------- | ------------------------------------------------------------------------------- |
128
- | Why OKE | [Why OKE](/docs/get-started/why) |
129
- | Folders | [Project structure](/docs/get-started/project-structure) |
130
- | Flow | [Flow](/docs/elements/flow) |
131
- | `fx` | [fx](/docs/reference/fx) |
132
- | Agents | [MCP](/docs/ai/mcp) · [Skills](/docs/ai/skills) · [llms.txt](/docs/ai/llms-txt) |
133
-
134
126
  ## Next Steps
135
127
 
136
- - [Why OKE](/docs/get-started/why)
137
- - [Installation](/docs/get-started/installation)
138
- - [Basic Usage](/docs/get-started/basic-usage)
139
- - [Project Structure](/docs/get-started/project-structure)
128
+ <Cards>
129
+ <Card
130
+ title="Why OKE"
131
+ description="Explore the problem of seams and the smaller model."
132
+ href="/docs/get-started/why"
133
+ />
134
+ <Card
135
+ title="Installation"
136
+ description="Scaffold a new OKEngine project with create-oke."
137
+ href="/docs/get-started/installation"
138
+ />
139
+ <Card
140
+ title="Basic Usage"
141
+ description="Write your first flow and verify it with bun test."
142
+ href="/docs/get-started/basic-usage"
143
+ />
144
+ </Cards>
@@ -3,8 +3,8 @@
3
3
  "icon": "Rocket",
4
4
  "pages": [
5
5
  "index",
6
- "introduction",
7
6
  "why",
7
+ "introduction",
8
8
  "installation",
9
9
  "basic-usage",
10
10
  "testing",
@@ -561,10 +561,7 @@ export const archive = on(
561
561
  <Tab value="(public)">
562
562
 
563
563
  ```typescript title="flows/main/(public)/health.ts"
564
- export const health = on(
565
- http.get().public(),
566
- flow({ out: z.object({ ok: z.literal(true) }), do: () => ({ ok: true as const }) }),
567
- );
564
+ export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
568
565
  // still GET /health named main.health
569
566
  ```
570
567
 
@@ -635,13 +632,9 @@ Do not put `index.ts` next to `health.ts` — that mix is a generate error. Use
635
632
  <Tab value="health.ts">
636
633
 
637
634
  ```typescript title="flows/main/health.ts"
638
- export const health = on(
639
- http.get().public(),
640
- flow({
641
- out: z.object({ ok: z.literal(true) }),
642
- do: () => ({ ok: true as const }),
643
- }),
644
- );
635
+ import { on, flow, http } from "okengine/http";
636
+
637
+ export const health = on(http.get().public(), flow({ do: () => ({ ok: true }) }));
645
638
  // GET /health name main.health
646
639
  ```
647
640