| title | Policy Packs |
|---|---|
| description | Complete reference for Policy Pack manifests, Policies, target dimensions, assertions, linking, and messages. |
A Policy Pack is a named, versioned collection of portable Policies. It defines governance, not architecture semantics. It contributes no Concepts, Contexts, Relations, or Rules.
Policy source evaluates facts of a Form. It never reads raw Terraform or OpenTofu values directly.
policy_pack "network-baseline" {
version = "0.1.0"
}
policy "subnet-has-network-context" {
target {
concept = rf.concept.subnet
rules = [aws.rule.subnet]
dialects = ["aws"]
}
assert = exists(
contexts(rf.context.network, rf.concept.virtual-network)
)
message = "Each subnet must declare its virtual network."
}
Canonical Policy ID is
network-baseline.policy.subnet-has-network-context.
| Property | Contract |
|---|---|
| Placement | Top level of a Policy Pack source root |
| Cardinality | Exactly one per source root |
| Labels | Exactly one required Pack name |
| Attributes | version |
| Nested blocks | None |
| Name | Type | Required | Default | Constraints |
|---|---|---|---|---|
| Label | Identifier | Yes | None | Lowercase kebab case, 1-64 bytes |
version |
Static string | Yes | None | Exact MAJOR.MINOR.PATCH |
A Policy Pack may contain zero Policies. Source files and directories do not create sub-packs or namespaces.
| Property | Contract |
|---|---|
| Placement | Top level of a Policy Pack source root |
| Cardinality | Zero or more |
| Labels | Exactly one required Policy name |
| Attributes | assert, message |
| Nested blocks | Exactly one target |
| Name | Type | Required | Default | Constraints |
|---|---|---|---|---|
| Label | Identifier | Yes | None | Lowercase kebab case, 1-64 bytes; unique in Pack |
assert |
Policy assertion | Yes | None | Must statically produce Boolean |
message |
Static string | Yes | None | Nonempty valid UTF-8, at most 1,024 bytes |
target |
Block | Yes | None | Exactly one, unlabeled |
Message is attached to each confirmed violation. It is not a Policy assertion or runtime template and cannot interpolate target data. Native syntax still accepts the constant string-expression variants described under Expressions.
target {
concept = rf.concept.subnet
rules = [aws.rule.subnet, google.rule.vpc-subnetwork]
dialects = ["aws", "google"]
}
| Property | Contract |
|---|---|
| Placement | Inside policy |
| Cardinality | Exactly one |
| Labels | Forbidden |
| Attributes | concept, rules, dialects |
| Nested blocks | None |
| Name | Type | Required | Default | Constraints |
|---|---|---|---|---|
concept |
Qualified Concept reference | Conditionally | No Concept filter | At least concept or rules is required |
rules |
Static nonempty list of qualified Rule references | Conditionally | No Rule filter | 1-1,024 unique entries; at least concept or rules is required |
dialects |
Static nonempty list of owner strings | No | No owner filter | 1-1,024 unique valid Dialect owners; rf forbidden |
Each dialects item is a static string expression, not a semantic reference.
Direct quoted strings are canonical:
dialects = ["aws", "google"]
This is invalid:
dialects = [aws, google]
A constant expression is accepted but normalized by compilation:
dialects = [true ? "aws" : "google"]
Dimensions combine as logical AND. Entries inside one list combine as logical OR.
For the target above, a Representation must:
- have Concept
rf.concept.subnet; - have Rule
aws.rule.subnetORgoogle.rule.vpc-subnetwork; - have Rule owner
awsORgoogle.
concept and rules may appear together. When rules is present, the linker
rejects POLICY_TARGET_CONTRADICTORY if none of the listed Rules can satisfy
optional concept and dialects filters. Without explicit rules, the linker does
not infer contradiction from the absence of current implementations: a valid
Concept target, with or without dialects, may select zero representations and
have outcome no_target. dialects alone is invalid because it does not define
a semantic target.
The target selects interpreted instances in the selected stage. A failed or indeterminate interpretation whose candidate Rule could satisfy the target is also selected for an indeterminate evaluation. An instance with no applicable Rule cannot satisfy a Rule, Concept, or Dialect target dimension. See Policy target selection.
assert uses closed Policy expression grammar:
assert = exists(contexts(rf.context.network))
assert = length(relations(aws.relation.subscribes-to)) >= 1
assert = (
exists(contexts(rf.context.runtime, rf.concept.kubernetes-cluster)) &&
!exists(contributions(aws.rule.s3-bucket-versioning))
)
Accepted result types:
| Expression | Type |
|---|---|
true, false |
Boolean |
exists(query) |
Boolean |
length(query) |
Number |
! Boolean |
Boolean |
Boolean && or || Boolean |
Boolean |
Same-type Boolean or number ==, != |
Boolean |
Number <, <=, >, >= number |
Boolean |
Bare queries, traversals, strings, and arbitrary calls are invalid. See Expressions and Built-ins.
Policy Pack source stores qualified references but no semantic versions or digests. Before evaluation, Rootform links source against one validated Form's semantics:
Save a Form from plan JSON first. The saved plan pairs with the
export and supplies reference traversals; the Policy Pack then links against
the semantics recorded in that Form. Run these commands from the Rootform
repository with the displayed Pack saved at policy-reference/pack.rf.hcl:
rootform run examples/playground/commerce-platform/head/plan.json \
--plan-file examples/playground/commerce-platform/head/plan.tfplan \
--no-serve -o analysis.json --color always
rootform compile policy-pack ./policy-reference \
--semantics analysis.json --output network-baseline.jsonPolicy Pack compiled
Policy Pack network-baseline@0.1.0
Form analysis.json
Semantic pins 2
Destination network-baseline.json
The first command writes analysis.json, a Form. The second
prints the Pack identity, semantic-pin count, and output path. Exit 0 means
linking succeeded; an unknown reference or incompatible semantic identity
fails instead. Keep the plan inputs and Form internal: outputs omit
sensitive values but still reveal topology and names.
Linking:
- resolves every owner, Concept, Context, Relation, and Rule;
- validates target intersections;
- derives exact owner kind, version, and semantic digest pins, including referenced Dialects' RF Vocabulary dependencies;
- writes deterministic compiled Policy Pack JSON.
A compiled pack can be evaluated offline without the Dialect sources that
produced the Form. Its pins must exactly match the Form. Mismatch produces
POLICY_SEMANTICS_MISMATCH; Rootform never relinks silently.
Unrelated semantic owners are not pinned.
See compile policy-pack for CLI flags and Evaluation for outcomes.
A valid Policy may select zero representations in one architecture. It is then
no_target, not passed. A selected Policy without targets prevents an
overall compliant result.
This Policy has only an owner filter:
policy_pack "invalid" {
version = "0.1.0"
}
policy "dialect-only" {
target {
dialects = ["aws"]
}
assert = true
message = "This target is incomplete."
}
It produces POLICY_INVALID because concept or nonempty rules is
required.
Unqualified semantic references such as concept.subnet produce
POLICY_REFERENCE_UNQUALIFIED. Empty rules or dialects lists,
duplicate entries, empty message, extra target block, or non-Boolean assertion
also fail compilation.