34 lines of JSON define an entire encrypted application. A transpiler derives Lean specs, the compiler validates, codegen produces web + mobile + E2E tests. Code ratio: JSON 1 : Lean 9 : TypeScript 683.
34 lines of JSON define an entire encrypted application. A transpiler derives Lean specs, the Lean compiler validates, and codegen scripts produce web + React Native mobile + E2E tests. The human writes a declaration. Math does the rest.
Human writes app.enc.json (34 lines per app)
│
│ gen_from_enc.py (transpiler)
▼
Lean 4 formal spec (~300 lines, compiler-verified)
│
│ yarn build:ts (6 codegen scripts)
▼
Full-stack application
+ TypeScript web frontend (Vite SPA)
+ React Native mobile (Expo Router + WDK wallet)
+ E2E tests (web + RNW + Waydroid, shared workflow)
+ Code ratio: JSON 1 : Lean 9 : TypeScript 683
| Traditional (vibe coding) | ENC (SDD) |
|---|---|
| AI → code → human reads it → debug | Human → 34 lines JSON → transpiler → Lean → compiler validates → ship |
| Hours and days (human bottleneck) | Seconds (compiler bottleneck) |
| Hope it works | 162 theorems checked by Lean's kernel |
| $50K-$500K security audit | Formal proofs, zero audit cost |
| Code is the artifact | Math is the artifact, code is a derivative |
| Rewrite everything for mobile | Same JSON → web + mobile + tests from one command |
| Flaky E2E tests (text matching) | __test_state bridge + testID: 0% flake rate |
Traditional development requires a human verification layer: read generated code, understand it, test it, debug it. SDD removes the human from the loop. The Lean compiler validates the derived specs. Codegen is deterministic. Same input always produces the same output. The question isn't "how do we help AI write better code?" — it's "why is anyone writing code at all?"
Implementation is a derivative — a by-product of the mathematical specification, generated on the fly. 34 lines of JSON produce ~300 lines of Lean, which produce ~23,000 lines of TypeScript. The code has no independent existence. Change the JSON, re-derive the spec, regenerate the app.
1. Write apps/your-app.enc.json (34 lines)
app, encryption, color, data, ui, test
2. gen_from_enc.py (transpiler)
→ App.lean (schema, event types, RBAC)
→ Frontend.lean (@frontend, @mobile, @service, @test_contract, @test_flow)
3. yarn build:ts (6 codegen scripts)
gen_mobile.py → Expo Router app (WDK wallet + screens)
gen_service_mobile.py → service layer
gen_test_contract.py → testID constants
gen_test_flow.py → E2E workflow
gen_frontend.py → Vite SPA
gen_js.py → backend (Cloudflare DO + Worker + SDK)
4. Ship.
✓ No handwritten code beyond 34 lines JSON
✓ Web + mobile + tests from one command
✓ All 5 apps byte-identical from transpiler
Seven layers. Each composes from the ones below. No cycles.
Each layer has a corresponding specification document.
| Document | Layer | What it specifies |
|---|---|---|
fta.md | 1 | Formal theory: primitives, axioms, 48 theorem obligations |
enc.md | 2 | Protocol: crypto, events, RBAC, validation, node, SDK |
middleware.md | 3 | Encryption: ECDH (1-to-1 DM) + Lazy MLS (group chat) |
server.md | 4 | Server: Enclave → Runtime → Service → Cloudflare DO |
client.md | 5 | Client: Enclave → ClientRuntime → Client → JS SDK |
web.md | 6 | Frontend: AppView → FrontendRuntime → React web |
native.md | 6 | Native: AppView → same specs → React Native mobile |
overview.md | — | This document |
Supporting references:
node-api.mdx | HTTP/WebSocket API reference (endpoints, auth, errors) |
proof.mdx | Proof wire formats (SMT, CT, Bundle) |
smt.mdx | Sparse Merkle Tree specification |
spec.mdx | Legacy specification (superseded by fta.md + enc.md) |
One pattern applied three times. Each layer is a composition of a spec type with an IO boundary, yielding a codegen target.
| Layer | Spec type | IO boundary | Composition | JS target |
|---|---|---|---|---|
| Server | Enclave | Runtime (12) | Service | Cloudflare DO |
| Client | Enclave (same) | ClientRuntime (10) | Client | SDK |
| Frontend | AppView | FrontendRuntime (8) | Frontend | React app |
The client does not define its own type.
ClientView = Enclave. The server’s Enclave is the single
source of truth for routes, reads, encryption, and schema. The client
just reads it from a different perspective.
Enclave = {
schema extraRoutes encrypted
│ │ │
├──Server──────┤ │
│ allRoutes │ │
│ ddl │ │
│ handlers │ │
│ │ │
├──Client──────┤─────────────┤
│ reads │ encrypt? │
│ writes │ │
│ protocol │ │
│ │ │
└──Frontend────┤ │
StateFns │ wiring │
Components │ │
Information is defined once and flows downward. No re-specification.
fta.md App.render : S → V pure function (Theorem 45)
│
├─ enc.md AppManifest.schema event types + RBAC rules
│ │
│ ├─ enc.md AppSDK W constructors 17 write operations
│ │ │
│ │ └─ proven: all reduce to createCommit (Theorem 42)
│ │
│ └─ enc.md Middleware (ECDH/MLS) encryption parameters
│
├─ server.md Enclave 7 fields, SINGLE SOURCE
│ │
│ ├─ Enclave.allRoutes derived (protocol + extra)
│ ├─ Enclave.ddl derived (hasDataView?)
│ └─ Enclave.reads derived (GET from extraRoutes)
│
├─ client.md ClientView = Enclave ZERO new fields
│ │
│ ├─ Client.write = AppSDK.buildCommit from enc.md
│ ├─ Client.read = Enclave.reads from server.md
│ └─ Client.query = protocolRoutes shared
│
└─ web.md AppView = (Enclave, AppDef, CSSApp)
│
├─ Components from @component specs (44 components, 3,904 lines React)
├─ Handlers → SDKFunc → Client.write
├─ Effects → StateFn → Client.read
└─ CSS from Theme.lean + app stylesheets (100% coverage)
37 axiomatized IO methods across three runtimes. Everything else is derived, proven, or structurally enforced.
| Boundary | Methods | Implementation | Lines JS |
|---|---|---|---|
Runtime | 12 | Cloudflare DO API | ~50 |
ClientRuntime | 10 | fetch + WebSocket | ~30 |
FrontendRuntime | 8 | useReducer + Cmd | 214 |
Crypto | 7 | noble-curves | ~10 |
| Total | 37 | ~110 |
Cryptographic axioms (standard hardness assumptions):
sha256_collision_resistance | if SHA-256 is secure |
schnorr_correctness | BIP-340 |
ecdh_symmetric | CDH assumption |
encrypt_roundtrip | XChaCha20Poly1305 AEAD |
hkdf_one_wayness | random oracle model |
These are not implementation trust — they are mathematical assumptions the entire field relies on.
162 theorems across all layers.
| Layer | Theorems | Key results |
|---|---|---|
| Theory | 10 | FTA meta-theorems |
| Core | 20 | SMT soundness, CT inclusion, expiry rejection |
| Middleware | 1 | ECDH roundtrip |
| Apps | 65 | Schema well-formedness, SDK reductions |
| Typeclasses | 1 | Complete witness existence |
| Composition | 43 | C1-C6 composition conditions (all 4 apps) |
| Bridge | 3 | 48 FTA theorem witnesses |
| Server | 15 | Route counts, capability matrix, DDL |
| Client | 4 | Read counts, no-DV-no-reads |
Notable proofs:
reduces_to_createCommit: All 17 write operations
across 4 applications reduce to
createCommit(identity, enclave, eventType, content, exp, tags).
Proven per-operation.
registry_reads = 5, timeline_reads = 7, chat_no_reads =
0: Client read endpoint counts derived from server route tables
and verified by decide. Not specified separately.
push_only_encnode: Only enc-node has push delivery. Structural property of the Enclave definitions.
alarm_noop: Services without push have no-op alarm handlers. Prevents unnecessary work.
The codegen pipeline is a faithful functor from Lean definitions to JavaScript artifacts. “Faithful” means structure-preserving: one output per input, no creative decisions.
Enclave → one DO class
Enclave.allRoutes → Worker route dispatch
Enclave.ddl → DO constructor (SQL CREATE TABLE)
Runtime (12 methods) → ~50 lines JS (Cloudflare DO API)
Service (4 entry points)→ DO class (constructor, fetch, webSocketMessage, alarm)
AppSDK W constructors → sdk.createPost(text), sdk.like(id), ...
Enclave.reads → sdk.getFeed(opts), sdk.getProfile(id), ...
protocolRoutes → sdk.query(filter), sdk.getSTH(), ...
ClientRuntime → fetch() / WebSocket (trusted FFI)
Enclave.encrypted → encrypt/decrypt wiring (conditional)
@component.state → useReducer init state
@component.messages → { type, payload } union
@component.update → (state, msg) → [state, Cmd] (pure function)
@component.view → JSX tree
@component.subscriptions → WebSocket event handlers
@component.initCmd → initial data fetch
@elements (Elements.lean) → inlined icons, helpers, shared elements
@css (Theme.lean) → generated-supplement.css
@component (all) → auto-generated test files (gen_tests.py)
Trust boundary: runtime.ts (214 lines) — Cmd executor only. gen_react.py generates 44 components (3,904 lines React).
| Registry | Timeline | Chat | DM | |
|---|---|---|---|---|
| schema | static | static | static | static |
| addressing | singleton | per-user | per-group | per-pair |
| DataView | ✓ | ✓ | ✗ | ✗ |
| Push | ✗ | ✗ | ✗ | ✗* |
| Bootstrap | ✗ | ✓ | ✓ | ✗ |
| encrypted | ✗ | ✗ | ✗ | ✗* |
| middleware | none | none | MLS | ECDH |
| reads (GET) | 5 | 7 | 0 | 0 |
| writes | 3 | 7 | 5 | 2 |
| components | 7 | 9 | 8 | 7 |
*enc-node handles push and transport encryption for DM.
Messenger (13 components) composes DM + Chat + Timeline at the frontend layer, importing their SDKs and states.
66 Lean files organized by layer.
Enc/
├── Theory/ Layer 1: FTA (946 lines)
│ ├── Primitives.lean Val, Key, Time, CryptoSuite
│ ├── Identity.lean Id (Anon|Hold|Share|Attest)
│ ├── Trust.lean Schema, Origin, Op
│ ├── Secrecy.lean Scheme (Direct|Tree), Transport
│ ├── State.lean Life, Persist
│ ├── Storage.lean Store, Atomicity, Interface
│ ├── Binding.lean Trigger, BindMode, Binding
│ ├── Transition.lean Action (set|del|bind)
│ ├── View.lean V (el|text|empty)
│ ├── Effect.lean Effect (fetch|open|close|...)
│ ├── Application.lean FTA.App typeclass (48 obligations)
│ └── Theorems.lean FTA meta-theorems
│
├── Core/ Layer 2: Protocol (3,361 lines)
│ ├── Primitives/ Types, Crypto, Hash, SMTKey
│ ├── SMT.lean Sparse Merkle Tree
│ ├── CT.lean Certificate Transparency
│ ├── Event/ Types, Commit, Lifecycle
│ ├── RBAC.lean Schema, permits, Grant/Revoke
│ ├── Validation.lean 14-step commit pipeline
│ ├── Node.lean NodeState, processCommit
│ ├── SDK.lean createCommit, verify*, encrypt*
│ │ └── Client.lean SessionManager, NodeClient, WS
│ ├── Handlers.lean Route dispatch, SQL type
│ ├── Persistence.lean NODE_TABLES_DDL
│ ├── Push.lean P/N delivery, retry backoff
│ ├── WSHandlers.lean WebSocket message handling
│ ├── DataView.lean SYNC_STATE_DDL, event indexing
│ └── Migration.lean Enclave migration protocol
│
├── Middleware/ Layer 3: Encryption (361 lines)
│ ├── ECDH.lean 1-to-1 (DM): agree, encrypt, decrypt
│ └── MLS.lean Group (Chat): epochs, fwd secrecy
│
├── Apps/ Layer 4: Applications (7,182 lines)
│ ├── Registry/ Discovery service
│ │ ├── App.lean Schema (3 event types)
│ │ ├── SDK.lean 3 writes
│ │ ├── DataView.lean NodeIndex, EnclaveIndex, REST
│ │ ├── State.lean AppState + 4 component states
│ │ └── Components.lean 8 components (520 lines)
│ ├── Timeline/ Public microblog
│ │ ├── App.lean Schema (7 event types)
│ │ ├── SDK.lean 7 writes
│ │ ├── DataView.lean PostIndex, ProfileIndex, REST
│ │ ├── State.lean AppState + 7 component states
│ │ └── Components.lean 12 components (1,049 lines)
│ ├── DM/ Encrypted messaging (ECDH)
│ │ ├── App.lean Schema (3 event types)
│ │ ├── SDK.lean 2 writes
│ │ ├── State.lean AppState + 5 component states
│ │ └── Components.lean 9 components (810 lines)
│ ├── Chat/ Group chat (MLS)
│ │ ├── App.lean Schema (5 event types)
│ │ ├── SDK.lean 5 writes
│ │ ├── State.lean AppState + 4 component states
│ │ └── Components.lean 9 components (868 lines)
│ └── Messenger/ Composed (DM + Chat + Timeline)
│ └── Components.lean 20 components (2,038 lines)
│
├── App/ Layer 5: Typeclasses (693 lines)
│ ├── Typeclasses.lean 6 typeclasses + ENCApp witness
│ └── Instances.lean 4 × 6 instances, 17 proofs
│
├── Bridge.lean Layer 6: Theory ↔ Protocol (508 lines)
├── Frontend/ Layer 6: Lean Component Architecture
├── Composition.lean Layer 5: C1-C6 theorems (522 lines)
│
├── Server.lean Layer 7: Server codegen (281 lines)
├── Client.lean Layer 7: Client codegen (134 lines)
└── Frontend.lean Layer 7: Frontend codegen (180 lines)
For understanding the protocol:
For understanding the Lean code:
Enc/Theory/Application.lean — the FTA.App
typeclassEnc/Core/Node.lean — the Node (ordering authority)Enc/App/Instances.lean — how apps satisfy the
typeclassesEnc/Server.lean — the Enclave (single source of
truth)Enc/Client.lean — the dual (ClientView = Enclave)Enc/Frontend/ — the Lean Component Architecture (Cmd,
Component, Elements, CSS)The ENC protocol is seven composable layers — from abstract math to
React components — where a single Enclave structure
determines the complete server, SDK, and frontend for any application,
with 162 theorems proving the pipeline preserves correctness at every
stage.