# V0 Authored Contract Schema

## Purpose

The authored contract schema defines the Git source of truth for data product contracts.

Authored contracts are written as YAML, validated by JSON Schema, collated by the contract engine, and projected into runtime-served JSON views.

This document defines the v0.1.0 authored schema shape. Pre-1.0 schema versions may break.

Machine-readable schema:

```text
schemas/data-product-contract.authored.v0.schema.json
```

## Contract Shape

Minimum authored contract fields:

- `schema_version`
- `id`
- `name`
- `version`
- `layer`
- `owner`
- `domain`
- `purpose`
- `usage`
- `assets`
- `schema`
- `freshness`
- `tests`
- `governance`
- `agent_permissions`
- `compatibility`

Optional fields become required under layer-specific validation profiles.

## Layers

The authored schema uses one universal contract format with layer-specific validation profiles.

Layers:

- `raw`
- `staging`
- `curated`
- `service`

Layer is not an ordered pipeline progression. It is the contract's declared responsibility and guarantee class.

## Layer Profiles

### Raw

Raw contracts must declare source information and access/retention intent.

Emphasis:

- Source provenance
- Schema capture
- Retention
- Access constraints
- Minimal semantic guarantees

### Staging

Staging contracts must declare source information, schema, freshness, tests, and caveats through usage/prohibited usage.

Emphasis:

- Type normalization
- Deduplication
- Schema/version guarantees
- Exploration and data science usage

### Curated

Curated contracts must declare semantics and at least one executable or observable test.

Emphasis:

- Business semantics
- Test thresholds
- SLOs
- Governed production consumption

### Service

Service contracts must declare an interface, semantics, and at least one executable or observable test.

Emphasis:

- Consumption-specific interfaces
- Marts, metrics, BI views, APIs, or agent-facing tools
- Strongest user-facing compatibility expectations

## Authored vs Runtime Fields

The authored contract contains declared intent.

Runtime-only facts do not belong as authored source-of-truth fields unless they are declared expectations or references.

Authored examples:

- Declared owner
- Declared layer
- Declared schema
- Declared freshness expectation
- Embedded tests
- Governance intent
- Agent permission intent
- Declared upstreams

Governance intent should be classification-driven where possible. Classifications may be declared at domain, product, asset, or field level and inherited down the hierarchy. Explicit policy declarations are refinements or approved exceptions.

The v0 starter classification mapping is defined in `docs/design/v0-governance-classifications.md`.

Runtime-served examples:

- Effective lineage
- Effective governance policy
- Effective agent permissions
- Current test results
- Current freshness state
- Observed schema state
- Run history
- Promotion provenance

## File Layout

Canonical product contracts should live at:

```text
contracts/<domain>/<data-product>/contract.yaml
```

Asset-local fragments may live near dbt models, Dagster assets, dlt sources, SQL files, or Python assets. The contract engine collates those fragments into the effective authored contract before publishing a runtime-served view.

## Example

```yaml
schema_version: 0.1.0
id: revenue.monthly_recurring_revenue
name: Monthly Recurring Revenue
version: 0.1.0
layer: curated

owner:
  type: team
  name: revenue-analytics
  contacts:
    - kind: slack
      value: "#revenue-analytics"
  approvers:
    - ywang

domain:
  name: revenue

purpose: >
  Provides governed monthly recurring revenue measures for finance,
  executive reporting, and agent-assisted revenue analysis.

usage:
  intended:
    - Finance reporting
    - Revenue analysis
    - Agent-assisted metric explanation
  prohibited:
    - Customer-facing billing calculations

assets:
  - id: mrr_by_account_month
    kind: table
    ref: analytics.revenue.mrr_by_account_month
    description: One row per account per billing month.

schema:
  kind: relational
  columns:
    - name: account_id
      type: string
      nullable: false
      description: Stable account identifier.
    - name: month
      type: date
      nullable: false
      description: Billing month.
    - name: mrr_usd
      type: decimal(18,2)
      nullable: false
      description: Monthly recurring revenue in USD.

semantics:
  metrics:
    - name: mrr
      expression: sum(mrr_usd)
      description: Monthly recurring revenue in USD.
      grain: account_id, month

freshness:
  max_age: PT24H
  timezone: UTC

tests:
  - id: mrr_non_negative
    type: sql
    severity: blocking
    description: MRR must not be negative.
    sql: |
      select *
      from analytics.revenue.mrr_by_account_month
      where mrr_usd < 0

declared_lineage:
  upstreams:
    - kind: data_product
      ref: billing.invoices
      required: true

governance:
  classifications:
    - internal
  access:
    default: restricted
    allowed_roles:
      - finance_analyst
      - revenue_agent
  masking:
    - field: account_id
      policy: hash_for_non_finance
  retention:
    period: P7Y
  audit:
    required: true
    events:
      - query
      - export

agent_permissions:
  default: deny
  grants:
    - principal: revenue-analysis-agent
      max_risk_tier: controlled_operational
      allowed_actions:
        - discover
        - query
        - explain
        - create_ticket
      constraints:
        - Must not export row-level data outside approved finance workspaces.

compatibility:
  change_policy: semver
  deprecation_window: P90D
```

## Runtime Projection

The runtime-served contract view should include a pointer back to the Git-authored contract:

- repository
- path
- commit SHA
- contract version
- promotion time
- promoter
- validation result

That provenance belongs to the runtime-served view, not the authored YAML.
