Skip to content
PtahOperator

PtahMigrationPlan

PtahMigrationPlan is a namespaced resource in operator.ptah.run, served as v1alpha1.

This page is generated from the API types by make docs-reference. The shipped CRDs carry no descriptions, so this is where the field documentation lives.

Nobody writes a PtahMigrationPlan. The operator publishes one when it has read the database’s history and worked out which versions are missing, and the object is immutable afterwards.

A migration plan names versions rather than carrying SQL: the statements stay in the artifact, and the plan records which versions run, in which order, and what each one’s checksum was when the plan was computed. Read it with the plugin:

Terminal window
kubectl ptah migration orders -n application

currentVersion is where the database was, and migrations is what would run. historyFingerprint binds the history the plan was computed against, so a version applied by anything else in the meantime retires this plan instead of letting it run against a database it no longer describes.

apiVersion: operator.ptah.run/v1alpha1
kind: PtahMigrationPlan
metadata:
name: ptah-mplan-19581e27de7ced00ff1ce50b
namespace: application
ownerReferences:
- apiVersion: operator.ptah.run/v1alpha1
kind: PtahMigration
name: orders
uid: 8d3f6c2b-1a4e-4f90-b7c5-2e6a8d0b3f41
controller: true
spec:
migrationRef:
name: orders
uid: 8d3f6c2b-1a4e-4f90-b7c5-2e6a8d0b3f41
fingerprint: sha256:19581e27de7ced00ff1ce50b2047e7a567c76b1cbaebabe5ef03f7c3017bb5b7
createdAt: "2026-09-20T09:12:44Z"
currentVersion: 12
historyFingerprint: sha256:4a44dc15364204a80fe80e9039455cc1608281820fe2b24f1e5233ade6af1dd5
migrations:
- version: 13
versionKey: "0013"
description: add order status index
checksum: sha256:3f79bb7b435b05321651daefd374cdc681dc06faa65e374e38337b88ca046dea
transactionMode: file
- version: 14
versionKey: "0014"
description: backfill order status
checksum: sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
transactionMode: file
contractVersion: 1
artifactDigest: sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
verificationPolicyDigest: sha256:084fed08b978af4d7d196a7446a86b58009e636b611db16211b65a9aadff29c5
coordinationDigest: sha256:e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
targetIdentityDigest: sha256:67586e98fad27da0b9968bc039a1ef34c939b9b8e523a8bef89d478608c5ecf6
policyFingerprint: sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
ptahVersion: v0.7.0
executorImage: ghcr.io/stokaro/ptah@sha256:1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014
runnerImage: ghcr.io/stokaro/ptah-runner@sha256:60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
runnerProtocolVersion: 5
controllerImage: ghcr.io/stokaro/ptah-operator@sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
controllerStateVersion: 2

A fresh database, bootstrapped from a checkpoint

Section titled “A fresh database, bootstrapped from a checkpoint”

A migration file marked checkpoint: true carries the whole schema up to its version. A database created after it starts there instead of replaying everything before it, so the plan for an empty database names the checkpoint and the versions after it, and nothing below it. status.history on the resource reports those lower versions as applied and names the checkpoint that covers them.

A checkpoint changes where a new database starts and nothing else. A database already at version 10 or beyond when this checkpoint arrived ignores it and goes on from whatever it has run. It does not undo statements a failed migration committed, clear a dirty revision, or make a backfill safe to run twice; those are answered by the revision table and by the recovery a person performs against it, which Operations describes.

apiVersion: operator.ptah.run/v1alpha1
kind: PtahMigrationPlan
metadata:
name: ptah-mplan-ef2d127de37b942baad06145
namespace: application
ownerReferences:
- apiVersion: operator.ptah.run/v1alpha1
kind: PtahMigration
name: orders
uid: 8d3f6c2b-1a4e-4f90-b7c5-2e6a8d0b3f41
controller: true
spec:
migrationRef:
name: orders
uid: 8d3f6c2b-1a4e-4f90-b7c5-2e6a8d0b3f41
fingerprint: sha256:ef2d127de37b942baad06145e54b0c619a1f22327b2ebbcfbec78f5564afe39d
createdAt: "2026-09-20T08:40:12Z"
# Nothing has run here yet.
currentVersion: 0
historyFingerprint: sha256:e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
migrations:
# The cumulative schema through version 10, and the plan runs it: a
# checkpoint covers the versions below itself, not itself. Versions 1 to 9
# are absent, because this file is what puts them in place.
- version: 10
versionKey: "0010"
description: cumulative schema through version 10
checksum: sha256:7902699be42c8a8e46fbbb4501726517e86b22c56a189f7625a6da49081b2451
transactionMode: file
checkpoint: true
- version: 13
versionKey: "0013"
description: add order status index
checksum: sha256:3f79bb7b435b05321651daefd374cdc681dc06faa65e374e38337b88ca046dea
transactionMode: file
- version: 14
versionKey: "0014"
description: backfill order status
checksum: sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
transactionMode: file
contractVersion: 1
artifactDigest: sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
verificationPolicyDigest: sha256:084fed08b978af4d7d196a7446a86b58009e636b611db16211b65a9aadff29c5
coordinationDigest: sha256:e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
targetIdentityDigest: sha256:67586e98fad27da0b9968bc039a1ef34c939b9b8e523a8bef89d478608c5ecf6
policyFingerprint: sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
ptahVersion: v0.7.0
executorImage: ghcr.io/stokaro/ptah@sha256:1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014
runnerImage: ghcr.io/stokaro/ptah-runner@sha256:60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
runnerProtocolVersion: 5
controllerImage: ghcr.io/stokaro/ptah-operator@sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
controllerStateVersion: 2

One version, on an engine with no DDL transaction

Section titled “One version, on an engine with no DDL transaction”

transactionMode: none is the artifact’s own declaration for that file. It says a failure partway through leaves what already ran in place, because the engine will not roll DDL back. The operator records the version as uncertain rather than claiming either outcome.

apiVersion: operator.ptah.run/v1alpha1
kind: PtahMigrationPlan
metadata:
name: ptah-mplan-6b51d431df5d7f141cbececc
namespace: application
spec:
migrationRef:
name: orders
uid: 8d3f6c2b-1a4e-4f90-b7c5-2e6a8d0b3f41
fingerprint: sha256:6b51d431df5d7f141cbececcf79edf3dd861c3b4069f0b11661a3eefacbba918
createdAt: "2026-09-20T10:03:51Z"
currentVersion: 14
historyFingerprint: sha256:9c56cc51b374c3ba189210d5b6d4bf57790d351c96c47c02190ecf1e430635ab
migrations:
- version: 15
versionKey: "0015"
description: widen order reference column
checksum: sha256:4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce
transactionMode: none
contractVersion: 1
artifactDigest: sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
verificationPolicyDigest: sha256:084fed08b978af4d7d196a7446a86b58009e636b611db16211b65a9aadff29c5
coordinationDigest: sha256:e7f6c011776e8db7cd330b54174fd76f7d0216b612387a5ffcfb81e6f0919683
targetIdentityDigest: sha256:67586e98fad27da0b9968bc039a1ef34c939b9b8e523a8bef89d478608c5ecf6
policyFingerprint: sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
ptahVersion: v0.7.0
executorImage: ghcr.io/stokaro/ptah@sha256:1b4f0e9851971998e732078544c96b36c3d01cedf7caa332359d6f1d83567014
runnerImage: ghcr.io/stokaro/ptah-runner@sha256:60303ae22b998861bce3b28f33eec1be758a213c86c93c076dbe9f558c11c752
runnerProtocolVersion: 5
controllerImage: ghcr.io/stokaro/ptah-operator@sha256:fd61a03af4f77d870fc21e05e7e80678095c92d808cfb3b5c279ee04c74aca13
controllerStateVersion: 2
Field Type What it does
spec.artifactDigest string, required ArtifactDigest is the OCI migration artifact this plan reads its files from, pinned to content rather than to the tag it was resolved through.
spec.contractVersion integer, required ContractVersion versions plan publication separately from the Kubernetes API version.
spec.controllerImage string, required ControllerImage is the digest-pinned manager that published this plan.
spec.controllerRevision string, required ControllerRevision is that manager’s revision, which distinguishes two deployments of the same image.
spec.controllerStateVersion integer, required ControllerStateVersion is the state semantics that manager writes.
spec.coordinationDigest string, required CoordinationDigest is the database realm this plan takes its turn in.
spec.createdAt string, required CreatedAt is when the controller published this plan.
spec.currentVersion integer, required CurrentVersion is the version the history stood at when the plan was made, published so an operator can read the plan’s premise.
spec.executionBindingID string, required ExecutionBindingID is a per-transition epoch. It changes even when an operator rollout returns to byte-identical component versions.
spec.executorImage string, required ExecutorImage is the digest-pinned image that ran Ptah.
spec.fingerprint string, required Fingerprint binds this plan to everything that decided it. An approval names it, and a changed input produces a different plan rather than a changed one.
spec.historyFingerprint string, required HistoryFingerprint is the history this plan was computed against. A history that changed between planning and execution invalidates the plan rather than being applied to.
spec.migrationRef object, required MigrationRef is the PtahMigration this plan was computed for.
spec.migrationRef.name string, required Name of the referenced object in the same namespace.
spec.migrationRef.uid string, required UID the object had when the reference was written. An object deleted and recreated under the same name is a different object, and this says so.
spec.migrations []object, required Migrations is the exact sequence, in execution order, and the order is the content: a plan that applies the same migrations in another order is a different plan. So the list is atomic rather than a map keyed by version – a map declares the order insignificant, and it would also require the version to be unique, which is the thing VersionKey exists to say it is not.
spec.migrations[].checkpoint boolean Checkpoint marks a migration whose up body is the cumulative schema at its version.
spec.migrations[].checksum string, required Checksum is what the file hashes to under the rule that decides what a revision row records. It is what makes a plan refuse an artifact whose bytes changed after the plan was published.
spec.migrations[].description string Description is the migration’s own description, as the artifact spells it.
spec.migrations[].transactionMode string, one of file, none TransactionMode is the file’s declared mode, resolved for this dialect: “file”, “none”, or empty where the file declares none and the engine’s own mode decides. A run that stops halfway is read differently depending on it, so the plan records what was true when it was made.
spec.migrations[].version integer, required Version is the migration’s numeric version.
spec.migrations[].versionKey string VersionKey is the exact revision identity. A version does not identify a row on its own: an Atlas repeatable migration carries an opaque token rather than a decimal spelling.
spec.policyFingerprint string, required PolicyFingerprint is the spec.policy the plan was computed under, so an edited policy retires a plan waiting for a person.
spec.ptahVersion string, required PtahVersion is the Ptah build that computed the sequence.
spec.runnerImage string, required RunnerImage is the digest-pinned image that supervised it.
spec.runnerProtocolVersion integer, required RunnerProtocolVersion is the result-frame protocol that runner speaks.
spec.targetIdentityDigest string, required TargetIdentityDigest identifies the database it was computed against without carrying anything that could reach it.
spec.verificationPolicyDigest string, required VerificationPolicyDigest is that policy’s content at the time.
spec.verificationPolicyUID string, required VerificationPolicyUID is the policy object that accepted the artifact.
Field Type What it does
status.conditions []object Conditions is empty. The operator publishes no Condition on a migration plan: a plan is an immutable artifact, and whether it is still the one to apply is a fact about the PtahMigration, which reports it there. The field stays so a later Condition about the plan itself has somewhere to go.
status.conditions[].lastTransitionTime string, required lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
status.conditions[].message string, required message is a human readable message indicating details about the transition. This may be an empty string.
status.conditions[].observedGeneration integer observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance.
status.conditions[].reason string, required reason contains a programmatic identifier indicating the reason for the condition’s last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty.
status.conditions[].status string, required, one of True, False, Unknown status of the condition, one of True, False, Unknown.
status.conditions[].type string, required type of condition in CamelCase or in foo.example.com/CamelCase.
status.observedGeneration integer ObservedGeneration is the plan generation this status was written for.