Skip to content

Resolve authoritativeDefinitions that reference another contract file - #1453

Open
simonharrer wants to merge 1 commit into
mainfrom
feature/local-business-definition-references
Open

Resolve authoritativeDefinitions that reference another contract file#1453
simonharrer wants to merge 1 commit into
mainfrom
feature/local-business-definition-references

Conversation

@simonharrer

Copy link
Copy Markdown
Contributor

A property can now link to a property in another contract file, and the CLI resolves that link relative to the referencing contract before linting, testing, or exporting:

# top-artists-by-year-view.odcs.yaml
properties:
  - name: artist_name
    logicalType: string
    physicalType: character
    primaryKey: true
    authoritativeDefinitions:
      - type: businessDefinition
        url: top-artists-by-year.odcs.yaml#schema/top_artists_by_year_ba/properties/artist_name

The technical contract keeps its own physical shape and inherits businessName, description, examples, and everything else the business attribute defines. This covers the common layering of a business-level contract plus one technical contract per materialization, where both live in the same repository and no server is involved.

How it works

  • The route is chosen by the url's shape, not by the link's type. A # fragment on a non-HTTP url is read from disk; anything else keeps going through the existing lookup. So every resolvable type accepts either form.
  • businessDefinition is now a resolvable type, alongside semantics, semantic, and definition — the type says what a reference means, not whether it is a file or a URL. Precedence becomes semanticssemanticdefinitionbusinessDefinition.
  • Fragments walk schema/<schema>/properties/<property>, matching on id first and falling back to name, and descend into nested properties and array items. A fragment must end at a property.
  • Chains resolve transitively (technical → business → glossary), each file parsed once per run. A cycle between files is reported as an error rather than followed.
  • Merge semantics are unchanged: inline values always win, and id / name / authoritativeDefinitions / properties / items are never merged.

Behaviour change

businessDefinition links pointing at an HTTP URL were previously informational and triggered no request; they are now fetched like definition links. A contract whose businessDefinition points at something that is not an ODCS property document (a Confluence page, say) will now fail to resolve, and --no-inline-references is the escape hatch. Flagging it explicitly since it affects existing contracts.

Also

  • examples/business-definitions/ — an anonymized two-contract example, linted by lint_examples.py in CI.
  • docs/docs/semantics.md — a "Reference another contract file" section.
  • tests/test_resolve_local_definitions.py — 20 tests covering resolution by id and name, nested properties and array items, relative paths, merge precedence, one-read-per-file, transitive chains, cycle detection, every failure mode, and --no-inline-references.

Full suite passes; the s3/schema-evolution failures seen under -n 8 are testcontainer port contention and pass serially. test_duckdb_json.py::test_nested_json and the test_test_mysql.py import error both fail on main too.

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

📖 Docs preview

Preview site: https://brave-water-0cee36e03-1453.westeurope.7.azurestaticapps.net

Changed pages (most-changed first):

A property can now link to a business definition kept in a file next to
the contract, resolved relative to the referencing contract. This lets a
technical contract own its physical shape while inheriting the business
meaning from the same repository, with no server involved.

Two shapes, both resolvable by every type:

  url: business.odcs.yaml#schema/orders/properties/order_id
  url: definitions/order_id.odcs.yaml

With a fragment, the reference addresses one property inside another
contract. Without one, the file *is* the definition and holds the
property's elements directly -- a glossary as one file per term.

The route is chosen by the url's shape, not by the link's type: a `#`
fragment reads from disk, as does a fragment-less url naming a .yaml,
.yml, or .json file; anything else keeps going through the existing
lookup, so `url: /definitions/order_id` stays a path on the configured
host. `businessDefinition` becomes a resolvable type alongside
`semantics`, `semantic`, and `definition`, since the type says what a
reference means and not whether it is a file or a URL.

Fragments walk `schema/<schema>/properties/<property>`, matching on `id`
first and falling back to `name`, and descend into nested properties and
array items. Chains resolve transitively; a cycle between files is
reported rather than followed.
@simonharrer
simonharrer force-pushed the feature/local-business-definition-references branch from 31d5059 to 0290d8f Compare July 29, 2026 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant