Skip to content

Language Reference Overview

USL is a layered, policy-driven specification language for building secure, correct applications.

Language Structure

USL specifications consist of five layers:

graph TD
    A[Domain Layer] --> B[Policy Layer]
    B --> C[Behavior Layer]
    C --> D[Service Layer]
    D --> E[Escape Layer]

    style A fill:#e3f2fd
    style B fill:#fff3e0
    style C fill:#f3e5f5
    style D fill:#e8f5e9
    style E fill:#fce4ec

Domain Layer

Define entities, value objects, and business rules:

domain MyApp {
  entity User {
    id: UserId @primary
    email: Email @unique
    name: String

    invariant valid_name {
      len(this.name) >= 2
    }
  }

  value Email {
    address: String

    invariant valid_format {
      matches(this.address, EMAIL_REGEX)
    }
  }
}

Key Concepts: - Entities (mutable, with identity) - Value objects (immutable, validated) - Invariants (business rules) - Relationships (foreign keys)

Learn more →

Policy Layer

Define authorization rules:

policy UserPolicy {
  actor user: User

  rule can_edit(target: User) {
    user.id == target.id || user.role == Role.Admin
  }

  deny rule no_self_delete {
    user.id == target.id
  }
}

Key Concepts: - Actor (who is acting) - Rules (authorization logic) - Allow/deny precedence - Policy composition

Learn more →

Behavior Layer

Model state machines and workflows:

behavior UserLifecycle for User {
  initial state Pending

  state Pending {
    on verify -> Active
      requires hasValidEmail(this)
      effects {
        this.verified = true
        this.verifiedAt = now()
      }
  }

  state Active {
    on suspend -> Suspended
  }

  state Suspended {
    on reactivate -> Active
  }
}

Key Concepts: - States and transitions - Guards (preconditions) - Effects (state changes) - Events

Learn more →

Service Layer

Define external APIs:

service UserService {
  action createUser(email: Email, name: String) -> User
    enforces UserPolicy.can_create
    effects { Write(User) }
    implementation {
      let user = User {
        id: generateId(),
        email: email,
        name: name,
        verified: false
      }
      store(user)
      emit UserCreated(user.id)
      return user
    }
}

Key Concepts: - Actions (API operations) - Policy enforcement - Effect tracking - Implementation logic

Learn more →

Escape Layer

Integrate with external systems:

escape SendEmail {
  capability Email.Send

  function send(to: Email, subject: String, body: String) -> Result[Void, Error]
    nondeterministic: true
    timeout: 5s

  adapter typescript {
    implementation "sendgrid"
  }
}

Key Concepts: - Capabilities (security permissions) - Adapters (platform-specific code) - Nondeterminism marking - Timeout constraints

Learn more →

Type System

USL has a rich type system:

// Primitive types
String, Int, Float, Boolean, Timestamp, Date, Time

// Custom types
UserId, Email, Money

// Collections
List[T], Set[T], Map[K, V]

// Optional
Option[T]  // Some(value) or None

// Result
Result[T, E]  // Ok(value) or Err(error)

// Variants (sum types)
variant Status {
  Active
  Suspended { reason: String }
  Banned { until: Date }
}

Learn more →

Expressions

Literals

42              // Int
3.14            // Float
"hello"         // String
true, false     // Boolean
[1, 2, 3]       // List

Operators

// Arithmetic
+ - * / %

// Comparison
== != < > <= >=

// Logical
&& || !

// String
+ (concatenation)

Control Flow

// If expression
if condition {
  value1
} else {
  value2
}

// Match expression
match value {
  Some(x) => x
  None => default
}

Functions

function calculateTotal(items: List[Item]) -> Money {
  sum(items.map(|item| item.price))
}

Modules

Organize code into modules:

module users {
  entity User { ... }
  service UserService { ... }
}

module posts {
  use users::User

  entity Post {
    authorId: UserId
  }
}

Annotations

entity User {
  id: UserId @primary         // Primary key
  email: Email @unique        // Unique constraint
  password: String @secret    // Sensitive data
  data: Json @indexed         // Database index
}

Comments

// Single-line comment

/*
  Multi-line
  comment
*/

/// Documentation comment
entity User { ... }

Compilation Model

graph LR
    A[USL Source] --> B[Lexer]
    B --> C[Parser]
    C --> D[AST]
    D --> E[Semantic Analysis]
    E --> F[Type Checking]
    F --> G[Verification]
    G --> H[IR]
    H --> I[Code Generation]
    I --> J[Target Code]
  1. Lexical Analysis: Tokenize source
  2. Parsing: Build AST
  3. Semantic Analysis: Resolve symbols
  4. Type Checking: Verify types
  5. Verification: Prove properties
  6. IR Generation: Intermediate representation
  7. Code Generation: Target platform code

Best Practices

DO ✅

  • Keep domains focused and cohesive
  • Write comprehensive invariants
  • Use value objects for validated concepts
  • Leverage type system for correctness
  • Document complex policies

DON'T ❌

  • Mix layers (domain logic in service layer)
  • Skip verification
  • Use primitive types for domain concepts
  • Hard-code configuration
  • Ignore compiler warnings

Language Design Principles

  1. Safety: Prevent bugs through types and verification
  2. Security: Authorization is built-in, not bolted-on
  3. Clarity: Express intent clearly
  4. Correctness: Mathematical guarantees
  5. Productivity: Generate boilerplate automatically

Further Reading

Examples

Complete examples available at: - GitHub Examples - Tutorial Series