Skip to content

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.

hcl
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

hcl
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

hcl
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

hcl
source inventory_grpc {
  protocol: grpc
  endpoint: "inventory.internal:9090"
  service:  "inventory.v1.InventoryService"
  mapping: {
    item_count: "GetStock(sku: $sku) -> .quantity"
  }
}

Database

hcl
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:

hcl
source test_data {
  protocol: static
  mapping: {
    tax_rate: "0.085"
    default_currency: "USD"
  }
}

Manual

For human-entered values:

hcl
source manual_input {
  protocol: manual
  mapping: {
    override_approved: "Entered by compliance officer via admin UI"
  }
}

Extension Protocols

Vendor-specific protocols use the x_ prefix:

hcl
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:

bash
tenor connect my-contract.tenor

For 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:

hcl
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.