Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

System Internals Guide

This guide covers deep system patterns for contributors working on Aura core. Use it when you need to understand guard chain internals, service layer patterns, core types, and reactive scheduling.

1. Guard Chain Internals

The guard chain coordinates authorization, flow budgets, and journal effects in strict sequence. See Authorization for the full specification.

Three-Phase Pattern

Guards are pure: evaluation runs synchronously over a prepared GuardSnapshot and yields EffectCommand items that an async interpreter executes.

#![allow(unused)]
fn main() {
// Phase 1: Authorization via Biscuit + policy (async, cached)
let token = effects.verify_biscuit(&request.token).await?;
let capabilities = token.capabilities();

// Phase 2: Prepare snapshot and evaluate guards (sync)
let snapshot = GuardSnapshot {
    capabilities,
    flow_budget: current_budget,
    leakage_budget: current_leakage,
    ..Default::default()
};

let commands = guard_chain.evaluate(&snapshot, &request)?;

// Phase 3: Execute commands (async)
for command in commands {
    match command {
        EffectCommand::ChargeBudget { cost } => {
            budget_handler.charge(cost).await?;
        }
        EffectCommand::RecordLeakage { budget } => {
            leakage_handler.record(budget).await?;
        }
        EffectCommand::CommitJournal { facts } => {
            journal_handler.commit(facts).await?;
        }
        EffectCommand::SendTransport { message } => {
            transport_handler.send(message).await?;
        }
    }
}
}

No transport observable occurs until the interpreter executes commands in order.

Guard Chain Sequence

The guards execute in this order:

  1. CapabilityGuard: Validates Biscuit token capabilities
  2. FlowBudgetGuard: Checks and charges flow budget
  3. LeakageTracker: Records privacy leakage
  4. JournalCoupler: Commits facts to journal
  5. TransportEffects: Sends messages

Security Patterns

Privacy Budget Enforcement:

#![allow(unused)]
fn main() {
// Secure default: denies undefined budgets
let tracker = LeakageTracker::new();

// Backward compatibility: allows undefined budgets
let tracker = LeakageTracker::legacy_permissive();

// Configurable default
let tracker = LeakageTracker::with_undefined_policy(DefaultBudget(1000));
}

2. Service Layer Patterns

Domain crates define stateless handlers that take effect references per-call. The agent layer wraps these with services that manage RwLock access.

Domain Handler (Layer 2-5)

#![allow(unused)]
fn main() {
// In domain crate (e.g., aura-chat/src/service.rs)
pub struct ChatFactService;

impl ChatFactService {
    pub fn new() -> Self { Self }

    pub async fn send_message<E>(
        &self,
        effects: &E,
        channel_id: ChannelId,
        content: String,
    ) -> Result<MessageId>
    where
        E: StorageEffects + RandomEffects + PhysicalTimeEffects
    {
        let message_id = effects.random_uuid().await;
        let timestamp = effects.physical_time().await?;
        // ... domain logic using effects
        Ok(message_id)
    }
}
}

Agent Service Wrapper (Layer 6)

#![allow(unused)]
fn main() {
// In aura-agent/src/handlers/chat_service.rs
pub struct ChatService {
    handler: ChatFactService,
    effects: Arc<RwLock<AuraEffectSystem>>,
}

impl ChatService {
    pub fn new(effects: Arc<RwLock<AuraEffectSystem>>) -> Self {
        Self { handler: ChatFactService::new(), effects }
    }

    pub async fn send_message(
        &self,
        channel_id: ChannelId,
        content: String,
    ) -> AgentResult<MessageId> {
        let effects = self.effects.read().await;
        self.handler.send_message(&*effects, channel_id, content)
            .await
            .map_err(Into::into)
    }
}
}

Agent API Exposure

#![allow(unused)]
fn main() {
// In aura-agent/src/core/api.rs
impl AuraAgent {
    pub fn chat_service(&self) -> ChatService {
        ChatService::new(self.runtime.effects())
    }
}
}

Benefits:

  • Domain crate stays pure (no tokio/RwLock)
  • Testable with mock effects
  • Consistent pattern across crates

3. Type Reference

ProtocolType

Canonical definition in aura-core. All crates re-export this definition.

#![allow(unused)]
fn main() {
pub enum ProtocolType {
    Dkd,        // Deterministic Key Derivation
    Counter,    // Counter reservation protocol
    Resharing,  // Key resharing for threshold updates
    Locking,    // Resource locking protocol
    Recovery,   // Account recovery protocol
    Compaction, // Ledger compaction protocol
}
}

SessionStatus

Lifecycle order:

  1. Initializing - Session initializing
  2. Active - Session executing
  3. Waiting - Waiting for participant responses
  4. Completed - Completed successfully
  5. Failed - Failed with error
  6. Expired - Expired due to timeout
  7. TimedOut - Timed out during execution
  8. Cancelled - Was cancelled

TimeStamp Domains

TimeStamp in aura-core is the only time type for new facts and public APIs.

DomainEffect TraitPrimary Use
PhysicalClockPhysicalTimeEffectsWall time: cooldowns, receipts, liveness
LogicalClockLogicalClockEffectsCausal ordering: CRDT merge, happens-before
OrderClockOrderClockEffectsDeterministic ordering without timing leakage
RangePhysicalTimeEffects + policyValidity windows with bounded skew
ProvenancedTimeTimeComparisonAttested timestamps for consensus

Guidelines:

  • Use effect traits for all time reads (no SystemTime::now())
  • Use the narrowest domain that satisfies the requirement
  • Compare mixed domains with TimeStamp::compare(policy)
  • Persist TimeStamp values directly in facts

Anti-patterns:

  • Mixing clock domains in one sort path without explicit policy
  • Using PhysicalClock for privacy-sensitive ordering
  • Using UUID or insertion order as time proxy
  • Exposing SystemTime or chrono types in interfaces

Capability System Layering

The capability system uses multiple layers:

  • Canonical types in aura-core: Lightweight references
  • Authorization layer (aura-authorization): Policy enforcement
  • Storage layer (aura-store): Capability-based access control

Clear conversion paths enable inter-layer communication.

4. Reactive Scheduling

The ReactiveScheduler in aura-agent/src/reactive/ processes journal facts and emits application signals.

Signal System Overview

#![allow(unused)]
fn main() {
// Application signals
pub const CHAT_SIGNAL: &str = "chat";
pub const CONTACTS_SIGNAL: &str = "contacts";
pub const CHANNELS_SIGNAL: &str = "channels";
pub const RECOVERY_SIGNAL: &str = "recovery";
}

The scheduler:

  1. Subscribes to journal fact streams
  2. Reduces facts to view state
  3. Emits signals when state changes
  4. TUI/CLI components subscribe to signals

TUI Reactive State

The TUI uses futures-signals for fine-grained reactive state management.

Note: The reactive architecture pattern below represents the target design for TUI state management. Implementation status varies by view.

Signal Types

#![allow(unused)]
fn main() {
use futures_signals::signal::Mutable;
use futures_signals::signal_vec::MutableVec;

// Single reactive value
let count = Mutable::new(0);
count.set(5);
let value = count.get_cloned();

// Reactive collection
let items = MutableVec::new();
items.lock_mut().push_cloned("item1");
}

View Pattern

#![allow(unused)]
fn main() {
pub struct ChatView {
    channels: MutableVec<Channel>,
    messages: MutableVec<Message>,
    selected_channel: Mutable<Option<String>>,
}

impl ChatView {
    // Synchronous delta application
    pub fn apply_delta(&self, delta: ChatDelta) {
        match delta {
            ChatDelta::ChannelAdded { channel } => {
                self.channels.lock_mut().push_cloned(channel);
                // Signals automatically notify subscribers
            }
            ChatDelta::MessageReceived { channel_id, message } => {
                if self.selected_channel.get_cloned() == Some(channel_id) {
                    self.messages.lock_mut().push_cloned(message);
                }
            }
        }
    }
}
}

Best Practices

  • Delta application should be synchronous (not async)
  • Use .get_cloned() for reading, .set() for mutations
  • Never hold lock guards across await points
  • Use derived signals for computed values

5. Policy Compliance

Application code must follow policies defined in Project Structure.

Impure Function Usage

All time, randomness, filesystem, and network operations must flow through effect traits.

Forbidden:

#![allow(unused)]
fn main() {
// Direct system calls break simulation and WASM
let now = SystemTime::now();
let random = thread_rng().gen();
let file = File::open("path")?;
}

Required:

#![allow(unused)]
fn main() {
// Use effect traits
let now = effects.physical_time().await?;
let random = effects.random_bytes(32).await?;
let data = effects.read_storage("key").await?;
}

Serialization

  • Wire protocols and facts: DAG-CBOR via aura_core::util::serialization
  • User-facing configs: JSON allowed
  • Debug output: JSON allowed

Architectural Validation

Run just check-arch before submitting changes. The checker validates:

  • Layer boundaries
  • Effect trait placement
  • Impure function routing
  • Guard chain integrity

6. Architecture Compliance Checklist

  • Layer dependencies flow downward only
  • Effect traits defined in aura-core only
  • Infrastructure effects implemented in aura-effects
  • Application effects in domain crates
  • No direct impure function usage outside effect implementations
  • All async functions propagate EffectContext
  • Production handlers are stateless, test handlers in aura-testkit
  • Guard chain sequence respected