Chapter 11
Under the hood
The full architecture map: twelve layers, the code layout and a request's complete journey.
The big picture — all the pieces together

Legion is built in layers, like a cake. Each layer depends only on the layers below it. This means you can understand one layer without needing to fully understand the others.
Let's go from the bottom up.
Layer 1: The Platform Abstraction Layer (PAL)
What it does: Provides a uniform interface to the operating system so Legion can run on any platform (Linux, Windows, embedded microcontrollers, etc.) without changes.
How it works: Instead of calling Linux functions directly, Legion calls function pointers stored in a structure called legion_pal_t. At startup, the correct implementation is loaded (POSIX for Linux, Win32 for Windows, FreeRTOS for microcontrollers).
Think of the PAL like a universal power adapter. The device (Legion) plugs into the adapter (PAL), and the adapter plugs into the wall (the OS). Same device, different outlets.
Key operations it abstracts:
- Threading and synchronization (mutexes, locks, condition variables)
- Networking (TCP, UDP, multicast)
- File I/O
- Time
- Cryptography (hashing, signing, encryption)
- Memory allocation
Where in the code: src/pal/pal_posix.c, src/pal/pal_win32.c, etc.
Layer 2: Core types and utilities
What it does: Defines the basic data structures that every component uses.
Key types:
legion_cohort_id_t— a 32-byte identifier for the grouplegion_peer_id_t— a string identifier for a nodelegion_command_t— a unit of work or data changelegion_capability_t— a description of what a node can dolegion_vec_t— a dynamic array (like a list that grows)legion_map_t— a hash table (key-value store)
Utilities:
- Logging — a callback-based logger (you provide the output destination)
- Error codes — a standard set of error values (
LEGION_OK,LEGION_ERR_TIMEOUT, etc.)
Where in the code: include/legion/legion_types.h, src/util/vec.c, src/util/map.c
Layer 3: Wire format and transport
What it does: Defines how data is serialized (packaged into bytes) for storage and network transmission, and how it's framed for UDP transport.
Wire format: A custom binary format with:
- An 8-byte header (magic bytes, version, message type, payload length)
- Repeated “field-value” pairs (similar to Protocol Buffers)
- Forward compatibility (unknown fields are skipped, not rejected)
LNMP (Legion Node Message Protocol): A framing layer for UDP packets:
- 36-byte header (sender ID, sequence number, timestamp, flags, checksum)
- Payload up to 1464 bytes (fits in one standard Ethernet packet of 1500 bytes)
Why custom? JSON is too big. msgpack is good but Legion wanted full control over versioning and field evolution. The custom format is about 4× smaller than JSON and fully auditable (no external library to maintain).
Where in the code: src/core/wire.c, src/core/lnmp.c
Layer 4: Discovery and networking
What it does: Finds other nodes on the network and maintains the peer list.
Three layers of discovery:
- Multicast — shout “I'm here!” on the local network
- Seed nodes — contact a known address for a peer list
- Gossip — share peer introductions organically
Transport: A shared UDP transport layer that handles:
- Listening for incoming messages
- Sending outgoing messages (multicast and unicast)
- Maintaining a peer registry
Where in the code: src/core/discovery.c, src/core/lnmp_transport.c
Layer 5: Identity
What it does: Manages cryptographic identities for users and devices.
User identity:
- Master seed (256 bits) → 12-word backup phrase (BIP-39)
- Key hierarchy (SLIP-0010): master key → device keys → tier encryption keys → protocol keys
- DID format:
did:legion:user:<base58_public_key> - DID document: a list of all registered devices and their certificates
Device identity:
- Each device generates its own keypair
- DID format:
did:legion:node:<base58_public_key> - Service certificate: user signs a certificate granting the device specific capabilities
Device pairing:
- PIN-based authentication (SPAKE2 protocol)
- Biometric confirmation (fingerprint, face ID)
- One-time transfer of device key material
Where in the code: src/identity/slip0010.c, src/identity/did_document.c, src/identity/device_pairing.c, src/identity/node_identity.c
Layer 6: Consensus and trust
What it does: Ensures all nodes agree on the same data and tracks how much each peer can be trusted.
Consensus engine:
- Commands are ordered in epochs (numbered rounds)
- Each command gets a hash chain link (prevents tampering)
- Trust scores adjust based on peer reliability
BFT (Byzantine Fault Tolerance):
- Optional Tendermint-style protocol for critical decisions
- Three phases: propose → pre-vote → pre-commit
- Requires 2/3+ agreement
- Three operating modes: observation, hybrid, full BFT
Trust manager:
- Rolling history of 4 epochs
- Anomaly detection (sudden reputation drops)
- Time-based decay (trust fades without activity)
- Reliability classification (healthy, degraded, unhealthy)
Where in the code: src/core/consensus.c, src/core/bft.c, src/core/trust.c
Layer 7: Capability management
What it does: Tracks what each node can do and routes requests to the right node.
Capability advertisement: Nodes announce their capabilities in beacons.
Delegation selection:
- Query the network for a matching capability
- Check focus (which node is the user at?)
- Check trust (is this node reliable?)
- Delegate the request
Where in the code: src/core/module_delegate.c
Layer 8: Plugin system
What it does: Allows nodes to extend their functionality with modular plugins.
How it works:
- Plugins declare a manifest (JSON) listing their methods and access controls
- The plugin manager loads manifests and routes calls
- Plugins can be chained (output of one feeds into another)
- Each method declares which data tier it can access
VM integration: The Legion VM has built-in opcodes for calling plugins:
CALL_PLUGIN— invoke a plugin methodLIST_PLUGIN_METHODS— discover what methods a plugin offers
Where in the code: src/core/plugin.c, src/modules/*/
Layer 9: Storage
What it does: Persistent storage for node state, data, and configuration.
Key-value store:
- Data stored as key-value pairs
- Tier-aware (encrypted at higher tiers)
- Cohort-shared (synced across all nodes)
Object store:
- Larger data objects (files, snapshots)
- Content-addressed (identified by content hash)
Where in the code: src/core/objectstore*.c, src/core/plugin.c (kvstore functions)
Layer 10: The Legion VM
What it does: A custom virtual machine for executing internal system programs.
Why a custom VM? General-purpose languages (like JavaScript) can't guarantee:
- Deterministic execution — every node must produce identical output
- Instruction-level metering — each opcode has a measurable cost
- State snapshotting — the entire VM state can be serialized for handoff
- No ambient OS access — pure state transition, no file system or network access
Opcodes (~100+):
- Data operations (STORE, LOAD, DEL, EXISTS)
- Stack operations (PUSH, POP, DUP, SWAP)
- Control flow (JMP, JZ, CALL, RET, LOOP)
- Resource checks (HASRES, REQRES, IFCAP)
- Trust operations (TRUST, IFTRUST, QUORUM, VOTE)
- Distributed compute (MAP, REDUCE, SCATTER, GATHER, SYNC)
- Time operations (EPOCH, WAIT, CRON, EXPIRE)
- Tier operations (GET_CURRENT_TIER, ELEVATE_TIER, CREATE_TIER)
- Plugin invocation (CALL_PLUGIN, LIST_PLUGIN_METHODS)
State: 16 registers, a stack, program counter, flags, key-value memory, call stack, trust map, locks, resources, transactions, proposals, and promises.
Where in the code: src/vm/ (entire directory)
Layer 11: The application platform
What it does: Runs user-written applications (TypeScript/JavaScript) on top of the core runtime.
Two-tier architecture:
- Legion VM — internal system code (consensus, trust, tiers)
- JS Engine — user applications (written in TypeScript)
JS engine abstraction: A vtable (function pointer table) that lets Legion support different JS engines on different platforms:
| Platform | JS Engine | Why |
|---|---|---|
| iOS | JavaScriptCore | Required by Apple App Store |
| Android | QuickJS | Small, fast, ES2023 support |
| Linux/macOS | QuickJS | Same as Android |
| ESP32 | MicroQuickJS | Tiny footprint (~100 KB) |
The legion global object: Auto-generated based on available capabilities. Missing capabilities are undefined, so apps can check before use.
App lifecycle:
- Fetch bundle by content CID
- Verify content hash
- Verify developer signature
- Show permission prompt
- Load into JS engine
- Run
Where in the code: src/js/legion_js_engine.h, src/js/legion_js_global.c, src/js/legion_js_app.c, src/js/app_cache.c, src/js/app_signing.c
Layer 12: Display GUI
What it does: Renders the visual interface for Legion apps.
Three tiers:
- Tier 1 — custom minimal renderer (ESP32, e-ink)
- Tier 2 — litehtml (Raspberry Pi, embedded Linux)
- Tier 3 — WebView (smartphone, desktop)
Event model: User interactions flow from renderer → event queue → JS engine. Apps register event handlers and respond to clicks, input, scroll, etc.
Asset system: Content-addressed asset references (legion-asset://sha256:...) resolved to inline data before rendering.
App handoff: VM state serialization for seamless device transfer.
Where in the code: src/plugins/display_gui.c, src/ui/renderer_litehtml.c, src/ui/asset_resolver.c, src/ui/vm_snapshot.c
Layer 13: Bridge and cloud infrastructure
What it does: Provides WAN (wide-area network) connectivity between devices on different networks.
- Runs as a daemon (
legion-bridge) - Listens on TCP port 7575 for incoming connections
- Manages encrypted tunnels between remote devices and home nodes
- Multi-user isolation (each user's traffic is separate)
- DID-based authentication (not passwords)
Registry:
- legios.cloud hosts a bridge discovery service
- Providers register their bridge endpoints
- Users discover bridges automatically
Where in the code: src/bridge/, src/registry/
The code layout

include/legion/ ← Public API headers
src/
pal/ ← Platform Abstraction Layer
core/ ← Consensus, discovery, trust, delegation
identity/ ← User and device identity
vm/ ← Legion virtual machine
js/ ← JavaScript engine integration
ui/ ← Rendering, assets, snapshots
bridge/ ← WAN relay daemon
modules/ ← Capability modules (audio, AI, etc.)
plugins/ ← Built-in plugins
tests/ ← Test suite
platform/ ← Platform-specific code (iOS, Android, etc.)
vendor/ ← Vendored dependencies (sqlite3, quickjs, etc.)How a request flows — the full journey
Let's trace a complete request from start to finish to see how all the layers work together.
Scenario: You type “Hello” in the Legion chat app on your phone.
- Display GUI (Layer 12): Your tap is captured as a UI event.
- JS Engine (Layer 11): The event is delivered to the chat app's
onEventhandler. - Capability delegation: The app calls
legion.ai.llm.chat({ message: "Hello" }). This goes through the capability manager (Layer 7). - Delegation selection: The system finds the orchestrator node that has
ai.llm. - Identity (Layer 5): The request is signed with your device key.
- Trust (Layer 6): The orchestrator's trust score is checked (0.9 — fully trusted).
- Consensus (Layer 6): If needed, the command enters the epoch consensus process.
- Transport (Layer 3): The request is encoded in wire format, wrapped in an LNMP frame, and sent over TCP to the orchestrator.
- VM (Layer 10): The orchestrator's VM processes the command (calls the LLM plugin).
- Plugin (Layer 8): The AI module receives the text and generates a response.
- Response flows back through the same layers in reverse.
- Display GUI (Layer 12): The reply is rendered on your smartphone screen.
You see: you typed “Hello” and got a response. Behind the scenes, 13 layers of infrastructure made that happen — all without a single central server.
The four data tiers — under the hood
Remember the four privacy layers? Here's how they're enforced technically:
| Tier | Encryption | Key derivation | Access rule |
|---|---|---|---|
| 1 (Sovereign) | XChaCha20-Poly1305 | m/2'/1'/epoch' | Only main device |
| 2 (Pragmatic) | XChaCha20-Poly1305 | m/2'/2'/epoch' | Certified devices, tier ≤ 2 |
| 3 (Group) | XChaCha20-Poly1305 | m/2'/3'/epoch' | All cohort members |
| 4 (Interface) | None (plaintext) | N/A | Anyone in the cohort |
Each tier has its own encryption key, derived from the master seed using the SLIP-0010 key hierarchy. Data flows downward only — from Tier 1 to Tier 4 — through authenticated pipes. Higher tiers cannot read lower-tier data.
Summary — the layer cake
| Layer | Name | One-line description |
|---|---|---|
| 1 | PAL | Universal OS interface |
| 2 | Core types | Basic data structures |
| 3 | Wire format | How data is packaged |
| 4 | Discovery | Finding other nodes |
| 5 | Identity | Who everyone is |
| 6 | Consensus | How everyone agrees |
| 7 | Capabilities | What everyone can do |
| 8 | Plugins | Extending capabilities |
| 9 | Storage | Persistent data |
| 10 | Legion VM | Internal execution engine |
| 11 | App platform | User applications |
| 12 | Display GUI | Visual rendering |
| 13 | Bridge | WAN connectivity |
What comes next
You now have the complete picture — from the high-level concept to the deep technical architecture. The glossary is your reference for every term mentioned in these pages.
If you want to dive deeper into any specific component, the specs directory contains detailed technical specifications for each layer.