infra-contract
infra-contract
Version-controlled infrastructure rules for people, CI, and AI agents.
infra-contract evaluates Terraform/OpenTofu infrastructure against a small,
reviewable YAML contract. It gives humans and agents the same answer before a change is
merged or deployed.
Architecture
Valid Terraform can still create public databases, overly broad IAM policies, unsupported architecture, or risky destructive changes. That gap becomes more important when AI agents generate infrastructure. This project makes the rules explicit, machine-readable, and independently enforced.
Developer or AI agent
|
v
Terraform / OpenTofu change
|
v
+------------------------+
| infra-contract.yaml |
| policy engine |
+------------------------+
| |
v v
CLI / MCP CI gate
\ /
+-- deployment decision --+
Features
- YAML contracts validated with Pydantic.
- Terraform/OpenTofu plan parsing, plus a lower-confidence source scan.
- Built-in security, networking, reliability, and architecture policies.
- CLI, Python API, MCP server, and a reusable GitHub Action using one engine.
- Change-risk reporting and optional human approval for destructive stateful changes.
- JSON output suitable for CI and agent tooling.
Install
Requires Python 3.10+.
uv tool install infra-contract
# or
pip install infra-contract
To work from a checkout:
uv sync --all-extras
uv run infra-contract --help
Quick start
Initialize a repository, then review the generated contract before relying on it.
cd my-infrastructure-repository
infra-contract init
infra-contract check
Use an actual plan for the highest-confidence validation:
terraform plan -out=tfplan
terraform show -json tfplan > tfplan.json
infra-contract check --plan tfplan.json
infra-contract plan tfplan.json
For scripts and CI, use JSON and set the blocking severity explicitly:
infra-contract check --plan tfplan.json --format json --fail-on high
Contract reference
version: "1"
project:
name: my-service
cloud:
provider: aws
regions: [eu-central-1]
architecture:
compute:
allowed: [ecs]
database:
allowed: [rds-postgres]
security:
database:
public_access: false
encryption: required
iam:
wildcard_permissions: forbidden
reliability:
production:
backups: required
multi_az: required
agent:
production_apply: false
destructive_changes:
require_human_approval: true
ci:
fail_on: [high, critical]
See basic-terraform, production-service, and rag-app for complete starting points.
Interfaces
CLI
infra-contract init [PROJECT_ROOT]
infra-contract check [TARGET] [--contract PATH] [--plan PLAN.json] [--format text|json]
infra-contract plan PLAN.json [--contract PATH]
infra-contract diff PLAN.json [--contract PATH]
infra-contract explain [--resource RESOURCE_ID] [--plan PLAN.json]
infra-contract fix [TARGET] [--plan PLAN.json]
infra-contract mcp [--contract PATH]
check returns exit code 1 for blocking findings. plan also reports risk;
a deletion or replacement of a database, cache, or storage resource is critical
when the contract requires human approval. fix only proposes changes—it never
modifies infrastructure.
Python
The flattened source layout intentionally exposes reusable packages directly:
from contracts import Contract, load_contract
from engine import Evaluator
from providers import TerraformProvider
contract = load_contract("infra-contract.yaml")
document = TerraformProvider().load("tfplan.json")
result = Evaluator().run(document, contract)
print(result.to_dict())
Public API packages are ai, cli, contracts, engine, ir, mcp,
policies, and providers. Their __init__.py files expose the intended
reusable symbols; import implementation modules only when you need a
specialized type.
MCP for AI agents
Run the server over stdio:
infra-contract mcp --contract infra-contract.yaml
The server offers contract discovery, policy lookup, source/plan validation, violation explanation, single-resource preflight checks, and change-risk analysis. It does not apply infrastructure. See the MCP example.
GitHub Actions
The repository itself is a composite action. Pin a tag or commit SHA in a consumer workflow:
name: Infrastructure contract
on: [pull_request]
permissions:
contents: read
pull-requests: write # only needed when comment-on-pr is true
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: OWNER/infra-contract@v0.1.0
with:
plan: tfplan.json
fail-on: high
comment-on-pr: true
The generated workflow from infra-contract init is a simple CLI-based
alternative. This repository also includes CI, dependency review, and CodeQL
workflows.
Docker and Compose
The image is a multi-stage build, uses a locked uv environment, and runs as a
non-root user. It is intentionally a CLI image, so it has no HTTP port or
healthcheck.
docker build -t infra-contract:local .
docker run --rm -v "$PWD:/workspace:ro" -w /workspace infra-contract:local \
check --contract examples/rag-app/infra-contract.yaml examples/rag-app
docker compose build
docker compose run --rm infra-contract check \
--contract examples/production-service/infra-contract.yaml path/to/terraform
Development
uv sync --all-extras
uv run isort --check-only src tests
uv run black --check src tests
uv run mypy src
uv run pytest -v
Apply local formatting with uv run isort src tests and uv run black src tests.
The project intentionally uses Black and isort rather than Ruff for formatting
and import ordering.
Convenience targets mirror CI:
make install
make check
make ci
make hooks-install
The pre-commit hook checks file hygiene, YAML/TOML, import ordering, and Black
on commits; mypy and pytest run on push. The included .pre-commit-hooks.yaml
also lets downstream repositories install infra-contract check as a reusable
hook.
Repository layout
src/
├── contracts/ # YAML schema and loader
├── ir/ # provider-neutral infrastructure model
├── policies/ # policy primitives and built-in rules
├── engine/ # evaluation, scoring, risk
├── providers/ # Terraform/OpenTofu adapters
├── cli/ # Typer commands
├── mcp/ # MCP server
└── ai/ # generated agent instructions
The dependency flow is one way: providers normalize into ir; policies and the
engine evaluate contracts plus ir; CLI/MCP/action only transport results.
Architecture tests prevent core packages from importing interface layers.
Security and release
GitHub Actions runs tests, Black, isort, mypy, package builds, dependency review on pull requests, and scheduled CodeQL analysis. Enable Dependabot and GitHub Advanced Security features in repository settings where available.
To publish the GitHub Action in Marketplace, first create a versioned release:
- Confirm CI is green and update the version/changelog as appropriate.
- Create and push an annotated tag such as
v0.1.0; the release workflow builds and publishes the Python package if PyPI Trusted Publishing is configured. - Open GitHub Releases → Draft a new release, choose that tag, add release notes, and publish it.
- GitHub will then offer Marketplace publication. Review the listing metadata, confirm the action is safe for public use, and publish the listing.
Do not click “Draft a release” until the tag/version and PyPI trusted-publisher
configuration are ready. Marketplace publication is optional; users can always
reference OWNER/infra-contract@v0.1.0 directly.
Dockerfile.goreleaser is intentionally not included. GoReleaser builds and
releases Go programs; this project publishes a Python package and a Docker CLI
image through uv and the existing release workflow.
Scope
infra-contract is a validation layer, not Terraform, a cloud deployment
platform, or an autonomous apply tool. Policies only cover modeled resource types;
an unknown resource produces no opinion, so pair this with cloud-native controls
and code review.
License
Release files for infra-contract 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| infra_contract-0.1.1.tar.gz | 147.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| infra_contract-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 186.9 kB
Release files / infra_contract-0.1.1.tar.gz
| Download URL | infra_contract-0.1.1.tar.gz |
|---|---|
| Size | 147.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
be9dc8d4e0e573c0b8ed58af17e1fcdfcf0ac38db4164d17e9b8df117ea2d47b
|
|
BLAKE2b-256 checksum How to use checksums |
3aad435eb9b4a71d2a083c653365ff8f1cd19b1a340406c8c465f1764398eb56
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / infra_contract-0.1.1-py3-none-any.whl
| Download URL | infra_contract-0.1.1-py3-none-any.whl |
|---|---|
| Size | 39.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
653f6aa271383c1ce50c6f70854f7ffa703807b8c7cbd8264329612786553e7b
|
|
BLAKE2b-256 checksum How to use checksums |
29d8ef2e9918f6c64a46cc059049267e2dd57052ec7a2d590ca46f0dbb0e17d7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency log