A Source is a named declaration of an external system from which facts are populated at runtime. Sources carry connection metadata and protocol identity but do not describe the external system's schema. Sources are infrastructure metadata with zero impact on evaluation -- the evaluator ignores Source constructs entirely. They are consumed by adapters, provenance enrichment, automated tooling (tenor connect), and deployment infrastructure.
DSL Syntax
source <source_id> {
protocol: <protocol_tag>
<field>: <value>
...
description: "<text>" // optional
}Fields
| Field | Required | Description |
|---|---|---|
protocol | Yes | A core protocol tag or extension tag identifying the external system type. |
description | No | Human-readable description of the source system. |
| Additional fields | Depends on protocol | Protocol-specific fields (e.g., base_url, dialect). All values are strings. |
Core Protocol Tags
The specification defines six core protocol tags. Each has required fields and semantic description:
| Protocol | Required Fields | Description |
|---|---|---|
http | base_url | HTTP/HTTPS REST API. Optional: auth, schema_ref. |
database | dialect | Relational database. Dialect values: postgres, mysql, sqlite. Optional: schema_ref. |
graphql | endpoint | GraphQL API. Optional: auth, schema_ref. |
grpc | endpoint | gRPC service. Optional: proto_ref. |
static | (none) | Static configuration or environment variable. |
manual | (none) | Human-provided input. |
The schema_ref field (where available) is an optional pointer to the external system's own schema document (OpenAPI, GraphQL SDL, Protobuf, SQL DDL). It is not parsed or validated by the elaborator -- it exists for tooling consumption (e.g., tenor connect uses it to introspect the external system).
Extension Protocol Tags (x_*)
Extension protocol tags use a namespaced identifier with the prefix x_. The namespace separator is .:
source risk_engine {
protocol: x_internal.event_bus
description: "Internal Kafka-backed risk engine"
}
source legacy_mainframe {
protocol: x_company.cics_gateway
description: "Legacy CICS transaction gateway"
}Extension tags have no elaborator-enforced required fields. The elaborator validates only that the tag matches the pattern x_[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*. Required-field validation for extension protocols is deferred to adapter-level tooling.
Source Declaration Examples
HTTP Source
source order_service {
protocol: http
base_url: "https://api.orders.com/v2"
auth: bearer_token
schema_ref: "https://api.orders.com/v2/openapi.json"
description: "Order management REST API"
}Database Source
source compliance_db {
protocol: database
dialect: postgres
description: "Compliance reporting database"
}GraphQL Source
source customer_service {
protocol: graphql
endpoint: "https://customers.internal/graphql"
auth: api_key
description: "Customer data GraphQL API"
}gRPC Source
source pricing_service {
protocol: grpc
endpoint: "pricing.internal:50051"
proto_ref: "protos/pricing/v1/pricing.proto"
description: "Real-time pricing gRPC service"
}Static Source
source config {
protocol: static
description: "Environment configuration values"
}Manual Source
source buyer_portal {
protocol: manual
description: "Human-provided input from buyer self-service portal"
}Linking Facts to Sources
Facts reference sources in two ways:
Freetext source reference
fact delivery_confirmed {
type: Bool
source: "tracking_service.delivered"
}Structured source reference
fact escrow_amount {
type: Money(currency: "USD")
source: order_service { path: "orders/{id}.balance" }
}Structured references are validated by the elaborator: the source_id must reference a declared Source construct (C-SRC-06). Freetext references are not validated beyond non-empty.
Zero Evaluation Impact
Sources have absolutely no effect on contract evaluation. Removing all Source declarations from a contract produces identical evaluation behavior. This separation preserves C5 (closed-world semantics): all evaluation-relevant state is contract-contained; all execution-relevant state is declared, named, and inspectable -- but never executed by the evaluator.
This means:
- You can change sources without changing the contract's behavior.
- You can evaluate a contract with manually-provided facts (no sources needed).
- Source declarations can be added or modified after the contract is deployed.
Non-Goals
The following are explicitly outside the scope of Source declarations:
- No fetch semantics. A Source declaration does not cause the evaluator or elaborator to connect to or fetch data from the declared system.
- No schema declaration. A Source does not describe the shape, fields, types, or structure of the external system's data.
- No credential storage. Authentication fields declare the type of authentication required, not credentials themselves.
- No health checking. A Source does not imply the external system is reachable or conforming.
Full Working Example
A complete contract with multiple source types:
// --- Sources ---
source order_service {
protocol: http
base_url: "https://api.orders.com/v2"
auth: bearer_token
schema_ref: "https://api.orders.com/v2/openapi.json"
description: "Order management REST API"
}
source compliance_db {
protocol: database
dialect: postgres
description: "Compliance reporting database"
}
source buyer_portal {
protocol: manual
description: "Human-provided input from buyer self-service portal"
}
// --- Facts referencing sources ---
fact escrow_amount {
type: Money(currency: "USD")
source: order_service { path: "orders/{id}.balance" }
}
fact compliance_threshold {
type: Money(currency: "USD")
source: compliance_db { path: "compliance_thresholds.amount" }
default: 10000.00
}
fact buyer_requested_refund {
type: Bool
source: buyer_portal { path: "refund_requested" }
}
fact delivery_confirmed {
type: Bool
source: "tracking_service.delivered"
default: false
}
// --- Personas ---
persona buyer
persona seller
persona escrow_agent
// --- Entity ---
entity EscrowAccount {
states: [held, released, refunded]
initial: held
transitions: [
(held, released),
(held, refunded)
]
}
// --- Rules ---
rule within_threshold {
stratum: 0
when: escrow_amount <= compliance_threshold
produce: verdict within_threshold { payload: Bool = true }
}
rule delivery_ok {
stratum: 0
when: delivery_confirmed = true
produce: verdict delivery_ok { payload: Bool = true }
}
// --- Operations ---
operation release_escrow {
personas: [escrow_agent]
require: verdict_present(within_threshold) and verdict_present(delivery_ok)
effects: [EscrowAccount: held -> released]
outcomes: [released]
}
operation refund_buyer {
personas: [escrow_agent]
require: buyer_requested_refund = true
effects: [EscrowAccount: held -> refunded]
outcomes: [refunded]
}Constraints
C-SRC-01 -- Unique source identifiers. (Pass 5) Source identifiers are unique within a contract. Violation: "duplicate source declaration '<source_id>'".
C-SRC-02 -- Source identifiers occupy a distinct namespace. (Pass 5) A Source named Foo does not conflict with a Fact, Entity, Persona, or other construct named Foo.
C-SRC-03 -- Core protocol required fields. (Pass 5) For core protocol tags, the elaborator validates all required fields are present. Violation: "source '<source_id>' with protocol '<tag>' is missing required field '<field>'".
C-SRC-04 -- Extension protocol tag format. (Pass 5) Extension tags must match x_[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*. Violation: "invalid extension protocol tag '<tag>'".
C-SRC-05 -- Source field values are strings. (Pass 5) All source field values are Text. No typed field values (numbers, booleans, nested records).
C-SRC-06 -- Structured source reference resolution. (Pass 5) If a fact uses a structured source, the source_id must reference a declared Source. Violation: "fact '<fact_id>' references undeclared source '<source_id>'".
Common Mistakes
Confusing sources with facts. A source is infrastructure metadata describing how data is fetched. A fact declares what data is needed. You can have a fact without a source declaration -- the fact's freetext source string is sufficient for documentation.
Over-specifying sources in early development. During contract design, focus on facts and types. Add source declarations when you are ready to wire up real systems.
Including credentials in source declarations. Auth fields declare the type of authentication, not actual credentials. Credentials belong in adapter configuration (TOML files), not in contracts.
Expecting sources to affect evaluation. Sources are invisible to the evaluator. Changing a source's base_url changes nothing about verdicts, entity state, or flow outcomes.
How Sources Connect to Other Constructs
- Facts reference sources via structured source references (the
source: <source_id> { path: "..." }form). - Adapters use source declarations to generate connection scaffolding (
tenor connect). - Provenance enrichment records which source and adapter fetched each fact value (executor capability, not obligation).
- Rules, operations, flows, and entities have no relationship to sources whatsoever.
Static Analysis Properties
- Sources are validated during Pass 5 for structural correctness (C-SRC-01 through C-SRC-06).
- Source declarations have no impact on any S-property (S1--S8). Removing all sources does not change any static analysis result.
- Source changes between contract versions are classified as INFRASTRUCTURE in the migration taxonomy -- they require adapter updates but do not affect evaluation correctness.