Skip to content

Root + component contracts

Problem. A repository ships several deployable units that release together — an HTTP API and a background worker, a Prefect server and its workers, a service plus its CLI shim. You want one deployment unit (one ArgoCD Application, one Helm release) but distinct runtime semantics, dependencies, and configurations for each component.

Primitives.

  • Multiple bundles in one repo, each with its own pacto.yaml
  • Root contract — declares the application boundary and lists components as dependencies[]
  • Component contracts — declare workload, state, interfaces, and configurations for a single deployable

Layout.

my-service/
├── charts/
│   └── my-service/                         # service chart (one per repo)
│       ├── Chart.yaml                      # depends on the per-component chart, aliased
│       └── values.yaml
└── pactos/
    ├── my-service-root/
    │   └── pacto.yaml                      # components as deps
    ├── my-service-api/
    │   ├── pacto.yaml                      # workload, state, configurations
    │   └── overrides/
    │       └── values.<env>.yaml
    └── my-service-worker/
        ├── pacto.yaml
        └── overrides/
            └── values.<env>.yaml

Root contract.

pactoVersion: "2.0"

service:
  name: my-service-root
  version: 1.2.0
  owner:
    team: example

dependencies:
  # Components — built from this repo, not deployed independently
  - name: api
    ref: oci://ghcr.io/example/pactos/my-service-api:1.2.0
    required: true
    compatibility: "^1.0.0"
  - name: worker
    ref: oci://ghcr.io/example/pactos/my-service-worker:1.2.0
    required: true
    compatibility: "^1.0.0"

  # External services this app talks to at runtime
  - name: auth
    ref: oci://ghcr.io/example/pactos/auth-root:4.0.0
    required: true
    compatibility: "^4.0.0"

Component contract.

pactoVersion: "2.0"

service:
  name: my-service-api
  version: 1.2.0
  owner:
    team: example

interfaces:
  - name: api
    type: openapi
    ref: interfaces/openapi.yaml
    visibility: internal

workload: service

state:
  type: stateless
  persistence:
    scope: local
    durability: ephemeral
  dataCriticality: low

capabilities:
  - type: health
    binding:
      type: http
      interface: api
      path: /health

configurations:
  - name: deployment
    ref: oci://ghcr.io/example/pactos/platform-service:2.0.0
    required: true

Why this works. A one-component repo pays almost nothing for this layout, and adding a second component is one new bundle dir plus one root dependency. The root maps to a single deployment unit; each component is validated and versioned independently. The root is a lean aggregator — it carries only service and dependencies[] (plus any policies), deliberately omitting workload, state, interfaces and configurations. Your own tooling can distinguish a root from a component by naming convention (e.g. a -root suffix) or structurally — dependencies[] present, configurations absent — since Pacto itself does not key off the name.

Cross-links: workload · dependencies