# Sruja Language Specification

This document provides a complete specification of the Sruja architecture-as-code language for AI code assistants and developers.

## Overview

Sruja is a domain-specific language (DSL) for defining software architecture models. It supports C4 model concepts (systems, containers, components), requirements, ADRs, scenarios, flows, policies, SLOs, and more.

## Language Grammar

### File Structure

Sruja uses a **nested syntax** that follows the C4 model hierarchy:

- **Systems** are defined at the top level
- **Containers** must be nested inside a system
- **Components** must be nested inside a container
- **Persons** can be defined at the top level (external actors)

```sruja
// partial
// Element kinds (required at top of file)
person = kind "Person"
system = kind "System"
container = kind "Container"
component = kind "Component"

// External actors (top level)
User = person "User" {
  description "End user of the system"
}

// System with nested containers
Shop = system "E-commerce Shop" {
  description "Online shopping platform"

  // Containers MUST be nested inside systems
  WebApp = container "Web Application" {
    technology "React"
    description "Customer-facing web app"

    // Components MUST be nested inside containers
    Cart = component "Shopping Cart" {
      description "Shopping cart functionality"
    }
  }

  API = container "API Gateway" {
    technology "Node.js"
    description "API gateway"
  }

  DB = database "Product Database" {
    technology "PostgreSQL"
    description "Product catalog storage"
  }
}

// Relationships between nested elements use dot notation
User -> Shop.WebApp "Browses"
Shop.WebApp -> Shop.API "Calls"
Shop.API -> Shop.DB "Reads/Writes"

// Governance (top level)
R1 = requirement functional "Must handle 10k users"
SecurityPolicy = policy "Encrypt all data" category "security"
```

### Element Kinds

Before using elements like `person`, `system`, `container`, etc., you must declare them as **kinds**. This establishes the vocabulary of element types available in your architecture.

```sruja
// Standard C4 kinds (required at top of file)
person = kind "Person"
system = kind "System"
container = kind "Container"
component = kind "Component"
database = kind "Database"
datastore = kind "Datastore"  // Alias for 'database', but 'database' is the preferred standard
queue = kind "Queue"
```

**Why kinds?** This allows Sruja to:

- Validate that you're using recognized element types
- Enable custom element types for domain-specific modeling
- Provide LSP autocompletion for your declared kinds

#### Custom Kinds

You can define custom element types for your domain:

```sruja
// partial
// Custom kinds for microservices
microservice = kind "Microservice"
eventBus = kind "Event Bus"
gateway = kind "API Gateway"

// Now use them
Catalog = microservice "Catalog Service"
Kafka = eventBus "Kafka Cluster"
```

### Schemas

Schemas allow you to define strict custom metamodels, specifying valid node kinds, edge kinds, and nesting rules for validation.

```sruja
schema "compliance" {
  node_kinds: ["regulation", "policy", "system"]
  edge_kinds: ["mandates", "violates"]
  nesting {
    regulation -> policy
    system -> policy
  }
}
```

### Imports

Import kinds and tags from the standard library or other Sruja files.

#### Standard Library Import

```sruja
// Import all from stdlib
import { * } from 'sruja.ai/stdlib'

// Now you can use person, system, container, etc. without defining them
User = person "User"
Shop = system "Shop"
```

#### Named Imports

```sruja
// Import specific kinds only
import { person, system, container } from 'sruja.ai/stdlib'

User = person "User"
Shop = system "Shop"
```

#### Relative Imports

```sruja
// Import from a local file
import { * } from './shared-kinds.sruja'
```

**Note**: When using imports, you don't need to redeclare the imported kinds.

### Elements

#### Persons

```sruja
User = person "User" {
    description "End user of the system"
}
```

#### Systems

```sruja
MySystem = system "My System" {
    description "Optional description"
    metadata {
        key "value"
        tags ["tag1", "tag2"]
    }
    slo {
        availability {
            target "99.9%"
            window "30d"
            current "99.95%"
        }
    }
}
```

#### Containers

```sruja
// partial
MyContainer = container "My Container" {
    technology "Technology stack"
    description "Optional description"
    version "1.0.0"
    tags ["api", "backend"]
    scale {
        min 3
        max 10
        metric "cpu > 80%"
    }
    slo {
        latency {
            p95 "200ms"
            p99 "500ms"
        }
    }
}
```

#### Components

```sruja
// partial
MyComponent = component "My Component" {
    technology "Technology"
    description "Optional description"
    scale {
        min 1
        max 5
    }
}
```

#### Data Stores

```sruja
// partial
MyDB = database "My Database" {
    technology "PostgreSQL"
    description "Optional description"
}
```

#### Queues

```sruja
// partial
MyQueue = queue "My Queue" {
    technology "RabbitMQ"
    description "Optional description"
}
```

### Architecture Index Fields

Sruja can serve as an **architecture index** — linking architecture elements to external resources like OpenAPI specs, Kubernetes manifests, documentation, and more. This enables AI agents to discover and navigate complex software ecosystems.

All element types (person, system, container, component, database, queue) support these optional fields in their body block:

| Field | Type | Description |
|-------|------|-------------|
| `canonical_id` | string | Unique, stable identifier for cross-system reference (e.g., `svc.payments`, `db.primary`) |
| `aliases` | string[] | Alternative names used in code, configs, or documentation |
| `owner` | string | Team or individual responsible for this element |
| `domain` | string | Business domain (e.g., `commerce`, `auth`, `platform`) |
| `criticality` | enum | Importance level: `low`, `medium`, `high`, `critical` |
| `sources` | block | Links to external resources (specs, configs, docs) |

#### Source Types

| Type | Description | Example |
|------|-------------|---------|
| `openapi` | OpenAPI/Swagger specification | `./specs/api.yaml` |
| `asyncapi` | AsyncAPI specification | `./specs/events.yaml` |
| `kubernetes` | Kubernetes manifests directory | `./k8s/payments/` |
| `terraform` | Terraform/IaC configuration | `./infra/database/` |
| `docs` | Documentation file | `./docs/services/payments.md` |
| `readme` | README or guide | `./services/payments/README.md` |
| `url` | External URL | `https://stripe.com/docs/api` |

```sruja
// partial
Payments = container "Payment Service" {
    technology "Node.js"
    description "Handles payment processing with Stripe integration"

    // Architecture index fields
    canonical_id "svc.payments"
    aliases ["payments-api", "payments-service", "PAYMENTS_SVC"]
    owner "team-payments"
    domain "commerce"
    criticality "high"

    sources {
        openapi "./specs/payments.yaml"
        kubernetes "./k8s/payments/"
        readme "./services/payments/README.md"
        docs "./docs/services/payments.md"
    }
}
```

```sruja
// partial
StripeAPI = system "Stripe Payment API" {
    description "Third-party payment processing"
    canonical_id "ext.stripe"
    owner "team-payments"

    sources {
        docs url "https://stripe.com/docs/api"
    }
}
```

### Relationships

```sruja
// partial
// Basic relationship
From -> To "Label"

// Nested element references use dot notation
System.Container -> System.Container.Component "calls"

// With tags
From -> To "Label" [tag1, tag2]
```

### Requirements

```sruja
// Minimal
R1 = requirement functional "Description"
R2 = requirement nonfunctional "Description"
R3 = requirement constraint "Description"
R4 = requirement performance "Description"
R5 = requirement security "Description"

// Enriched with PRD-aligned fields
R6 = requirement functional "User can checkout" {
    description "Detailed description"
    priority "must"                    // MoSCoW: must | should | could | wont
    status "accepted"                  // proposed | accepted | deprecated | superseded
    user_journey "Narrative of the user's path through the feature"
    acceptance_criteria {
        given "Precondition"
        when "User action"
        then "Expected outcome"
    }
    scenario CheckoutFlow              // Link to scenario element
    adr ADR001                         // Link to ADR element
    affects System.Container.Component // Link to architecture elements
    source "prd://checkout-prd"        // Cross-repo PRD reference
    tags ["checkout", "critical"]
}
```

Requirements support MoSCoW priority, acceptance criteria (Given-When-Then), and traceability links to scenarios, ADRs, and architecture elements. The `source` field enables cross-repo PRD linking — multiple repos can reference the same central PRD.

### ADRs (Architectural Decision Records)

```sruja
ADR001 = adr "Title" {
    status "accepted"
    context "What situation led to this decision"
    decision "What was decided"
    consequences "Trade-offs, gains, and losses"
}
```

### Scenarios and Flows

#### Scenarios

```sruja
// partial
MyScenario = scenario "Scenario Title" {
    step User -> System.WebApp "Credentials"
    step System.WebApp -> System.DB "Verify"
}

// 'story' is an alias for 'scenario'
CheckoutStory = story "User Checkout Flow" {
    step User -> ECommerce.CartPage "adds item to cart"
}
```

**Note**: The `step` keyword is recommended for clarity, but optional. Both syntaxes work:

- With `step`: `step User -> System.WebApp "action"`
- Without `step`: `User -> System.WebApp "action"` (inside scenario block)

#### Flows (DFD-style data flows)

```sruja
// partial
OrderProcess = flow "Order Processing" {
    step Customer -> Shop.WebApp "Order Details"
    step Shop.WebApp -> Shop.Database "Save Order"
    step Shop.Database -> Shop.WebApp "Confirmation"
}
```

**Note**: Flows use the same syntax as scenarios. The `step` keyword is recommended for clarity.

### Metadata

```sruja
metadata {
    key "value"
    anotherKey "another value"
    tags ["tag1", "tag2"]
}
```

### Overview Block

```sruja
overview {
    summary "High-level summary of the architecture"
    audience "Target audience for this architecture"
    scope "What is covered in this architecture"
    goals ["Goal 1", "Goal 2"]
    nonGoals ["What is explicitly out of scope"]
    risks ["Risk 1", "Risk 2"]
}
```

### SLO (Service Level Objectives)

```sruja
// partial
slo {
    availability {
        target "99.9%"
        window "30 days"
        current "99.95%"
    }
    latency {
        p95 "200ms"
        p99 "500ms"
        window "7 days"
        current {
            p95 "180ms"
            p99 "420ms"
        }
    }
    errorRate {
        target "0.1%"
        window "7 days"
        current "0.08%"
    }
    throughput {
        target "10000 req/s"
        window "peak hour"
        current "8500 req/s"
    }
}
```

SLO blocks can be defined at:

- Architecture level (top-level)
- System level
- Container level

### Scale Block

```sruja
// partial
scale {
    min 3
    max 10
    metric "cpu > 80%"
}
```

Scale blocks can be defined at:

- Container level
- Component level

### Deployment

```sruja
deployment Prod "Production" {
    node AWS "AWS" {
        node USEast1 "US-East-1" {
            infrastructure LB "Load Balancer"
            containerInstance Shop.API
        }
    }
}
```

### API Contracts

API Contracts allow you to model precise request-response specifications, input/output structures, error conditions, and constraints.

```sruja
// partial
contract "GetUserContract" {
  description "Fetch user details by ID"
  input {
    userId "string"
  }
  output {
    email "string"
    isActive "boolean"
  }
  error {
    "404" "User not found"
    "401" "Unauthorized access"
  }
  constraint "Response time must be < 50ms"
}
```

### State Machines

State Machines let you model component lifecycles, states, and transition behaviors based on events, actions, and guards.

```sruja
// partial
state_machine "OrderLifecycle" {
  description "Order lifecycle state machine"
  initial "Created"
  terminal ["Completed", "Cancelled"]

  "Created" -> "Processing" on "payment_received" {
    guard "payment.amount > 0"
    action "send_receipt()"
    description "Transition order to processing after successful payment"
  }
  "Processing" -> "Completed" on "shipment_delivered"
}
```

### Systems Thinking Loops

Sruja supports causal loop diagrams and feedback loops to model complex system dynamics, reinforcing/balancing feedback loops, polarities, and delays.

#### Feedback Loops

```sruja
// partial
UserLoop = feedback "User Growth" {
  loop_type "reinforcing"
  loop_id "R1"
  description "Growth in users leads to more word-of-mouth referrals"
  
  UserBase -> Referrals "increases"
  Referrals -> UserBase "leads to"
}
```

#### Causal Loops

```sruja
// partial
InventoryLoop = causal_loop "Supply & Demand" {
  loop_type "balancing"
  loop_id "B1"
  
  variable Demand "Customer Demand"
  variable Price "Product Price"
  
  Demand -> Price {
    effect "increases"
    polarity "+"
  }
  Price -> Demand {
    effect "decreases"
    polarity "-"
    delay "2 days"
  }
}
```

### Governance

#### Policies

```sruja
// partial
// Two equivalent forms:
SecurityPolicy = policy "Enforce TLS 1.3" {
    category "security"
    enforcement "required"
}

policy SecurityPolicy "Enforce TLS 1.3" category "security" enforcement "required"

// Or with body block (and optional structured rules)
policy DataRetentionPolicy "Retain data for 7 years" {
    category "compliance"
    enforcement "required"
    description "Detailed policy description"
}

policy NoExtToDb "External APIs must not call databases" {
    category "security"
    enforcement "required"
    rule deny edge from { kind "external_api" } to { kind "database" }
}
```

#### Constraints

```sruja
constraints {
    "Constraint description"
    "Another constraint"
}
```

#### Conventions

```sruja
conventions {
    "Convention description"
    "Another convention"
}
```

### Incidents

Incidents allow you to track production outages, capture post-mortems, and link them directly to affected architecture components.

```sruja
// partial
incident INC001 "API Gateway Outage" {
  date "2026-05-01"
  severity "high"
  affected [Shop.API]
  cause "Memory leak under high load"
  resolution "Restarted cluster and updated memory limits"
  lesson "Implement auto-scaling based on memory thresholds"
}
```

### Views (Optional)

Views are **optional** — if not specified, standard C4 views are automatically generated.

```sruja
// partial
view index {
    title "System Context"
    include *
}

view container_view of Shop {
    title "Shop Containers"
    include Shop.*
    exclude Shop.WebApp
    autolayout lr
}

styles {
    element "Database" {
        shape "cylinder"
        color "#ff0000"
    }
}
```

### View Types

- `index` - System context view (C4 L1)
- `container` - Container view (C4 L2)
- `component` - Component view (C4 L3)
- `deployment` - Deployment view

### View Expressions

- `include *` - Include all elements in scope
- `include Element1 Element2` - Include specific elements
- `exclude Element1` - Exclude specific elements
- `autolayout "lr"|"tb"|"auto"` - Layout direction hint

## Implied Relationships

Relationships are automatically inferred when child relationships exist:

```sruja
// partial
User -> API.WebApp "Uses"
// Automatically infers: User -> API
```

This reduces boilerplate while maintaining clarity.

## Complete Example

```sruja
// partial
// Element Kinds (required)
person = kind "Person"
system = kind "System"
container = kind "Container"
component = kind "Component"
datastore = kind "Datastore"  // Alias for 'database'

// Overview
overview {
    summary "E-commerce platform architecture"
    audience "Development team"
    scope "Core shopping and payment functionality"
}

// Elements
Customer = person "Customer"
Admin = person "Administrator"

Shop = system "E-commerce Shop" {
    description "High-performance e-commerce platform"

    WebApp = container "Web Application" {
        technology "React"
        Cart = component "Shopping Cart"
        Checkout = component "Checkout Service"
    }

    API = container "API Gateway" {
        technology "Node.js"
        scale {
            min 3
            max 10
        }
        slo {
            latency {
                p95 "200ms"
                p99 "500ms"
            }
        }
    }

    DB = database "PostgreSQL Database" {
        technology "PostgreSQL 14"
    }
}

// Relationships
Customer -> Shop.WebApp "Browses"
Shop.WebApp -> Shop.API "Calls"
Shop.API -> Shop.DB "Reads/Writes"

// Requirements
R1 = requirement functional "Must support 10k concurrent users"
R2 = requirement constraint "Must use PostgreSQL"

// ADRs
ADR001 = adr "Use microservices architecture" {
    status "accepted"
    context "Need to scale different parts independently"
    decision "Adopt microservices architecture"
    consequences "Gain: Independent scaling. Trade-off: Increased complexity"
}

// Policies
SecurityPolicy = policy "Enforce TLS 1.3" {
    category "security"
    enforcement "required"
}

// Constraints and Conventions
constraints {
    "All APIs must use HTTPS"
    "Database must be encrypted at rest"
}

conventions {
    "Use RESTful API design"
    "Follow semantic versioning"
}

// Scenarios
PurchaseScenario = scenario "User purchases item" {
    step Customer -> Shop.WebApp "Adds item to cart"
    step Shop.WebApp -> Shop.API "Submits order"
    step Shop.API -> Shop.DB "Saves order"
}

// Views (optional - auto-generated if omitted)
view index {
    title "System Context"
    include *
}

view container_view of Shop {
    title "Shop Containers"
    include Shop.*
}
```

## Key Rules

1. **Nested Syntax**: Containers and components must be nested inside their parent element (system and container respectively). Only persons, systems, and governance items (requirements, ADRs, policies) can be at top level.
2. **IDs**: Must be unique within their scope
3. **References**: Use dot notation (e.g., `System.Container`, `System.Container.Component`)
4. **Relations**: Can be defined anywhere (implied relationships are automatically inferred)
5. **Metadata**: Freeform key-value pairs
6. **Descriptions**: Optional string values
7. **Views**: Optional — C4 views are automatically generated if not specified
8. **SLOs**: Can be defined at architecture, system, or container level
9. **Scale**: Can be defined at container or component level

## Common Patterns

### C4 Model Levels

- **Level 1 (System Context)**: Systems and persons
- **Level 2 (Container)**: Containers within systems
- **Level 3 (Component)**: Components within containers

## Resources

- [Syntax reference](syntax.md) – Short reference in this book
- [Examples](../examples/index.md) – Example architectures in this book
- [Sruja repo examples](https://github.com/sruja-ai/sruja/tree/main/examples) – More examples in the repository
