Release
The release layer turns data living on the CROSS platform into a
self-contained, portable Frictionless Data Package —
a single .zip that bundles the data files together with a machine-readable
descriptor (datapackage.json and datapackage.yaml).
Where the CrossRegistry is about working with data
interactively, the release layer is about publishing a frozen, citable
snapshot of it: the right resources, fetched and shaped exactly once, packaged
with the metadata a downstream consumer needs to understand and cite the data
without any access to the platform.
The whole process is driven by a single function, create_data_package, and a
declarative release specification that you author as a YAML (or JSON) file.
How it works
You describe what to release in a release specification and call
create_data_package. The function then:
- Fetches the data for each resource from the platform through the
registry, applying any
filtersandaggregationyou declared. - Resolves references: every dimension referenced by a released value
contract is fetched and added to the package automatically, so the package
stays self-contained (set
resolve_references=Falseto opt out). - Embeds the contract: each resource's
schemais taken from its underlying contract, and the contract's descriptive metadata is used as the baseline, with anything you supplied in the specification overlaid on top. - Writes one data file per resource plus
datapackage.jsonanddatapackage.yamlinto the output.zip.
from crosscontract import CrossRegistry
from crosscontract.release import create_data_package
registry = CrossRegistry(username="me", password="secret")
create_data_package(
registry=registry,
release_spec="my_release.yaml",
fn_out="my_release.zip",
)
release_spec accepts either a path to a YAML/JSON file or a
CrossDataPackageReleaseSpec instance directly. fn_out must end in .zip
(or have no suffix — the suffix is added for you).
The release specification
A release specification has two levels: package metadata that describes the release as a whole, and a list of resources, each pairing its own descriptive metadata with the instructions for fetching its data.
# my_release.yaml
name: gdp-release-2025
title: Gross Domestic Product — 2025 Release
description: |
Annual GDP figures released by the CROSS platform.
Markdown is encouraged in descriptions.
# Citation guidance for downstream users (see "What CROSS standardizes" below).
citeas: "CROSS Team (2025): Gross Domestic Product. https://example.org/gdp"
licenses:
- name: CC-BY-4.0
title: Creative Commons Attribution 4.0
path: https://creativecommons.org/licenses/by/4.0/
contributors:
- title: Jane Doe
email: jane.doe@example.org
organization: CROSS
role: author # restricted to author | maintainer | contributor
- title: John Smith
role: maintainer
keywords:
- gdp
- macroeconomics
resources:
- title: Gross Domestic Product
description: GDP in current prices, by country and year.
data_instructions:
fetch:
contract: gdp # the contract to pull from the platform
format: csv # "csv" (default) or "parquet"
filters:
year: [2023, 2024, 2025]
# aggregation: ... # optional, see the registry tutorial
A few things worth knowing:
nameis required on the package but optional on a resource — a resource's name defaults to the name of the contract it fetches from.data_instructions.fetchis the bridge to the platform. Itscontract,filters,aggregation, andformatare the same fetch-and-shape directives the registry uses, so the data is pushed-down and shrunk before it crosses the wire.- Dimensions are added automatically. You only list the value contracts you want; the dimensions they reference (e.g. country, year) are resolved and bundled for you.
- The schema comes from the contract. You do not author field definitions in
the release spec — each resource embeds the schema of its underlying contract
from the platform as the Frictionless
schema, so the published data is fully described and validatable. - Metadata is inherited from the contract. Descriptive fields that a contract
already carries —
title,description,contributors,licenses, andsources— are filled in automatically from that contract when you don't supply them in the release spec. Anything you do set in the spec overrides the contract's value, so the specification only has to state what differs.
What is taken from the contract vs. the specification
For each resource, the released metadata is the contract's metadata with the specification overlaid on top:
| Field | If set in the spec | If omitted in the spec |
|---|---|---|
schema |
always taken from the contract — not authorable in the spec | taken from the contract |
name |
(reserved — currently always the contract name) | the contract's name |
title, description |
the spec value | the contract's value |
contributors, licenses, sources |
the spec value | the contract's value |
The same overlay applies at the package level: package-wide licenses,
contributors, and other metadata you author in the spec describe the release as
a whole, independently of the per-resource fallbacks above.
What CROSS standardizes
The release specification is intentionally permissive: it accepts any extra keys and passes them straight through into the descriptor, so you can enrich a package with whatever metadata your consumers expect. On top of that, CROSS narrows a few parts of the Frictionless standard to keep releases consistent:
- Contributors with a restricted role. The Frictionless standard treats a
contributor's
roleas a free-form string. CROSS restricts it to one ofauthor,maintainer, orcontributor(defaulting tocontributor), so the meaning of a role is unambiguous across every release. A contributor still carriestitle,email,organization, andpath. - Resource-level contributors. Upstream Frictionless allows
contributorsonly on the package. CROSS additionally permits them on each resource, because a single contract may have its own authors and maintainers distinct from the package as a whole. - Validated licenses and sources.
licensesandsourcesfollow the Frictionless rules strictly — e.g. a license must define at least one ofname(an Open Definition identifier) orpath. - Citation via
citeas(recommended pass-through). CROSS does not (yet) formally model a citation field, but because the specification is permissive, aciteaskey authored at the package (or resource) level is carried through verbatim into the descriptor. We recommend addingciteasto every release so downstream users have an authoritative way to cite the data.
Beyond metadata, CROSS also guarantees a few content invariants on every release:
- Self-contained by default. Referenced dimensions are bundled, so a
package needs no platform access to be understood. Foreign keys whose target
is not in the package (e.g. when
resolve_references=False) are dropped so the descriptor stays Frictionless-compliant. - Scenario/model dimensions are pruned. The
dim_modelanddim_scenariodimensions are reduced to exactly the rows the released data references, so a single-scenario release never ships the full platform catalog.
The output package
The resulting .zip is a standard Frictionless Data Package:
my_release.zip
├── datapackage.json # the package descriptor
├── datapackage.yaml # the same descriptor, as YAML
├── gdp.csv # one file per released resource …
├── dim_country.csv # … including the auto-resolved dimensions
└── dim_year.csv
It can be opened by any Frictionless-compatible tooling, archived, or handed to a consumer who has never touched the CROSS platform.