# Data Contract: [Dataset or data product name] [version]

> Agreement between the producer of a dataset and its consumers: who owns
> it, what the schema means, which quality rules and service levels it
> guarantees, who may access it, and how it may change. The concepts
> follow the Open Data Contract Standard (ODCS) maintained by the Bitol
> project, so the contract can also be kept as a machine-readable YAML
> file. Replace every `[bracketed]` value and every row marked *Example*.

<!--
Guidance: How to use this template
- Write the contract with the main consumers in the room. A contract that
  only the producer agreed to is a wish list.
- Keep the human-readable document and the YAML file (section 10) in the
  same repository and change them together in one reviewed pull request.
- Every quality rule and service level must be checked automatically;
  write down which job enforces it.
- Breaking changes follow section 7, without exception. Most data
  incidents start with an unannounced column change.
-->

| Field | Value |
|---|---|
| Contract ID | [dc-orders-001] |
| Data product / dataset | [Name] |
| Contract version | [1.2.0] |
| Status | [Proposed / Active / Deprecated / Retired] |
| Domain | [Business domain, for example Sales] |
| Producer owner | [@producer-owner], [team] |
| Data steward | [@steward] |
| Physical location | [Platform, database, schema and table, or topic] |
| Effective from | YYYY-MM-DD |
| Last updated | YYYY-MM-DD |

## 1. Fundamentals

<!-- Guidance: Describe the dataset in plain words: what it represents, why it exists, what it may be used for and its known limitations. -->

### 1.1 Purpose

[Example: "One row per confirmed customer order, used for revenue
reporting, demand forecasting and customer analytics."]

### 1.2 Usage and limitations

| Item | Description |
|---|---|
| Intended uses | *Example:* Daily revenue reporting; forecasting models; cohort analysis |
| Not suitable for | *Example:* Real-time fraud decisions (data is up to 1 hour old); financial statutory reporting (use the ledger) |
| Known limitations | *Example:* Orders before 2022-01-01 lack `channel`; marketplace orders arrive up to 24 hours late |

## 2. Schema

<!-- Guidance: List every column with type, meaning, nullability, keys and classification. The description must be specific enough that two analysts compute the same number from it. -->

Table: `[sales.orders]`. Grain: one row per order.

| Column | Logical type | Physical type | Required | Key | Classification | Description | Example |
|---|---|---|---|---|---|---|---|
| `order_id` | string | `VARCHAR(20)` | Yes | Primary, unique | Internal | Order identifier from the order service | `ORD-2026-0048213` |
| `customer_id` | string | `VARCHAR(20)` | Yes | Foreign key to `customers` | Personal (pseudonymous) | Customer identifier | `CUS-778120` |
| `order_ts` | timestamp | `TIMESTAMP_TZ` | Yes | | Internal | Time the order was confirmed, UTC | `2026-10-14T09:12:44Z` |
| `channel` | string | `VARCHAR(10)` | No | | Internal | One of `web`, `app`, `store`, `marketplace`; null before 2022 | `app` |
| `net_amount` | decimal | `NUMBER(12,2)` | Yes | | Confidential | Order value after discounts, before tax and shipping, in `currency` | `84.50` |
| `currency` | string | `CHAR(3)` | Yes | | Internal | ISO 4217 code | `EUR` |
| `status` | string | `VARCHAR(12)` | Yes | | Internal | One of `confirmed`, `shipped`, `delivered`, `cancelled`, `returned` | `shipped` |
| [column] | [type] | [physical type] | [Yes / No] | [Key] | [Class] | [Description] | [Example] |

## 3. Data quality rules

<!-- Guidance: Each rule has a dimension, a measurable threshold, the check that enforces it and what happens on failure. -->

| ID | Dimension | Rule | Threshold | Check | On failure |
|---|---|---|---|---|---|
| DQ-01 | Uniqueness | `order_id` is unique | 100% | Test in pipeline, every load | Block publish; page producer |
| DQ-02 | Completeness | `customer_id` not null | 100% | Every load | Block publish |
| DQ-03 | Validity | `currency` in the allowed ISO 4217 list | 100% | Every load | Quarantine rows; alert |
| DQ-04 | Accuracy | Daily sum of `net_amount` matches the order service within tolerance | Difference at most 0.1% | Daily reconciliation job | Alert producer; mark day as provisional |
| DQ-05 | Volume | Daily row count within expected range | 50% to 200% of 28-day median | Every load | Alert; consumers notified |
| [DQ-nn] | [Dimension] | [Rule] | [Threshold] | [Check] | [Action] |

## 4. Service levels

<!-- Guidance: Commit to numbers the producer can actually meet and measure. Say how each is measured and over what period. -->

| Property | Commitment | Measured as | Period |
|---|---|---|---|
| Freshness (latency) | *Example:* Data no older than 60 minutes | Now minus max `order_ts` loaded | Checked every 15 min |
| Availability | *Example:* 99.5% of hours queryable | Successful synthetic query per hour | Monthly |
| Late data | *Example:* Marketplace orders complete within 24 hours | Reconciliation | Daily |
| Retention | *Example:* 7 years | Partition lifecycle policy | Continuous |
| Support response | *Example:* Incident acknowledged within 1 business hour | Ticket timestamps | Monthly |
| [Property] | [Commitment] | [Measure] | [Period] |

## 5. Access and security

<!-- Guidance: State who may read the data, how access is granted, and how sensitive columns are protected. -->

| Item | Rule |
|---|---|
| Access request | *Example:* Through [access portal], approved by the data steward |
| Roles | *Example:* `orders_reader` for all columns except `net_amount`; `orders_finance` for all columns |
| Personal data handling | *Example:* `customer_id` is pseudonymous; joining to identity tables requires a privacy-approved purpose |
| Masking | *Example:* `net_amount` masked for non-finance roles |
| Legal basis and purposes | [Reference to records of processing] |
| Audit | *Example:* Query logs retained 1 year |

## 6. Consumers

<!-- Guidance: Register who depends on the contract so they can be notified of changes. -->

| Consumer | Team | Use | Columns used | Contact | Criticality |
|---|---|---|---|---|---|
| *Example:* Revenue dashboard | Finance analytics | Daily revenue | All | [@name] | High |
| *Example:* Demand forecast model | Data science | Training features | `order_ts`, `channel`, `net_amount` | [@name] | High |
| [Consumer] | [Team] | [Use] | [Columns] | [@name] | [H / M / L] |

## 7. Change management and breaking-change policy

<!-- Guidance: Define what counts as breaking, the notice period, and how versions are numbered. -->

Versions follow semantic versioning:

- **Major** (breaking): removing or renaming a column, changing a type or meaning, changing the grain, tightening a nullable column to drop rows, lowering a service level.
- **Minor** (compatible): adding a nullable column, adding an allowed value with notice, improving a service level.
- **Patch**: description fixes, documentation only.

| Rule | Policy |
|---|---|
| Notice for breaking change | *Example:* 30 days to all registered consumers |
| Parallel run | *Example:* Old and new versions published side by side for at least 30 days |
| Approval | *Example:* Producer owner and data steward; consumers with High criticality must acknowledge |
| Emergency change | *Example:* Allowed for security or legal reasons; consumers notified within 1 hour |

## 8. Support

<!-- Guidance: Tell consumers where to ask questions and report problems. -->

| Channel | Use | Hours |
|---|---|---|
| [Team chat channel] | Questions | Business hours |
| [Issue tracker or queue] | Data issues and change requests | Business hours |
| [On-call rota] | Incidents breaching section 4 | 24 x 7 for High criticality consumers |

## 9. Change log

| Version | Date | Author | Change | Type |
|---|---|---|---|---|
| 1.0.0 | YYYY-MM-DD | [@name] | *Example:* First active contract | n/a |
| 1.1.0 | YYYY-MM-DD | [@name] | *Example:* Added nullable `channel` column | Minor |
| 1.2.0 | YYYY-MM-DD | [@name] | *Example:* Freshness improved from 3 hours to 60 minutes | Minor |
| [x.y.z] | YYYY-MM-DD | [@name] | [Change] | [Major / Minor / Patch] |

## 10. Machine-readable contract (YAML skeleton)

<!-- Guidance: Keep this file in the repository and validate it in CI. Field names below are illustrative of ODCS concepts; check the current ODCS specification for the exact field names and version before relying on a validator. -->

The skeleton below mirrors sections 1 to 8 in a YAML layout inspired by
the Open Data Contract Standard. Validate the real file against the ODCS
version you adopt.

```yaml
apiVersion: v3.0.0          # ODCS version adopted
kind: DataContract
id: dc-orders-001
name: orders
version: 1.2.0
status: active
domain: sales
description:
  purpose: One row per confirmed customer order for reporting and forecasting.
  limitations: Marketplace orders may arrive up to 24 hours late.
schema:
  - name: orders
    physicalName: sales.orders
    properties:
      - name: order_id
        logicalType: string
        physicalType: VARCHAR(20)
        required: true
        primaryKey: true
        unique: true
      - name: net_amount
        logicalType: number
        physicalType: NUMBER(12,2)
        required: true
        classification: confidential
    quality:
      - rule: rowCount
        description: Daily volume within 50% to 200% of the 28-day median
slaProperties:
  - property: latency
    value: 60
    unit: minutes
  - property: availability
    value: 99.5
    unit: percent
team:
  - username: producer-owner
    role: owner
support:
  - channel: "#orders-data"
    tool: chat
```

## Standard and licence note

Concepts aligned with the Open Data Contract Standard (ODCS) published by
the Bitol project (bitol-io/open-data-contract-standard, a Linux
Foundation AI and Data project). Only concept and field names are used;
this template is original text written for this collection and copies no
text from the specification. Template licence: MIT.
