0026. Node parity as an adapter and a v1 milestone
0026. Node parity as an adapter and a v1 milestone
Status
Superseded by ADR-0025
Date
2026-10-04
Deciders
operator, through the ruling that v1 is M0 to M14; the content of M14 was the plan’s (roadmap author’s)
Context
Mesh is a TypeScript framework modelled on Ash. A runtime executes the build tool and the generated programs. When the architecture was first drawn, the project assumed it should not depend on one runtime. The project’s agent instructions, written before the rulings of 2026-10-04, list the replaceable pieces behind core contracts: “database, server, runtime (Bun and Node), query library”. The research ring table agrees: the core owns “Web-standard APIs only; no runtime-specific calls”, with “Bun and Node” as first adapters, and “drivers are per-runtime adapters” because better-sqlite3 does not run on Bun (research synthesis, section 10, “Runtime” row).
Decision
As it stood: Mesh supports Bun and Node. The runtime host is an adapter slot. Core stays on web-standard APIs, runtime-specific drivers live inside data adapters, and a final v1 milestone, M14, “proves it on Node” (plan revision 2 (superseded), section 3.2 and M14). M14’s goal was “Mesh runs on Bun and on Node”, last in v1 “because it runs every other milestone’s tests”. It also contained the single-binary build.
The operator ruled that v1 is M0 to M14 (rulings of 2026-10-04, “Review note”: “M0–M14, SQLite and Postgres, HTTP after” is what the operator chose), which included M14. It seemed right because it applied the three-ring rule (ADR-0001): a runtime is replaceable, so it should be an adapter. It also hedged against a young runtime: Bun 1.4 is the first Rust release, and findSourceMap and AsyncLocalStorage have gaps (synthesis section 12, risks 2 to 4).
Why superseded. ADR-0025 replaces this. The operator ruled on 2026-10-04 (“Rulings after the decision review”, row “Runtime”, rulings of 2026-10-04): “Node is dropped. Mesh runs on Bun only (old M14 disappears). The run-time library keeps to web-standard APIs where it can.” The same review moved the single binary out of v1 (row “After v1”: “M14 (Node parity, single binary)”).
Options considered
Option A: Bun and Node, Node proven in the last milestone (this ADR)
| Dimension | Assessment |
|---|---|
| Complexity | High: per-runtime drivers, bundling, a test runner that works on both. |
| Cost | One milestone of size M, but it touches every package. |
| Reversibility | Easy to drop, as happened. |
| Reach | Widest. |
Pros: Largest audience; no lock to one runtime.
Cons: Bun’s test runner, used by PR #1, does not run under Node, so M14 had to rerun suites through another runner or drive a Node-built example. Deciding the runner at M0 would have been cheaper (plan revision 2 (superseded), M14 risks).
Option B: Bun only (ADR-0025)
| Dimension | Assessment |
|---|---|
| Complexity | Lowest. |
| Cost | Lowest. |
| Reversibility | Medium. |
| Exposure to Bun defects | Highest. |
Cheapest, and now chosen. See ADR-0025 for the full assessment.
Option C: Node first, Bun later
| Dimension | Assessment |
|---|---|
| Complexity | Medium. |
| Cost | Gives up Bun’s built-in drivers and compile. |
| Reversibility | Same two-runtime work later. |
| Fit with ring rule | Same as A. |
Pros: Mature runtime. Cons: Not argued for in the research.
Trade-off analysis
The decision was cheap to state and expensive to deliver: a runtime hedge that needed its own driver, bundling path and test runner. The operator judged the reach not worth that cost for v1.
Consequences
Nothing remains to build. What survives is the habit of keeping runtime on web-standard APIs, now enforced by a check (ADR-0025). Anyone re-proposing Node support should read the M14 risks above first.
Action items
- M0: remove M14 and the Node items from the plan (done in roadmap).