Skip to content

Latest commit

 

History

History
298 lines (226 loc) · 9.02 KB

built-ins.md

File metadata and controls

298 lines (226 loc) · 9.02 KB
title Built-ins
description Complete RF Policy built-in signatures, required and optional parameters, return types, support, and completeness semantics.

Rootform language 0.1.0 has five built-ins. They are available only in a Policy assert expression.

Function Signature Return
exists exists(query) Boolean or unknown
length length(query) Integer or unknown
contexts contexts(dimension[, target]) Opaque query
relations relations(predicate[, target]) Opaque query
contributions contributions(contributor) Opaque query

Query values are opaque. They can appear only as a direct argument to exists or length.

Complete example

policy_pack "architecture-contracts" {
  version = "0.1.0"
}

policy "subnet-has-network" {
  target {
    concept = rf.concept.subnet
    rules   = [aws.rule.subnet]
  }

  assert = exists(
    contexts(rf.context.network, rf.concept.virtual-network)
  )

  message = "Each subnet must declare its virtual network."
}

policy "subscription-has-topic" {
  target {
    rules = [aws.rule.sns-topic-subscription]
  }

  assert = exists(
    relations(aws.relation.subscribes-to, aws.concept.message-topic)
  )

  message = "Each subscription must declare its topic."
}

policy "bucket-has-versioning-contribution" {
  target {
    concept  = rf.concept.object-storage-container
    dialects = ["aws"]
  }

  assert = length(
    contributions(aws.rule.s3-bucket-versioning)
  ) >= 1

  message = "Each AWS bucket must have a versioning contribution."
}

Executable architecture

This Terraform configuration can produce one target and one matching fact for each Policy above. Export its plan JSON and pair it with the saved plan when running Rootform so reference-based endpoints can be established. OpenTofu users run the same commands with tofu; see Plan inputs. Saved plans and plan JSON can contain secrets in clear text. Keep them out of Git and public artifacts. Rootform reads them locally; it never runs Terraform or OpenTofu and never contacts providers.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "= 6.62.0"
    }
  }
}

resource "aws_vpc" "main" {
  cidr_block = "10.20.0.0/16"
}

resource "aws_subnet" "application" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.20.1.0/24"
}

resource "aws_sns_topic" "events" {}

resource "aws_sns_topic_subscription" "events" {
  topic_arn = aws_sns_topic.events.arn
  protocol  = "https"
  endpoint  = "https://example.com/events"
}

resource "aws_s3_bucket" "assets" {
  bucket = "rootform-docs-assets"
}

resource "aws_s3_bucket_versioning" "assets" {
  bucket = aws_s3_bucket.assets.id

  versioning_configuration {
    status = "Enabled"
  }
}

Save the configuration as built-ins/main.tf, produce its plan JSON and saved plan, then run it with the displayed Policy Pack. The Planned stage has six instances, three resolved facts (one of each kind), and three Policy targets. All three Policies pass with exit 0. If a closure is indeterminate, exists cannot claim absence and length cannot claim a complete count; inspect that closure before treating a failed check as an architectural violation. The plan-input guide gives the export commands.

exists

exists(query) -> Boolean | unknown
Parameter Type Required Default Meaning
query Direct contexts, relations, or contributions call Yes None Architecture fact selection for current Policy target

Exactly one argument is required.

Query evidence Result
One or more confirmed facts true, even if other evidence is incomplete
Supported, complete, zero facts false
Unsupported or incomplete, zero confirmed facts Unknown

exists can prove presence from one confirmed fact. It cannot prove absence without both support and completeness.

length

length(query) -> integer | unknown
Parameter Type Required Default Meaning
query Direct contexts, relations, or contributions call Yes None Architecture fact selection for current Policy target

Exactly one argument is required.

length returns deduplicated fact count only when query is supported and complete. Any relevant uncertainty makes count unknown, even if some facts are confirmed, because exact cardinality is not proved. A numeric comparison can still be decided from the confirmed lower bound when it suffices; see Query truth.

assert = length(contexts(rf.context.network)) == 1

contexts

contexts(dimension[, target]) -> query

Returns direct outgoing Context facts from current Policy target representation.

Parameter Type Required Default Meaning
dimension Qualified Context reference Yes None Exact Context dimension
target Qualified Concept or Rule reference No No target filter Restrict emission target contract

Accepted arity is one or two.

assert = exists(contexts(rf.context.network))
assert = exists(
  contexts(rf.context.network, rf.concept.virtual-network)
)

Without second argument, support exists when applied Rule declares compatible Context emission for dimension. With second argument, emission's to must match exact Concept or Rule reference.

Function does not follow Contexts transitively.

relations

relations(predicate[, target]) -> query

Returns direct outgoing Relation facts from current Policy target representation.

Parameter Type Required Default Meaning
predicate Qualified Relation reference Yes None Exact Relation predicate
target Qualified Concept or Rule reference No No target filter Restrict emission target contract

Accepted arity is one or two.

assert = exists(relations(aws.relation.subscribes-to))
assert = exists(
  relations(aws.relation.subscribes-to, aws.concept.message-topic)
)

Second argument matches emission's authored to contract exactly. AWS subscription Rule emits to = concept.message-topic, so aws.concept.message-topic is supported; replacing it with aws.rule.sns-topic would not describe same query contract even when concrete topic representation carries that Rule.

No inverse, recursive, or transitive relation query exists.

contributions

contributions(contributor) -> query

Returns Contributions arriving at current Policy target representation from a matching contributor.

Parameter Type Required Default Meaning
contributor Qualified Concept or Rule reference Yes None Required semantic identity of contributing representation

Accepted arity is exactly one.

assert = exists(contributions(aws.rule.s3-bucket-versioning))
assert = length(contributions(aws.concept.storage-configuration)) >= 1

Unlike Contexts and Relations, Contributions are queried from receiving target back toward contributors. Query considers Rules whose Contribution emission to matches current target representation and whose own identity satisfies contributor. A compatible contributor Rule can establish query support even when architecture has zero instances of that Rule; facts and support are separate.

Qualified arguments

All semantic arguments are owner-qualified in Policy source:

Accepted Rejected
rf.context.network context.network
aws.relation.subscribes-to relation.subscribes-to
aws.rule.subnet rule.subnet
rf.concept.virtual-network concept.virtual-network

Linker verifies each referenced symbol against the Form before producing compiled Policy Pack.

Support, completeness, and evidence

Each query internally carries:

Signal Meaning
Facts Confirmed matching fact IDs in the selected stage
Supported Loaded Rule emission contracts can answer query shape
Complete Relevant architecture and emission evidence has no unresolved gap
Evidence Emission, omission, resolution, and diagnostic IDs inspected

A known-empty emission can support complete zero result. Missing compatible emission contract means unsupported, not empty. Emission warning can leave confirmed facts while marking result incomplete.

These signals explain why exists and length differ under uncertainty. See Evaluation for truth tables.

Rejected calls

assert = contexts(rf.context.network)
assert = exists()
assert = exists(contexts())
assert = length(relations(aws.relation.subscribes-to, aws.rule.sns-topic, aws.rule.subnet))
assert = contributions(aws.rule.s3-bucket-versioning)
assert = count(contexts(rf.context.network))

Failures include bare query, wrong wrapper arity, wrong query arity, and unknown function. Each produces POLICY_INVALID.