Tenor's formal guarantees hold conditional on executor conformance. The language describes a closed world, but its foundations --- Fact values, transition atomicity, snapshot isolation --- depend on the executor and runtime environment. Where executor obligations are not met, the provenance chain is corrupt, not merely incomplete, and Tenor cannot detect non-conformance internally.
The twenty obligations are organized into four groups:
| Group | Obligations | Scope |
|---|---|---|
| Logic | E1-E9 | Core evaluation and execution semantics |
| Protocol | E10-E14 | Discovery, manifest, and agent interaction |
| Instance | E15-E17 | Entity instance lifecycle management |
| Trust | E18-E20 | Cryptographic attestation and provenance |
Logic Conformance vs. Operational Conformance
Before diving into the individual obligations, understand this distinction:
Logic conformance means the executor correctly implements the contract's logic as expressed in the interchange JSON. Given the same interchange bundle and the same FactSet, a logic-conforming executor produces the same verdicts, the same entity state transitions, and the same flow outcomes as any other logic-conforming executor. Logic conformance is verifiable against the artifact --- the conformance test suite exercises it with known-input/expected-output triples.
Operational conformance means the executor honors E1-E20 under real production conditions. Atomicity under failure. Snapshot isolation under concurrency. External source integrity across network boundaries. These obligations cannot be verified from the artifact alone --- they depend on the executor's storage substrate, concurrency model, network topology, and failure recovery semantics.
A conforming elaborator plus a signed interchange artifact proves logic conformance. It makes no claims about operational conformance. Operational conformance is the executor's responsibility and must be verified separately.
Obligations marked (trust boundary) are specifically those where logic conformance and operational conformance diverge. The language specifies what must happen; only the executor can ensure it does.
Logic Obligations (E1-E9)
E1 --- External Source Integrity (trust boundary)
Facts are populated from genuinely external sources as declared. An executor must not populate Facts from internal computations or cross-Fact dependencies.
Requirements:
- Every fact value must originate from the external source identified in the contract's Fact or Source declaration.
- The executor must not synthesize fact values from other facts, from internal state, or from evaluation results.
- The executor must not populate a fact with a value derived from another fact's value.
Why this is a trust boundary: Violation of E1 corrupts the provenance root. Every provenance chain built on a non-externally-sourced fact is semantically invalid. The language cannot detect this --- it has no mechanism to verify that a fact value actually came from the declared source. E1 is enforced by the executor's integrity, not by the language.
What breaks if violated: If a fact is populated from an internal computation rather than an external source, the entire evaluation is contaminated. Verdicts derived from that fact carry false provenance. Operations gated on those verdicts execute under false pretenses. The audit trail is fiction.
E2 --- Transition Source Validation
Before applying an Operation's effects, the executor must validate that the current state of the targeted instance matches the transition source for each declared effect.
Requirements:
- For each effect
(entity_id, from_state, to_state)in the operation, the executor reads the current state of the targeted instance (identified by the(EntityId, InstanceId)pair from the flow's instance binding map). - If the current state does not match
from_state, the executor must abort the operation with anInvalidEntityStateerror. - The validation must occur after precondition evaluation (step 2) and before effect application (step 4) in the execution sequence.
What breaks if violated: An entity transitions from a state it was not in. Subsequent operations that check entity state will see an impossible state history. The entity's state machine invariants are violated.
E3 --- Atomicity Enforcement (trust boundary)
An Operation's effect set must be applied atomically across all targeted instances. Either all declared state transitions for all targeted instances occur, or none do.
Requirements:
- If an operation's effects span multiple entity types (and therefore potentially multiple instances), all transitions must succeed or all must be rolled back.
- Partial application across instances is not permitted.
- The atomicity mechanism depends on the executor's storage substrate (database transactions, two-phase commit, etc.).
Why this is a trust boundary: The language defines what atomicity means but cannot verify that it was achieved. Partial application that is not detected produces invalid entity states that subsequent operations act upon, silently compounding the error.
Concurrency note: E3 requires atomicity for a single operation's effect set but does not specify isolation semantics for concurrent invocation of multiple operations against the same entity. Two operations that concurrently read the same entity state, compute valid transitions, and write may produce conflicting final states. Executors must document their concurrency model. Serializable isolation is recommended but not required by v1.0.
E4 --- Snapshot Isolation (trust boundary)
A Flow's snapshot must not be modified after initiation. Rule evaluation during Flow execution must not affect an in-progress Flow.
Requirements:
- At flow initiation, the executor captures a snapshot of the FactSet and VerdictSet (the "frozen snapshot").
- No operation, rule evaluation, or external event may modify this snapshot during the flow's execution.
- Entity state changes during flow execution are tracked separately in a mutable EntityStateMap, not in the frozen snapshot.
Why this is a trust boundary: In a concurrent environment, a non-isolated snapshot may cause a flow to make decisions against a logical universe that no longer exists. The flow would produce verdicts and state transitions based on stale or inconsistent data, with no mechanism for detection.
E5 --- Sub-flow Snapshot Inheritance
Sub-flows must execute under the invoking flow's snapshot. A sub-flow must not take an independent snapshot at initiation.
Requirements:
- When a SubFlowStep invokes a nested flow, the nested flow inherits the parent flow's frozen snapshot.
- The nested flow sees exactly the same FactSet and VerdictSet as the parent flow.
- Entity state changes made by the sub-flow are visible to subsequent steps in the parent flow (they modify the shared mutable EntityStateMap).
What breaks if violated: A sub-flow that takes an independent snapshot may see different verdicts than the parent flow, leading to inconsistent decisions within a single logical execution.
E6 --- UTC Normalization
DateTime values must be normalized to UTC at FactSet assembly time, before any predicate evaluation.
Requirements:
- All DateTime facts must be in UTC when the evaluator receives them.
- The executor performs timezone conversion before fact assembly, not during evaluation.
- The evaluator assumes all DateTime values are UTC and performs no timezone conversion.
What breaks if violated: DateTime comparisons produce incorrect results. A predicate comparing deadline > now gives wrong answers if the values are in different timezones. Provenance timestamps become unreliable for audit.
E7 --- Numeric Model Conformance
All arithmetic must use fixed-point decimal arithmetic per the NumericModel specification. Floating-point arithmetic is not permitted.
Requirements:
- Maximum 28 significant digits.
- Round-half-to-even (banker's rounding) exclusively.
- No floating-point arithmetic at any stage of evaluation --- not in predicate evaluation, not in payload computation, not in comparison.
- Implementations in languages without native fixed-point decimal must implement the NumericModel explicitly. Delegating to native floating-point is not conforming, regardless of how "close" the results are in common cases.
What breaks if violated: Different executors produce different numeric results for the same inputs. A rule that passes on one executor fails on another. Money calculations are silently incorrect. Determinism (design constraint C3) is violated.
E8 --- Branch Isolation (trust boundary)
Parallel branches execute under the parent flow's snapshot. No branch sees entity state changes produced by another branch during execution.
Requirements:
- All branches in a ParallelStep share the parent flow's frozen snapshot.
- Entity state changes made by one branch are invisible to all other branches.
- Branch execution order is implementation-defined (parallel, sequential, or interleaved --- all are conforming as long as isolation holds).
- After all branches complete, the join step merges results.
Why this is a trust boundary: The language specifies isolation but the executor must enforce it. If branch A's entity state changes leak into branch B's execution, the results depend on execution order, violating determinism.
E9 --- Join Evaluation After Full Branch Completion
The join step evaluates after all branches have reached a terminal state. The join condition is evaluated against the set of branch terminal outcomes.
Requirements:
- The executor must not evaluate the join condition until every branch in the ParallelStep has completed (reached a terminal outcome or failed).
- The order of branch completion does not affect the join outcome.
- The join policy has access to all branch outcomes simultaneously.
What breaks if violated: A premature join evaluation may miss branch outcomes, leading to incorrect join decisions. The flow's terminal outcome depends on which branches happened to finish first.
Protocol Obligations (E10-E14)
Protocol obligations govern how executors expose contracts to agents and how agents interact with the execution environment. These obligations are defined in the Contract Discovery and Agent Orientation section of the specification (section 19).
E10 --- Manifest Endpoint
A conforming executor must serve a valid TenorManifest at /.well-known/tenor.
Requirements:
- The resource must be served with
Content-Type: application/json. - The
ETagHTTP response header must match the manifest'setagfield value. - No file extension is appended to the path.
- The path is prescribed exactly --- executors must not serve the manifest only at implementation-specific paths. Executors may additionally serve the manifest at other paths.
TenorManifest structure:
{
"tenor": "1.1",
"etag": "<sha256 hex digest>",
"bundle": { /* full TenorInterchange JSON */ },
"capabilities": { /* optional */ },
"trust": { /* optional */ }
}E11 --- Complete Bundle
The manifest's inlined bundle must be complete. An agent that has fetched the manifest must have all information necessary to understand the contract without any additional out-of-band documentation.
Requirements:
- No required fields may be omitted from the bundle.
- No construct references may be unresolved.
- The bundle alone must be sufficient for agent cold-start: one fetch of
/.well-known/tenorprovides the complete interchange bundle. - After cold-start, an agent has: all Facts, Entities, Rules, Personas, Operations, Flows; the complete state space (S1); the authority topology (S4); all possible verdicts; and the etag for change detection.
E12 --- Etag Integrity
The executor must update the manifest's etag field whenever the interchange bundle changes, and must not change the etag field when the bundle has not changed.
Requirements:
- The etag is a pure function of bundle content:
lowercase_hex(SHA-256(canonical_json_bytes(bundle))). - The etag changes if and only if the interchange bundle changes.
- The etag does not change when deployment metadata, timestamps, or other non-bundle state changes.
- HTTP integration: the executor must support
If-None-Matchconditional GET, returning304 Not Modifiedwhen the etag matches. - The
capabilitiesfield is excluded from etag computation. Capability changes do not constitute contract changes.
E13 --- Dry-Run Evaluation
A conforming executor must support dry-run evaluation for all Operations.
Requirements:
- Dry-run requests execute steps (1) through (3) of the operation execution sequence: persona check, precondition evaluation, outcome determination.
- Step (4) --- atomic effect application --- is not performed. No entity state changes occur.
- Every dry-run response must carry
"simulation": trueat the top level of the response body. - SimulatedProvenance records must not be written to the authoritative audit log.
- A dry-run that would succeed returns the same status code as a real success. A dry-run that would fail returns the same error as a real failure. The
simulation: truefield is the sole distinguishing signal.
Dry-run semantics:
dry_run(op, persona, verdict_set, entity_state) =
if persona not in op.allowed_personas:
return SimulatedError("persona_rejected", simulation: true)
if precondition evaluates false:
return SimulatedError("precondition_failed", simulation: true)
outcome = determine_outcome(op, entity_state)
return SimulatedOutcome(outcome, simulation: true)E14 --- Capability Advertisement
A dynamic executor (one that evaluates operations, executes flows, and applies entity state transitions) must include a capabilities object in its manifest.
Requirements:
- The
capabilitiesobject must accurately reflect the executor's actual behavior. - Static file deployments (serving from CDN, object storage, or file system with no live executor) are exempt from E14.
- A manifest without a
capabilitiesfield is interpreted as a static deployment or pre-v1.1 executor. Agents must assume conservative defaults.
ExecutorCapabilities fields:
{
"migration_analysis_mode": "conservative",
"multi_instance_entities": true,
"source_adapters": true
}| Field | Values | Meaning |
|---|---|---|
migration_analysis_mode | "conservative" or "aggressive" | How the executor classifies REQUIRES_ANALYSIS changes. Conservative treats them as breaking. |
multi_instance_entities | boolean | Whether the executor supports multiple runtime instances per entity type. |
source_adapters | boolean | Whether the executor resolves structured source references via adapters and records enriched fact provenance. |
Instance Obligations (E15-E17)
Instance obligations govern entity instance lifecycle management. These obligations apply when the executor supports the multi-instance entity model (advertised via capabilities.multi_instance_entities: true). Even in single-instance mode (one instance per entity type, using the default _default InstanceId), the guarantees must hold.
E15 --- Instance Creation
An executor that creates new entity instances must initialize them in the entity's declared initial state.
Requirements:
- New instances start in
Entity.initial--- the state declared in the contract. - Instances must not be created in arbitrary states.
- An instance that appears in the EntityStateMap in a state other than
Entity.initialwithout a provenance chain of operations that transitioned it there is a conformance violation.
What breaks if violated: An instance created in a non-initial state has no provenance chain explaining how it got there. Operations that check entity state may see impossible state histories. The audit trail has a gap at the instance's origin.
E16 --- Instance Identity Stability
An InstanceId must remain stable for the lifetime of the instance.
Requirements:
- The executor must not reassign an InstanceId to a different logical instance.
- InstanceId reuse after instance deletion is permitted only if the executor guarantees that no provenance records, in-flight flows, or external references refer to the deleted instance.
- InstanceIds are opaque UTF-8 strings. The executor chooses the format (UUIDs, sequential integers, composite keys, etc.).
What breaks if violated: Provenance records reference instances by InstanceId. If an InstanceId is reassigned, provenance records from the old instance appear to belong to the new instance. Audit queries return incorrect history. In-flight flows that hold an InstanceId reference may operate on the wrong instance.
E17 --- Instance Enumeration
The executor must be able to enumerate all instances of a given entity type and their current states.
Requirements:
- The
EntityStateMapprovided to the evaluator must be complete --- it must contain every active instance. - Omitting an active instance from the state map is a conformance violation.
- An omitted instance is invisible to evaluation, potentially enabling actions that should be blocked (e.g., an operation that checks "no instances are in state X" would incorrectly succeed if instances in state X are omitted).
What breaks if violated: The evaluator makes decisions based on an incomplete view of the world. Operations may proceed that should have been blocked. Flows may take paths that assume no instances exist when instances do exist. The action space computation (compute_action_space) returns incorrect results.
Trust Obligations (E18-E20)
Trust obligations concern cryptographic attestation, provenance authenticity, and deployment identity. These obligations define capabilities the executor must possess --- activation of those capabilities is an operational decision.
E18 and E19 require the executor to be capable of producing attestations and authenticity claims. They do not require attestations to be produced for every bundle or provenance record. An executor that is capable but never activated is conformant but unattested. This is a deliberate design choice: trust infrastructure should not be a barrier to adoption. Development, testing, and simulation deployments routinely operate without trust attestation.
E18 --- Artifact Integrity Attestation
A conforming executor must be able to produce a cryptographic attestation that a given interchange bundle is identical to the one used during evaluation.
Requirements:
- The attestation must cover the complete interchange bundle (all constructs, all metadata).
- The attestation must be independently verifiable without access to the executor's runtime state.
- The bundle's
etagfield (SHA-256 of canonical JSON bytes) provides content identity. The attestation binds this content identity to a signer identity.
Non-requirements:
- The spec does not prescribe the signing algorithm, key format, or signature encoding. (The reference implementation uses Ed25519.)
- The spec does not prescribe who signs: author, build system, deployment pipeline, or executor itself.
- The spec does not prescribe key distribution, revocation, or trust anchor establishment.
- A single-developer local deployment may omit attestation. The capability must exist in the executor implementation; its activation is an operational decision.
E19 --- Provenance Authenticity
When an executor records provenance (FactProvenance, OperationProvenance, FlowOutcome, TriggerProvenance), it must be able to associate provenance entries with an authenticity claim.
Requirements:
- The authenticity claim asserts that the provenance record was produced by the identified executor and has not been modified since recording.
- The authenticity claim must be verifiable independently of the executor that produced it.
- The authenticity mechanism must be tamper-evident: modification of a provenance record after attestation must be detectable.
- Provenance entries without authenticity claims are valid but unattested. Tools and auditors may distinguish between attested and unattested provenance.
Non-requirements:
- The spec does not prescribe the authenticity mechanism (digital signatures, append-only logs, blockchain, trusted timestamping, etc.).
- The spec does not prescribe per-record vs. batch attestation granularity.
- The spec does not prescribe retention or availability of authenticity claims.
E20 --- Trust Domain Identification
An executor may declare a trust domain identifier. The trust domain identifies the organizational, environmental, or deployment boundary within which the executor operates.
When declared:
- The trust domain identifier must be included in all provenance records produced by the executor.
- The trust domain identifier must be included in TriggerProvenance records for cross-contract triggers, enabling auditors to trace trust boundaries across System compositions.
- The trust domain identifier must be stable for the lifetime of a deployment. Changing the trust domain identifier constitutes a new deployment from a trust perspective.
Format:
- A trust domain identifier is a non-empty UTF-8 string.
- Recommended convention (non-normative):
{organization}.{environment}.{region}(e.g.,acme.prod.us-east-1).
Non-requirements:
- Trust domain declaration is optional. An executor without a declared trust domain is not non-conforming.
- The spec does not prescribe trust domain registration, uniqueness verification, or hierarchical relationships between trust domains.
System Executor Obligations (E-SYS-01 through E-SYS-04)
When an executor evaluates a System (a multi-contract composition), additional obligations extend E1-E9 to the cross-contract context. These are summarized here; see the full specification section 17.3 for detailed sub-requirements.
E-SYS-01 --- Cross-Contract Trigger Execution
When a flow in a source member contract reaches a terminal outcome matching a trigger condition, the executor must initiate the target flow in the target contract. Triggers are asynchronous: the source flow completes independently of the target flow.
Key guarantees: triggers fire if and only if the source flow reaches the specified outcome; triggers fire at most once per source flow execution; the target flow takes a fresh snapshot of the target contract's state; trigger failures are recorded (never silently discarded).
E-SYS-02 --- Cross-Contract Entity State Coordination (trust boundary)
For shared entities, the executor must ensure state coordination across all member contracts. Operations in one contract that transition a shared entity must eventually be visible to operations in other contracts sharing that entity. The coordination mechanism is implementation-defined.
E-SYS-03 --- Shared Persona Identity Enforcement
When a persona is shared across member contracts, the executor treats operations in different contracts bearing that persona as executed by the same actor. Authentication equivalence applies: a persona authenticated in one contract is authenticated in all contracts sharing that persona. However, shared persona identity does not override per-contract allowed_personas sets.
E-SYS-04 --- Cross-Contract Snapshot Coordination (trust boundary)
Each member contract's flows operate under their own snapshot (per E4). Cross-contract snapshot coordination --- ensuring snapshots across member contracts reflect a consistent logical moment --- is implementation-defined. The executor must not merge snapshots across contracts.
Conformance Testing
The executor conformance test suite (crates/executor-conformance/) provides test cases for E1-E20. The suite exercises:
- Logic conformance via known-input/expected-output triples
- Transition validation (E2) with state mismatch scenarios
- Snapshot isolation (E4, E5) with concurrent modification attempts
- Numeric model conformance (E7) with edge cases (rounding, overflow, cross-type promotion)
- Manifest and discovery protocol (E10-E12)
- Dry-run semantics (E13) with simulation flag verification
- Instance lifecycle (E15-E17) with creation, identity, and enumeration checks
Operational conformance (atomicity under failure, branch isolation under concurrency) requires integration testing against the executor's actual storage and concurrency infrastructure. The conformance suite tests observable behavior; operational trust boundaries require separate verification.
# Run the conformance suite against an executor
cargo test -p executor-conformanceObligation Summary Table
| Obligation | Category | Trust Boundary | Description |
|---|---|---|---|
| E1 | Logic | Yes | External source integrity. Facts from genuinely external sources only. |
| E2 | Logic | No | Transition source validation. Current state must match effect's from_state. |
| E3 | Logic | Yes | Atomicity enforcement. All effects in an operation apply or none do. |
| E4 | Logic | Yes | Snapshot isolation. Flow snapshot immutable after initiation. |
| E5 | Logic | No | Sub-flow snapshot inheritance. Nested flows use parent's snapshot. |
| E6 | Logic | No | UTC normalization. DateTime values in UTC before evaluation. |
| E7 | Logic | No | Numeric model. Fixed-point decimal, round-half-to-even, no floats. |
| E8 | Logic | Yes | Branch isolation. Parallel branches cannot see each other's state changes. |
| E9 | Logic | No | Join after completion. Join evaluates only after all branches finish. |
| E10 | Protocol | No | Serve manifest at /.well-known/tenor with correct headers. |
| E11 | Protocol | No | Complete bundle. Manifest alone sufficient for agent cold-start. |
| E12 | Protocol | No | Etag integrity. Etag is pure function of bundle content. |
| E13 | Protocol | No | Dry-run evaluation. Read-only operation preflight with simulation: true. |
| E14 | Protocol | No | Capability advertisement. Dynamic executors declare capabilities. |
| E15 | Instance | No | Instance creation in initial state only. |
| E16 | Instance | No | Instance identity stability. InstanceIds never reassigned. |
| E17 | Instance | No | Instance enumeration. Complete EntityStateMap required. |
| E18 | Trust | No | Artifact integrity attestation capability. |
| E19 | Trust | No | Provenance authenticity capability. |
| E20 | Trust | No | Trust domain identification (optional). |