Abstract framework. Three primitives, three functions, 48 theorem obligations. Plus typeclasses, composition, and full theorem mapping.
FTA is the theoretical foundation underlying ENC. It defines a complete formal framework for building verifiable applications from three primitives, three functions, and 48 theorems. Everything in the protocol is an instantiation of this theory.
The theory assumes: a single ordering authority per data space (total order guaranteed), forks detectable but not prevented (transparency proofs), no multi-writer consensus (ordering is assigned, not agreed), schema immutability (new schema = new data space), and commit-hash idempotency (identical inputs → identical hash, no nonces).
reduce and all signatures verify, then every action in that bundle was produced by a key with strength ≥ the threshold required by the schema. This ties cryptography to state transitions in a single safety boundary.Effect/runtime separation: effect returns descriptions, not executions. Runtime execution may retry, partially fail, or execute out of order. Only reduce mutates S, and reduce is only called with verified Actions. This preserves referential transparency at the core.
Distribution is a detection problem (transparency log fork detection), not a consensus problem. This drastically simplifies the theory.
Three foundations. Everything is what, who, or when.
Null | Bool | Int | Float | String | Bytes | [τ] | {k:τ} | τ|τ | κ→ν. The data universe.
Sym Secret | Asym Pub Priv | Shard Pub K N. Six operations: agree, kdf, derive, encrypt/decrypt, sign/verify, hash, split/combine.
Time = Nat. Window = Time × Time. valid(s,e) now ⟺ s ≤ now ≤ e.
-- Asymmetric key agreement agree : PrivKey × PubKey → SharedSecret -- Key derivation kdf : SharedSecret × Context → SymKey derive : Key × Label → Key -- Symmetric authenticated encryption encrypt : SymKey × τ → Cipher decrypt : SymKey × Cipher → Option τ -- Digital signatures sign : PrivKey × τ → Sig verify : PubKey × τ × Sig → Bool -- Hashing & secret sharing hash : τ → Digest split : Key × K × N → [Key] combine : [Key] → Option Key -- Canonical asymmetric → symmetric path: symKey = kdf(agree(my_priv, their_pub), context)
agree_sym : agree(a_priv, B_pub) = agree(b_priv, A_pub) encrypt_rt : decrypt(k, encrypt(k, m)) = Some m hash_cr : collision resistant (idealized as injective) derive_oneway : derive(k, l) does not reveal k derive_sep : l ≠ l' → derive(k, l) ≠ derive(k, l') split_threshold : |keys| < k → combine keys = None split_sufficient : |keys| ≥ k → ∃ key, combine keys = Some key valid_iff : valid (s,e) now ⟺ s ≤ now ≤ e
The theory rests on five named assumptions. All theorems involving keys, signatures, hashing, or encryption depend on one or more:
| Axiom | Statement | ENC Instantiation |
|---|---|---|
CR | Hash is collision resistant (idealized as injective) | SHA-256 |
EUF-CMA | Signatures existentially unforgeable under CMA | BIP-340 Schnorr |
CDH | Computational Diffie-Hellman hard on chosen group | secp256k1 |
KDF-OW | Key derivation is one-way | HKDF-SHA256 |
AEAD-SEC | IND-CPA + INT-CTAG secure authenticated encryption | XChaCha20Poly1305 |
Commit-hash determinism is the replay protection mechanism. No nonces. The guarantee chain: (1) canonical encoding is deterministic and injective (CBOR RFC 8949 §4.2), (2) hash injectivity from CR, (3) identical inputs → identical commit hash, (4) ordering authority rejects duplicate hash. This makes idempotency a theorem, not a convention.
Identity is key possession. Four variants with cryptographic strength levels. A session is a derived key with a time window — not a new concept, just Key + Time. Anon cannot create sessions.
Id = Anon -- no key, strength 0 | Hold Public -- I have the private half, strength 1 | Share Public K -- I hold one shard, strength 0 | Attest Public Sig Nonce -- I just proved it, strength 2 session : Id → Label → Window → Option Session session Anon _ _ = None session (Hold k) label w = Some (derive(k, label), w) session (Share k _) label w = Some (derive(k, label), w) session (Attest k _ _) l w = Some (derive(k, l), w)
Five concerns govern all data. Each composes the three primitives. Having one does not imply another. All five = full trust.
Id × Resource × Schema → Bool
Keys govern permission.
τ × Origin → Bool
Keys prove authorship.
SymKey × τ → Cipher
Keys hide content.
Log → Bool
Time sequences events.
Claim × Evidence × Digest → Bool
Hash verifies state.
Access rules: Schema = [Rule], Rule = (Resource, Role, [Op]). Set once at creation. Immutable. New schema = new data space.
Origin = Unsigned | Signed Public Sig | Endorsed (Public, Sig) (Public, Sig, Nat, Time) | CoSigned [(Public, Sig)] K | Logged Digest BundleIndex -- Endorsed = author signs, endorser co-signs with seq + time -- Logged = included in append-only verifiable log -- Replay protection: commit hash is deterministic replay identifier -- Verifier checks: time ∈ skew window, hash not previously accepted, seq monotonic
Every stored datum: Envelope = (Visible τ, Hidden (Cipher | τ), Origin). Visible fields are queryable plaintext. Hidden content is opaque — may be ciphertext.
Entry = (τ, Nat, Time, Origin) -- (data, seq, time, origin) wellFormed : [Entry] → Bool wellFormed log = consecutive(seq) ∧ nonDecreasing(time) ∧ allVerified(origin) consistent : [Entry] → [Entry] → Bool consistent(l1, l2) = ∃ proof, verify_consistency(root(l1), root(l2), proof) = true -- l1's CT root is a prefix of l2's CT root Claim = Has Digest τ | Missing Digest | Included Entry Digest | Consistent Digest Digest
agree + kdf + encrypt compose to build any encryption protocol. Transport controls distribution topology. Evolution controls key lifecycle. Time optionally bounds ciphertext and forces rotation.
Transport = Direct -- 1:1, shared = agree(my, their) | Tree Nat -- 1:N, secret = root(tree), O(log N) update Evolution = Static -- key never changes | Epoch -- key per group change: keyₙ = derive(epoch, seq) | Ratchet -- key per use, forward only: -- keyₙ = derive(stateₙ, "use") -- stateₙ₊₁ = derive(stateₙ, "next"), delete stateₙ Scheme = (Transport, Evolution, Option Window, Option Window) -- ↑ TTL ↑ Rotation -- Instances: Plaintext = (Direct, Static, ∅, ∅) DH_Session = (Direct, Epoch, ∅, ∅) Ratchet_DM = (Direct, Ratchet, ∅, ∅) Group_Lazy = (Tree N, Epoch, 24h, 24h) Group_Secure = (Tree N, Ratchet, ∅, ∅) Group_Ephemeral = (Tree N, Epoch, 1h, 1h)
Four components: Global (shared), Local (per view), Persist (across sessions), Binding (lifecycle). Optionally, Global can be Convergent (CRDT-compatible with semilattice merge).
S = G × L × P × B G : { id : Id, schema : Schema, ... } -- global, shared L : Scope → τ -- local, per view P : String → τ -- persisted across sessions B : Binding → Life -- data binding lifecycle -- Persistence: get(k, p) : Option τ set(k, v, p) : P del(k, p) : P
One lifecycle type for all bindings. Six states, defined transitions, mandatory timeout enforcement:
Life = Idle | Pending Time -- waiting, with deadline | Active τ Time -- has data, received at | Failed Err Time -- error, occurred at | Stale τ Time -- data expired | Done Reason -- terminated Reason = Completed | Revoked | Expired | Closed | Timeout | Error Err -- Transitions: Idle --> Pending t Pending t --> Active (if now <= t) Pending t --> Failed (if now > t, MANDATORY -- Theorem 48) Active --> Stale --> Pending t --> Active Active | Pending | Failed | Stale --> Done
Storage is a set of capabilities and guarantees, not a category. Each store declares which operations it supports. Bindings are checked against the store's ops set.
Storage = { ops : [Op], -- {Get, Put, Del, Scan, Batch, ...} atomicity : None | Record | Global, consistency : Eventual | Strong | Causal, provable : Bool -- provides inclusion proofs? } Op = Read Query | Write Mutation Query = Select | Get | Scan | List Mutation = Insert | Put | Del | Batch Store = { storage : Storage, interface : [Interface], -- REST | GraphQL | WebSocket | Local auth : [Auth], -- None | Bearer | ApiKey | Sig | OAuth protect : Protection } Protection = (Scope, Scheme, Signing) Scope = Open | Content | Record | Field (Name → Scope) Signing = Unsigned | Signed Key | Multi [Key] K | Chain
A binding connects a Store to State. If the Store is another App, the binding is an inter-app protocol. Two modes: Pull (trigger → query → response) and Push (subscribe → stream).
Binding = { store : Store, -- App satisfies Store via : Interface ∈ store.interface, -- checked: Theorem 31 auth : Auth ∈ store.auth, -- checked: Theorem 32 mode : Pull Query Trigger | Push Query Session, parse : τ → Option τ, target : Path S, guard : Id × Schema → Bool } Trigger = Init | Tick Duration | On Event | Change Path Session = derive(id.key, label) + Window -- Every datum passes through trust: -- Inbound: guard → auth → request → [transport] → verify(origin) -- → verify(claim)? → decrypt(scheme) → parse → state -- Outbound: guard → sign → encrypt(scheme) → request → [transport]
Three action types. reduce is a pure function of state and action — no external inputs. If access check fails, state is unchanged.
Action = Set Path τ -- set value at path in S | Del Path -- delete value at path | Bind Binding Life -- update binding lifecycle reduce : S × Action → S reduce(s, a) = if access(s.id, a, s.schema) then apply(s, a) else s -- Theorem 4: Guard Event = Click | Input | Select | Submit | Nav | Scroll | Gesture | Custom String
render is a pure function of state. No external inputs. The virtual DOM is a tree of elements, text, and empty nodes.
V = El Tag [Attr] [V] | Text String | Empty Attr = Class String | On Event Action | Bind Path | Prop String τ | If (S → Bool) | Key τ render : S → V -- pure, total, no IO
effect is a pure function of state, action, and environment. Env makes external inputs (time) explicit parameters. execute performs I/O — outside the purity guarantee. Crypto operations are not separate effects — they are steps in the Binding pipeline.
Env = { time : Time } -- explicit external inputs Effect = Fetch Binding Op (τ → Action) -- read or write store | Open Binding (Life → Action) -- open push connection | Close Binding -- close connection | Route String -- navigate | Sync P -- persist | Batch [Effect] -- parallel | None effect : S × Action × Env → [Effect] -- pure execute : Effect → IO () -- impure, outside guarantee
Three functions. Two pure of state alone, one pure of state + environment. Everything else is structure. An App that exposes an Interface is a Store. Other Apps can bind to it. Composition is structural, not special-cased.
App = (S₀, B, reduce, effect, render) S₀ : S -- initial state B : [Binding] -- all data bindings reduce : S × Action → S -- pure state transition effect : S × Action × Env → [Effect] -- pure effect description render : S → V -- pure view function
The ordering authority is trusted to order and assign seq/time, but not trusted to read or forge client payloads. Content encryption keys are never shared with it. Compromised authority key allows ordering manipulation but not content forgery or decryption.
| Adversary | Capabilities | Defense |
|---|---|---|
| Authority misbehavior | Censor, reorder, fork | CT signed-head comparison detects forks |
| Network attacker | Eavesdrop, replay, MITM | ECDH + AEAD per query/response/push |
| Key compromise (client) | Exfiltrate, impersonate | Epoch rotation limits historical exposure |
| Key compromise (authority) | Order manipulation | Not content access (keys never shared) |
| Replay | Resubmit valid commits | Hash dedup + expiration windows |
Honest witness requirement: Forced migration security depends on at least one honest client retaining a previously observed signed tree head. Without this, colluding Owner + new authority can truncate history — the fundamental limit of any append-only log without external anchoring (equivalent to the CT trust model).
Notify delivery is best-effort (censorship undetectable). Guard failures must not leak store existence. Group key state must be rebuilt from event log on reconnection. Dedup prevents identical events, not identical intents.
Inbound Outbound
======= ========
+-------------------+
Store --[pull]------>| |--[write]--> Store
| access |
Store ==[push]======>| verify |--[route]--> URL
(stream) | | prove? |
| | decrypt |--[sync]---> Device
User --[event]---+-->| parse |
| reduce |
Key --[sign]------->| render |--[view]---> DOM
| effect |
| |
| G x L x P x B |
| proven |
+-------------------+
In: access -> verify -> prove? -> decrypt(scheme) -> parse
Out: sign -> encrypt(scheme) -> write(origin)A complete group chat using all five trust concerns, both transport and content encryption, the full Life state machine, and App-as-Store composition.
-- Outbound (alice sends): 1. guard: access(alice, Chat_Message, schema) -> true (Member, C) 2. sign: sig = schnorr(commit_hash, alice_priv) 3. encrypt: key = MLS.deriveMessageKey(epochSecret) cipher = encrypt(key, plaintext) 4. commit: hash = H(0x10, enclave, alice_pub, "Chat_Message", cipher, exp, tags) 5. transport: ECDH(signer_priv, seq_pub) + HKDF("enc:query") + XChaCha20 -- Inbound (bob receives via push): 1. transport: ECDH(seq_priv, bob_signer_pub) + HKDF("enc:push") 2. verify: check sig (alice) + seq_sig (node) 3. decrypt: MLS.decrypt(epochKey, cipher) -> plaintext 4. parse: parse(ChatMessage) -> Some msg 5. state: reduce(s, Set L.messages (append msg))
seq=0 Manifest -> epoch 0 (alice, bob initial members) seq=1 Grant Member carol -> MLS.addMember(carol) -> epoch 1 seq=2 Chat_Message (alice) -> encrypted with epoch 1 key seq=3 Revoke Member carol -> MLS.removeMember(carol) -> epoch 2 seq=4 Chat_Message (bob) -> encrypted with epoch 2 key carol CANNOT decrypt (forward secrecy)
Every FTA obligation is machine-checked in Lean 4. The abstract theory is defined as typeclasses — a contract with proof obligations. ENC provides concrete instances that fill every obligation. If any proof is missing, the specification does not compile.
Abstract theory Typeclasses class FTA.CryptoSuite 6 key theorems (7-12) as fields class FTA.App 48 theorem obligations as fields structure FTA.Compliant CryptoSuite + App = full compliance Concrete protocol Instances ENC types + axioms 83+ theorems proven FTA instantiation Maps each proof to its FTA obligation -- The existence of instances IS the proof. -- No sorry. No axiom escape. The kernel verifies the mapping.
Lean 4 has no interfaces or inheritance. Three approaches exist for proving "ENC satisfies FTA":
| Approach | Mechanism | Trade-off |
|---|---|---|
| Typeclasses ✓ | Define FTA as class, provide ENC instance | Generic theorems auto-apply; compile-time enforcement |
| Structure witness | Define FTA as structure, construct ENC term | More explicit but less composable |
| Theorem-level | Prove each property individually on ENC types | Works, but correspondence is implicit |
-- FTA defines the abstract interface class FTA.CryptoSuite (Hash Sig PubKey PrivKey SymKey Cipher : Type) where hash : ByteArray → Hash sign : PrivKey → ByteArray → Sig verify : PubKey → ByteArray → Sig → Bool agree : PrivKey → PubKey → SymKey encrypt : SymKey → ByteArray → Cipher decrypt : SymKey → Cipher → Option ByteArray -- Theorem obligations (FTA 7-12) agree_sym : ∀ a_priv b_priv a_pub b_pub, agree a_priv b_pub = agree b_priv a_pub encrypt_rt : ∀ k m, decrypt k (encrypt k m) = some m hash_injective : ∀ a b, hash a = hash b → a = b derive_sep : ∀ k l l', l ≠ l' → derive k l ≠ derive k l' -- ENC provides the concrete instance instance : FTA.CryptoSuite (ByteVec 32) (ByteVec 64) (ByteVec 32) (ByteVec 32) (ByteVec 32) ByteArray where hash := sha256 sign := schnorrSign verify := schnorrVerify agree := ecdh encrypt := xchacha20_encrypt decrypt := xchacha20_decrypt agree_sym := enc_agree_sym -- FTA 7 ← CDH axiom encrypt_rt := dm_roundtrip -- FTA 8 ← proven theorem hash_injective := sha256_injective -- FTA 9 ← CR axiom derive_sep := enc_derive_sep -- FTA 11 ← KDF-OW axiom
class FTA.App (S : Type) where -- Components S₀ : S bindings : List Binding schema : Schema reduce : S → Action → S -- pure (FTA 1-3 by type) effect : S → Action → Env → List Effect render : S → V -- total (FTA 45 by type) -- Theorem obligations guard : ¬access(id, a, schema) → reduce(s, a) = s -- FTA 4 no_escalation : strength(reduce(s,a)) ≤ strength(s) -- FTA 5 schema_fixed : getSchema(reduce(s,a)) = getSchema(s) -- FTA 6 session_finite : ∀ w, ∃ t, ¬valid(w, t) -- FTA 14 life_machine : transitions follow Life graph -- FTA 34 state_isolation: pa ≠ pb → set(pa, v) does not affect pb -- FTA 36 coverage : ∀ path ∈ S₀, ∃ b targeting path -- FTA 46 deadline : Pending t ∧ now > t → runtime emits Failed -- FTA 48 -- Combined witness: existence IS the proof structure FTA.Compliant (S Hash Sig PubKey PrivKey SymKey Cipher : Type) where crypto : FTA.CryptoSuite Hash Sig PubKey PrivKey SymKey Cipher app : FTA.App S
Each of the 48 FTA theorems is witnessed by one of five proof kinds:
| Kind | Count | How proven |
|---|---|---|
| Theorem | 10 | Machine-checked Lean proof (H_injective, dm_roundtrip, expired_always_rejected, etc.) |
| Axiom | 11 | Cryptographic assumption — the bridge to computational security (sha256_injective, enc_agree_sym, etc.) |
| Type sig | 7 | Encoded in Lean's type system (reduce : S → Action → S proves Preservation + Totality + Purity) |
| Def | 3 | True by definition (Window.valid, Life.canTransition, Persist.set/del) |
| Structural | 17 | Follows from architecture (validation pipeline, dual-sig constructor, CT consistency, etc.) |
FTA# Name ENC Proof Kind ---- ---- --------- ---- 1 Preservation reduce : S → Action → S Type sig 2 Totality total function, no partial Type sig 3 Purity no IO in return type Type sig 4 Guard expired_always_rejected Theorem terminated_rejects_all Theorem 5 No Escalation enc_no_escalation Theorem 6 Schema Fixed enc_schema_fixed Theorem 7 Agree Sym enc_agree_sym Axiom 8 Encrypt RT dm_roundtrip Theorem 9 Hash CR sha256_injective → H_injective Theorem 10 Derive Oneway enc_derive_oneway Axiom 11 Derive Sep enc_derive_sep Axiom 12 Threshold enc_split_threshold/sufficient Axiom 13 Window Window.valid definition Def 14 Session Finite enc_session_finite Theorem 15 Expiry Rejects expired_always_rejected Theorem 16 Verify validateCommit pipeline Structural 17 Endorse Event (sig + seq_sig) Structural 18 Append Only CT.inclusion_sound Axiom 19 Seq Strict Node assigns monotonic seq Structural 20 Time Weak Node assigns nondecr time Structural 21 Sound SMT.membership_sound Axiom 22 Non-Forgery SMT.nonmembership_sound Axiom 23 Direct Sym = Theorem 7 (ecdh) Axiom 24 Epoch Fresh mls_add/remove_advances Axiom 25 Ratchet Fwd mls_forward_secrecy Axiom 26 TTL auto-delete mechanism Structural 27 Rotation epoch rotation on stale Structural 28 Query Visible Filter on Envelope.visible Structural 29 Hidden Opaque AEAD-SEC axiom Axiom 30 Meta Queryable Envelope.visible = plaintext Structural 31 Interface Node declares [REST, WS] Structural 32 Auth Node declares [Sig, Session] Structural 33 Op Valid Schema validates ops Structural 34 Life Machine Life.canTransition Def 35 Revoke/Expire RBAC revoke → UNAUTHORIZED Structural 36 Isolation SMT namespace separation Structural 37 Persist Set KV store property Def 38 Persist Del KV store property Def 39 Hydration Event log replay Structural 40 Safe CBOR decode : Option τ Type sig 41 No Raw Typed structures only Type sig 42 Effect Only createCommit only write path Type sig 43 Sign First sign(hash) before encrypt Structural 44 Origin sig + from mandatory Structural 45 View Total render : S → V (total) Type sig 46 Coverage bindings cover all paths Structural 47 Isolation Composition theorems Theorem 48 Deadline enc_deadline_accepted Theorem
Any protocol can prove FTA compliance by defining concrete types, providing typeclass instances with proofs for each obligation, and verifying the result compiles with zero sorry.
FTA defines 48 theorems across 15 categories. ENC instantiates all of them — 162 proven in Lean 4 with zero sorry.
1–3 Pure reduce is total, preserving, effect-free 4–6 Access Guard, No Escalation, Schema Fixed 7–12 Keys ECDH Symmetric, Encrypt RT, Hash CR, Derive OW, Derive Sep, Threshold 13–15 Time Window (MAX_EXP_WINDOW), Session (7200s max), Expiry (±60s skew) 16–18 Origin Verify (schnorr), Endorse (dual-sig), Append Only (CT) 19–20 Order Seq Strict (monotonic), Time Weak (non-decreasing) 21–22 Proof SMT Sound (membership + non-membership), Non-Forgery 23–27 Secrecy Direct Sym, Epoch Fresh, Ratchet Fwd, TTL, Rotation 28–30 Scope Query Visible, Hidden Opaque, Meta Queryable 31–35 Binding Interface, Auth, Op Valid, Life Machine, Revoke/Expire 36–39 State Isolation, Persist Set, Persist Del, Hydration 40–41 Parse Safe (CBOR + hash verify), No Raw (type system enforced) 42–44 Write Effect Only, Sign First, Origin 45–46 Complete View Total, Coverage (all content types creatable) 47 Compose Isolation (App-as-Store) 48 Deadline Pending timeout enforced by runtime
46 composition theorems across 4 reference apps (Timeline, Registry, DM, Chat) prove the system holds together.
| Condition | Count | What it proves |
|---|---|---|
| C1 | 17 | Every SDK write reduces to createCommit |
| C2 | 14 | DataView data bounded by schema (P or N) |
| C3 | 5 | Middleware roundtrip = identity (ECDH + MLS) |
| C4 | 4 | Every content type creatable by some role |
| C5 | 2 | Middleware isolation (no cross-contamination) |
| C6 | 4 | Components compose only from AppSDK |
If an application requires multi-writer convergence without a sequencer, G can be configured as Convergent τ Merge where Merge must satisfy full semilattice laws:
merge(a, b) = merge(b, a) -- commutativity merge(a, merge(b, c)) = merge(merge(a, b), c) -- associativity merge(a, a) = a -- idempotence
This is outside the core theory's single-sequencer model and not counted among the 48 theorems. Applications requiring convergent state should verify these properties independently.
ENC PROTOCOL · 66 FILES · 14,869 LINES · 162 THEOREMS