Skip to main content
Private Preview·Early access by invitation.Request access →
Kirimana.
Docs · Contracts

Handle schema drift

The contract is the source of truth; the warehouse table is a materialisation of it. Drift is what you call it when the two disagree — someone altered a column in the catalog, or a source changed shape under a bronze table, or a proposed contract edit would break a consumer. Kirimana catches drift in two places: at apply time against the live table, and at PR time against the previous version of the contract. Editing the catalog directly is drift; Kirimana surfaces it rather than quietly pulling it back.

Apply-time drift: the live table diverged

When a table already exists in the catalog, you want to know whether it still matches its contract before you trust it. kiri contract verify-live diffs the live Unity Catalog table against the contract and reports every difference:

kiri contract verify-live \
  --contract contracts/dim_customer.yml \
  --catalog acme_prod \
  --schema gold \
  --fail-on type-mismatch

--fail-on is a closed menu — add, drop, type-mismatch, meta-mismatch, or all — and it decides which class of finding fails the command. A column added to the live table that the contract doesn’t know about is an add; a contract column missing from the live table is a drop; a column whose live type no longer matches the contract is a type-mismatch. The default --fail-on type-mismatch blocks on the most dangerous class (wrong types silently corrupt reads) while reporting the rest. The JSON report lands at verify-live.json unless you redirect it. Wire this into CI against your production catalog and a schema someone hand-edited can’t stay hidden.

When the live table is the truth you want to adopt

Sometimes drift is intentional — a source legitimately gained a column and you want the contract to catch up. kiri contract sync-from-live reads the live table and proposes the patch that would bring the contract back in line:

kiri contract sync-from-live \
  --contract contracts/dim_customer.yml \
  --catalog acme_prod \
  --schema gold \
  --propose

--propose writes a reviewable YAML proposal (./sync-proposal.yml by default) — it does not touch the contract. You read the proposal, and only if you agree do you re-run with --apply to patch the contract on disk. The two are mutually exclusive, and --apply is refused when project policy is fail_closed, so adopting live schema is always a deliberate, reviewed act. The reconciliation flows one way: change the YAML, open a PR, apply — never the reverse.

Full-load drift: the source changed shape

For a full-load bronze table, drift originates upstream — the source system changed its columns between loads. kiri sources discover can compare a discovered stream against a contract’s declared columns and print a drift report before you ever apply:

kiri sources discover --against-contract silver_customer

This tells you a source gained, lost, or retyped a column while the contract still expects the old shape — the earliest possible warning, at the boundary where the data enters, so you fix the contract before a full load lands data that violates it.

PR-time drift: a proposed contract change

The second kind of drift is a change you’re about to make. Before a contract edit merges, you want a semantic-aware diff of what actually changed — not a raw text diff that flags reordered keys, but one that understands the contract model. kiri diff compares two contract files:

kiri diff contracts/dim_customer.yml /tmp/dim_customer.proposed.yml

For silver contracts specifically, kiri silver diff A B gives the same semantic comparison scoped to silver shapes. And kiri contract lint runs the whole governance rule set across the changed project, which is where breaking-change and compatibility findings surface at review.

What blocks and what warns

Kirimana is deliberate about severity — not every difference should stop a release, but the dangerous ones must:

  • Blocks (error / non-zero exit): a type-mismatch under the default verify-live policy; any error-severity kiri contract lint finding; a validation failure from kiri contract validate --strict. These fail CI and keep the change off main.
  • Warns (reported, exit 0): a live column addition or drop under the default verify-live policy (surfaced, not fatal unless you widen --fail-on); deprecation findings; anything below error severity.

The rule of thumb: silent divergence is never allowed — every drift is reported — but you choose, per class, which ones are hard gates. Widen --fail-on all when you want zero tolerance, keep the default when you want types guarded and additions merely visible.

Post-migration reconciliation

When you migrate a table from a legacy warehouse onto your platform, schema agreement isn’t enough — you also want to know the data reconciles. kiri reconcile runs post-migration validation between the source and the target: row counts, primary-key coverage, null rates, date bounds, and SCD2 business-key alignment, emitting a JSON or markdown report. It answers the question verify-live can’t: not just “does the shape match” but “did every row arrive intact.” A locked report mode omits raw values when the reconciliation itself must stay governed.

Where next

Updated 5 July 2026 · v1.0.0-beta.1