Skip to content

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

FunctionSignatureReturn
existsexists(query)Boolean or unknown
lengthlength(query)Integer or unknown
contextscontexts(dimension[, target])Opaque query
relationsrelations(predicate[, target])Opaque query
contributionscontributions(contributor)Opaque query

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

Complete example

built-ins/pack.rf.hcl RF
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.

built-ins/main.tf HCL
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

Signature
exists(query) -> Boolean | unknown
ParameterTypeRequiredDefaultMeaning
queryDirect contexts, relations, or contributions callYesNoneArchitecture fact selection for current Policy target

Exactly one argument is required.

Query evidenceResult
One or more confirmed factstrue, even if other evidence is incomplete
Supported, complete, zero factsfalse
Unsupported or incomplete, zero confirmed factsUnknown

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

length

Signature
length(query) -> integer | unknown
ParameterTypeRequiredDefaultMeaning
queryDirect contexts, relations, or contributions callYesNoneArchitecture 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.

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

contexts

Signature
contexts(dimension[, target]) -> query

Returns direct outgoing Context facts from current Policy target representation.

ParameterTypeRequiredDefaultMeaning
dimensionQualified Context referenceYesNoneExact Context dimension
targetQualified Concept or Rule referenceNoNo target filterRestrict emission target contract

Accepted arity is one or two.

RF
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

Signature
relations(predicate[, target]) -> query

Returns direct outgoing Relation facts from current Policy target representation.

ParameterTypeRequiredDefaultMeaning
predicateQualified Relation referenceYesNoneExact Relation predicate
targetQualified Concept or Rule referenceNoNo target filterRestrict emission target contract

Accepted arity is one or two.

RF
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

Signature
contributions(contributor) -> query

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

ParameterTypeRequiredDefaultMeaning
contributorQualified Concept or Rule referenceYesNoneRequired semantic identity of contributing representation

Accepted arity is exactly one.

RF
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:

AcceptedRejected
rf.context.networkcontext.network
aws.relation.subscribes-torelation.subscribes-to
aws.rule.subnetrule.subnet
rf.concept.virtual-networkconcept.virtual-network

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

Support, completeness, and evidence

Each query internally carries:

SignalMeaning
FactsConfirmed matching fact IDs in the selected stage
SupportedLoaded Rule emission contracts can answer query shape
CompleteRelevant architecture and emission evidence has no unresolved gap
EvidenceEmission, 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

invalid built-ins RF
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.