Skip to content

Latest commit

 

History

History
218 lines (165 loc) · 6.7 KB

dialects.md

File metadata and controls

218 lines (165 loc) · 6.7 KB
title Dialect declarations
description Complete reference for Dialect identity, provider envelopes, Concepts, Contexts, and Relations.

A Dialect is one named and versioned interpretation unit. Its Rules add architecture meaning to observed plan or state instances.

Definitions and Rules are top-level siblings of the dialect block. Only provider blocks are nested inside dialect.

Complete layout

dialect "example" {
  version = "0.1.0"

  provider "hashicorp/example" {
    version = ">= 1.0.0, < 2.0.0"
  }
}

concept "application" {
  description = "A deployable application service."
}

context "runtime" {
  description = "The runtime selected for an application."
}

relation "calls" {
  description = "A declared application dependency."
}

A source root may split these blocks across any number of .rf.hcl and .rf.json files.

dialect block

Property Contract
Placement Top level of a Dialect source root
Cardinality Exactly one per source root
Labels Exactly one required Dialect owner
Attributes version
Nested blocks provider only

Parameters

Name Type Required Default Constraints
Label Identifier Yes None Lowercase kebab case, 1-64 bytes; rf forbidden
version Static string Yes None Exact MAJOR.MINOR.PATCH

Canonical unit identity combines label and version, for example example@0.1.0.

A Dialect has no authored dependency list. It may reference its own symbols and rf.* only. Compiler derives RF Vocabulary dependency when used.

provider block

dialect "example" {
  version = "0.1.0"

  provider "hashicorp/example" {
    version = ">= 1.4.0, < 2.0.0"
  }

  provider "registry.example.com/acme/platform" {
    version = "~> 3.2.0"
  }
}
Property Contract
Placement Inside dialect
Cardinality Zero or more; at least one when source root declares any Rule
Labels Exactly one required provider source
Attributes version
Nested blocks None

Parameters

Name Type Required Default Constraints
Label Provider source Yes None namespace/type or host/namespace/type
version Static string Yes None One or more comma-separated clauses

Accepted clause operators are =, !=, >, >=, <, <=, and ~>. Every clause must include an operator and an exact three-component version:

provider-constraint = clause, { ",", clause } ;
clause              = operator, version ;
operator            = "=" | "!=" | ">" | ">=" | "<" | "<=" | "~>" ;

All clauses combine with logical AND against one known exact provider version.

Operator Version test
= 3.2.0 Equal to 3.2.0
!= 3.2.0 Not equal to 3.2.0
> 3.2.0 Greater than 3.2.0
>= 3.2.0 Greater than or equal to 3.2.0
< 3.2.0 Less than 3.2.0
<= 3.2.0 Less than or equal to 3.2.0
~> 3.2.0 Greater than or equal to 3.2.0 and less than 3.3.0

Whitespace around clauses is normalized. Duplicate clauses are removed and remaining clauses are sorted in compiled output. A bare version such as "1.4.0" is invalid.

Two-part provider sources bind the equivalent Terraform and OpenTofu public registry addresses for that namespace and type. Three-part sources require exact host, namespace, and type. Duplicate normalized provider sources produce DUPLICATE_ID.

Provider source binding participates in Rule eligibility; plan/state selection does not compare an observed exact provider version to the declared envelope:

Every Rule in the Dialect uses this shared provider list. Rules do not declare their own provider selector.

  • a fully qualified provider address binds that exact registry host;
  • a public-registry shorthand binds equivalent Terraform and OpenTofu public registry addresses for the same namespace and type;
  • an observed provider without a selected binding produces PROVIDER_UNBOUND and leaves interpretation unsettled;
  • an unavailable provider alias is uncertain, not proof of a different provider.

Semantic definition blocks

concept, top-level context, and top-level relation share one shape:

concept "database" {
  description = "A database service."
}

context "runtime" {
  description = "The runtime selected for a service."
}

relation "reads-from" {
  description = "A declared read dependency."
}
Property Contract
Placement Top level of a Dialect source root
Cardinality Zero or more of each kind
Labels Exactly one required name
Attributes Optional description
Nested blocks None

Parameters

Name Type Required Default Constraints
Label Identifier Yes None Lowercase kebab case, 1-64 bytes; unique within symbol kind
description Static string No Empty Valid UTF-8, at most 1,024 bytes; empty allowed

Meaning

Block Defines Does not define
concept Optional nominal classification Shape, inheritance, properties, or structural coverage
context Named directed placement dimension A fact by itself
relation Named directed relation predicate A fact by itself

Rules emit concrete Contexts, Relations, and Contributions. Concepts classify a representation only when a Rule uses as. A Concept is optional and never inferred from a Rule name or source type.

Descriptions are editorial metadata. They affect exact content identity but are excluded from Dialect semantic digest.

Labeled Rule emissions may introduce a local Context or Relation without a separate top-level definition. Top-level definition remains useful for a description. Concepts always require explicit definition.

Allowed references

A Dialect may resolve:

Reference syntax Scope
concept.name, context.name, relation.name, rule.name Current Dialect
owner.kind.name where owner equals current Dialect Current Dialect
Supported rf.* ID Embedded RF Vocabulary

Foreign Dialect references are invalid. File location never changes scope. See Symbols and references for complete resolution rules.

Rejected syntax

dialect "example" {
  version = "0.1.0"

  provider "example" {
    version = "1.4.0"
  }
}

Provider source has too few slash-separated segments and version clause has no operator. Compiler reports PROVIDER_INVALID.

A requires block, nested concept, unknown attribute, or second dialect block also fails closed.