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

The Shape of Agreement

Agreement has structure. You can add conditions, narrow scope, or delegate what you were given. You cannot expand what was agreed to or grant yourself permissions you were never offered.

This asymmetry reflects how consent works. Consent flows downward and outward. It can be refined and passed along but cannot be inflated or reversed without returning to the source.

Digital systems have mostly ignored this structure. Permissions live in databases controlled by administrators, with privileged ability to read, write, and access. Your identity is a row in someone else's table. Lattice theory captures the structure of consent precisely through semilattices. These provide operations that move in only one direction. Some things can only grow. Other things can only shrink.

graph TD
    subgraph "Facts: Join-Semilattice"
        F1[Evidence] --> F2[More Evidence]
        F2 --> F3[Even More Evidence]
        style F1 fill:#e1f5fe
        style F2 fill:#b3e5fc
        style F3 fill:#81d4fa
    end

    subgraph "Capabilities: Meet-Semilattice"
        C1[Full Authority] --> C2[Restricted]
        C2 --> C3[More Restricted]
        style C1 fill:#fff3e0
        style C2 fill:#ffe0b2
        style C3 fill:#ffcc80
    end

    F1 -.->|"⊔ join: can only grow"| F3
    C1 -.->|"⊓ meet: can only shrink"| C3

Two Directions

A semilattice is a set with a binary operation that is associative, commutative, and idempotent. There is a way to combine any two elements that produces a consistent result regardless of order. Combining something with itself changes nothing.

A join-semilattice finds the least upper bound. If you know A and I know B, together we know the combination. Information only accumulates. A meet-semilattice finds the greatest lower bound. If you can do A and I can do B, what we can do together is only their intersection. Authority only restricts.

Aura uses both structures simultaneously. Facts live in a join-semilattice and accumulate over time. Capabilities live in a meet-semilattice where delegation can only give a subset of what you have.

graph LR
    subgraph "Join: Evidence Accumulates"
        A1["Attestation 1"] --> M1["Merged State"]
        A2["Attestation 2"] --> M1
        A3["Attestation 3"] --> M1
    end

    subgraph "Meet: Authority Restricts"
        P1["Policy A"] --> I1["Intersection"]
        P2["Policy B"] --> I1
        I1 --> E1["Effective Capability"]
    end

    M1 -->|"evidence supports"| E1

The Journal as Constitutional Record

Traditional databases store state directly. The history of how you got there is separate and might not exist. This gives enormous power to whoever controls the database.

Aura instead uses a journal, which stores signed, timestamped facts. Current state is computed by reducing facts according to deterministic rules. The journal is the source of truth. State is derived.

Facts form a join-semilattice through set union. If two replicas have different facts, merging produces all facts from both. This is why distributed replicas converge without coordination beyond gossip.

graph TD
    subgraph "Traditional Database"
        DB[(Mutable State)]
        Admin[Administrator] -->|"can modify"| DB
        Log[Audit Log] -.->|"separate, optional"| DB
    end

    subgraph "Aura Journal"
        J1[Fact 1] --> R[Reduction Function]
        J2[Fact 2] --> R
        J3[Fact 3] --> R
        R --> S[Derived State]
    end

    style DB fill:#ffcdd2
    style S fill:#c8e6c9

Authorization as Logic

Most authorization systems check a table. Does user have permission on resource ? The basis for any permission is opaque.

Aura uses Biscuit tokens with embedded Datalog rules. When you delegate, you attenuate the token by adding checks. Each check narrows what is permitted. Checks cannot expand authority because the token is cryptographically sealed.

This is the meet-semilattice in action. Authorization becomes a logical derivation rather than a table lookup. The same Datalog engine powers both authorization and journal queries.

graph TD
    subgraph "Token Attenuation Chain"
        Root["Root Token<br/>full authority"] --> T1["Attenuated<br/>+check: read_only"]
        T1 --> T2["Further Attenuated<br/>+check: expires(tomorrow)"]
        T2 --> T3["Final Token<br/>+check: resource='public/*'"]
    end

    subgraph "Capability Shrinks"
        C1["read, write, delete"] --> C2["read, write"]
        C2 --> C3["read"]
        C3 --> C4["read public/*<br/>until tomorrow"]
    end

    Root -.-> C1
    T1 -.-> C2
    T2 -.-> C3
    T3 -.-> C4

    style Root fill:#fff3e0
    style T3 fill:#ffcc80

Context as Jurisdiction

What you share with your doctor differs from what you share with your employer. Most digital systems collapse these distinctions into a singular identity.

Aura models relationships through contexts. A context is a separate namespace with its own journal and capability frontier. Cross-context transfer requires an explicit protocol that both sides accept. Context identifiers are opaque UUIDs that reveal nothing about participants.

This maps to how sovereignty works. Authority within a context does not extend beyond it. Relations across contexts require protocols both sides accept.

graph TD
    subgraph "Authority A"
        JA[Journal A]
    end

    subgraph "Authority B"
        JB[Journal B]
    end

    subgraph "Context: A↔B Relationship"
        JC[Shared Journal]
        JC --> FA["Facts from A"]
        JC --> FB["Facts from B"]
    end

    JA -.->|"explicit bridge"| JC
    JB -.->|"explicit bridge"| JC

    subgraph "Context: A↔C Relationship"
        JD[Different Journal]
    end

    JA -.-> JD

    JC x--x|"no automatic flow"| JD

    style JC fill:#e8f5e9
    style JD fill:#e3f2fd

The Guard Chain

Every operation that could produce an observable effect passes through a guard chain. Each guard checks one aspect. If any guard fails, the operation produces no effect.

The first guard checks capabilities via Biscuit tokens. The second checks flow budgets. The third couples the operation to the journal before effects occur. Guards evaluate conditions and produce commands. A separate interpreter executes those commands. This allows the same logic in production, simulation, and tests.

flowchart LR
    R[Request] --> CG[CapGuard<br/>check authorization]
    CG -->|pass| FG[FlowGuard<br/>check budget]
    CG -->|fail| X1[Blocked]
    FG -->|pass| JC[JournalCoupler<br/>commit facts]
    FG -->|fail| X2[Blocked]
    JC -->|pass| TE[TransportEffects<br/>send message]
    JC -->|fail| X3[Blocked]
    TE --> Done[Effect Occurs]

    style X1 fill:#ffcdd2
    style X2 fill:#ffcdd2
    style X3 fill:#ffcdd2
    style Done fill:#c8e6c9

Effects as Values

Programs traditionally have side effects that interleave with computation in unpredictable ways. Algebraic effects produce descriptions of effects as values. A separate runtime interprets the descriptions and performs the effects.

When a protocol wants to send a message, it produces a SendEnvelope command. The guard chain evaluates permission. If allowed, an effect interpreter performs the send. This enables simulation where the same protocol code runs against virtual networks with controlled failures. It also enables auditability since effects are logged before execution.

graph TD
    subgraph "Protocol Specification"
        G["Global Choreography"]
        G --> PA["Projection: Alice's View"]
        G --> PB["Projection: Bob's View"]
    end

    subgraph "Effect Commands"
        PA --> EA["Effects as Data"]
        PB --> EB["Effects as Data"]
    end

    subgraph "Interpretation"
        EA --> I1["Production Interpreter"]
        EA --> I2["Simulation Interpreter"]
        EA --> I3["Audit Interpreter"]
        I1 --> R1["Real Network"]
        I2 --> R2["Virtual Network"]
        I3 --> R3["Logged Record"]
    end

    style G fill:#e8eaf6
    style EA fill:#fff3e0
    style EB fill:#fff3e0

Reactive Propagation

User interfaces need to stay synchronized with underlying state. Aura uses functional reactive programming built on lattice foundations. Signals represent time-varying values. Updates only move forward.

The pipeline from facts to display preserves lattice structure. Facts commit through the guard chain. Reduction functions compute deltas. Views apply deltas monotonically. The UI is a projection of the fact lattice. This ensures end-to-end coherence where the UI cannot show state that lacks evidentiary basis.

graph LR
    subgraph "Fact Layer"
        F[Facts] -->|"⊔ join"| J[Journal]
    end

    subgraph "View Layer"
        J --> Red[Reduction]
        Red --> D[Delta]
        D --> V[View State]
    end

    subgraph "UI Layer"
        V --> S[Signal]
        S --> C1[Component]
        S --> C2[Component]
        S --> C3[Component]
    end

    style F fill:#e1f5fe
    style V fill:#e8f5e9
    style S fill:#fff3e0

Recover Identity Through Your Social Graph

Traditional systems use forgot password flows that rely on central authority. Aura has no central authority. Recovery happens through the social graph.

Users designate guardians before losing access. Each guardian receives a capability to attest recovery. When a user initiates recovery, guardians add attestation facts that accumulate in the recovery journal. When evidence crosses a threshold set by the original user, recovery succeeds. Guardian capabilities form a meet-semilattice where each can only attest within delegated scope.

graph TD
    subgraph "Setup Phase"
        U[User] -->|"delegates recovery authority"| G1[Guardian 1]
        U -->|"delegates recovery authority"| G2[Guardian 2]
        U -->|"delegates recovery authority"| G3[Guardian 3]
    end

    subgraph "Recovery Phase"
        R[Recovery Request] --> A1["Attestation 1<br/>(Guardian 1)"]
        R --> A2["Attestation 2<br/>(Guardian 2)"]
        R --> A3["Attestation 3 ❌<br/>(Guardian 3 unavailable)"]
        A1 -->|"⊔"| J["Joined Evidence"]
        A2 -->|"⊔"| J
        J -->|"threshold met: 2 of 3"| S[Recovery Succeeds]
    end

    style S fill:#c8e6c9
    style A3 fill:#ffcdd2

Centralized search requires an index operator who sees everything. Aura permits a different design where search queries are capabilities that propagate with attenuation at each hop.

Outbound propagation uses meet semantics. Each relay narrows scope. Results accumulate via join semantics as responses merge. Budget constraints prevent abuse. The same mechanism that prevents spam prevents surveillance.

graph TD
    subgraph "Query Propagation"
        Q["Query<br/>full scope"] -->|"⊓ attenuate"| N1["Node 1<br/>narrower scope"]
        N1 -->|"⊓ attenuate"| N2["Node 2<br/>narrower still"]
        N1 -->|"⊓ attenuate"| N3["Node 3<br/>narrower still"]
    end

    subgraph "Result Accumulation"
        R2["Results 2"] -->|"⊔ join"| M["Merged Results"]
        R3["Results 3"] -->|"⊔ join"| M
        N2 --> R2
        N3 --> R3
    end

    M --> F["Final Response"]

    style Q fill:#fff3e0
    style F fill:#c8e6c9

Lattice as Constitution

Sovereignty requires structure. Traditional institutions use constitutions to specify how authority is organized and what limits apply.

The semilattice properties are structural constraints built into how Aura operates. Facts will always join. Capabilities will always meet. The guard chain will always enforce. Within this structure, users choose guardians, authorities set context boundaries, and policies determine thresholds. These choices happen within lattice constraints that do not change.

Mathematics as Political Design

Mathematical structures encode assumptions about what is possible. Aura chooses semilattices because they capture the structure of consent. Things that only grow. Things that only shrink. Operations that commute and associate. Idempotence. Convergence.

Building on these foundations means the system respects these properties by construction. Violations are not expressible. This is consent as a mathematical structure that determines what operations are even possible. The lattice ensures basic conditions for self-determination. Authority cannot be manufactured. Evidence cannot be erased. Boundaries cannot be overridden.