# What Is the Cell Scope Validation Security Model in celld? A Complete Technical Guide

> Understand celld's cell scope validation security model. Learn how durable objects use SQLite and epoch leases for exclusive access and secure state modification.

- Repository: [Deno/celld](https://github.com/denoland/celld)
- Tags: deep-dive
- Published: 2026-08-15

---

**Celld's cell scope validation security model isolates each Durable Object in a dedicated SQLite database and enforces exclusive access through epoch-based ownership leases, ensuring only the legitimate node can modify a cell's state.**

This article explains how the celld runtime—an open-source Durable Object platform developed by Deno—implements **cell scope validation**, a layered security architecture that prevents unauthorized access, stale writes, and cross-tenant data leakage. The model combines physical database separation, cryptographically secured leases, and runtime fencing checks.

---

## Overview of the Cell Scope Validation Architecture

The celld runtime treats every **cell** (analogous to a Cloudflare Durable Object) as an isolated unit with three core guarantees:

- **Physical isolation**: Each cell owns a dedicated SQLite database file
- **Temporal ownership**: A node must hold a valid lease to access the cell
- **Operational fencing**: Every write operation validates the lease epoch against the database

These guarantees are enforced through mechanisms implemented across [`crates/celld/ownership_store.rs`](https://github.com/denoland/celld/blob/main/crates/celld/ownership_store.rs), [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs), and the internal operator API endpoints.

---

## Core Mechanism 1: Per-Cell SQLite Database Isolation

According to the celld source code and documentation, each cell receives its own SQLite database file stored on disk. This design choice eliminates shared table spaces that could enable cross-cell data leakage or resource contention attacks.

```rust
// Conceptual structure from ownership_store.rs
// Each cell maps to a unique database path
let db_path = format!("{}/{}.db", cell_storage_root, cell_id);

```

The physical separation means that even if a process-level compromise occurred, an attacker cannot `ATTACH` another cell's database without first obtaining its ownership lease and passing epoch validation.

---

## Core Mechanism 2: Ownership Leases and Epoch Tracking

The **ownership lease** system in [`crates/celld/ownership_store.rs`](https://github.com/denoland/celld/blob/main/crates/celld/ownership_store.rs) controls which node in the celld cluster may access a cell. Key properties include:

- **Lease storage**: Leases are persisted to the fleet bucket (typically S3-compatible object storage)
- **Epoch counter**: Each lease carries a monotonically increasing integer called the **epoch**
- **Lease acquisition**: Nodes compete for leases through a coordination protocol; only the winner may proceed

The epoch serves as a **fence token**—a distributed systems pattern that detects stale participants. When a node loses its lease (through expiration, eviction, or graceful release), the epoch increments. Any subsequent operation by the previous holder fails validation.

---

## Core Mechanism 3: Fencing with Epoch Validation

The **fencing mechanism**, detailed in [`docs/fencing.md`](https://github.com/denoland/celld/blob/main/docs/fencing.md), is the runtime enforcement layer. Before any write operation to a cell's SQLite database, celld performs:

```rust
// Simplified logic from ownership_store.rs
async fn validate_fence(&self, cell_id: &str, expected_epoch: u64) -> Result<(), FenceError> {
    let stored_epoch = self.db.get_epoch(cell_id).await?;
    if stored_epoch != expected_epoch {
        return Err(FenceError::EpochMismatch {
            expected: expected_epoch,
            found: stored_epoch,
        });
    }
    Ok(())
}

```

**Fence failure scenarios:**

- A node with a stale lease attempts a write → epoch mismatch → operation aborted
- A partitioned node rejoins after lease expiration → its lease is invalid → rejected
- A malicious node fabricates a lease → HMAC verification fails → rejected (see peer protocol below)

The fencing check occurs at the SQLite layer, ensuring the database file itself records the authoritative epoch.

---

## Core Mechanism 4: Authenticated Peer Protocol

Celld nodes communicate through a **peer protocol** implemented in [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs). Every peer request includes:

| Component | Security Function |
|-----------|-------------------|
| **HMAC** | Request authentication using a shared cluster secret |
| **Body signature** | Integrity verification of the message payload |
| **Clock limit** | Prevention of replay attacks via time windows |
| **Replay protection** | Nonce or sequence tracking to reject duplicate requests |

```rust
// From protocol.rs — peer request structure
pub struct PeerRequest {
    cell_id: String,
    payload: Vec<u8>,
    hmac: [u8; 32],
    signature: [u8; 64],
    timestamp: u64,
    nonce: [u8; 16],
}

```

The receiving node validates the HMAC against the shared secret stored in the fleet bucket. Without this secret, a compromised node cannot forge valid peer requests, even if it possesses an old lease.

---

## Core Mechanism 5: Internal Operator API Boundaries

The **operator API** enforces cell scope validation through network-layer separation:

- **Public listener**: Exposes only health and metadata endpoints; rejects cell-specific operations
- **Internal listener**: Bound to `127.0.0.1` or protected interfaces; requires valid lease for cell access

This design, documented in [`docs/security.md`](https://github.com/denoland/celld/blob/main/docs/security.md), prevents external actors from directly invoking cell operations. Even with network access to the celld node, attackers cannot reach cell-scoped endpoints without bypassing firewall rules.

### Example: Cell Resolution via Internal API

```bash

# Succeeds only if node holds valid lease for my-cell

curl http://127.0.0.1:12345/cell/my-cell

```

### Example: Forced Eviction (Administrative)

```bash

# Removes ownership lease, incrementing epoch and invalidating all pending operations

curl -X POST http://127.0.0.1:12345/evict/my-cell

```

The evict endpoint demonstrates administrative override of cell scope—intentionally restricted to the internal listener.

---

## Security Model Integration: How the Layers Interact

The complete **cell scope validation** flow for a write operation:

1. **Lease check**: Verify local ownership lease exists and is unexpired
2. **Peer authentication** (if request proxied from another node): Validate HMAC and signature
3. **Fence check**: Compare lease epoch against database-stored epoch
4. **Write execution**: Open SQLite database, apply transaction, increment epoch
5. **Lease renewal**: Extend lease in fleet bucket with new epoch

Any failure in steps 1–3 aborts the operation before database contact. Step 4's epoch increment ensures subsequent writes require the new epoch value.

---

## Source Code References

| File | Role in Cell Scope Validation |
|------|------------------------------|
| [`crates/celld/ownership_store.rs`](https://github.com/denoland/celld/blob/main/crates/celld/ownership_store.rs) | Lease storage, epoch management, fence validation |
| [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs) | Peer request HMAC, signatures, replay protection |
| [`docs/security.md`](https://github.com/denoland/celld/blob/main/docs/security.md) | Listener separation, forwarded headers, internal API exposure |
| [`docs/fencing.md`](https://github.com/denoland/celld/blob/main/docs/fencing.md) | Epoch-based fencing specification and failure modes |

---

## Summary

Celld's **cell scope validation security model** provides defense in depth through:

- **Physical isolation** of cell state in dedicated SQLite databases
- **Lease-based ownership** with monotonic epoch counters
- **Runtime fencing** that rejects stale or unauthorized operations
- **Cryptographic peer authentication** using HMAC and body signatures
- **Network-layer access control** separating public and internal APIs

These mechanisms ensure that a cell's scope—its data and execution context—is strictly bound to the legitimate owner node at all times.

---

## Frequently Asked Questions

### How does celld prevent a stale node from writing to a cell after losing its lease?

Celld implements **epoch-based fencing** in [`crates/celld/ownership_store.rs`](https://github.com/denoland/celld/blob/main/crates/celld/ownership_store.rs). Each write validates the lease epoch against the epoch stored in the cell's SQLite database. A stale node holds an outdated epoch; the mismatch causes immediate operation abort before any data modification occurs.

### What happens if an attacker gains access to the internal operator API?

The internal listener is typically bound to `127.0.0.1` or protected by firewall rules as documented in [`docs/security.md`](https://github.com/denoland/celld/blob/main/docs/security.md). Even with network access, every cell-specific endpoint requires a valid ownership lease. Without holding the current epoch-lease from the fleet bucket, requests return 404 or 403 errors.

### Can a compromised celld node forge peer requests to access other cells?

No. The peer protocol in [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs) requires an HMAC computed with a shared cluster secret stored in the fleet bucket. A compromised node without this secret cannot generate valid request authentication codes. Additionally, lease holders must still pass epoch fencing at the target node.

### Where is the authoritative cell state stored if nodes can lose leases?

Each cell's **authoritative state** resides in its dedicated SQLite database file on durable storage. The fleet bucket stores only lightweight **lease metadata** (node ID, epoch, expiration). When a new node acquires the lease, it opens the same database file and validates epoch continuity through fencing.