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

Federation — cross-project catalogs

Federation is how one Kirimana project’s contracts become visible to other projects — other teams, other environments, other clouds — without standing up a central catalog vendor. Each team keeps its own repo, its own release cadence, and its own catalog; federation gives everyone else a read-only, versioned view of what that team publishes.

Git is the source of truth

The contracts library — sources/, contracts/, models — lives in one git repository per project. Every platform catalog (Unity Catalog on Databricks, or a Horizon/Purview sink) is a materialisation of that library, never an independent authority. A classification change lands once as a PR; kiri apply --target <env> rolls it out. Changes made inside a catalog are drift: Kirimana surfaces them, it does not pull them back.

Federation extends this one step: instead of only materialising into your own platform, a project can publish a snapshot of its catalog that other projects consume — same git-first discipline, across team boundaries.

Catalog snapshots

The unit of exchange is the federation export: a public-facing JSON snapshot of one project’s contracts, written to <project>/.kirimana/federation/export.json by default.

What the export carries:

  • Identityschema_version, project_urn, release_sha, generated_at, catalog_etag
  • Per contract — URN, domain, owner, classification, AI policy, schema (column name, type, classification, from_columns lineage), reporting goals, release state, active flag

What it deliberately does not carry: model SQL bodies, internal customProperties (kiri._internal.*), audit-log entries, quality-engine results, and — critically — secrets, vault references, and connection strings. A consumer reading the export cannot reconstruct production credentials.

The wire format is locked to schema_version: "1"; bumps are never silent. Writes are atomic (temp file + rename), so a consumer never observes a half-written snapshot.

Publish one-shot:

kiri catalog publish \
  --project-urn kirimana:project:<slug> \
  --release-sha <git-sha>

Or auto-republish after every successful kiri apply by setting KIRIMANA_FEDERATION_PUBLISH_ENABLED=1. The hook is opt-in, silently skips when no catalog exists yet, and never fails your apply — a publish failure logs a warning and the apply stays green.

Three transports, one contract

All consumers speak the same resolver protocol — resolve, list_contracts, lineage_in, lineage_out, health — over one of three transports. Switching transport is a one-line change; the operation surface is identical.

TransportWhen to use itHow it stays fresh
In-processConsumer runs in the same process as the producer — kiri apply, kiri contract lint, lineage queries inside one projectReads the catalog directly; no network, always fresh
HTTP + ETagCross-team, cross-cloud. Producer mounts a small REST endpoint (GET /api/federation/v1/export, GET /api/federation/v1/contracts/{urn})First fetch caches body + ETag; later fetches send If-None-Match, and a 304 Not Modified short-circuits with no body
Filesystem-staticGitOps and air-gapped setups — the producer commits federation/<producer-slug>/export.json to a repo, consumers git pullmtime-watched; a changed mtime triggers re-parse, an unchanged one serves the cache

HTTP supports anonymous read or bearer-token auth (wrong or missing token → 401). Filesystem access control is just file permissions plus git access — auth lives a layer above the resolver.

Health: ok, stale, unavailable

Every resolver answers health() with a status, a cache_age_seconds, and a message:

StatusMeaningOperator action
okQueries served, cache freshNothing
staleCache still serveable, but the live source was unreachable on the last refreshInvestigate the producer endpoint or file mount; the cached snapshot keeps serving
unavailableCache cold and source unreachableProducer must publish first, or the path/URL is wrong

One subtlety worth internalising: cache_age_seconds reflects the age of the content, not the time since the last successful probe. A 304 revalidation does not reset it — polling frequently will not mask a producer that stopped publishing.

Fail-closed where it matters, stale-with-marker where it doesn’t

Operations over a federated source split into two classes, and the degraded-mode behaviour differs deliberately:

Security and correctness operations fail closed. Classification checks during contract approval, AI-policy enforcement, cross-domain consumption gating — anything where acting on stale metadata could leak or misgovern data refuses to proceed when the resolver can’t prove freshness within the caller’s window (typically seconds to minutes). A lint or apply that depends on an unreachable federated source fails rather than guesses. The error names the degraded resolver so the fix is obvious.

Convenience operations serve stale data, marked. Browsing another team’s contracts, computing an impact graph for PR review, populating a recently-changed feed — these keep working from the cached snapshot, with a visible staleness warning when the cache falls outside the freshness window (hours to days is a common tolerance). You can browse during a producer outage; you just can’t approve a classification change against data that might be wrong.

Inspecting a remote catalog from the CLI

Three verbs cover the consumer’s day-to-day:

# Is the producer healthy? (http or filesystem transport)
kiri federation health --transport http --base-url https://producer.example
kiri federation health --transport filesystem --path federation/sales-team/export.json

# What does the producer publish? Filterable by domain,
# classification, and release state.
kiri federation list --base-url https://producer.example \
  --domain sales --classification internal --release-state gold

# Look up one contract by URN
kiri federation resolve kirimana:contract:sales.customer:1 \
  --base-url https://producer.example

Pass --token for bearer-authenticated producers; omit it for anonymous-read ones.

Multi-team governance without a catalog vendor

Put together, this is a governance topology with no central chokepoint:

  • Each team owns its contracts in its own repo and publishes a snapshot on every release — stamped with the release_sha that produced it, so consumers always know which commit they’re reading.
  • Consumers pick the transport that matches their trust boundary: in-process inside a project, HTTP across clouds, plain files in a GitOps repo for air-gapped estates.
  • Classifications, AI policies, and column lineage travel with the snapshot; secrets and internals never do.
  • Nothing is bidirectional. There is no merge conflict between catalogs because there is only one authority per contract: the producing team’s git repo.

If a team later changes platforms, the federation surface doesn’t move — the export format is platform-agnostic, so consumers are untouched. Your metadata library is yours, in git, in a format every adapter reads.

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