One versioned contract per service
What is Pacto?¶
A service's operational facts are scattered. Ownership is in a wiki. The API is an OpenAPI file in another repository. What it depends on is implied by Helm values and a Service name. What breaks if you change it is in someone's memory.
Pacto is an operational contract system. It puts those facts in one YAML file, published to the container registry you already run.
pactoVersion: "2.0"
service:
name: checkout
version: 4.2.0
owner: { team: commerce, dri: alice }
interfaces:
- name: rest-api
type: openapi
ref: interfaces/openapi.yaml # the OpenAPI document you already maintain
visibility: public
dependencies:
- name: auth
ref: oci://ghcr.io/acme/auth-pacto
required: true
compatibility: "^2.0.0" # the range this revision accepts
Who breaks when a dependency ships a new version¶
The compatibility range above records which versions of auth this revision
accepts, and pacto.lock pins every dependency below it to the exact published
build. So when auth is about to ship 3.0, Pacto answers per consumer:
$ pacto impact ./auth-2.1.0 ./auth-3.0.0 --local .
Impact: auth 2.1.0 -> 3.0.0
Classification: BREAKING
Breaking changes: 1
Potentially breaking changes: 0
Affected consumers (2):
checkout direct confidence=contractual compat=incompatible owner=commerce
reporting direct confidence=contractual compat=compatible owner=analytics
checkout accepts ^2.0.0 and 3.0.0 falls outside it. reporting accepts
>=2.0.0 <4.0.0 and 3.0.0 is inside. direct means each one declares auth
itself rather than reaching it through another service, and contractual means
the dependency is declared with a usable range and nothing observed it running.
One file, checked when you write it, compared against the previous revision, then compared against what is actually running.
When Pacto cannot observe something it says Unknown. It never reports it as a
pass.
What each command answers¶
| Command | Question it answers |
|---|---|
pacto validate |
Is this contract legal? |
pacto diff |
Did I break my own consumers? |
pacto impact |
Which consumers, and where do they run? |
| The operator | Does reality still match what was declared? |
validate and diff pay off at one service; impact and the graph pay off at
the second consumer.
Check what is actually running¶
Pacto can check what a running service actually does on the network against what its contract says, on any Linux machine, and tells you only what it can prove:
| What it catches | Finding |
|---|---|
| A process reports healthy but nothing listens on the declared port | INTERFACE_ABSENT |
| A declared dependency the service keeps failing to reach | DEPENDENCY_UNREACHABLE |
A call to another Pacto service no dependency declares (Kubernetes, pacto agent) |
DEPENDENCY_UNDECLARED |
Pacto watches TCP connections in the Linux kernel with eBPF (small, safe
programs the kernel runs on events). It never reads payloads or secrets, and
when it cannot see it says "don't know" instead of guessing. Run it three ways:
pacto run wraps one command (a laptop, a CI job), pacto agent watches a
Docker host or a server and the Kubernetes operator deploys the same agent on
every node. See Runtime conformance.
Where to start¶
- What the live demo shows — the dashboard runs in your browser against a fixture fleet, nothing to install
- Quickstart — an empty directory to a validated contract, a breaking change and the consumers it reaches, about five minutes
- Put it in your repository — validate and diff on every pull request
- Contract reference — every field and every validation rule