<!--
Copyright (c) 2026 Jeffery Davis. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this work except in compliance with the License.
You may obtain a copy of the License at

    https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, this work
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations.
-->

# TELEMETRY Trust Events — Specification v0.1.0 (DRAFT — Rev 4)

**Status:** Draft — publication-grade. Rev 4 closes Rev 3's remaining 13 findings: defines "logically equivalent action" precisely; adds `ABANDONED` Producer-emittable state to fill the timeout semantic gap; marks `cap:` proof form informative pending v0.2.0 normative spec; replaces Test Vector 1 placeholder hash with computed value; adds mandatory `x_consumer_observation` rule for audit-only Consumers; adds failure-behavior step to delegation-chain test vector; defines initial Commerce Scheme Registry values; specifies CloudEvents source format for merchant-local producers; adds `none` vs `null` rationale note; adds non-binding caveat to version dates; resolves citation accessibility for capability-security and Lethal Trifecta references.
**Author:** Jèf Davis (sole author / Trust Events Editor)
**Date:** 2026-05-26
**License:** Apache License 2.0
**Canonical URL:** https://trustevents.org
**Canonical reference:** the cryptographically hashed markdown document at https://trustevents.org/versions/v0.1.0 is normative. If the human-readable website disagrees with the hashed markdown document, the hashed markdown document prevails.
**Prior version:** v0.0.1 (2026-05-25)
**Release target:** v0.1.0 ships 2026-07-14.

---

## Changelog from v0.0.1

This is a backward-additive MINOR revision per the SemVer 2.0.0 discipline established in §11.

1. **`actor.authority_proof` added** — third sub-field of `actor` (§5.6). Cryptographically verifiable evidence that the actor was authorized to take the action at the moment of emission. REQUIRED when `status` is `VERIFIED` or `COMPLETED`; OPTIONAL otherwise. The signed input binds the proof to `event_id`, `session_id`, and `merchant_id` to prevent cross-event and cross-tenant replay.
2. **Field-count discipline reconciled.** v0.0.1 §4 stated "Eight fields. No more, no less." but §5 enumerated eight numbered fields plus `merchant_id` as a "trailing field" — effectively nine. v0.1.0 corrects this: **nine fields. No more, no less.** `merchant_id` is renumbered as §5.9.
3. **`status` enum revised.** `OBSERVED` is removed (incoherent producer-vs-consumer semantics; replaced by the `x_consumer_observation` extension). `EXPIRED` is added as a Consumer-assigned terminal state. **`ABANDONED` is added as a Producer-emittable state** for actions explicitly withdrawn by the producer before verification — fills the semantic gap where FAILED's "authorized-but-failed-in-execution" connotation is wrong.
4. **Canonicalization mandated.** `action.payload_hash` MUST be computed over RFC 8785 (JSON Canonicalization Scheme) — eliminates cross-implementation hash drift.
5. **Cryptographic input format normatively defined.** `authority_proof` signature canonical input, JWKS endpoint rules, freshness window (300 seconds default, 3600 maximum via `x_proof_validity_seconds`), and issuer trust model all specified in §5.6 and §12.
6. **Delegation chain hardened.** Agent-type actors MUST use the `delegation:` proof form (was SHOULD). `x_parent_event_id` MUST reference the specific `delegation`-type event that authorized this sub-agent (no longer ambiguous in parallel sub-agent scenarios).
7. **Conformance behavior for non-conformant events defined** in §2 — Consumers treat them as UNVERIFIED with `none` proof.
8. **Terminal-state requirement added** — Producers emitting `UNVERIFIED` MUST emit a terminal-state event for the same logical action within the declared validity window. Closes the "UNVERIFIED-only producer" loophole.
9. **"Logically equivalent action" defined precisely.** The COMPLETED-after-VERIFIED constraint now requires `action.type` and `action.target` identity; `action.payload_hash` divergence is a normative escalation trigger. See §5.10.
10. **`cap:` proof form marked informative in v0.1.0.** Capability-token binding semantics deferred to v0.2.0 normative specification. Producers using `cap:` in v0.1.x are explicitly outside the conformance guarantee.
11. **§10.4 example corrected** — the broken `x_parent_event_id` reference to a `BLOCKED` parent is replaced with a chain through a `VERIFIED` `delegation`-type parent.
12. **New sections.** §15 Conformance Test Vectors (with computed hash for Vector 1), §16 Registration Procedures and initial Commerce Scheme Registry, §17 Mappings & Interop (OTel / CloudEvents), §18 Errata Process, §19 Deprecation Policy.
13. **Three v0.0.1 promised deliverables explicitly deferred.** JSON Schema draft-2020-12 validation document, JSON-LD `@context`, and formal ingest endpoint specification (OpenAPI 3.1) are deferred to v0.2.0 (target 2026-09-01). Reference implementations in **TypeScript and Python** are recommitted, also for v0.2.0.

All v0.0.1 producers and consumers remain conformant under v0.1.0 with these exceptions: producers emitting `VERIFIED` or `COMPLETED` events MUST populate `actor.authority_proof`; producers emitting events MUST canonicalize `action.payload_hash` per RFC 8785; agent-type actors MUST use the `delegation:` proof form.

---

## Abstract

A **Trust Event** is a structured, atomic, runtime-emitted observation of a single action taken by an autonomous software agent at a transaction boundary. Trust Events provide a runtime-neutral vocabulary for recording what an agent did, on whose authority, against which target system, and against which observable threat surface — independent of which agent framework, model provider, or commerce platform produced the action.

Trust Events are the foundational artifact of agentic commerce governance. They are designed to be emitted by any AI agent runtime, ingested by any compliant governance platform, and audited by any third party with appropriate access. The specification is permanently free, open, and Apache 2.0 licensed.

---

## 1. Status of This Document

This is the v0.1.0 working draft, publication-grade. It introduces the first backward-compatibility commitments, the first cryptographically verifiable governance primitive (`actor.authority_proof`), and the first conformance test vectors.

Implementations consuming v0.1.0 events MUST tolerate missing optional fields, MUST tolerate unknown extension fields (see §6), and MAY depend on field stability for all REQUIRED v0.1.0 fields.

The canonical home for this specification is https://trustevents.org. The canonical reference implementation is published at https://github.com/uxxxacto/trust-events-spec.

**Normative artifact.** The cryptographically hashed markdown document at https://trustevents.org/versions/v0.1.0 is the normative reference. If the human-readable website or any HTML rendering disagrees with the hashed markdown document, the hashed markdown document prevails.

---

## 2. Conformance

The key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, and **MAY** in this document are to be interpreted as described in RFC 2119.

A **Conforming Producer** emits Trust Events that satisfy the schema in §5, the cross-field constraints in §5.10, and the canonicalization rules in §5.5.

A **Conforming Consumer** accepts any Trust Event satisfying the schema in §5 and tolerates any unknown `x_`-prefixed extension fields.

A **v0.1.0-Conforming Producer** additionally:

- populates `actor.authority_proof` on every event where `status` is `VERIFIED` or `COMPLETED`;
- canonicalizes `action.payload_hash` per RFC 8785;
- uses the `delegation:` proof form for all events where `actor.type` is `agent`;
- emits a terminal-state event (`VERIFIED`, `BLOCKED`, `COMPLETED`, `FAILED`, `ABANDONED`, or accepts a Consumer-emitted `EXPIRED`) for any logical action whose initial event was `UNVERIFIED`, within the declared validity window.

**Behavior toward non-conformant events.** Consumers receiving non-conformant events MUST treat the event as having `status: UNVERIFIED` and `actor.authority_proof: "none"` regardless of declared values. Consumers SHOULD log the conformance failure with sufficient detail for operator review (the offending field name and the rule violated). Consumers MUST NOT silently accept non-conformant `VERIFIED` or `COMPLETED` claims.

---

## 3. Terminology

- **Agent.** A software process that operates in a perceive-decide-act loop, typically driven by a large language model, capable of invoking tools, reading external state, and producing externally-visible effects on real systems.
- **Runtime.** The framework that provides the agent's execution loop, tool dispatch, context management, and permission gating. Examples: Claude Agent SDK, OpenAI Agents SDK, LangChain, Open Claw.
- **Action.** A single externally-observable operation initiated by an agent — a transaction attempt, a read against external state, a tool invocation, a credential use, a delegation, or a communication.
- **Actor.** The principal whose authority the agent is acting under at the moment an action is taken. Typically a human end-user, but may be another agent in delegated workflows, or a system identity in autonomous workflows.
- **Authority Proof.** Cryptographically verifiable evidence — a signed OAuth subject assertion, a delegated credential signature, an attested system identity, or an equivalent cryptographic artifact — demonstrating that the actor was authorized to initiate the action at the time the event was emitted. Authority proof is verifiable by any third party with access to the relevant public key material, without trusting the producer.
- **Issuer.** The signing authority whose public key material verifies a given `authority_proof`. Issuers are identified by their JWKS endpoint URL embedded in the proof's `kid` parameter. See §5.6 and §12 for issuer trust rules.
- **Freshness Window.** The maximum acceptable age of an `authority_proof` measured against the Consumer's current time. Default 300 seconds; producers MAY signal an extended window up to 3600 seconds via `x_proof_validity_seconds`.
- **Logically Equivalent Action.** Two `action` objects are logically equivalent when they share identical `action.type` and `action.target` values. `action.payload_hash` divergence between two otherwise-equivalent actions is permitted but is a normative escalation trigger per §5.10.
- **Threat Surface.** The architectural layer through which an adversarial input could compromise the action. See §7 for the enumerated set.
- **Merchant.** The commerce platform tenant on whose behalf the transaction is occurring (or `null` for non-commerce contexts).
- **Event.** A single Trust Event record, conforming to §5.
- **Session.** A continuous interaction context within which a sequence of related events occurs. Session boundaries are runtime-defined; `session_id` must be globally unique per §5.4.
- **Producer.** The agent runtime, SDK, or instrumentation library that emits Trust Events.
- **Consumer.** A Conforming governance platform that ingests Trust Events, verifies authority proofs, and assigns terminal status values.

---

## 4. Design Principles

The schema is constrained by four hard rules:

1. **Nine fields. No more, no less.** Future versions MAY add optional fields under the `x_` extension namespace (§6); the core schema remains nine.
2. **Runtime-neutral.** No field name, enumeration value, or semantic depends on a specific agent framework, model, or commerce platform.
3. **Privacy-preserving by default.** Payloads are referenced by cryptographic hash, never by content. Operator-private data MUST NOT appear in any required field.
4. **Verifiable without trust.** Every field is observable, recordable, and reproducible by third-party auditors with appropriate access. No field requires the producer's good faith. `actor.authority_proof` is the load-bearing instantiation of this principle.

---

## 5. Event Schema — The Nine Fields

Each Trust Event MUST be a JSON object containing the following nine fields. Field order is not significant. All field names are case-sensitive.

### 5.1 `event_id` — REQUIRED — string

A ULID (per the ULID specification), prefixed with the literal string `te_`. ULIDs are lexicographically sortable by emission time, monotonic within a single producer, and globally unique with high probability.

**Immutability.** Once an event has been emitted, its `event_id` MUST NOT be reused for any subsequent logical event. Producers operating under at-least-once delivery MUST retransmit the original `event_id` for retries of the same logical event — never a fresh ULID.

```json
"event_id": "te_01HXK7P9QRMN5BVWZJ3Y4DG8C"
```

### 5.2 `timestamp` — REQUIRED — string

The wall-clock time at which the event was emitted, formatted per ISO 8601 with explicit timezone or `Z` UTC indicator. Sub-second precision SHOULD be included. Consumers MUST tolerate up to 30 seconds of clock skew between producer and consumer clocks; producers SHOULD synchronize to NTP or equivalent.

```json
"timestamp": "2026-05-26T15:43:12.000Z"
```

### 5.3 `agent_id` — REQUIRED — string

A stable identifier for the agent instance that emitted the event. The recommended format is `<provider>:<model_or_runtime>:<instance>`, but producer-defined formats are permitted provided the identifier is stable across the lifetime of a single agent process.

**Process restart.** When a producer restarts the agent process, the new instance MUST emit `agent_id` distinguished from the prior instance, typically by appending a fresh instance suffix or restart counter. A naïve restart that reuses the prior `agent_id` masks the restart event and any permission resets — Consumers will treat the reused identifier as a single continuous agent and may grant authority that should have re-attested.

```json
"agent_id": "claude-sonnet-4-20250514:instance-7-restart-2"
```

### 5.4 `session_id` — REQUIRED — string

An opaque identifier grouping events from the same continuous agent session. All events emitted within one session MUST share the same `session_id`.

**Global uniqueness.** `session_id` MUST be globally unique across all producers and merchants. Recommended format is `sess_<producer_id>_<opaque>` where `<producer_id>` is the emitting producer's identifier (e.g., domain or registered producer name). Producers MUST NOT reuse session_ids across distinct sessions.

```json
"session_id": "sess_pioneer.telemetrydata.ai_8812937"
```

### 5.5 `action` — REQUIRED — object

The substantive description of what the agent attempted. MUST contain exactly three sub-fields:

- **`type`** — string, one of the action types enumerated in §8.
- **`target`** — string, a URI identifying the target system. Producers SHOULD use scheme-qualified URIs (`shopify://`, `mcp://`, `https://`, `stripe://`).
- **`payload_hash`** — string, a `sha256:` prefixed hex digest. The hash MUST be computed over the **RFC 8785 (JSON Canonicalization Scheme — JCS)** canonicalization of the action's request payload. Producers MUST NOT include payload contents.

**Canonicalization.** The `payload_hash` input MUST be derived as follows: serialize the action's request payload as JSON, apply RFC 8785 canonicalization to produce a deterministic byte sequence, then compute SHA-256 over those bytes and hex-encode the digest. Implementations that diverge from RFC 8785 (custom key ordering, alternate Unicode normalization, etc.) will produce hashes that do not verify against this specification's signatures and are non-conformant.

```json
"action": {
  "type":         "transaction_attempt",
  "target":       "shopify://orders/create",
  "payload_hash": "sha256:a3f1c8d9e2b7..."
}
```

### 5.6 `actor` — REQUIRED — object

The principal on whose authority the agent acted, and the cryptographic evidence of that authority. MUST contain exactly three sub-fields:

- **`type`** — string, one of `human`, `agent`, `system`.
- **`id`** — string, opaque identifier for the actor. For `human` actors, this SHOULD be an OAuth subject identifier or equivalent (e.g., `oauth:google:118293...`). For `agent` actors, this MUST reference the upstream delegating agent's `agent_id`. For `system` actors, this is producer-defined.
- **`authority_proof`** — string. Cryptographically verifiable evidence that the actor of type `type` and id `id` was authorized to initiate the action at the time of emission. The proof MUST be independently verifiable by any third party with access to the relevant public key material; it MUST NOT require trust in the producer.

**Note on the literal string `"none"` vs JSON `null`.** Throughout this specification, `actor.authority_proof` uses the literal string `"none"` to indicate an intentionally empty proof state, while `merchant_id` uses JSON `null` to indicate non-commerce contexts. This is a deliberate design choice: `"none"` is a recognized, explicitly emitted proof form that producers MUST consciously assert, while `null` for `merchant_id` signals the structural absence of the merchant concept entirely. The distinction matters for audit-trail clarity — a missing proof field and a "no proof exists" assertion are different governance signals.

#### 5.6.1 Canonical signature input

For all proof forms requiring a signature (`oauth_sig`, `delegation`), the signature MUST cover the UTF-8 encoding of the following seven fields joined by newline characters (`\n`) with no trailing newline:

```
event_id + "\n" +
session_id + "\n" +
merchant_id + "\n" +     // literal string "null" if the JSON value is null
actor.id + "\n" +
action.target + "\n" +
action.payload_hash + "\n" +
timestamp
```

This binding prevents replay across events, sessions, and merchants. A proof valid for one event MUST NOT verify against any other event.

#### 5.6.2 Proof forms

- **Signed OAuth assertion** — `oauth_sig:<algorithm>:kid=<jwks_url>:<base64url-signature>`
  The `<jwks_url>` MUST be an `https://` URL from which the verifying public key can be retrieved.
  Example: `oauth_sig:ES256:kid=https://auth.google.com/.well-known/jwks:MEYCIQD...`

- **Attested capability token** — `cap:<token_format>:kid=<jwks_url>:<base64url-token>`
  **INFORMATIVE IN v0.1.0.** The `cap:` proof form is reserved but not normatively specified in v0.1.0. The capability-token binding semantics (which event fields the token covers, the required claims set, the verification procedure) are deferred to v0.2.0. Producers using `cap:` in v0.1.x are explicitly outside the v0.1.0-Conforming Producer guarantee. Consumers receiving `cap:` proofs in v0.1.x SHOULD treat the event as UNVERIFIED and log the proof form for operator review. Implementations requiring capability-token semantics in v0.1.x should use `oauth_sig:` against a capability-aware OAuth authorization server instead.

- **Delegated agent signature** — `delegation:<delegating_agent_id>:kid=<jwks_url>:<base64url-signature>`
  REQUIRED for `agent`-type actors. The signature MUST cover the §5.6.1 canonical input. The `<delegating_agent_id>` MUST match the `agent_id` of the specific `delegation`-type parent event referenced by `x_parent_event_id` (see §5.10).

- **System-identity attestation** — `attestation:<attester>:kid=<jwks_url>:<base64url-attestation>` for `system`-type actors, where the attester is an identifiable signing authority with a publicly resolvable JWKS endpoint.

- **Null proof** — the literal string `"none"`.
  REQUIRED when `status` is `UNVERIFIED`, `BLOCKED`, `ABANDONED`, or `EXPIRED` and no authority proof exists or was not collected. Producers MUST use exactly the string `"none"` (not JSON `null`, not an empty string).

#### 5.6.3 Issuer trust model

The JWKS endpoint URL embedded in `kid` is the foundation of proof verification. Consumers MUST apply the following trust rules:

1. **Transport.** The JWKS endpoint MUST be fetched over HTTPS. Consumers MUST validate the TLS certificate of the JWKS endpoint and MUST NOT trust JWKS material returned by an endpoint with an invalid or untrusted certificate.

2. **Issuer co-location (default).** Unless the Consumer maintains an explicit operator-configured issuer allow-list, the JWKS endpoint's effective domain MUST be co-located with the actor's identity domain:
   
   - For `actor.id` of the form `oauth:<provider>:<subject>`, the JWKS endpoint's domain MUST match `<provider>` or be a public-suffix-controlled subdomain of it (e.g., `oauth:google:...` → `kid=https://*.google.com/...`).
   - For `delegation:<delegating_agent_id>:...` proofs, the JWKS endpoint MUST match the domain of the delegating agent's identity provider.
   - For `attestation:<attester>:...` proofs, the JWKS endpoint MUST match the attester's declared domain.

3. **Operator allow-list (alternative).** A Consumer MAY override the co-location rule by maintaining an explicit operator-configured allow-list of trusted JWKS endpoint domains. The allow-list MUST be documented and auditable. Consumers using an allow-list MUST log every proof verification against the allow-list with the matched entry.

4. **Key rotation.** Consumers MUST tolerate JWKS key rotation. When verification fails because the `kid` is not found in the current JWKS response, Consumers SHOULD re-fetch the JWKS endpoint with cache controls disabled and retry verification once before declaring the proof invalid.

5. **Freshness.** Consumers MUST reject `authority_proof` whose `timestamp` is older than 300 seconds from the Consumer's current time, adjusted for the §5.2 clock-skew tolerance, UNLESS the producer has signaled an extended window via the `x_proof_validity_seconds` extension. The maximum permitted extended window is 3600 seconds. Proofs with declared windows exceeding 3600 seconds MUST be rejected as non-conformant.

6. **Cleartext prohibition.** The producer MUST NOT include unsigned identifiers, OAuth bearer tokens in cleartext, or any secret material in this field. The field carries only signatures, attestations, and references to verifiable public-key artifacts. A producer that includes a bearer token in cleartext is non-conformant and creates a credential leak.

```json
"actor": {
  "type":            "human",
  "id":              "oauth:google:118293847562910",
  "authority_proof": "oauth_sig:ES256:kid=https://www.googleapis.com/oauth2/v3/certs:MEYCIQD...base64url..."
}
```

### 5.7 `status` — REQUIRED — string

The lifecycle state of the event at the moment of emission. MUST be one of the enumerated values in §9.

```json
"status": "VERIFIED"
```

### 5.8 `threat_surface` — REQUIRED — string

The architectural layer most directly implicated in the event. MUST be one of the enumerated values in §7.

```json
"threat_surface": "AGENT_RUNTIME"
```

### 5.9 `merchant_id` — REQUIRED — string or null

The commerce platform tenant on whose behalf the action is occurring. MUST be a stable identifier scoped to the platform (e.g., `merchant_<myshop>_myshopify_com`). For non-commerce contexts, MUST be the JSON literal value `null`.

For purposes of the §5.6.1 canonical signature input, a `null` value MUST be canonicalized to the literal four-character string `null`.

```json
"merchant_id": "merchant_mystore_myshopify_com"
```

### 5.10 Cross-Field Constraints

The following normative constraints apply across fields and MUST be satisfied by Conforming Producers:

| Constraint                                             | Rule                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Delegation chain origin                                | When `action.type` is `delegation`, the downstream sub-agent's event MUST set `actor.type` to `agent` and `actor.id` to the spawning agent's `agent_id`. The sub-agent event MUST set `x_parent_event_id` to the `event_id` of the specific `delegation`-type event that authorized this sub-agent. A parent agent that spawns multiple sub-agents in parallel MUST emit a separate `delegation`-type event per sub-agent, each with a unique `event_id`.                                                                                                                                                                         |
| Delegated authority proof                              | When `actor.type` is `agent`, `actor.authority_proof` MUST use the `delegation:` form. The embedded `<delegating_agent_id>` MUST match the `agent_id` of the parent event referenced by `x_parent_event_id`.                                                                                                                                                                                                                                                                                                                                                                                                                      |
| **Logically equivalent action — COMPLETED constraint** | A `COMPLETED` event MUST only appear after a `VERIFIED` event with the same `session_id` and a logically equivalent `action`. **Equivalence requires identical `action.type` AND identical `action.target`.** `action.payload_hash` SHOULD be identical between the antecedent `VERIFIED` event and the `COMPLETED` event; divergence MUST be logged by the Consumer and SHOULD trigger an escalation review. A `COMPLETED` event whose `action.target` differs from its antecedent `VERIFIED` event is non-conformant regardless of session_id match.                                                                            |
| BLOCKED status and action                              | When `status` is `BLOCKED`, the action described MUST NOT have produced external side effects. Producers MUST NOT emit a `BLOCKED` event for an already-executed action.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| FAILED proof carry-forward                             | When `status` is `FAILED` and an antecedent `VERIFIED` event exists in the same session, `actor.authority_proof` MUST carry forward verbatim from that antecedent event. When no antecedent `VERIFIED` event exists, `actor.authority_proof` MAY be `"none"` and Consumers SHOULD treat the event as unverified.                                                                                                                                                                                                                                                                                                                  |
| ABANDONED status                                       | Producers MAY emit `ABANDONED` to terminate a logical action that has not been `VERIFIED` and is being explicitly withdrawn (timeout, agent cancellation, user revocation, upstream resource unavailability). `ABANDONED` events MUST set `actor.authority_proof` to `"none"`. `ABANDONED` MUST NOT be used after a `VERIFIED` event in the same session — use `FAILED` for post-authorization failures.                                                                                                                                                                                                                          |
| Terminal state requirement                             | For every logical action whose initial event was emitted with `status: UNVERIFIED`, the producer MUST emit a terminal-state event (`VERIFIED`, `BLOCKED`, `COMPLETED`, `FAILED`, or `ABANDONED`) with the same `session_id` and a logically equivalent `action`, within the producer-declared validity window (default 300 seconds, max 3600 seconds via `x_proof_validity_seconds`). If no terminal-state event is emitted within the window, Consumers MUST assign the action a Consumer-emitted `EXPIRED` event (see §9). Producers that emit only `UNVERIFIED` events provide no governance guarantee and are non-conformant. |
| Commerce URI / merchant_id consistency                 | When `merchant_id` is `null`, `action.target` MUST NOT use a URI scheme listed in the Trust Events Commerce Scheme Registry (see §16). When `merchant_id` is non-null, `action.target` SHOULD use a registered commerce URI scheme.                                                                                                                                                                                                                                                                                                                                                                                               |

---

## 6. Extension Fields

Producers MAY include additional fields beyond the nine defined above. Extension field names MUST be prefixed with `x_` to avoid future collision with reserved names.

Consumers MUST tolerate unknown `x_`-prefixed fields without erroring. Consumers MAY ignore or process extension fields at their discretion.

**Reserved extensions.** The following extension fields are reserved with normative semantics:

- **`x_parent_event_id`** — string, a valid `event_id` from a prior event in the same session. Used to link a sub-agent event to the specific `delegation`-type event that authorized it. Consumers implementing delegation chain verification MUST process this field and MUST follow the chain to a root authority (human or system) before accepting a delegated `VERIFIED` or `COMPLETED` status. Promoted to core schema in v0.2.0.

- **`x_atlas_techniques`** — array of MITRE ATLAS technique identifiers applicable to the event. Informative in v0.1.x. Promoted to core schema in v0.2.0.

- **`x_owasp_top10_agentic`** — array of OWASP Agentic Top 10 category identifiers. Informative in v0.1.x. Promoted to core schema in v0.2.0.

- **`x_proof_validity_seconds`** — non-negative integer, producer-declared maximum age in seconds for `actor.authority_proof`. When absent, the default 300-second freshness window applies. Maximum permitted value is 3600. Consumers MUST reject events with `x_proof_validity_seconds > 3600` as non-conformant.

- **`x_consumer_observation`** — object, Consumer-emitted annotation indicating that the Consumer observed the event but deliberately chose not to perform full policy validation (audit-only mode, exempt action type, merchant-disabled validation). Producers MUST NOT populate this field; it is populated only when a Consumer re-emits or annotates an event. Replaces the v0.0.1 / Rev 2 `OBSERVED` status.
  **Audit-only mode mandate.** **Consumers operating in audit-only mode MUST annotate each event they observe without validating with an `x_consumer_observation` field.** Consumers that process events without validation and do not emit `x_consumer_observation` create undetectable audit gaps and are non-conformant. Silent non-validation is indistinguishable from a failure to process; this annotation closes that gap.
  Schema: `{ "observed_at": <ISO 8601 timestamp>, "observer_id": <string>, "reason": <string> }`. The `reason` field SHOULD use one of: `audit_only_mode`, `exempt_action_type`, `merchant_disabled_validation`, `expired_terminal_assignment`, or a producer-defined value documented in the Consumer's operator manual.

**Deduplication.** Consumers MUST treat `event_id` as the deduplication key. Receipt of a second event with an identical `event_id` MUST NOT produce a second governance decision and SHOULD be silently discarded. Producers operating under at-least-once delivery guarantees MUST NOT change any field value between retransmissions of the same event.

---

## 7. Threat Surface Enumeration

The `threat_surface` field (§5.8) MUST be one of:

- **`PROMPT`** — the prompt or instruction layer where adversarial injection can occur.
- **`INPUT_CHANNEL`** — the source channel from which the agent received input (email, chat, voice, etc.).
- **`TOOL_MCP`** — a Model Context Protocol server or tool surface that the agent invoked.
- **`AGENT_RUNTIME`** — the agent SDK or framework layer itself (e.g., hook bypass, permission escalation).
- **`MODEL`** — the LLM model layer (e.g., prompt-tuned compromise, model exfiltration).
- **`IDENTITY_OAUTH`** — the authentication or authorization token layer.
- **`SEARCH_INDEX`** — retrieved content from search, RAG, or knowledge-base systems that could be poisoned.

New values MAY be registered per §16.

---

## 8. Action Type Enumeration

The `action.type` field (§5.5) is enumerated informatively for v0.1.0. Producers MAY emit values outside this set during the v0.1.x window; Conforming Consumers MUST tolerate unknown `action.type` values without erroring. v1.0 will normatively constrain the enumeration; producers emitting non-enumerated values after v1.0 will be non-conformant.

- **`transaction_attempt`** — a state-changing operation against an external system (order, payment, write).
- **`read_attempt`** — a read against external state.
- **`tool_invocation`** — a tool call dispatched by the runtime.
- **`credential_use`** — a credential, token, or key was used in the action.
- **`delegation`** — the agent delegated to a sub-agent or external service.
- **`communication`** — the agent sent a message to an external recipient.
- **`model_completion`** — the agent received a model inference response.

New values MAY be registered per §16.

---

## 9. Status State Machine

The `status` field (§5.7) MUST be one of:

- **`UNVERIFIED`** — event emitted by a producer but not yet validated by any Conforming Consumer. The correct initial status at the moment of emission, before governance processing. `actor.authority_proof` MAY be `"none"`. Producers emitting `UNVERIFIED` MUST emit a terminal-state event for the same logical action within the declared validity window (see §5.10 Terminal state requirement).

- **`VERIFIED`** — event passed governance validation; action is authorized to proceed. Assigned by a Conforming Consumer after successful policy evaluation including independent verification of `actor.authority_proof`. Producers MAY emit `VERIFIED` events from internal validators provided the authority_proof is independently verifiable by any downstream Consumer. `actor.authority_proof` MUST be non-`"none"` and independently verifiable.

- **`BLOCKED`** — event failed governance validation; action MUST NOT proceed. Assigned by a Conforming Consumer after failed policy evaluation. The failure MAY itself be the absence of a valid authority proof. `actor.authority_proof` MAY be `"none"`.

- **`COMPLETED`** — action was authorized and successfully executed. `actor.authority_proof` MUST be non-`"none"` and independently verifiable. MUST only follow a `VERIFIED` event in the same session per §5.10.

- **`FAILED`** — action was authorized but failed during execution (network error, timeout during execution, downstream rejection after authorization). Proof-carry-forward rule applies per §5.10.

- **`ABANDONED`** — **Producer-emittable.** A logical action that had not yet been `VERIFIED` is being explicitly withdrawn by the producer (user revocation, agent cancellation, upstream resource unavailability, producer-side timeout). Distinct from `FAILED` (which implies prior authorization) and from `EXPIRED` (which is Consumer-assigned). `actor.authority_proof` MUST be `"none"`. `ABANDONED` MUST NOT be emitted after a `VERIFIED` event in the same session.

- **`EXPIRED`** — **Consumer-assigned terminal state.** A Consumer-emitted state for an action whose initial `UNVERIFIED` event was not followed by any terminal-state event within the declared validity window. Consumers issuing `EXPIRED` MUST populate `x_consumer_observation` with the issuing observer's identity and the original `event_id` that expired. `actor.authority_proof` MUST be `"none"`.

Producers SHOULD emit events at every lifecycle transition. A single logical action MAY produce multiple linked events via `x_parent_event_id`.

---

## 10. Examples

All `authority_proof` values shown here are illustrative; the base64url signatures are abbreviated. Real-world implementations produce signatures over the §5.6.1 canonical input.

### 10.1 A transaction attempt blocked at the runtime surface

```json
{
  "event_id":       "te_01HXK7P9QRMN5BVWZJ3Y4DG8C",
  "timestamp":      "2026-05-26T15:43:12.000Z",
  "agent_id":       "claude-sonnet-4-20250514:instance-7",
  "session_id":     "sess_pioneer.telemetrydata.ai_8812937",
  "action": {
    "type":         "transaction_attempt",
    "target":       "shopify://orders/create",
    "payload_hash": "sha256:a3f1c8d9e2b7..."
  },
  "actor": {
    "type":            "human",
    "id":              "oauth:google:118293847562910",
    "authority_proof": "none"
  },
  "status":         "BLOCKED",
  "threat_surface": "AGENT_RUNTIME",
  "merchant_id":    "merchant_mystore_myshopify_com"
}
```

### 10.2 A tool invocation verified at the MCP surface

```json
{
  "event_id":       "te_01HXK7P9QSAN5BVWZJ3Y4DG8D",
  "timestamp":      "2026-05-26T15:44:22.501Z",
  "agent_id":       "claude-sonnet-4-20250514:instance-7",
  "session_id":     "sess_pioneer.telemetrydata.ai_8812937",
  "action": {
    "type":         "tool_invocation",
    "target":       "mcp://gmail/send_message",
    "payload_hash": "sha256:b9c2e4a8d1f6..."
  },
  "actor": {
    "type":            "human",
    "id":              "oauth:google:118293847562910",
    "authority_proof": "oauth_sig:ES256:kid=https://www.googleapis.com/oauth2/v3/certs:MEYCIQD8K2X7vF3pN..."
  },
  "status":         "VERIFIED",
  "threat_surface": "TOOL_MCP",
  "merchant_id":    "merchant_mystore_myshopify_com"
}
```

### 10.3 A credential use in a non-commerce system context

```json
{
  "event_id":       "te_01HXK7P9QTBN5BVWZJ3Y4DG8E",
  "timestamp":      "2026-05-26T15:45:01.110Z",
  "agent_id":       "openai-gpt-4o-2024-08-06:instance-2",
  "session_id":     "sess_pioneer.telemetrydata.ai_internal_audit_77x",
  "action": {
    "type":         "credential_use",
    "target":       "stripe://restricted_keys/read",
    "payload_hash": "sha256:c4d8e1f3a5b2..."
  },
  "actor": {
    "type":            "system",
    "id":              "scheduled-audit-job",
    "authority_proof": "attestation:vault-issuer-prod:kid=https://vault.telemetrydata.ai/.well-known/jwks:eyJhbGciOiJFUzI1NiJ9..."
  },
  "status":         "COMPLETED",
  "threat_surface": "IDENTITY_OAUTH",
  "merchant_id":    null
}
```

### 10.4 A delegated agent-to-agent transaction with full authority chain

Two events are shown. First, the parent `delegation`-type event from the planning agent; second, the sub-agent's `transaction_attempt` event referencing the parent. The chain illustrates how `x_parent_event_id` resolves the ambiguity when one parent spawns multiple sub-agents.

**Parent event** (the planning agent emits a `delegation` action authorizing the purchaser sub-agent):

```json
{
  "event_id":       "te_01HXK7P9QU00DELEG5VENT5DG8G",
  "timestamp":      "2026-05-26T15:46:30.000Z",
  "agent_id":       "anthropic:claude-sonnet-4:planner-instance-3",
  "session_id":     "sess_pioneer.telemetrydata.ai_8812937",
  "action": {
    "type":         "delegation",
    "target":       "agent://anthropic/claude-sonnet-4/purchaser-instance-9",
    "payload_hash": "sha256:e5b1c7d2a4f8..."
  },
  "actor": {
    "type":            "human",
    "id":              "oauth:google:118293847562910",
    "authority_proof": "oauth_sig:ES256:kid=https://www.googleapis.com/oauth2/v3/certs:MEYCIQDx9pK..."
  },
  "status":         "VERIFIED",
  "threat_surface": "AGENT_RUNTIME",
  "merchant_id":    "merchant_mystore_myshopify_com"
}
```

**Sub-agent event** (the purchaser executes the transaction under the delegated authority):

```json
{
  "event_id":       "te_01HXK7P9QUCN5BVWZJ3Y4DG8F",
  "timestamp":      "2026-05-26T15:46:33.220Z",
  "agent_id":       "anthropic:claude-sonnet-4:purchaser-instance-9",
  "session_id":     "sess_pioneer.telemetrydata.ai_8812937",
  "action": {
    "type":         "transaction_attempt",
    "target":       "shopify://orders/create",
    "payload_hash": "sha256:d2e9a4c1b8f5..."
  },
  "actor": {
    "type":            "agent",
    "id":              "anthropic:claude-sonnet-4:planner-instance-3",
    "authority_proof": "delegation:anthropic:claude-sonnet-4:planner-instance-3:kid=https://auth.anthropic.com/.well-known/jwks:MEUCIQDx9pK..."
  },
  "status":         "VERIFIED",
  "threat_surface": "AGENT_RUNTIME",
  "merchant_id":    "merchant_mystore_myshopify_com",
  "x_parent_event_id": "te_01HXK7P9QU00DELEG5VENT5DG8G"
}
```

A Conforming Consumer verifies the sub-agent event by: (1) confirming the `delegation:` proof signature against the planning agent's JWKS, (2) following `x_parent_event_id` to the parent event, (3) verifying the parent's human authority proof against the human's JWKS, (4) accepting the sub-agent's `VERIFIED` status only if the full chain verifies back to a root authority.

### 10.5 An abandoned action (Producer-emitted)

A planning agent began an action that requires human approval. The human revoked their approval before the Consumer issued `VERIFIED`. The producer emits `ABANDONED`:

```json
{
  "event_id":       "te_01HXK7P9QVDN5BVWZJ3Y4DG8H",
  "timestamp":      "2026-05-26T15:48:10.000Z",
  "agent_id":       "claude-sonnet-4-20250514:instance-7",
  "session_id":     "sess_pioneer.telemetrydata.ai_8812937",
  "action": {
    "type":         "transaction_attempt",
    "target":       "shopify://orders/create",
    "payload_hash": "sha256:f7a3b1c9d2e6..."
  },
  "actor": {
    "type":            "human",
    "id":              "oauth:google:118293847562910",
    "authority_proof": "none"
  },
  "status":         "ABANDONED",
  "threat_surface": "AGENT_RUNTIME",
  "merchant_id":    "merchant_mystore_myshopify_com"
}
```

---

## 11. Version Discipline

This specification follows Semantic Versioning 2.0.0.

- **PATCH** (e.g., v0.1.0 → v0.1.1) — clarifications, examples, errata, non-normative changes.
- **MINOR** (e.g., v0.1.x → v0.2.0) — additive, backward-compatible changes (new enumerations, promoted extensions, new optional fields).
- **MAJOR** (e.g., v0.x → v1.0) — breaking changes; producers and consumers MUST coordinate migration.

**Release target dates in this lineage table are planning estimates, not binding commitments.** The Editor will publish a revised roadmap if a target date is missed by more than 60 days.

**Full version lineage:**

| Version | Date                | Status     | Key change                                                                                                                                                                                                                                                                                                                      |
| ------- | ------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| v0.0.1  | 2026-05-25          | Released   | Initial publication. Eight fields (counted awkwardly). Five-state machine. Apache 2.0.                                                                                                                                                                                                                                          |
| v0.1.0  | 2026-07-14 (target) | This draft | `actor.authority_proof` added with full canonical-input binding. Nine fields. `ABANDONED` and `EXPIRED` states added; `OBSERVED` removed. RFC 8785 canonicalization mandated. JWKS issuer trust model. `cap:` form marked informative pending v0.2.0. First conformance test vectors. First backward-compatibility commitments. |
| v0.2.0  | 2026-09-01 (target) | Planned    | JSON Schema draft-2020-12 validation document. JSON-LD `@context`. OpenAPI 3.1 ingest endpoint spec. MITRE ATLAS + OWASP field promotion. Normative `cap:` proof form specification. Reference implementations in TypeScript and Python.                                                                                        |
| v1.0    | 2027 (target)       | Planned    | Breaking changes coordinated. `action.type` enumeration normatively constrained. Full cryptographic event signing (Ed25519). Committer CLA process for ASF-style governance.                                                                                                                                                    |

All versioned releases are published with an immutable cryptographic hash at https://trustevents.org/versions.

v0.1.0 is the first release with formal backward-compatibility commitments. v0.0.x events remain valid under v0.1.0 except as noted in the changelog (proof on `VERIFIED`/`COMPLETED`, RFC 8785 canonicalization, `delegation:` form for agent actors).

---

## 12. Security Considerations

### 12.1 Threat model

Trust Events defend against the following attacker capabilities:

- **Forged authority claims by malicious or compromised producers.** A producer cannot claim `VERIFIED` status without producing a cryptographically valid `authority_proof` that any third party can verify against publicly resolvable key material. The producer's good faith is not a verification input.
- **Replay across events, sessions, and merchants.** The §5.6.1 canonical signature input binds the proof to `event_id`, `session_id`, and `merchant_id`. A valid proof for one event MUST NOT verify against any other event.
- **Indefinite replay of stale proofs.** The 300-second default freshness window (max 3600s via `x_proof_validity_seconds`) bounds how long a captured proof remains usable.
- **Cross-implementation hash drift.** RFC 8785 canonicalization eliminates ambiguity in `action.payload_hash` computation, so two conformant implementations compute identical hashes for identical payloads.
- **Delegation chain forgery.** The mandatory `delegation:` form for agent-type actors, combined with the `x_parent_event_id` linkage and recursive verification requirement, prevents an agent from claiming delegated authority without the full chain back to a root authority being independently verifiable.
- **Action substitution between VERIFIED and COMPLETED.** The §5.10 "logically equivalent action" rule requires identical `action.type` and `action.target` between the authorizing `VERIFIED` event and the executing `COMPLETED` event, with `action.payload_hash` divergence triggering Consumer escalation. An attacker who controls a producer cannot VERIFY one action and COMPLETE a different one.
- **Duplicate-event abuse.** The `event_id` deduplication key prevents replay-as-double-decision.
- **Audit-trail tampering by intermediate Consumers.** Each event carries its own authority proof, so a downstream Consumer that mutates events after ingest produces records whose proofs no longer verify.
- **Silent non-validation by audit-only Consumers.** The mandatory `x_consumer_observation` annotation in audit-only mode prevents Consumers from creating undetectable audit gaps.

Trust Events DO NOT defend against:

- **Compromise of the actor's underlying credential.** If an attacker steals the human user's OAuth refresh token and uses it to mint valid signatures, the resulting Trust Events will verify correctly. Trust Events record *authorized* actions; they cannot distinguish a legitimate user from an attacker who has stolen the user's credentials.
- **Malicious Conforming Consumers.** A Consumer that correctly verifies proofs but then mis-applies policy decisions (e.g., approves a transaction the policy should have blocked) is outside the spec's threat model. A future release MAY introduce Consumer attestation as an additional cryptographic layer.
- **Compromise of the JWKS issuer.** If the issuer's signing key is compromised, all proofs issued under that key are forgeable. Trust Events delegate issuer-security to the underlying identity infrastructure.
- **Side-channel attacks on producer infrastructure.** Memory disclosure, timing attacks, or kernel-level compromise of the producer's signing environment are outside scope.
- **Denial-of-service against the JWKS endpoint.** A Consumer unable to retrieve key material cannot verify proofs. Mitigations (caching, rate-limiting, fallback issuers) are operator concerns.
- **Capability-token-based proofs in v0.1.0.** The `cap:` proof form is informative in v0.1.0; Consumers receiving `cap:` proofs SHOULD treat events as UNVERIFIED until v0.2.0 normatively specifies the binding.

### 12.2 Field-level security rules

- Producers MUST NOT include unredacted secrets, credentials, or full payload contents in any field. Payloads are referenced by `sha256:` hash only.
- `actor.authority_proof` carries only signatures, attestations, and references to verifiable public-key artifacts — never cleartext tokens or shared secrets.
- Consumers SHOULD encrypt Trust Event records at rest and SHOULD use TLS 1.3 minimum for transit.
- Consumers receiving events with claimed `VERIFIED` or `COMPLETED` status MUST independently verify `actor.authority_proof` before relying on the status. A Consumer that trusts claimed status without verifying the proof provides no governance guarantee.
- The integrity of individual Trust Events does not imply integrity of the event stream. v1.0 will introduce optional Ed25519 signing of entire events to detect stream tampering and replay attacks.
- Cross-merchant event correlation MUST respect tenant isolation. Consumers MUST NOT join events across `merchant_id` values without explicit cross-tenant authorization from both merchants.
- Public key material referenced via JWKS URLs MUST be fetched over HTTPS with validated TLS certificates. Consumers MUST apply the §5.6.3 issuer trust model.
- Consumers MUST treat `event_id` as the deduplication key per §6. Duplicate events MUST NOT produce duplicate governance decisions.
- Consumers operating in audit-only mode MUST annotate observed events with `x_consumer_observation`. Silent observation without annotation is non-conformant.

---

## 13. References

- **RFC 2119** — Key words for use in RFCs to Indicate Requirement Levels — https://www.rfc-editor.org/rfc/rfc2119
- **RFC 8126** — Guidelines for Writing an IANA Considerations Section in RFCs — https://www.rfc-editor.org/rfc/rfc8126 (referenced by §16)
- **RFC 8785** — JSON Canonicalization Scheme (JCS) — https://www.rfc-editor.org/rfc/rfc8785 (mandated by §5.5)
- **RFC 9457** — Problem Details for HTTP APIs (referenced for error reporting in reference implementations)
- **OAuth 2.0 — RFC 6749** and **OAuth 2.0 Bearer Token Usage — RFC 6750** (referenced for the `oauth_sig` proof form)
- **CloudEvents v1.0.2** — https://cloudevents.io (referenced by §17)
- **OpenTelemetry Specification** — https://opentelemetry.io (referenced by §17)
- **ULID Specification** — https://github.com/ulid/spec
- **ISO 8601** — Date and time format
- **Model Context Protocol Specification** — https://modelcontextprotocol.io
- **MITRE ATLAS** — Adversarial Threat Landscape for AI Systems — https://atlas.mitre.org
- **OWASP Top 10 for LLM and Generative AI** — https://genai.owasp.org
- **Semantic Versioning 2.0.0** — https://semver.org
- **Developer Certificate of Origin 1.1** — https://developercertificate.org
- **W3C Verifiable Credentials Data Model 2.0** — https://www.w3.org/TR/vc-data-model-2.0/
- **Capability-Based Security** — Wikipedia overview at https://en.wikipedia.org/wiki/Capability-based_security (non-normative pointer for the historical background referenced in §14)

---

## 14. Acknowledgments

This specification draws on prior art from OpenTelemetry, CloudEvents, OAuth 2.0 audit conventions, and the OWASP LLM Top 10 governance taxonomy. The nine-field constraint is a deliberate echo of the Zen of Python's "Simple is better than complex."

`actor.authority_proof` is the load-bearing primitive that distinguishes Trust Events from generic structured logs. The design draws on **capability-based security** (originating with Dennis & Van Horn's 1966 paper *"Programming Semantics for Multiprogrammed Computations,"* Communications of the ACM 9(3); see also the Wikipedia overview cited in §13 References for a publicly accessible summary) and on recent work on **verifiable credentials** (W3C VC Data Model 2.0, cited in §13 References).

The `threat_surface` enumeration draws on the **Lethal Trifecta** governance framework — private data + untrusted content + external communication as the three axes of unsafe agent action — as articulated in *"The Lethal Trifecta: Why AI Agents Need Hardened Boundaries"* (Coder.com working paper, 2026; canonical URL pending — currently distributed as an internal framework document, citation will be updated in v0.1.1 errata when a stable public URL is published). The seven-surface enumeration in §7 also draws on the **TELEMETRY Adversarial AI Threat Map v0.1** (Davis, 2026), which maps the seven surfaces to OWASP Agentic Top 10 and real-world exploit evidence.

**Contributing.** All contributions to this specification require a Developer Certificate of Origin (DCO) 1.1 sign-off per https://developercertificate.org/. See CONTRIBUTING.md in the reference implementation repository at https://github.com/uxxxacto/trust-events-spec. The DCO-only model is intentional for v0.1.x to maximize ecosystem velocity. A formal Contributor License Agreement (CLA) process for committers will be introduced in v1.0 alongside ASF-style governance — enterprise contributors requiring CLA today may sign the spec's individual contributor CLA template, available on request, but a DCO sign-off remains sufficient for accepted contributions. Contributions without a valid DCO sign-off will not be accepted. This requirement protects the copyright chain and the Apache 2.0 patent grant for all downstream implementers.

---

## 15. Conformance Test Vectors

The following test vectors are normative for v0.1.0 conformance. Implementations claiming v0.1.0 conformance MUST produce identical outputs for identical inputs across all five vectors.

### Vector 1 — RFC 8785 canonicalization

**Input payload:**

```json
{"sku": "ABC-123", "qty": 2, "currency": "USD", "amount": 49.99}
```

**Canonicalized bytes (RFC 8785):**

```
{"amount":49.99,"currency":"USD","qty":2,"sku":"ABC-123"}
```

**SHA-256 of canonical bytes (hex):**

```
sha256:071dde479ea369116950a6e2e319ab10b15d7c67ac0e976e66f5ec2091204bab
```

Computed 2026-05-26 with Python 3 `hashlib.sha256` over the UTF-8 canonical bytes. Any RFC 8785 conformant implementation MUST produce this identical hash; producing a different hash for the same input payload indicates a canonicalization defect.

### Vector 2 — `oauth_sig` canonical signature input

**Event fields:**

- `event_id`: `te_01HXK7P9QSAN5BVWZJ3Y4DG8D`
- `session_id`: `sess_pioneer.telemetrydata.ai_8812937`
- `merchant_id`: `merchant_mystore_myshopify_com`
- `actor.id`: `oauth:google:118293847562910`
- `action.target`: `mcp://gmail/send_message`
- `action.payload_hash`: `sha256:b9c2e4a8d1f6...`
- `timestamp`: `2026-05-26T15:44:22.501Z`

**Canonical signature input bytes (UTF-8):**

```
te_01HXK7P9QSAN5BVWZJ3Y4DG8D
sess_pioneer.telemetrydata.ai_8812937
merchant_mystore_myshopify_com
oauth:google:118293847562910
mcp://gmail/send_message
sha256:b9c2e4a8d1f6...
2026-05-26T15:44:22.501Z
```

(Seven lines joined by `\n`, no trailing newline.)

### Vector 3 — `merchant_id` null canonicalization

When `merchant_id` JSON value is `null`, the signature canonical input MUST use the literal four-character string `null`. Verification implementations that substitute an empty string or omit the line entirely are non-conformant.

### Vector 4 — Delegation chain verification

A Consumer presented with the §10.4 sub-agent event MUST:

1. Verify the `delegation:` proof signature against `https://auth.anthropic.com/.well-known/jwks`.
2. Fetch the parent event referenced by `x_parent_event_id`.
3. Verify the parent's `oauth_sig` proof against `https://www.googleapis.com/oauth2/v3/certs`.
4. Confirm `actor.id` of the sub-agent event matches `agent_id` of the parent event.
5. Confirm `agent_id` of the sub-agent event matches the `action.target` resolution of the parent event.
6. **Failure behavior.** If any step 1–5 fails, the Consumer MUST treat the event as non-conformant per §2 (downgrade the event to `status: UNVERIFIED` and `actor.authority_proof: "none"`, log the failure with the specific step that failed and the reason), and MUST NOT assign `VERIFIED`. A Consumer that passes the event through with claimed `VERIFIED` status after any verification step fails is non-conformant and provides no governance guarantee.

### Vector 5 — Freshness rejection

A Consumer presented with an otherwise-valid proof whose `timestamp` is 301 seconds older than the Consumer's clock (no `x_proof_validity_seconds` extension) MUST reject the proof and downgrade the event to `UNVERIFIED` with `authority_proof: "none"` per §2.

A canonical regression suite implementing all five vectors will ship with the v0.2.0 TypeScript and Python reference implementations.

---

## 16. Registration Procedures

New values for `action.type` (§8) and `threat_surface` (§7) MAY be registered under the **Specification Required** policy of RFC 8126. New URI schemes for the **Trust Events Commerce Scheme Registry** (referenced by §5.10) follow the same procedure.

**Registrar.** Jèf Davis serves as the initial Trust Events Editor with sole registration authority through v0.x. A multi-stakeholder Trust Events Working Group will assume the registrar role at v1.0.

**Registration request format.** A registration request MUST include:

1. The proposed enumeration value (case-sensitive).
2. A concise definition (≤ 80 words).
3. The enumeration this value extends (action.type / threat_surface / commerce-scheme).
4. At least one implementation reference or specification URL.
5. The requester's name, contact, and DCO sign-off.

Registration requests are submitted as GitHub issues at the reference repository. The Editor will accept, reject with rationale, or request revision within 30 days of submission. Accepted values are published in the next PATCH release and become permanent.

**Conflict resolution.** When two registration requests propose semantically overlapping values, the Editor will reject both and ask the requesters to coordinate on a single proposal. Editor decisions during v0.x are appealable only to the Editor.

### 16.1 Trust Events Commerce Scheme Registry — Initial Values (v0.1.0)

The following URI schemes are registered as commerce-platform identifiers at v0.1.0. Use of these schemes in `action.target` requires a non-null `merchant_id` per the §5.10 commerce URI / merchant_id consistency rule.

| URI scheme        | Platform                                                | Initial registration |
| ----------------- | ------------------------------------------------------- | -------------------- |
| `shopify://`      | Shopify (Shop Pay, merchant storefronts, Plus tier)     | v0.1.0               |
| `stripe://`       | Stripe (payments, checkout, billing, treasury)          | v0.1.0               |
| `amazon://`       | Amazon (marketplace, Pay, Seller Central)               | v0.1.0               |
| `mcp://commerce/` | Generic MCP commerce surface; producer-defined sub-path | v0.1.0               |

Additional schemes (`paypal://`, `square://`, `klarna://`, `affirm://`, `visa://`, `mastercard://`, `adyen://`, etc.) MAY be registered per the procedures above. The Editor will accept registrations meeting the request format requirements within 30 days.

---

## 17. Mappings & Interop

### 17.1 OpenTelemetry

Trust Events are **NOT** OpenTelemetry spans. The semantic models differ:

- OpenTelemetry spans describe execution traces of distributed system operations.
- Trust Events describe governance decisions at agent action boundaries.

Implementations MAY carry Trust Event references inside OpenTelemetry span attributes for correlation purposes. The recommended attribute is `trust_event.event_id`. The full Trust Event payload SHOULD NOT be embedded as an OTel attribute due to size and semantic-layer mismatch.

### 17.2 CloudEvents

Trust Events MAY be carried as a CloudEvents v1.0.2 payload. The CloudEvents envelope mapping is:

- `type`: `org.trustevents.v0_1_0`
- `source`: the producer's stable URI. For hosted producers, use the producer's canonical domain (e.g., `https://pioneer.telemetrydata.ai`). **For merchant-local producers, the recommended source format is `telemetrydata.ai/producers/<merchant_id>`, where `<merchant_id>` matches the event's `merchant_id` field.** For non-commerce producers running locally, use `telemetrydata.ai/producers/local/<producer_id>` where `<producer_id>` is the emitting producer's identifier per §5.4.
- `id`: the Trust Event's `event_id`
- `time`: the Trust Event's `timestamp`
- `subject`: the Trust Event's `session_id`
- `datacontenttype`: `application/json`
- `data`: the full Trust Event JSON object

CloudEvents `id` and `time` MUST be identical to the Trust Event's `event_id` and `timestamp` respectively. Divergence is non-conformant.

### 17.3 MCP

Trust Events emitted by the TELEMETRY MCP Observability Server (SDK Shape 1) follow the schema defined here unchanged. The MCP server is a Producer; its consumers MAY be any Conforming Consumer.

---

## 18. Errata Process

Errata against a released version are published at `https://trustevents.org/versions/<version>/errata` and tracked as GitHub issues labeled `errata` in the reference repository.

**Versioning.** Errata are numbered sequentially per release: `v0.1.0-erratum-1`, `v0.1.0-erratum-2`, etc. Each erratum carries a cryptographic hash committed alongside the original spec hash.

**Conformance impact.** Conforming Producers and Consumers MUST track erratum-applied state. An implementation conformant with `v0.1.0` is not automatically conformant with `v0.1.0-erratum-3` if the erratum introduces normative changes. The Editor will mark errata as either:

- **Editorial** — non-normative; does not affect conformance.
- **Normative** — alters conformance; implementations claiming conformance after the erratum publication date MUST incorporate the change.

Errata accumulate until the next PATCH release, at which point they are folded into the spec and the erratum log resets.

---

## 19. Deprecation Policy

Values, fields, or rules marked deprecated in a release are:

1. **Tracked** in the changelog of the release that deprecates them, with the planned removal version.
2. **Warned** during one MINOR release — Conforming Consumers SHOULD emit a deprecation-warning audit log when accepting events that use deprecated values. Producers emitting deprecated values remain conformant during the warning period.
3. **Removed** in the next MAJOR release. Producers emitting removed values after the MAJOR release are non-conformant.

Deprecation does not apply to errata — errata correct errors and apply immediately per §18.

The deprecation policy ensures producers have one MINOR cycle of advance notice before a removal lands.

---

*End of TELEMETRY Trust Events Specification v0.1.0 (DRAFT — Rev 4).*
*© 2026 Jèf Davis. Licensed under Apache 2.0.*
*Draft date: 2026-05-26. Release target: 2026-07-14.*
