Receipt
gitopsctr.io/v1 Receipt records the result of reconciling one exact desired unit. The controller and unit driver
write it to units/<unit-qualified-name>.yaml|json on the observed ref; users do not author receipts.
apiVersion: gitopsctr.io/v1
kind: Receipt
metadata:
name: infrastructure
spec:
subject:
apiVersion: unit.gitopsctr.io/v1
kind: Terraform
name: infrastructure
qualifiedName: infrastructure
desired:
unitBlob: 0123456789abcdef0123456789abcdef01234567
resolvedInputs: {}
status:
controller: {}
result:
applied:
sourceRevision: fedcba9876543210fedcba9876543210fedcba98
outputs:
api_url: https://api.example.test
spec.subject identifies the unit kind, spec.desired.unitBlob binds the receipt to the serialized desired unit, and
spec.resolvedInputs records the reference fingerprints used by that unit. status.result follows the subject
driver's typed result contract. Drivers that publish artifacts also add descriptors under status.artifacts.
spec.subject.qualifiedName persists the operator address that was authenticated when the Receipt was written. It is
stack/unit for a Stack-owned Unit and the Unit name for a direct Unit; inspection re-authenticates it against the
selected desired snapshot. The Receipt mirrors the Unit's hierarchical path in the observed collection while retaining
the Unit's local name in metadata.name.
Receipt and Unit state
A Receipt is a separately stored observed resource, not the status field of its desired Unit. The two resources may
come from different Git revisions, and a desired Unit may have a current Receipt, a stale Receipt for an older Unit
blob, or no Receipt. Conversely, deleting a desired Unit can leave an orphaned Receipt in a selected observed
snapshot.
The default Unit table makes this relationship convenient without hiding it:
gitopsctr get units --environment dev
gitopsctr get receipts --environment dev
gitopsctr get unit infrastructure --environment dev -o yaml
gitopsctr get receipt infrastructure --environment dev -o yaml
The table derives observation and reconciliation columns by joining the resources. The two YAML commands return the
exact persisted Unit and Receipt documents; neither command synthesizes the Receipt into Unit status. Use
gitopsctr get receipt infrastructure --environment dev --artifact NAME for one described Artifact resource, or
--artifacts for all of them.
How fromReceipt resolves
flowchart LR
reference["fromReceipt<br/>unit + pointer"] --> receipt["Observed receipt<br/>units/<unit>"]
desired["Current desired unit<br/>units/<unit>"] --> freshness{"unitBlob matches?"}
receipt --> freshness
freshness -->|yes| result["Validate typed<br/>status.result"]
result --> pointer["Apply JSON Pointer"]
For fromReceipt: {unit: infrastructure, pointer: /outputs/api_url}, gitopsctr:
- Loads
units/infrastructure.*from the current desired and observed trees. - Requires the receipt's
spec.desired.unitBlobto match the current desired unit blob. - Validates the receipt and its
status.resultagainst the Terraform receipt profile. - Applies
/outputs/api_urlrelative tostatus.resultand fingerprints the receipt blob.
A missing or stale receipt leaves the consumer waiting; an invalid current receipt is an error. pointer: "" selects
the whole typed result. See Reference expressions for dryFallback and pointer syntax.
The generic Receipt schema describes the envelope. Each
unit kind also publishes a receipt profile that specializes status.result and status.artifacts.