Source declarations describe how facts are fetched from external systems. They bridge the gap between the contract's data requirements (facts) and the infrastructure that provides the data.
What Source Declarations Are
Every fact has a source field — a string like "billing_service.payment_status" that names the external system and data point. A source declaration provides the infrastructure details: protocol, endpoint, authentication, and field mapping.
fact payment_received {
type: Bool
source: "billing_service.payment_status"
}
source billing_service {
protocol: http
endpoint: "https://billing.internal/api/v1"
auth: "bearer_token"
mapping: {
payment_status: "GET /payments/{order_id}/status -> .paid"
}
}Separating "What" from "How"
This separation is deliberate:
- Facts are part of the behavioral specification. They declare what data the contract needs.
- Sources are infrastructure metadata. They declare how to get that data.
You can change sources — switch from HTTP to gRPC, move to a different endpoint, change authentication — without changing the contract's behavioral semantics. The evaluator never reads source declarations.
Supported Protocols
HTTP
source billing_api {
protocol: http
endpoint: "https://billing.example.com/api/v2"
auth: "bearer_token"
mapping: {
payment_status: "GET /payments/{id}/status -> .is_paid"
order_total: "GET /orders/{id} -> .total.amount"
}
}GraphQL
source customer_graph {
protocol: graphql
endpoint: "https://customers.example.com/graphql"
auth: "api_key"
mapping: {
customer_tier: "query { customer(id: $id) { tier } } -> .data.customer.tier"
account_status: "query { customer(id: $id) { status } } -> .data.customer.status"
}
}gRPC
source inventory_grpc {
protocol: grpc
endpoint: "inventory.internal:9090"
service: "inventory.v1.InventoryService"
mapping: {
item_count: "GetStock(sku: $sku) -> .quantity"
}
}Database
source warehouse_db {
protocol: database
endpoint: "postgresql://warehouse:5432/inventory"
mapping: {
stock_level: "SELECT quantity FROM stock WHERE sku = :sku"
}
}Static
For constants or test values:
source test_data {
protocol: static
mapping: {
tax_rate: "0.085"
default_currency: "USD"
}
}Manual
For human-entered values:
source manual_input {
protocol: manual
mapping: {
override_approved: "Entered by compliance officer via admin UI"
}
}Extension Protocols
Vendor-specific protocols use the x_ prefix:
source salesforce_crm {
protocol: x_salesforce
endpoint: "https://myorg.salesforce.com"
mapping: {
account_tier: "SOQL: SELECT Tier__c FROM Account WHERE Id = :id"
}
}Using tenor connect
The tenor connect command reads source declarations and generates adapter scaffolding:
tenor connect my-contract.tenorFor each source, the tool generates:
- Client code for the declared protocol
- Type-safe request/response mappings
- Authentication setup scaffolding
- Error handling boilerplate
The generated code is a starting point. Customize it for your specific infrastructure, error handling, and retry policies.
Example: Complete Source Wiring
A contract with three facts from two sources:
fact payment_cleared {
type: Bool
source: "billing.payment_cleared"
}
fact order_amount {
type: Money(USD)
source: "billing.order_amount"
}
fact customer_tier {
type: Enum(standard, premium, enterprise)
source: "crm.customer_tier"
}
source billing {
protocol: http
endpoint: "https://billing.internal/api/v1"
auth: "service_token"
mapping: {
payment_cleared: "GET /payments/{order_id} -> .cleared"
order_amount: "GET /orders/{order_id} -> .total"
}
}
source crm {
protocol: graphql
endpoint: "https://crm.internal/graphql"
auth: "api_key"
mapping: {
customer_tier: "query { customer(id: $id) { tier } } -> .data.customer.tier"
}
}Running tenor connect against this contract generates HTTP client code for the billing API and a GraphQL client for the CRM, with type mappings that produce the fact values the evaluator expects.