Infrastructure contracts¶
Problem. Your platform offers a fixed set of infrastructure types — Postgres, Redis, object storage, secrets — provisioned by some declarative tool (Crossplane, Terraform, an internal operator). You want each infrastructure type to be self-describing, governed like services, and machine-readable by the tool that turns claims into real resources.
Primitives.
- A pacto contract per infrastructure type, published by the platform team
policies[]carrying the platform rules (HA, backups, version floors)configurations[]carrying the provisioning schema (the team-controllable subset of fields)metadata.labelscarrying provisioner hints — opaque to pacto, meaningful to your CI tool
Example: a postgres infrastructure contract.
pactoVersion: "1.2"
service:
name: postgres
version: 17.0.0
owner:
team: platform
metadata:
labels:
platform/provisioner: crossplane
platform/claim-kind: PostgreSQLClaim
platform/claim-api-version: database.platform.example.com/v1alpha1
policies:
- name: postgres-policy
schema: policy/schema.json # enforces version >= 17, backups enabled, HA in prod
configurations:
- name: provisioning
schema: configuration/schema.json # derived from the provisioning claim's OpenAPI schema — the team-controllable subset of fields
The provisioning schema validates "did the team write a sensible claim?" — instances in range, valid size enum, schedule cron syntax, etc.
Pacto doesn't invent this schema — it's derived from the provisioning claim's own OpenAPI schema (a Crossplane XRD, a Terraform module's variables), the team-controllable subset of the claim. The configuration a team writes through the contract is the configuration that feeds the underlying claim — validated once, with no second definition to drift out of sync. The contract adds what the claim can't express on its own — an owner, a version, a policy and a stable ref other contracts depend on.
{
"type": "object",
"properties": {
"instances": { "type": "integer", "minimum": 1, "maximum": 5 },
"size": { "type": "string", "enum": ["small", "medium", "large"] },
"backups": {
"type": "object",
"properties": {
"enabled": { "type": "boolean" },
"schedule": { "type": "string" }
}
}
}
}
How services consume it. A service contract references the infra contract as a configuration (see pattern 3). When CI generates deployment artifacts, it reads metadata.labels from the resolved infra contract to dispatch — no hardcoded mapping from "this configuration name" to "that claim kind". Adding a new infrastructure type is one new contract, not a code change in CI.
Versioning the contract is versioning the platform interface. A bump from postgres:17.0.0 to postgres:18.0.0 lets services migrate at their own pace by ref-pinning, and the policy can tighten with each major version (see pattern 5).
Cross-links: metadata · policies · configurations