Enabling-Technology Timeline — What Moved, When, and How It Affects Us¶
Scope. An academic, dated record of the browser/runtime technologies the BIM OOTB
+ Spatial ERP stack depends on (or deliberately does not). Each row is classified by
its effect on us and traces to a source. Companion to SpatialERP_OOTB.md §11.5
(market-timing thesis) and ERP.md §0.18(d) (concurrency-layer detail).
Prime-directive note. Dates here are extracted and cited, not asserted from memory.
External version/date claims from the May-2026 DeepSeek analysis of ERP.md were largely
fabricated (e.g. a non-existent "SQLite 3.53.0 opfs-wl, April 2026") and are not used.
Where a date could not be independently confirmed this session it is marked (unverified).
Effect classification¶
| Tag | Meaning |
|---|---|
| FOUNDATION | We are built directly on it; remove it and the product does not exist |
| ENABLER | Materially widened what we can do (perf, scale, fidelity) |
| NEUTRAL | Available / relevant to the field, but we neither depend on nor are blocked by it |
| ROUTED-AROUND | A capability the field is still maturing that we deliberately do not use — its immaturity does not touch us, and is evidence we arrived by another path first |
| FUTURE | Not yet load-bearing; would lift a ceiling we have not hit |
The timeline¶
| Date | Move | What changed | Effect on us | Source |
|---|---|---|---|---|
| 2010-04 | three.js created (Ricardo Cabello / Mr.doob) | WebGL 3D library for the browser | FOUNDATION — the rendering substrate the viewer is built on | Wikipedia: Three.js |
| ~2014 | sql.js (kripken) — SQLite cross-compiled to JS, later WASM, in-memory only | A full relational engine in a page, microsecond queries, no server, no persistence layer | FOUNDATION — the DB we actually ride. Load file → query in RAM → export whole file. Zero OPFS access-handle contention by construction | PowerSync, May 2026 |
| ~2018 | Web Payment Request API (browser-native) (date unverified) | Native checkout without a payment server | ENABLER — the third leg of the Spatial-ERP timing thesis (§11.5) | §11.5 (date not re-verified this session) |
| ~2021–2023 | web-ifc / ThatOpen — IFC parse in-browser via WASM | IFC STEP files readable client-side | ENABLER — drop-IFC onboarding (IFC2x3+IFC4). We pre-extract to SQLite so repeat loads skip re-parse (our 10× vs re-parse-every-load) | [FeatureComparison.md §vs IFC.js] |
| 2022-03 | BroadcastChannel cross-browser (Chrome 54 2016 / Firefox 38 2015; Safari 15.4 completes the set) | same-origin multi-tab message bus, no server | ENABLER — instant multi-tab relay (viewer ↔ BOQ-charts 4D-Gantt sync, main.js S240 / boq_charts.html S253); degrades gracefully to DB-load / generateSchedule when absent, so it lifts UX, not capability |
MDN · caniuse |
| 2022-11 | SQLite 3.40.0 — first official WASM build + OPFS VFS | SQLite team ships browser WASM; OPFS sync-access-handle VFS (concurrent connections, single transaction) | NEUTRAL — reference/option only. We do not depend on the persistent build; our persistence is the op-log + in-memory sql.js | devclass 2022-11-17; sqlite.org/wasm |
| 2023-02-23 | three.js r150 | PBR maturity, mobile 60fps with 100K+ objects | ENABLER — perf/fidelity baseline behind §11.5's "Three.js r150+" leg | r150 release (23 Feb) |
| 2023-05-02 | WebGPU ships in Chrome 113 (stable) | GPU compute/render API beyond WebGL | FUTURE — viewer is WebGPU-ready (navigator.gpu.requestAdapter()), currently WebGL fallback everywhere (S276b). Activates automatically when GPU/driver support matures |
Chrome ships WebGPU |
| 2023 | SQLite 3.43.0 — opfs-sahpool VFS |
Fast OPFS persistence, no COOP/COEP headers, but zero multi-tab concurrency | ROUTED-AROUND — the first of the "persistent-OPFS" options we skip | PowerSync |
| 2023-12-22 | three.js r160 (ESM) | ES-module distribution; our pinned baseline | FOUNDATION/ENABLER — the viewer's long-time runtime version | ROADMAP L90; r160 release (22 Dec) |
| 2024-07-02 | three.js r166 — BatchedMesh.addInstance() required |
Native per-slot batching/culling primitives | ENABLER — the mechanism behind 122K-element buildings / 1M-element cities smooth in a tab | ROADMAP L97; r166 release (2 Jul) |
| 2024-10 | Firefox 131 — JSPI behind a flag | Promise-integration for WASM async I/O | NEUTRAL — relevant only to persistent-VFS performance, which we don't use | PowerSync |
| 2024–2025 | wa-sqlite OPFSCoopSyncVFS | Concurrent connections, single transaction; good general-purpose persistent VFS | ROUTED-AROUND — the field's current best persistent option; still not our path | PowerSync |
| 2025-05 | Chrome 137 — JSPI without a flag | Async WASM I/O at Asyncify-parity perf | NEUTRAL — see above | PowerSync |
| 2026-04-16 | three.js r184 | Native perObjectFrustumCulled (zero-JS-cost culling), WebGPU-ready architecture |
ENABLER — current viewer target; WebGL r184 beats r160 even without WebGPU | r184 release (16 Apr); FeatureComparison.md L29 |
| 2026-04 | wa-sqlite OPFSWriteAheadVFS | First VFS allowing reads parallel to a writer (Chrome 121+ only) | ROUTED-AROUND — the most-advanced persistent-concurrency option to date, and the layer the field is still waiting on. We shipped without it | PowerSync |
| 2026 | kernel_ops (our op-log) | Append-only op-log as the persistence + sync + undo/redo + time-machine substrate, in-browser | OUR APPLICATION of a known primitive (see Prior art below) — an operation-based CRDT (CmRDT, ERP.md §0.18c). Idea-gated, not tech-gated: its substrate (sql.js 2014 + IndexedDB ~2015) existed a decade earlier |
ERP.md §14, SpatialERP_OOTB.md §11.3 |
| future | WASM Memory64 (Safari pending) (no confirmed date) | >4GB linear memory in a tab | FUTURE — would lift the in-memory ceiling (our real scaling axis: RAM + the ~1GB IndexedDB blob cap), unrelated to multi-tab concurrency | flagged speculative; not used for any decision |
The thesis the timeline supports¶
Read top to bottom, two independent stacks matured into the same window and we stand on the mature halves of both:
- Rendering: three.js 2010 → r150 (2023) → r166 (2024) → r184 (2026). The 122K/1M-element capability is a 2024 (r166) ENABLER — this is the genuinely recent edge.
- Data: sql.js in-memory, mature since ~2014 is our FOUNDATION. Everything dated 2022→2026 in the persistent-OPFS column is ROUTED-AROUND.
The "are we too early?" worry is about the ROUTED-AROUND column — opfs-sahpool (2023) →
OPFSCoopSyncVFS (2024–25) → OPFSWriteAheadVFS (2026), still Chrome-only, still no general
multi-tab write concurrency. That column never touches us. Its unsettled state is not a
risk we carry; it is the receipt that we walked through on the 2014 in-memory path while that
half of the field is still at the gate. First-mover, not early-mover.
The only move that would migrate us into the ROUTED-AROUND column is abandoning in-memory sql.js for a persistent VFS — a choice to make only when a concrete need forces it, at which point this table is the caveat list.
The Turso / core-SQLite ferment (2024–2026) — parallel, mostly ROUTED-AROUND¶
While this project was being assembled, the SQLite core was in the most active stretch of its history: a full Rust rewrite (Turso/Limbo) and the long-sought attack on the single-writer write path (MVCC concurrent writes). Recorded here because it is the honest "how close to the edge" backdrop — but classified by our standard tags, none of it is a dependency. Several of these milestones solve precisely the problem DistributedERP §0–§5 dissolves by modelling, so they land in ROUTED-AROUND, the same column as the OPFS-concurrency work above. Dates verified 2026‑06‑24 against the linked primary sources.
| Date | Move | What changed | Effect on us | Source |
|---|---|---|---|---|
| 2024‑01‑15 | SQLite 3.45.0 — JSONB | binary JSON stored in the DB, no re-parse | NEUTRAL — present in the substrate; the engine rides the relational core + op-log, not JSONB as its store | releaselog 3_45_0 |
| 2024‑12‑10 | Limbo announced | "a complete rewrite of SQLite in Rust" | NEUTRAL — a different bet on SQLite's future; we run sql.js (C→WASM) | Turso blog |
| ~2025‑07‑01 | Turso first alpha | Limbo → "Turso, the next evolution of SQLite" | NEUTRAL — date is the announcement post (≈, not a tagged release) | Turso blog |
| 2025‑10‑06 | Turso concurrent writes (MVCC), tech preview | BEGIN CONCURRENT via Hekaton-style MVCC — "beyond the single-writer limitation" |
ROUTED-AROUND — the headline concurrency we deliberately don't use; we partition writers by physics + op-log instead | Turso blog |
| 2025‑11‑04 | SQLite 3.51.0 — 64-bit WASM build | canonical WASM stays 32-bit; a 64-bit build is now a plain make |
NEUTRAL — our sql.js runs fine 32-bit | releaselog 3_51_0 |
| 2026‑01‑05 | Turso v0.4.0 — MVCC overhaul | indexes, checkpointing, recovery for concurrent writes | ROUTED-AROUND | Turso blog |
| 2026‑03‑04 | Turso v0.5.0 | concurrent writes → beta (PRAGMA journal_mode='mvcc'), Change Data Capture |
ROUTED-AROUND | Turso blog · LinkedIn |
The contrast worth keeping. The most-quoted milestone — Turso shipping concurrent writes to "go beyond the single-writer limitation" (Oct 2025) — is, for this project, an argument in the other direction. The same season the industry shipped a sophisticated MVCC engine to let many writers share one database file, this project shipped the claim that, modelled correctly, you never needed it: ~90% of ERP is single-writer by physics, the rest is a daily one-way fold, and the one genuinely contended op-class is a compare-and-set — not concurrency in the store. So "close to the edge" here does not mean we adopted the newest engine; it means we are contemporaneous with, and a counterpoint to, the hottest SQLite-core work of the moment — having walked in on the 2014 in-memory path (the FOUNDATION above) while that half of the field is still at the gate. First-mover, not early-mover — the same thesis the OPFS column already shows, now with the SQLite-core column added.
Compass date — the counterfactual margin ("we could have missed this by…")¶
Not every enabler was a close call. The trick is to find the last-to-arrive capability we genuinely depend on — the binding constraint — and measure from there.
- sql.js (2014) gave a ~10-year lead. We could not have missed the data half.
- three.js for basic 3D (2010) — same, no risk.
- The binding constraint is rendering at our headline scale (122K-element buildings,
1M-element cities, smooth in a tab). That capability rests on
BatchedMesh.addInstance, required since three.js r166 (2 Jul 2024) —ROADMAP.md L97: "required since r166, added at 3 call sites in streaming.js." The per-instance batching path we depend on did not exist before r166 (theBatchedMeshclass itself landed earlier, in r159; r166 added theaddInstanceAPI our streaming uses).
Compass. Had BIM OOTB attempted its headline scale in 2022, the batching primitive behind 122K/1M-element smoothness did not yet exist — a wall no amount of engineering routes around. It landed 2 Jul 2024; we exercised it across the following months (S260 BatchedMesh work). We cleared the binding constraint by months, not years. On the data side we had a decade of slack; on the rendering-scale side we walked in almost the moment the door opened.
The other edge (closing, not opening). The first-mover advantage has its own compass:
the ROUTED-AROUND column (persistent-OPFS concurrency) is maturing — OPFSWriteAheadVFS
(Apr 2026) is the field catching up. Every month it matures, the architectural moat narrows
for would-be followers. So the window is open on the capability side (we're in) and still
ajar on the differentiation side (others not yet through) — which is exactly the first-mover
position, timed to months of margin on the enabling edge.
Two compasses — BIM and ERP are gated differently¶
The single most important refinement: the binding constraint is not the same for the two products.
| Binding enabler | Arrived | Margin / slack | Gating type | |
|---|---|---|---|---|
| BIM (headline scale) | three.js r166 BatchedMesh.addInstance |
~mid-2024 | months — the genuine near-miss | technology-gated |
| ERP | sql.js in-memory (AD renderer + kernel_ops + queries) |
~2014 | ~10 years | idea-gated, not tech-gated |
ERP could have been built a decade earlier — every technology it needs (in-memory SQLite, DOM/CSS, an op-log) existed by ~2014. What was missing was the insight (AD-as-data, the 5-table reduction, op-log-as-kernel), not a browser capability. So ERP carries no enabling-tech near-miss; its window has been wide open for years and stays open. The "compass margin" idea applies to BIM.
Does the renderer touch ERP at all? Only the spatial 3D ERP view (globe, container heatmap,
mini-3D swipe-card thumbnails — SpatialERP_OOTB.md §ThreeScene). The document-mode erp.html
is Three.js-free — pure DOM+CSS (SpatialERP_POC.md: "No Three.js. No WebGL."). Therefore
r184 (and the whole r150→r184 arc) is a BIM enabler with near-zero ERP effect — it improves the
optional 3D ERP surface's culling/perf, nothing in ERP logic, persistence, or the AD pipeline.
Per-enabler margin — "by what before"¶
| Enabler we depend on | Arrived | When we leaned on it | Margin | Band |
|---|---|---|---|---|
| three.js basic 3D | 2010-04 | viewer (S200+) | ~13 yr | decade of slack |
| sql.js (in-memory) | ~2014 | viewer + ERP | ~10 yr | decade of slack |
| three.js r160 (ESM) | 2023-12-22 | viewer baseline | months | comfortable |
| three.js r166 (BatchedMesh) | 2024-07-02 | BatchedMesh scale (S260) | months | the near-miss |
| three.js r184 | 2026-04-16 | current target (enhancement, not binding) | weeks | enhancement only |
| WebGPU (Chrome 113) | May 2023 | not yet — WebGL fallback (S276b) | — | door open, not walked (FUTURE) |
| WASM Memory64 | pending | not yet (no ceiling hit) | — | FUTURE |
| kernel_ops (op-log) | 2026 | persistence/sync substrate | — | our own contribution |
Reading: the only line in the near-miss band is r166 — and only for BIM scale. sql.js gave a decade; r184 is weeks of polish on top of a baseline that already worked; WebGPU/Memory64 are doors we have not yet needed to walk through (so no margin to report — they widen future ceilings).
Discrepancies / open verification¶
- three.js r184 date — RESOLVED. Confirmed 2026-04-16 from the GitHub release tag.
ROADMAP.mdL90 previously said "Apr 2025" (a year typo); corrected to 16 Apr 2026. Verified r-tag dates: r150 = 2023-02-23, r160 = 2023-12-22, r166 = 2024-07-02, r184 = 2026-04-16. - sql.js first year. PowerSync dates the in-memory JS port to 2014; the kripken origin (asm.js era) may be earlier (~2012). Used 2014 as the cited figure.
- Web Payment Request API date (~2018). Asserted in §11.5; not re-verified this session.
- Turso/core-SQLite ferment — harvested with LLM help, two corrections logged. When an LLM was asked to "show how close we were to the cutting edge," it surfaced the right milestones but slipped twice — both caught on verification against primary sources (the same discipline that rejected the fabricated DeepSeek "SQLite 3.53.0 opfs-wl" above): (1) JSONB was attributed to SQLite 3.51.0; the version/date are real (3.51.0, 2025‑11‑04) but JSONB actually shipped in 3.45.0 (2024‑01‑15) — 3.51.0's WASM-relevant item is the 64‑bit build. (2) Turso MVCC / edge-DB replication were offered as what made the project possible; they are the opposite of the architecture and are tagged ROUTED-AROUND here, not ENABLER. Lesson, restated: an LLM is a fast harvester of where the edge is, not an authority on it — extract, then verify.
Prior art — the log concept is NOT ours (no novelty-of-concept claim)¶
The log-as-source-of-truth is one of the most trodden ideas in computing; we claim application and
combination, never the primitive. Lineage (already credited in SpatialERP_OOTB.md §11.3):
Write-Ahead Log / ARIES (1970s–1992) · Event Sourcing (Fowler, ~2005) · Git (2005) · CQRS / Event Store
(~2010s) · operation-based CRDTs / CmRDT (Shapiro et al., 2011) · Datomic (Hickey, 2012 — "the log is
the database," philosophically nearest) · Kafka / "The Log" (Kreps, 2013) · Redux (2015, but RAM-only) ·
local-first / Automerge (Kleppmann, Ink & Switch, 2019). And adjacent today: Replicache, Triplit,
InstantDB, RxDB, ElectricSQL, PowerSync all do persisted client-side op-logs/CRDTs.
Undo/redo and log-as-business-database are equally NOT ours — they are event sourcing's home turf. Undo/redo via a command/event log is the Command + Memento patterns (GoF, 1994) and Redux time-travel devtools. Log-as-database for business apps specifically is where Event Sourcing was born (Greg Young, Vaughn Vernon; EventStoreDB / Axon / Marten run in banks and insurers) — and its 500-year ancestor is double-entry bookkeeping (Pacioli, 1494): an append-only log as the immutable source of business truth. Business + log is the oldest pairing in the field.
The "stable, secured" axis is where we are weaker, not novel — state it plainly. A server-side event store has real security boundaries (auth, access control, tamper-evidence, controlled durability). A browser-resident log (SQLite-WASM + OPFS/IndexedDB) sits on the user's device, is LRU-evictable, and its security depends entirely on signing + cloud-sync-as-source-of-truth (the OPFS-as-cache discipline). So on "secured" we make no novelty and no superiority claim — it is a trade-off we pay for (zero-server + offline in exchange for weaker default durability/security), and the part of the model needing the most care.
What is honestly distinctive about kernel_ops (narrowly, with humility — local-first DBs are nearby):
(1) a persisted, offline, browser-resident op-log as the primary ERP substrate (most prior art is
server-side; Redux is client-side but ephemeral); (2) one log spanning BIM geometry and ERP (same
kernel_ops drives construction time-machine and document ops) — the cross-domain unification is the
genuinely unusual part; (3) a semantic op-CRDT carrying ERP intent (merges concentrated at
document-handoff seams, vs. cr-sqlite-style LWW that silently violates invariants — §0.18c); (4) applied
as a reduction — ~150 lines of op-log + verbs standing in for iDempiere's ~15,000-line AD model.
Framing: a known primitive, placed where few place it, applied as a radical reduction — not "we invented
the log."
Provenance — extracted facts vs synthesized framing (non-invent honesty)¶
Keeping the two strata apart, per the prime directive:
- Extracted / citable (existed in the computing world independently of us): sql.js is in-memory-only
(documented since ~2014); the OPFS VFS concurrency matrix (curated by the field — PowerSync's
State of SQLite Persistence survey, running since ~2023; Chrome 2023 blog; sqlite.org/wasm docs);
three.js r-tag dates and
BatchedMesharriving in r166 (official release notes). These are sources, not our claims. - Synthesized / our analysis (NOT an external citation): the "two compasses" (BIM tech-gated vs ERP idea-gated), "first-mover-not-early-mover / the immature layer is a bonus," and the counterfactual margin ("cleared the binding constraint by months"). These are reasoning over the extracted facts + this project's own docs — defensible, but they trace to analysis, not to a source you can point at.
The facts are extraction; the narrative is interpretation. Cite the first as fact, attribute the second as our reading.
Sources (consolidated): PowerSync — State of SQLite Persistence (May 2026) · sqlite.org/wasm · Chrome ships WebGPU · devclass — SQLite 3.40 · three.js releases · Wikipedia: Three.js