Why Lithair does things
differently

Every decision in Lithair has a reason. This page explains the philosophy behind the code, the features, and the choices that make Lithair what it is.

Pillar 1

Code that explains itself

Too many open-source projects treat comments as optional. You open a file, see a function, and have to reverse-engineer why it exists, what it does, and what happens if you change it.

In Lithair, every module, every function, every non-obvious decision is documented inline. Not boilerplate comments that restate the code. Real explanations of intent, trade-offs, and consequences.

Yes, AI helps write Lithair. That's precisely why the comments matter. AI-assisted code without context is a liability. AI-assisted code with clear documentation is an asset anyone can audit, understand, and maintain.

The goal

Zero back-and-forth between the code and external documentation. If you're reading a file, you have everything you need to understand it.

src/cache/mod.rs — Module documentation
//! Module de cache memory-first pour Lithair
//!
//! Ce module implémente un système de cache memory-first
//! générique qui s'inspire directement du système d'assets
//! frontend de Lithair.
//!
//! # Architecture
//!
//! - `traits.rs`     : Trait CacheableContent
//! - `memory_cache.rs`: Implémentation du cache
//! - `server_integration.rs`: Intégration serveur
//!
//! # Comparaison avec les Assets Frontend
//!
//! | Fonctionnalité          | Assets  | Cache |
//! |-------------------------|---------|-------|
//! | Préchargement auto      | ✅      | ✅    |
//! | Memory-first serving    | ✅      | ✅    |
//! | Headers x-cache         | ✅      | ✅    |
//! | Monitoring intégré      | ✅      | ✅    |
src/main.rs — Explains WHY, not just what
// 🔐 MFA/TOTP - Multi-Factor Authentication!
// IMPORTANT: Must be configured BEFORE RBAC so login
// handler can access MFA storage!
//
// Generates 5 MFA endpoints automatically:
// - GET  /auth/mfa/status  (check if MFA enabled)
// - POST /auth/mfa/setup   (generate secret + QR)
// - POST /auth/mfa/enable  (activate with verification)
// - POST /auth/mfa/disable (deactivate MFA)
// - POST /auth/mfa/verify  (validate TOTP at login)
//
// Compatible: Google Authenticator, Authy, 1Password
//
// ⚠️ DEV MODE: Set LITHAIR_DEV=1 to disable enforcement
.with_mfa_totp(MfaConfig {
    issuer: "Lithair Blog".into(),
    required_for: vec!["Admin".into()],
    optional_for: vec!["Editor".into()],
})
src/utils/static_files.rs — Architecture explained at the top
//! Revolutionary Memory-First Static Asset Serving
//!
//! This module serves static assets directly from memory
//! via StaticAsset API — demonstrating zero disk I/O with
//! event sourcing and SCC2 performance optimization.
//!
//! Traditional: Browser → Nginx → Disk → Response
//! Lithair:     Browser → SCC2 (RAM) → Response
//!
//! No disk read. No file descriptor. Just memory.
Pillar 2

Logs that tell a story

You start a server. You see a wall of text. You have no idea if it's normal, if something is misconfigured, or where to look when something breaks.

Lithair takes a different approach: every log has a purpose. At startup, you see exactly what's configured, what's loaded, how much memory is used. At runtime, you see cache hits, auth events, data operations — with timing.

Visual prefixes make scanning instant. Timing data makes performance visible. And log levels are respected: info gives you the overview, debug gives you the details, trace gives you everything.

The goal

When something goes wrong at 3am, your logs should tell you what happened without having to reproduce the issue.

Startup — you know exactly what's running
🚀 Lithair Website - Simple & Declarative
==========================================
📁 Data: ./blog_data
🌐 Port: 3007
🔐 RBAC: Declarative (Admin, Editor, Viewer)
📦 Models: Article (DeclarativeModel with auto CRUD)
🎨 Frontend: Astro + mdBook docs (public/)
🛡️  Admin: /secure-a1b2c3

INFO  ✅ RBAC configured with 3 roles
INFO  ✅ 3 demo users created
INFO  ✅ Sessions: ./blog_data/sessions
INFO  ✅ Articles: ./blog_data/articles
INFO  ✅ Admin routes protected declaratively
Cache — memory usage is visible
INFO  🔄 Initializing memory-first cache for 'public/'
       (extensions: [html, css, js, svg, png, woff2])
INFO  ✅ Cache initialized in 23ms
       (47 items loaded, 2.34MB/100MB memory - 2.3%)

TRACE 🎯 Cache HIT '/index.html' in 0.003ms
       (age: 4m 23s)
DEBUG ❌ Cache MISS '/unknown.css' in 0.001ms
       (total: 1,247 hits, 3 misses)

WARN  ⚠️ Memory usage is high (82.1%),
       consider increasing CACHE_MAX_MEMORY_MB
Auth — who did what, when
INFO  ✅ User logged in: admin as Admin
INFO  👋 User logged out: editor (session: a3f2...)
DEBUG 🔍 SCC2 Data Access: Retrieved 12 articles
       from persistent storage
Pillar 3

Tested at every layer

Lithair does a lot. It handles your HTTP, your data, your auth, your persistence, your admin. When you do everything, everything must be tested.

Unit tests validate individual components. Integration tests verify the full stack. And Gherkin scenarios describe expected behavior in human-readable language, so you can read and validate what the system is supposed to do without reading Rust.

This is the DevOps mindset: the CI pipeline is not a nice-to-have. It's the safety net that lets you ship with confidence. Every PR is tested. Every feature has coverage. Every security-sensitive path is verified.

The goal

If it's not tested, it doesn't exist. If a scenario is not in Gherkin, the behavior is not guaranteed. The tests ARE the specification.

tests/features/auth.feature — Human-readable scenarios
Feature: Authentication
  As a user of a Lithair application
  I want authentication to be secure by default

  Scenario: Login with valid credentials
    Given a user "admin" with role "Admin" exists
    When I POST to /auth/login with valid credentials
    Then the response status should be 200
    And I receive a session token
    And the session is stored in memory

  Scenario: Admin route requires authentication
    Given I am not authenticated
    When I access /admin/
    Then I am redirected to /admin/login/
    And no admin content is leaked

  Scenario: MFA enforcement for Admin role
    Given a user "admin" with MFA required
    When I login without TOTP code
    Then I receive "mfa_required" status
    And the session is NOT fully activated
src/cache/mod.rs — Security tests: path traversal attacks
#[test]
fn test_path_validation_security() {
    // Valid paths
    assert!(
        validate_and_normalize_path("docs/index.md", "docs")
            .is_ok()
    );

    // Directory traversal attacks — MUST fail
    assert!(
        validate_and_normalize_path("../etc/passwd", "docs")
            .is_err()
    );
    assert!(
        validate_and_normalize_path(
            "docs/../../../etc/passwd", "docs"
        ).is_err()
    );
}
src/rbac/declarative_checker.rs — Permission boundary tests
#[test]
fn test_declarative_permission_checker() {
    let checker = DeclarativePermissionChecker
        ::from_definitions(vec![
        ("Admin", vec!["*"]),
        ("Editor", vec!["ArticleRead", "ArticleWrite"]),
        ("Viewer", vec!["ArticleRead"]),
    ]);

    // Admin has wildcard — everything passes
    assert!(checker.has_permission("Admin", "ArticleDelete"));

    // Editor: read + write, NOT delete
    assert!(checker.has_permission("Editor", "ArticleWrite"));
    assert!(!checker.has_permission("Editor", "ArticleDelete"));

    // Viewer: read ONLY
    assert!(!checker.has_permission("Viewer", "ArticleWrite"));
}

CI pipeline roadmap: Every PR triggers unit tests, integration tests, and Gherkin scenario validation. Security-sensitive paths (auth, path traversal, RBAC boundaries) have dedicated test suites. Coverage reports are enforced, not optional.

Feature deep dive

Static files — loaded in memory, served from RAM

Your HTML, CSS, JS, images — everything is read from disk once at startup, stored in SCC2, and served directly from memory for every request after that.

Why not just serve from disk?

Traditional web servers (Nginx, Apache) read files from disk for every request. They use OS-level caching (page cache) which helps, but you're still going through the kernel's filesystem layer, file descriptors, and system calls.

Lithair skips all of that. At startup, files are loaded into a lock-free concurrent HashMap (SCC2). Serving a file is a direct memory lookup — no syscall, no file descriptor, no kernel involvement.

For a typical frontend (50 files, 2-3 MB), the memory cost is negligible. The performance gain is not.

How it works

1. Startup

All files in ./public are read, MIME-typed, and stored in SCC2. Configurable max file size (default 10MB) and total memory (default 100MB).

2. Request

URL path is mapped to a key in SCC2. Direct memory read. Response includes x-cache: HIT header with timing.

3. Hot reload (dev mode)

File watcher detects changes and updates SCC2 in-place. No restart needed during development.

4. Configuration

CACHE_MAX_MEMORY_MB, CACHE_MAX_FILE_SIZE_MB, CACHE_ENABLE_HOT_RELOAD — all via environment variables.

Traditional (disk) Lithair (memory)
Latency 5-50ms 0.001-0.5ms
Syscalls per request open + read + close 0
File descriptors 1 per request 0
Cold start cost None (lazy) ~23ms (preload all)
Feature deep dive

Admin panel — secured by design, not by hope

Most admin panels rely on client-side redirects and token checks. Lithair protects the admin at the server level with declarative route guards, randomized paths, and multi-factor authentication.

Why traditional admin panels fail

Predictable paths

/admin, /dashboard, /wp-admin — bots scan these 24/7. You're relying on your auth layer to handle a constant stream of attacks.

Client-side guards

A JavaScript redirect to /login is not security. The HTML, JS, and API endpoints are still reachable. An attacker doesn't need the UI to exploit the API.

No MFA by default

Admin accounts with password-only auth are the #1 attack vector. MFA is always "we'll add it later" and later never comes.

How Lithair handles it

Randomized admin path

RS_ADMIN_PATH=random generates a unique path like /secure-a1b2c3 on each deploy. Bots can't find what they can't predict.

Server-side route guards

Declarative guards protect URL patterns at the HTTP layer. No valid session? The server returns a redirect — no admin content, no API access, no HTML leak.

MFA enforced per role

Admin role requires TOTP by default. Editor can opt in. 5 endpoints auto-generated, compatible with Google Authenticator, Authy, 1Password.

RBAC on every operation

Field-level permissions checked on every API call. An Editor can write articles but not delete them. A Viewer can read but not modify. All enforced automatically.

src/main.rs — 3 lines of code for full admin security
// 🛡️ DECLARATIVE ROUTE GUARD
// Protect admin routes — server-side, no client JS needed
.with_route_guard(RouteGuard {
    protected_prefix: "/admin".into(),
    login_path: "/admin/login".into(),
    session_cookie: "lithair_session".into(),
})
// 🔐 MFA required for Admin, optional for Editor
.with_mfa_totp(MfaConfig {
    issuer: "Lithair Blog".into(),
    required_for: vec!["Admin".into()],
    optional_for: vec!["Editor".into()],
})
Feature deep dive

Event sourcing — why there's no UPDATE or DELETE

In a traditional database, an UPDATE overwrites the previous value. It's gone. Forever. In Lithair, every change is an event that's appended to a log. Nothing is ever lost.

The problem with mutable state

A user edits their profile. You run UPDATE users SET name = 'new' WHERE id = 1. The old name is gone. If you need to know what it was yesterday? You can't. Unless you built a separate audit system, which most people don't.

Now multiply that by every field, every model, every user. You have a database that shows the current state but has zero memory of how it got there.

Event sourcing flips this: instead of storing the current state, you store every change that ever happened. The current state is simply the result of replaying all events.

What you get for free

Complete audit trail

Every change tracked with timestamp, user, old value, new value. Not a separate audit table — it's the data model itself.

Time-travel

Reconstruct any entity's state at any point in history. #[lifecycle(versioned = 3)] keeps the last 3 versions automatically.

Safe replication

Events are stored in .raftlog files that any node can replay. This is how Raft consensus keeps nodes in sync.

Zero-cost recovery

Snapshots consolidate events into current state. On restart: load latest snapshot + replay remaining events into SCC2. Milliseconds, not minutes.

events.raftlog — append-only, immutable
// Traditional database: current state only
UPDATE articles SET title = 'New Title' WHERE id = 'abc';
// Old title? Gone. Who changed it? Unknown. When? No idea.

// Lithair: every change is an event
{ "type": "ArticleUpdated",
  "id": "abc",
  "field": "title",
  "old": "Old Title",
  "new": "New Title",
  "user": "editor",
  "timestamp": "2026-02-23T09:15:42Z" }
// Old title? "Old Title". Who? "editor". When? 09:15:42.

Convinced?

Lithair is open source. Read the code, run it, break it, contribute.