Forgecroft Docs
Guides / Governance

Writing Rego Policies

Write Rego policies that evaluate plan changes and control infrastructure safety.

Required Structure

Every Rego policy in Forgecroft must use the forgecroft.policy package:

package forgecroft.policy

Deny Rules

Deny rules block a run when they fire. They return an array of violation messages:

deny[msg] {
    input.workspace.attributes.environment == "production"
    input.plan_changes.destroyed[_].resource_type == "aws_db_instance"
    msg := "Destroying a database instance in production is not allowed"
}

Each matching rule instance adds one message to the deny array. If any messages exist and the policy set is mandatory, the run is rejected.

Require Approval Rules

Approval rules trigger a multi-stage approval requirement:

require_approval[r] {
    input.workspace.attributes.environment == "production"
    count(input.plan_changes.changed) > 5
    r := {
        "team": "platform-leads",
        "min": 2,
        "stage": 1,
        "reason": "Production workspace with significant changes",
        "timeout_hours": 24
    }
}

The returned object:

FieldTypeDescription
teamstringTeam name or ID to approve
minintMinimum number of approvals needed
stageintApproval stage (1 = first)
reasonstringWhy approval is required
timeout_hoursintHours before escalation (0 = no timeout)

Input Schema

Policies receive the following input:

{
  "workspace": {
    "id": "uuid",
    "name": "production",
    "attributes": { "environment": "production", "team": "platform" },
    "detected_attributes": {
      "providers": ["aws"],
      "resource_types": ["aws_instance", "aws_security_group"]
    }
  },
  "run": {
    "id": "uuid",
    "run_type": "plan",
    "trigger": "push",
    "triggered_by": "user@example.com"
  },
  "org": {
    "id": "uuid"
  },
  "user": {
    "id": "uuid",
    "email": "user@example.com"
  },
  "plan_changes": {
    "added": [
      { "address": "aws_instance.web", "resource_type": "aws_instance", "provider_name": "aws" }
    ],
    "changed": [
      { "address": "aws_security_group.main", "resource_type": "aws_security_group" }
    ],
    "destroyed": []
  }
}

Example Policies

Block Destroy in Production

package forgecroft.policy

deny[msg] {
    input.workspace.attributes.environment == "production"
    count(input.plan_changes.destroyed) > 0
    msg := sprintf("Production destroy: %d resource(s) would be destroyed", [count(input.plan_changes.destroyed)])
}

Require Approval for IAM Changes

package forgecroft.policy

require_approval[r] {
    input.plan_changes.added[_].resource_type == "aws_iam_role"
    r := {
        "team": "security",
        "min": 1,
        "stage": 1,
        "reason": "IAM role creation requires security review",
        "timeout_hours": 48
    }
}

Limit Changes Per Run

package forgecroft.policy

deny[msg] {
    total := count(input.plan_changes.added) + count(input.plan_changes.changed) + count(input.plan_changes.destroyed)
    total > 50
    msg := sprintf("Too many changes: %d (max 50)", [total])
}

Require Approval for PR-Triggered Production Changes

package forgecroft.policy

require_approval[r] {
    input.run.trigger == "pr"
    input.workspace.attributes.environment == "production"
    r := {
        "team": "platform-leads",
        "min": 1,
        "stage": 1,
        "reason": "PR-triggered production change requires approval",
        "timeout_hours": 12
    }
}

Block Unapproved Providers

package forgecroft.policy

approved_providers := {"aws", "google", "cloudflare"}

deny[msg] {
    provider := input.workspace.detected_attributes.providers[_]
    not approved_providers[provider]
    msg := sprintf("Unapproved provider: %s", [provider])
}

Using Workspace Attributes

Workspace attributes are the primary mechanism for targeting policies:

deny[msg] {
    input.workspace.attributes.criticality == "high"
    input.plan_changes.destroyed[_].resource_type == "aws_instance"
    msg := "Cannot destroy instances in high-criticality workspaces"
}

Set attributes on workspaces via PATCH /workspaces/{id} with an attributes object.

Testing Policies

Use the Rego playground endpoints to test your policies:

See the Rego Playground guide for details.