Skip to content

Data Contracts: schemas, teams, and linked Data Products

A Data Contract in Datahub describes the shape, owner, lifecycle, and SLOs of a published data interface — the "API" between the team that produces a dataset and the teams that consume it. This page covers how contracts attach to the assets they describe (via Data Products), the team & schema metadata you maintain on each contract, and the ODCS export.

When to choose this

Use a Data Contract when you want to:

  • Publish a stable interface. A contract pins a version, an owner, an SLO, and a schema that downstream consumers can rely on.
  • Govern who depends on what. The contract's Linked Products tab is the bridge between the contract and every underlying asset (metrics, glossary terms, catalog assets, processes, connections, alert rules) — wrapped in Data Products.
  • Export ODCS. Datahub emits valid Open Data Contract Standard YAML for every contract; consumers can pull this into their own pipelines.

You do not need a Data Contract for:

  • Internal scratch tables or work-in-progress notebooks.
  • Ad-hoc views that no team outside yours consumes.
  • A glossary term in isolation (it lives in the glossary; promote to a Data Product first if it earns a contract).

What changed in April 2026 — contracts link to Data Products only

Read this first if you used to link contracts directly to metrics, glossary terms, catalog assets, processes, connections, or alert rules.

Before April 2026, the Link entity modal on a contract detail page offered six entity types behind a tabbed picker: Data Product, BPM Process, Data Catalog Asset, Glossary Term, Metric, Connection. As of April 2026 the modal collapses to a single Data Product picker.

Then Now
Pick Metric → pick mrr → linked. Open the metric's detail page → Register as Data Product → link the new Data Product to the contract.
Pick Glossary Term → pick Customer → linked. Open the glossary term → Register as Data Product → link the product to the contract.
Pick Connection → pick prod-warehouse → linked. Open the connection → Register as Data Product → link the product.
Pick Data Product → pick Customer 360 → linked. Unchanged — the Linked Product modal still works exactly the same way for products.

The functional reason: a contract describes a product that a team ships to consumers, and the product is the noun that makes sense as the link target. The architectural reason: it removes a polymorphic lookup that bled the contracts module into every consumer module. See docs/customer/data-products.md for the bundle bridge.

What about my legacy non-product links? They were deleted at the lockdown migration. If you had a real direct link that mattered, register the asset as a Data Product (it takes one click on the asset detail page) and re-attach the resulting product to the contract.

What a Data Contract looks like

Surface Where What you see
List /data-contracts Filterable table — name, version, status, domain, contract team. KPIs / chart at the top of the lander.
Detail — Overview tab /data-contracts/{id} (default tab) Name, description, version, status with state-machine actions, domain, owner, ODCS export download, audit metadata.
Detail — Schema tab /data-contracts/{id} Schema objects (datasets, fields, types, constraints, descriptions).
Detail — Team tab /data-contracts/{id} Contract team members + roles.
Detail — Linked Products tab /data-contracts/{id} Every Data Product linked to this contract. Each row: product name, type badge (always Data Product), linked-at, unlink (gated on the contract write role). Use Link Data Product to attach more — the picker shows every Data Product not yet linked to this contract.

After April 2026 this modal contains exactly one combobox: Data product. The list is useDataProducts filtered to exclude any product already linked to this contract, so you can never pick a product you can't actually attach. Submit is disabled until you pick one; the modal protects against discarding a picked-but-not-saved value with a confirmation if you press Escape, click the backdrop, or hit the close button.

Setup — what an admin needs to do once

There is no per-tenant setup required for the Linked Products bridge itself. The relevant prereqs are:

Prereq Where Why
At least one Data Product exists /data-products (or via the Register as Data Product flow on any asset) The Link Data Product modal needs at least one product to pick from.
Roles /admin/users (role groups) datacontracts.contracts.read to view, datacontracts.contracts.write to create / edit / link / unlink products. The Register as Data Product flow on the asset side requires dataproducts.products.write (different module).

Linking an asset to a contract — the full path

The full path used to be one click. After April 2026 it is two clicks:

  1. On the asset's detail page (metric, glossary term, catalog asset, process, connection, alert rule) — find the Part of N data products panel and click Register as Data Product. Either create a new product or add the asset to an existing one.
  2. On the contract's detail pageLinked Products tab → Link Data Product → pick the product → save.

If multiple assets need to flow into the same contract, wrap them all in one Data Product and link that product once. Example: Customer 360 contract → Customer 360 product (4 metrics + 2 catalog assets + 1 glossary term inside) → one link from contract to product.

How it works

What entity_type='data_product' means under the hood

The contract_product_links table has a polymorphic shape (entity_type + entity_id) that historically supported six entity types. As of April 2026 it carries a CHECK constraint that locks entity_type to the literal 'data_product', and the ContractProductLink domain model rejects any other value at the API layer. Both safeguards are explicit; the database refuses bad direct writes and the API refuses bad request bodies.

ODCS export

The ODCS YAML emitted by GET /datacontractsmodule/contracts/{id}/odcs derives the info.dataProduct block from the Data Products linked to this contract. The shape of the export is unchanged from before April 2026 — only the source data is now uniform (one product type) instead of polymorphic.

Limitations

Limit Why Workaround
You cannot link a metric / glossary term / catalog asset / process / connection / alert rule directly to a contract DPB-D3 — see What changed in April 2026. Register the asset as a Data Product first, then link the product.
The Link Data Product modal does not show products you've already linked Already-linked products are filtered out of the dropdown so you never see a 409. Unlink the product first if you want to "re-link" it (rarely useful).
Pre-2026 direct links to non-product entities were deleted at migration DPB-D4 — chosen over a "wrap each one in a synthetic product" backfill that would have generated curator-less products. Re-register the relevant assets as Data Products.

Audit & compliance

Question a CISO might ask Where to look
"Which Data Products does this contract govern?" The contract's Linked Products tab.
"Which assets sit inside those Data Products?" Click each linked product → switch to the product's Assets tab.
"Can someone link an unrelated entity to a contract by editing the API directly?" No. contract_product_links.entity_type has a CHECK constraint at the SQL layer AND ContractProductLink.create() rejects any value other than 'data_product' at the model layer. Both paths are enforced.
"Where do legacy direct links live now?" They were deleted at the lockdown migration; the migration logged the row count via RAISE NOTICE.
"Who can link or unlink a Data Product from a contract?" Anyone with datacontracts.contracts.write. Read-only viewers see the tab but no buttons.

Troubleshooting

Symptom Likely cause Fix
Link Data Product modal dropdown is empty No Data Products exist yet (or all are already linked) Register an asset as a Data Product on its detail page first.
The asset I want to put on the contract is not in any product You haven't wrapped it yet Open the asset's detail page → Register as Data Product.
Submit on the modal stays disabled No product is selected Pick a product from the dropdown. The modal disables submit until a value is picked.
Pressing Escape / closing the modal silently loses my selection The dirty-state guard is intentional — confirm the discard Pick a product first → the close affordances now show a discard confirmation. Re-open and pick again.
ODCS export info.dataProduct shows the wrong name The product name was edited after the link was created The ODCS export reads the current product name; re-export to refresh.
The Linked Products tab is empty for a contract that "had links last week" Pre-2026 direct links were deleted at the lockdown migration Re-register the relevant assets as Data Products and re-attach.
HERC says "I can't link a metric directly to a contract" when asked This is the new product behaviour, not a bug Tell HERC to register the metric as a data product first, then link the product.

If something is broken that this page does not cover, ping your Datahub contact with the contract ID (visible in the URL) and the error text from the toast / banner.

See also