Data Contracts Registry
Version, publish, and manage your schemas centrally with the Data Contracts Registry.
Quick Start
# Publish a schema version
fake_data_dsl contracts publish User -v 1.0.0 -s schemas/ -m "Initial release"
# List all contracts
fake_data_dsl contracts list
# Check compatibility
fake_data_dsl contracts diff User 1.0.0 2.0.0
CLI Commands
Publish
fake_data_dsl contracts publish <Schema> -v <version> [options]
Options:
-s, --schema-dir DIR Schema directory
-m, --message MSG Changelog message
-d, --dir DIR Contracts directory (default: contracts)
Example:
fake_data_dsl contracts publish User -v 1.0.0 -s schemas/ -m "Initial User schema"
Deprecate
fake_data_dsl contracts deprecate <Schema> -v <version> [options]
Options:
--sunset DATE Sunset date (YYYY-MM-DD)
-m, --message MSG Deprecation message
Example:
fake_data_dsl contracts deprecate User -v 1.0.0 --sunset 2026-06-01 -m "Use v2.0.0 instead"
List
fake_data_dsl contracts list
Output:
Data Contracts:
User:
✅ v2.0.0 (5 fields)
⚠️ v1.0.0 (3 fields)
Order:
✅ v1.0.0 (8 fields)
History
fake_data_dsl contracts history User
Output:
History for User:
2026-01-24T10:30:00Z - v2.0.0 published
Added avatar field, changed email validation
2026-01-01T09:00:00Z - v1.0.0 deprecated
Use v2.0.0 instead
2025-06-15T14:00:00Z - v1.0.0 published
Initial release
Diff
fake_data_dsl contracts diff User 1.0.0 2.0.0
Output:
Comparing User v1.0.0 → v2.0.0
❌ Breaking changes detected!
Changes:
Removed: legacy_field
Added: avatar, updated_at
Type changed: age (text → number)
Ruby API
Initialize Registry
# Create registry with storage directory
registry = FakeDataDSL::ContractsRegistry.new("contracts/")
Publish
schema = FakeDataDSL.load("schemas/user.dsl")
contract = registry.publish(
"User",
version: "1.0.0",
schema: schema,
changelog: "Initial release"
)
puts contract[:schema_hash] # Content hash for integrity
puts contract[:fields] # Field signatures
Deprecate
registry.deprecate(
"User",
version: "1.0.0",
sunset_date: Date.new(2026, 6, 1),
message: "Migrate to v2.0.0"
)
Retire
registry.retire("User", version: "1.0.0")
Get Contract
# Get specific version
contract = registry.get("User", version: "1.0.0")
# Get latest published version
latest = registry.get("User") # Returns newest published
List Versions
versions = registry.versions_for("User")
# => ["1.0.0", "1.1.0", "2.0.0"]
Check Compatibility
result = registry.compatible?("User", "1.0.0", "2.0.0")
if result[:breaking]
puts "Breaking changes detected!"
puts "Removed fields: #{result[:changes][:removed_fields]}"
puts "Type changes: #{result[:changes][:type_changes]}"
else
puts "Compatible!"
end
Compatibility result:
{
compatible: false,
breaking: true,
changes: {
removed_fields: ["legacy_field"],
added_fields: ["avatar", "updated_at"],
type_changes: [{ field: "age", from: "text", to: "number" }],
required_changes: [{ field: "email", change: "optional → required" }]
},
summary: "Removed fields: legacy_field; Type changed: age (text → number)"
}
Validate Against Contract
current_schema = FakeDataDSL.load("schemas/user.dsl")
result = registry.validate("User", version: "1.0.0", schema: current_schema)
if result[:valid]
puts "Schema matches contract!"
else
puts "Schema drift detected!"
puts "Missing: #{result[:missing_fields]}"
puts "Extra: #{result[:extra_fields]}"
end
History
history = registry.history("User")
history.each do |entry|
puts "#{entry[:timestamp]} - v#{entry[:version]} #{entry[:action]}"
puts " #{entry[:message]}" if entry[:message]
end
Export/Import
# Export all contracts to directory
registry.export("exported_contracts/")
# Import contracts from directory
registry.import("imported_contracts/")
Contract States
| State | Description |
|---|---|
draft |
Not yet published |
published |
Active and available |
deprecated |
Scheduled for removal |
retired |
No longer available |
Breaking Changes
The following changes are considered breaking:
| Change | Breaking? | Description |
|---|---|---|
| Field removed | ✅ Yes | Consumers depend on this field |
| Type changed | ✅ Yes | number → text breaks parsing |
| Optional → Required | ✅ Yes | Consumers may not provide |
| Field added | ❌ No | Backwards compatible |
| Required → Optional | ❌ No | Backwards compatible |
CI Integration
Use contracts in CI pipelines:
# .github/workflows/schema-check.yml
name: Schema Validation
on: [push, pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Check for breaking changes
run: |
# Publish current schema
bundle exec fake_data_dsl contracts publish User \
-v ${{ github.sha }} \
-s schemas/
# Compare with main branch
bundle exec fake_data_dsl contracts diff User main ${{ github.sha }}
Storage Format
Contracts are stored as JSON files:
contracts/
├── schemas/
│ ├── User_v1.0.0.json
│ ├── User_v2.0.0.json
│ └── Order_v1.0.0.json
└── history/
├── User.json
└── Order.json
Contract file structure:
{
"name": "User",
"version": "1.0.0",
"state": "published",
"schema_hash": "abc123def456",
"fields": [
{ "name": "id", "type": "uuid", "optional": false, "nullable": false }
],
"published_at": "2026-01-24T10:30:00Z",
"changelog": "Initial release"
}