# 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.

### Modeling paths (progressive disclosure)

Start with the smallest model that answers your workflow; add blocks when validation or review needs them.

| Tier | What to model first | Typical follow-on |
|------|---------------------|-------------------|
| **Core** | C4 elements, relationships, nesting, sources, ownership | Lint + drift as trust gates |
| **Progressive** | Requirements, ADRs, scenarios/flows, SLOs | Intent checks, PR review |
| **Advanced** | Contracts, state machines, policies, incidents, deployment, views | Specialized compliance or operational review |

Treat advanced blocks as optional depth—not a checklist you must declare up front.

## Language Grammar

### File Structure

Sruja uses a **flat syntax** — all declarations are top-level, no wrapper blocks required.

```sruja
// Elements
User = person "User"
Shop = system "E-commerce Shop"

// Relationships
User -> Shop "uses"

// Governance
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
// 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

**Element syntax:** `Id = kind "Label" { ... }`. IDs use PascalCase by convention. Indent with 2 spaces.

#### 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%"
    }
  }
}
```

#### Component knowledge (doc)

Elements can link to a **component knowledge** markdown file for deeper context (purpose, risks, improvements, code locations). The path is relative to the workspace root. Generated knowledge is often placed under `.sruja/knowledge/<id>.md`.

```sruja
PaymentService = container "Payment Service" {
  technology "Node.js"
  description "Handles payment processing"
  doc ".sruja/knowledge/PaymentService.md"
}
```

You can use `doc` or `documentation`; both accept a single string path.

#### Containers

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

#### Components

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

### 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.

**Core principle**: Sruja owns structure and linkage, NOT detailed content. It points to source artifacts rather than duplicating them.

#### Available Fields

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

| 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` |

#### Example: Full Architecture Index Element

```sruja
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"
  }
}
```

#### Example: External System with URL

```sruja
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"
  }
}
```

#### Example: Database with Terraform

```sruja
PrimaryDB = database "Primary Database" {
  technology "PostgreSQL"
  description "Main application database"
  canonical_id "db.primary"
  owner "team-platform"
  criticality "critical"

  sources {
    docs "./docs/database/schema.md"
    terraform "./infra/database/"
  }
}
```

#### Design Philosophy

- **Sruja = Index + Graph**: Structure and relationships, not content duplication
- **Markdown = Story**: Narratives, explanations, guides
- **OpenAPI/AsyncAPI = Contract**: Detailed API specifications
- **Kubernetes = Deployment**: Runtime configuration

Sruja ties these together by providing canonical identities and source references, allowing AI agents to discover the right artifact for any query.

#### Data Stores

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

#### Queues

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

### Relationships

```sruja
// 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
R1 = requirement functional "Description"
R2 = requirement nonfunctional "Description"
R3 = requirement constraint "Description"
R4 = requirement performance "Description"
R5 = requirement security "Description"

// With body block
R6 = requirement functional "Description" {
    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 LoginFlow                 // Link to scenario element
    adr ADR001                         // Link to ADR element
    affects "System.Container.Component" // Link to architecture elements (quote dotted IDs)
    source "prd://checkout-prd"        // Cross-repo PRD reference
    tags ["auth", "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
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
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
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
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

Policies define architectural rules and constraints. Policy evaluation is **deterministic and rule-based**: rules in the DSL are evaluated by the rule engine (no ad-hoc phrase parsing for structured rules).

```sruja
// 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 (category, enforcement, description, and optional rules)
policy DataRetentionPolicy "Retain data for 7 years" {
  category "compliance"
  enforcement "required"
  description "Detailed policy description"
}

// Policy with structured rules (evaluated by rule engine)
policy NoExtToDb "External APIs must not call databases" {
  category "security"
  rule deny edge from { kind "external_api" } to { kind "database" }
}
```

**Policy rules (inside the policy block):**

- **`rule deny edge from { ... } to { ... }`** — Denies edges matching a source selector and target selector. Supports `except from { ... } to { ... }`, `message "..."`, and repeatable `suggest "..."`.
- **`rule require tags on { ... } tags ["..."]`** — Requires tags on matched elements. Supports `except { ... }`, `message "..."`, and `suggest "..."`.
- **`rule require metadata on { ... } key "..." [value "..."]`** — Requires a metadata key (and optionally a specific value) on matched elements. Supports `except { ... }`, `message "..."`, and `suggest "..."`.
- **`rule require slo on { ... }`** — Requires an `slo { ... }` block on matched elements. Supports `except { ... }`, `message "..."`, and `suggest "..."`.

**Selector fields (inside `{ ... }`):**

- `kind "..."`, `id "..."`, `tag "..."`, `technology "..."`, `meta "key" "value"`

#### 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
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
User -> API.WebApp "Uses"
// Automatically infers: User -> API
```

This reduces boilerplate while maintaining clarity.

## Complete Example

```sruja
// 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. **Flat Syntax**: All declarations are top-level, no `specification {}`, `model {}`, or `views {}` wrapper blocks
2. **IDs**: Must be unique within their scope
3. **References**: Use dot notation (e.g., `System.Container`)
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

- Official Documentation: https://sruja.ai
- Examples: `book/valid-examples/` (canonical, rendered in the mdBook)
- Grammar: Defined in `crates/sruja-language/` (parser and AST)

---

## Ubiquitous Language

This section defines the shared terminology for Sruja development. All conversations, code, and documentation derive from this domain model.

### Core Concepts

| Term | Definition | Example |
|------|-----------|--------|
| Architecture | The structural design of a software system | C4 model with Systems, Containers, Components |
| Context | Evidence extracted from codebase that informs architecture | File imports, function calls, dependencies |
| Drift | Gap between documented architecture and actual code | Missing components, new dependencies |
| Element | A node in the architecture graph | System, Container, Component, Person, Database, Queue |
| Relationship | Connection between two elements | `SystemA -> SystemB "HTTPS"` |
| Scoping | Determining which files to analyze | `.srujaignore`, `.sruja/` directory |

### Sruja DSL Terms

| Term | Definition | Syntax |
|------|-----------|--------|
| System | Top-level boundary in C4 hierarchy | `MySystem = system "Label" { ... }` |
| Container | Deployable unit within a system | `MyContainer = container "Label" { ... }` |
| Component | Code unit within a container | `MyComponent = component "Label" { ... }` |
| Person | Human actor in the system | `User = person "User" { ... }` |
| Database | Data storage element | `DB = database "DB" { technology "PostgreSQL" }` |
| Queue | Async message processing | `Queue = queue "Queue" { technology "RabbitMQ" }` |

### Validation Rules

| Rule | Description |
|------|-------------|
| Orphan | Element with no relationships (should have at least one) |
| Cycle | Circular dependency between elements |
| Layer Violation | Cross-layer relationship (e.g., component bypassing container) |
| Container Nesting | Components must be inside containers/systems |
| Unique ID | Each element must have a unique ID |

### CLI Commands

| Command | Purpose |
|---------|--------|
| `sruja lint` | Validate .sruja file syntax and rules |
| `sruja scan` | Extract architecture evidence from code |
| `sruja export` | Export architecture diagram |
| `sruja drift` | Detect architecture drift |
| `sruja ai-context` | Build context payload for AI editors |
| `sruja doctor` | Validate health signals |
| `sruja mcp` | Start MCP server |

### Quality Signals

| Term | Definition |
|------|-----------|
| Health Score | 0-100 score for architecture quality |
| Context Score | AI-readiness across 5 dimensions |
| Comprehension Debt | Gap between code and human understanding |
| Code Churn | Lines rewritten/deleted within 2 weeks |

### Technology Stack

| Component | Technology |
|-----------|------------|
| Core | Rust |
| CLI | Rust + clap |
| Language | tree-sitter |
| WASM | wasm-bindgen |
| Extension | TypeScript + VS Code API |
