Contracts¶
contracts/ is the only directory domain teams author directly. Every downstream artifact — Debezium connector configs, Flink job schemas, Iceberg table DDL, SLO YAML files, Kafka retention settings — is derived from or generated by these files.
Avro Schemas¶
Every Kafka topic has a schema in contracts/schemas/. These are the wire format contracts: producers and consumers are bound to them. Schema evolution follows BACKWARD_TRANSITIVE compatibility (ADR-0006).
Schemas use Avro logical types throughout — uuid for identifiers, timestamp-millis for all timestamps. This makes field intent unambiguous and ensures correct deserialization in Flink and Iceberg without ad-hoc parsing.
{
"type": "record",
"name": "OrderPlaced",
"namespace": "com.chakraview.orders.events.v1",
"fields": [
{ "name": "event_id", "type": { "type": "string", "logicalType": "uuid" } },
{ "name": "occurred_at", "type": { "type": "long", "logicalType": "timestamp-millis" } },
{ "name": "order_id", "type": { "type": "string", "logicalType": "uuid" } },
...
{ "name": "metadata", "type": { "type": "record", "name": "EventMetadata",
"fields": [{ "name": "trace_id", "type": "string" }] } }
]
}
CDC envelope schema — includes operation enum (INSERT/UPDATE/DELETE/READ), before/after union types, and source.lsn for WAL sequence ordering.
{
"name": "operation",
"type": { "type": "enum", "name": "CdcOperation",
"symbols": ["INSERT", "UPDATE", "DELETE", "READ"] }
}
Data Product Contracts¶
Each data product is defined by a YAML file in contracts/data-products/. This file is the boundary between a domain team's responsibility and the platform team's responsibility.
A data product contract specifies:
| Section | What it defines | Who uses it |
|---|---|---|
slas.ingestion_freshness |
Max lag Bronze ≤ 30s | Alert generation script |
slas.gold_freshness |
Max lag Gold ≤ 5 min | SLO YAML, Prometheus alert |
slas.dlq_rate |
Max DLQ events/hour | Alert threshold |
kafka_retention_days |
Kappa reprocessing window | MSK topic config |
gold_tables[].schema |
Public Gold layer interface | Iceberg DDL generation |
dead_letter.fields |
DLQ record schema | Flink DLQ sink, audit queries |
owner_team |
Who is paged on SLA breach | PagerDuty routing |
orders-analytics.yaml highlights
slas:
gold_freshness:
max_lag_minutes: 5
error_budget_minutes: 43.2
window: 30d
gold_tables:
- name: order_daily_summary
schema:
- { name: order_date, type: date }
- { name: total_revenue_cents, type: long }
- { name: unique_customers, type: long }
- { name: updated_at, type: timestamp_tz }
How Contracts Flow Downstream¶
flowchart TD
S["contracts/schemas/*.avsc"]
DP["contracts/data-products/*.yaml"]
S -->|"Debezium value.converter"| DC["pipeline/debezium/*.json\nconnector config"]
S -->|"Flink deserialization"| FJ["pipeline/flink/*.py\nAvroRowDeserializationSchema"]
S -->|"Silver table schema"| ICE["Iceberg Silver table DDL\n(agent-generated)"]
DP -->|"gold_tables schema"| GOLD["Iceberg Gold table DDL\n(agent-generated)"]
DP -->|"slas.gold_freshness"| SLO["observability/slos/*.yaml"]
DP -->|"kafka_retention_days"| MSK["MSK topic retention\nTerraform variable"]
DP -->|"slas.dlq_rate"| ALERT["observability/alerts/*.yaml"]
DP -->|"owner_team"| PD["PagerDuty routing"]
Validation¶
tooling/validate-data-contracts.sh (generated by Script Authoring Agent) checks:
- Every
contracts/schemas/*.avscis valid Avro JSON - Every
contracts/data-products/*.yamlreferences a schema that exists incontracts/schemas/ - Every data product has a matching
observability/slos/*.yaml - Every Gold table name in a data product has a matching dbt model in
pipeline/dbt/models/gold/
Run locally: bash tooling/validate-data-contracts.sh