# Trust Card Protocol v1.1

> **Status:** v1.1 shipped (Phase 18 — November 2026). v1 cards remain valid; v1.1 adds a second proof and an operator ToS block. See §11 for the v1 → v1.1 changelog.
> **Purpose:** A universal, portable, self-verifiable trust signal for autonomous agents in the agentic economy.
> **Audience:** Third-party platforms (marketplaces, wallets, gateways, regulators) that need to verify an agent's safety posture without trusting Agent Resources.
> **Non-goal:** Re-creating discrete tier systems (graduation, probation/elite, bronze/silver/gold). Trust is continuous — see §2.

---

## 1. Why a Trust Card?

The agentic economy has millions of autonomous agents acting on behalf of humans and other agents. Before a third party (an LLM orchestrator, a marketplace, a wallet, a custodian, a regulator) delegates work to an agent, it needs a _standard, immutable, self-verifiable_ answer to:

1. **Who is this agent?** — wallet + ERC-8004 Identity token.
2. **How safe is it?** — continuous KYA score (0–100), with recent scan history.
3. **What is its track record?** — lifetime task count, success rate, hallucination rate.
4. **Has it misbehaved?** — active flags, quarantine status, violation history.
5. **Can I prove all of this without trusting AR?** — yes, via on-chain anchoring + Merkle proofs.

Today, every platform builds this ad-hoc. The Trust Card Protocol publishes it as a **single signed document** any verifier can fetch, parse, and prove on-chain.

### Design principles

| Principle              | How we enforce it                                                                                         |
| ---------------------- | --------------------------------------------------------------------------------------------------------- |
| **Portable**           | Keyed by agent wallet address — follows the agent across workspaces, platforms, and custody changes       |
| **Immutable**          | Every card is signed (EIP-712) and its Merkle root is anchored on Base L2 once per day                    |
| **Self-verifiable**    | Verifier needs only the agent's wallet address + a Base L2 RPC — no AR API key, no trust in AR            |
| **Continuous**         | No discrete tiers. KYA score is a float 0–100; scan history is a time series; Merkle anchor is cumulative |
| **Standards-based**    | JSON-LD + VC-compatible; ERC-8004 Identity; x402 for paid deep-dives; DIDs for off-chain identity         |
| **Privacy-preserving** | Card exposes aggregate scores + anchors, not raw telemetry or PII; operators opt-in to richer disclosures |

---

## 2. Card structure

A Trust Card is a JSON-LD document signed by the issuer (Agent Resources) with EIP-712, returned from a well-known URL keyed by agent wallet:

```
GET https://api.agentresources.xyz/.well-known/trust-card/{agentWallet}
```

Or the issuer-agnostic reverse lookup:

```
GET https://api.agentresources.xyz/.well-known/trust-card/lookup?did=did:ar:0x...
```

### 2.1. Canonical JSON-LD schema (v1)

```json
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://schema.agentresources.xyz/trust-card/v1"
  ],
  "type": ["VerifiableCredential", "TrustCard"],
  "id": "urn:ar:trust-card:0xAGENT_WALLET:2026-04-20T14:32:00Z",
  "issuer": {
    "id": "did:web:agentresources.xyz",
    "name": "Agent Resources"
  },
  "issuanceDate": "2026-04-20T14:32:00Z",
  "validUntil": "2026-04-21T14:32:00Z",
  "credentialSubject": {
    "id": "did:pkh:eip155:8453:0xAGENT_WALLET",
    "agentWallet": "0xAGENT_WALLET",
    "displayName": "string | null",

    "kya": {
      "score": 92.4,
      "tier": "verified",
      "lastScanAt": "2026-04-20T13:15:00Z",
      "scanCount30d": 41,
      "successRate30d": 0.961,
      "hallucinationRate30d": 0.0029,
      "activeDays": 178
    },

    "status": {
      "state": "active",
      "flaggedAt": null,
      "quarantineUntil": null,
      "activeFlags": []
    },

    "identity": {
      "erc8004": {
        "chainId": 8453,
        "registry": "0xERC8004_REGISTRY",
        "tokenId": "12345",
        "mintedTx": "0xMINT_TX_HASH"
      },
      "reputation": {
        "registry": "0xERC8004_REPUTATION",
        "score": 9241,
        "lastUpdateTx": "0xREP_UPDATE_TX"
      }
    },

    "telemetryAnchor": {
      "lastAnchorAt": "2026-04-20T00:00:00Z",
      "lastAnchorMerkleRoot": "0xMERKLE_ROOT",
      "lastAnchorTx": "0xANCHOR_TX_HASH",
      "chainId": 8453,
      "contract": "0xTELEMETRY_ANCHOR_CONTRACT",
      "eventsIncluded": 14782
    },

    "lifecycle": {
      "createdAt": "2025-10-24T09:11:00Z",
      "ownerLinkAttestedAt": "2025-10-24T09:14:00Z",
      "lastRetrainedAt": "2026-04-12T22:47:00Z"
    },

    "disclosures": {
      "operatorDid": "did:pkh:eip155:8453:0xOPERATOR_WALLET | null",
      "publicMetadataUri": "ipfs://Qm.../metadata.json | null"
    }
  },
  "proof": {
    "type": "EthereumEip712Signature2021",
    "created": "2026-04-20T14:32:00Z",
    "verificationMethod": "did:web:agentresources.xyz#key-1",
    "proofPurpose": "assertionMethod",
    "domain": {
      "name": "AgentResources-TrustCard",
      "version": "1",
      "chainId": 8453,
      "verifyingContract": "0xTELEMETRY_ANCHOR_CONTRACT"
    },
    "signature": "0xSIG",
    "types": "…EIP-712 typed-data schema…"
  }
}
```

### 2.2. Field semantics

| Field                                | Type                                                | Semantics                                                                                                                                                                                         |
| ------------------------------------ | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `credentialSubject.kya.score`        | float 0–100                                         | Continuous trust score. Replaces discrete tiers. Computed per [CANONICAL_LIMITS §1](../00-Index/CANONICAL_LIMITS.md).                                                                             |
| `credentialSubject.kya.tier`         | `basic` \| `verified` \| `trusted` \| `null`        | Human-readable band derived from `score` + thresholds in CANONICAL_LIMITS §1. Informational only — consumers should key decisions off `score`, not `tier`.                                        |
| `credentialSubject.status.state`     | `active` \| `flagged` \| `quarantined` \| `revoked` | Current enforcement state. `flagged` = under review; `quarantined` = no paid actions allowed; `revoked` = ERC-8004 Identity token burned or agent deleted.                                        |
| `credentialSubject.telemetryAnchor`  | object                                              | The most recent daily Merkle anchor. Consumers can verify any telemetry event by walking the Merkle proof against `lastAnchorMerkleRoot` and cross-checking the root on-chain via `lastAnchorTx`. |
| `credentialSubject.identity.erc8004` | object                                              | On-chain identity token; the card's issuer proves ownership of `tokenId` is bound to `agentWallet`.                                                                                               |
| `proof.signature`                    | 0x-hex                                              | EIP-712 signature over the canonicalised card. Issued by AR's signer key (recorded in `did:web:agentresources.xyz/.well-known/did.json`).                                                         |
| `validUntil`                         | ISO-8601                                            | Max 24 h from `issuanceDate`. Consumers must reject expired cards.                                                                                                                                |

### 2.3. Caching semantics

- **Edge cache:** 60 s (gateway-level). Cards change at telemetry-event frequency but never faster than 1 min aggregation.
- **Consumer cache:** obey `validUntil` (≤ 24 h).
- **Cache bust:** an agent's card cache is invalidated server-side on `status.state` transitions, on daily Merkle anchor, and on any scan completion.

---

## 3. Verification algorithm

A third-party verifier performs these checks in order. **Only steps 1–3 require trusting AR; steps 4–6 prove the card's claims against on-chain state.**

### 3.1. Structural & signature verification

1. Fetch `GET /.well-known/trust-card/{agentWallet}`.
2. Parse JSON-LD; check `type` includes `"TrustCard"`; check `issuer.id === "did:web:agentresources.xyz"`.
3. Resolve the issuer DID (`GET https://agentresources.xyz/.well-known/did.json`) to obtain the signer's public key.
4. Verify the EIP-712 signature against the canonicalised card bytes and the issuer key. **Fail → reject.**
5. Check `validUntil > now()`. **Fail → reject.**

### 3.2. On-chain cross-check (trustless)

6. Read the ERC-8004 Identity registry at `credentialSubject.identity.erc8004.registry` on chain `chainId`. Confirm `ownerOf(tokenId) === agentWallet`. **Fail → card is impersonating a wallet it does not own.**
7. Read the telemetry anchor contract at `credentialSubject.telemetryAnchor.contract`. Confirm that `getAnchor(agentWallet, lastAnchorAt)` returns `lastAnchorMerkleRoot`. **Fail → telemetry claims are fabricated.**
8. (Optional, for high-value verification) Walk a Merkle proof for a specific telemetry event the consumer cares about (e.g., last 10 task completions) against the anchored root. AR serves proofs at `GET /api/v1/telemetry/{agentWallet}/merkle-proof?eventId=…`.

### 3.3. Trust decision

With the above verified, the consumer decides using `kya.score`, `status.state`, and `scanCount30d` — not using discrete tiers. Recommended thresholds (not enforced by AR):

| Use case                                                               | Recommended minimum                                                                            |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| Low-value, reversible actions (search, read)                           | `score ≥ 70` and `state === "active"`                                                          |
| Medium-value actions (posting content, chat)                           | `score ≥ 85` and `state === "active"` and `scanCount30d ≥ 10`                                  |
| High-value, irreversible actions (payments, trades, legal commitments) | `score ≥ 95` and `state === "active"` and `scanCount30d ≥ 30` and fresh Merkle anchor (≤ 24 h) |

---

## 4. Reference client — `@agent-resources/verify`

A zero-dep TypeScript/ESM package (pure JS + `viem` for on-chain reads) that implements §3:

```ts
import { verifyAgent } from "@agent-resources/verify";
import { createPublicClient, http } from "viem";
import { base } from "viem/chains";

const baseClient = createPublicClient({ chain: base, transport: http() });

const result = await verifyAgent({
  agentWallet: "0xAGENT_WALLET",
  chainClient: baseClient,
  // optional: issuerDid override for staging
  // issuerDid: "did:web:staging.agentresources.xyz",
});

if (!result.valid) {
  // result.reasons: Array<{ step: 1|2|3|4|5|6|7; message: string }>
  throw new Error(`TrustCard invalid: ${result.reasons[0].message}`);
}

console.log(result.card.credentialSubject.kya.score); // 92.4
console.log(result.card.credentialSubject.status.state); // "active"
console.log(result.anchor.verifiedOnChain); // true
```

### 4.1. Package surface

```ts
export async function verifyAgent(opts: {
  agentWallet: `0x${string}`;
  chainClient: PublicClient; // viem
  issuerDid?: string; // default: did:web:agentresources.xyz
  fetchImpl?: typeof fetch; // for tests
  now?: () => Date; // for tests
}): Promise<VerifyResult>;

export async function fetchTrustCard(
  agentWallet: `0x${string}`,
  opts?: { issuer?: string; fetchImpl?: typeof fetch },
): Promise<TrustCard>;

export async function verifyMerkleProof(opts: {
  agentWallet: `0x${string}`;
  eventId: string;
  chainClient: PublicClient;
}): Promise<{ valid: boolean; root: `0x${string}`; anchorTx: `0x${string}` }>;

export type VerifyResult = {
  valid: boolean;
  card: TrustCard | null;
  anchor: { verifiedOnChain: boolean; merkleRoot: `0x${string}` | null };
  identity: { verifiedOnChain: boolean; tokenOwner: `0x${string}` | null };
  reasons: Array<{ step: number; message: string }>;
};
```

### 4.2. Distribution

- npm: `@agent-resources/verify` (MIT-licensed)
- CDN: `https://cdn.jsdelivr.net/npm/@agent-resources/verify/dist/verify.min.js` (UMD ~18 KB)
- Python port: `agentresources-verify` (mirrors API shape; uses `web3.py` instead of viem)

### 4.3. Forks encouraged

The package is intentionally small and MIT-licensed. Other verifiers may fork it or re-implement in any language. The spec — not the library — is the source of truth.

---

## 5. Gateway endpoint contract

Implemented in `apps/gateway/src/routes/well-known.ts` (new sub-route). Public, unauthenticated, aggressively cached.

### 5.1. `GET /.well-known/trust-card/{agentWallet}`

**Path:** `agentWallet` — lowercase hex, `^0x[a-f0-9]{40}$`.

**Response 200:** `Content-Type: application/vc+ld+json; charset=utf-8`, body = Trust Card per §2.1.

**Response 404:** `Content-Type: application/problem+json`, `{"type": "ar:trust-card:not-found", "title": "Unknown agent wallet", "status": 404}`. Returned when no active agent is bound to the wallet.

**Response 410:** `{"type": "ar:trust-card:revoked", "title": "Agent revoked", "status": 410}`. Returned when the agent's ERC-8004 Identity token has been burned or the agent row has been soft-deleted + grace period elapsed. Body includes a `revocation` sub-object with `{ reason, at, burnTx }`.

**Headers:**

- `Cache-Control: public, max-age=60, s-maxage=60`
- `ETag: "<sha256 of canonical card bytes>"`
- `AR-Trust-Card-Version: 1`

### 5.2. `GET /.well-known/trust-card/lookup`

Query params:

- `did` (required) — a `did:pkh:eip155:...` or `did:web:...` identifier.

Returns 302 to the canonical `/trust-card/{agentWallet}` URL on resolution, or 404.

### 5.3. `GET /api/v1/telemetry/{agentWallet}/merkle-proof`

Query params:

- `eventId` (required) — the telemetry event primary key.
- `anchorDate` (optional, ISO date) — which daily anchor to prove against. Defaults to the most recent anchor that includes the event.

Response 200:

```json
{
  "eventId": "…",
  "anchorDate": "2026-04-20",
  "merkleRoot": "0x…",
  "anchorTx": "0x…",
  "chainId": 8453,
  "contract": "0x…",
  "proof": ["0x…", "0x…", "…"],
  "leaf": "0x…"
}
```

This endpoint **is** paid (x402, $0.001/proof) — Merkle proofs are opt-in deep-dives, not part of the free Trust Card surface. The Trust Card itself is always free.

---

## 6. On-chain surface (deferred to v2)

Version 1 of the protocol is REST + EIP-712 only. Version 2 (tentatively Phase 10) adds an optional on-chain view contract:

```solidity
interface ITrustCardRegistry {
  struct Card {
    uint256 kyaScore;       // scaled 0-10000 (2 decimal places)
    bytes32 lastMerkleRoot;
    uint256 lastAnchorAt;
    uint8 status;           // 0=active, 1=flagged, 2=quarantined, 3=revoked
    uint256 erc8004TokenId;
  }

  function getCard(address agentWallet) external view returns (Card memory);
  event CardUpdated(address indexed agentWallet, uint256 kyaScore, uint8 status);
}
```

This would let Solidity contracts consume Trust Cards directly (e.g., a DEX checks `getCard(agent).kyaScore > 9500` before routing). Deferred until the daily Merkle anchor cadence is proven reliable in production.

---

## 7. Threat model

| Threat                                                        | Mitigation                                                                                                                                                                                                                             |
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **AR fabricates a high score**                                | Third parties verify `telemetryAnchor.merkleRoot` on-chain. If AR's telemetry claims don't match the anchored root, the card is proven false.                                                                                          |
| **AR selectively omits bad events from the Merkle tree**      | Partially mitigated: anchors include monotonic event counts per agent; gaps are detectable by third parties who run their own telemetry indexers. Full mitigation in v2 via event-chain hashing (each event includes prev-event-hash). |
| **Agent forks wallet, reuses score**                          | ERC-8004 Identity token is non-transferable (soulbound). Forking the wallet breaks the binding and the verifier's step 6 fails.                                                                                                        |
| **Agent gets new wallet, old card is stale but still served** | `status.state` transitions to `revoked` on wallet migration. `validUntil` ≤ 24 h caps staleness.                                                                                                                                       |
| **Replay of old card**                                        | `validUntil` enforcement; strict EIP-712 domain binds to issuance time.                                                                                                                                                                |
| **MITM on the .well-known URL**                               | HTTPS + HSTS + DNSSEC for `agentresources.xyz`. Card signature prevents mutation; MITM can only block, not alter.                                                                                                                      |
| **Issuer key compromise**                                     | Key rotation is published in `did:web:agentresources.xyz/.well-known/did.json`; cards include `verificationMethod` referencing a specific key. Old cards are re-issued on rotation.                                                    |
| **Sybil / fake identity**                                     | ERC-8004 mint requires KYA-Basic (100 lifetime tasks + owner-link attestation). Trust surface is continuous, so trivially-minted identities start at score ≈ 0 and gain trust only through verified work.                              |

---

## 8. Rollout

**Phase 5.1 — Specification (this doc)** ✅

- Publish spec.
- Gather third-party review (2-week window).

**Phase 5.2 — Implementation**

- Implement `GET /.well-known/trust-card/{agentWallet}` in gateway.
- Implement daily Merkle anchor job (CRON-040 — next free ID).
- Ship `@agent-resources/verify` npm package (TypeScript first, Python in parallel).
- Stand up the ERC-8004 Identity + Reputation contracts on Base mainnet.

**Phase 5.3 — Public launch**

- Docs site: dedicated `/trust-card` landing page with live verifier demo.
- Blog post + HN launch.
- Reach out to 10 initial integrator partners (marketplaces, wallet providers, LLM orchestrators).

**Phase 5.4 — Standards push**

- Submit to W3C Credentials Community Group as an agentic-specific VC type.
- Submit to ERC discussion for a companion "Trust Card" standard complementing ERC-8004.
- Target: 3 independent reference implementations (rust, go, swift) within 6 months of launch.

---

## 9. Versioning

- **v1.0** (this doc) — April 2026
- Breaking changes bump the major version and the `@context` URL (`v1` → `v2`). Consumers must read `@context` to pick the parser.
- Non-breaking additions (new optional fields) are minor-versioned and announced in the changelog at `https://schema.agentresources.xyz/trust-card/CHANGELOG.md`.

---

## 10. Cross-references

- [CANONICAL_LIMITS.md §1](../00-Index/CANONICAL_LIMITS.md) — KYA score thresholds
- [AGENT_RESOURCES_PROTOCOL_V1.md](./AGENT_RESOURCES_PROTOCOL_V1.md) — Umbrella AR protocol
- [SDK_TELEMETRY_EVENT_SCHEMA.md](./SDK_TELEMETRY_EVENT_SCHEMA.md) — Telemetry event format (Merkle-tree leaves)
- [AGENT_VERIFICATION_API_SPEC.md](./AGENT_VERIFICATION_API_SPEC.md) — Scan, KYA, retraining API
- [AGENT_ONLY_PIVOT_PLAN.md Phase 5](../Platform-update/AGENT_ONLY_PIVOT_PLAN.md#phase-5) — Why graduation was deleted in favour of this

---

## 11. Changelog: v1 → v1.1 (Phase 18)

v1.1 is **fully backward compatible** with v1. Existing v1 verifiers (single-proof EIP-712) accept v1.1 cards by reading the first element of the `proof` array. v1.1-aware verifiers gain stronger guarantees through the second proof and the operator block.

### 11.1 Header

Cards emitted by a gateway with the Ed25519 issuer key configured carry:

```
AR-Trust-Card-Version: 1.1
```

Cards without the Ed25519 key continue to advertise `AR-Trust-Card-Version: 1` and a single-object `proof`.

### 11.2 Dual-issued proof (W3C VC v2 conformance)

`proof` becomes an **array** of two proof objects:

1. **`EthereumEip712Signature2021`** — unchanged from v1. Domain `{name:"AgentResources-TrustCard", version:"1", chainId:8453}`; signs `(agentWallet, issuanceDate, validUntil, cardHash)`. Signer = the wallet referenced by `verificationMethod` `did:web:agentresources.xyz#key-1` (an `EcdsaSecp256k1RecoveryMethod2020`).
2. **`Ed25519Signature2020`** — new. `verificationMethod` = `did:web:agentresources.xyz#key-2`. `proofValue` is `z`-prefix base58btc multibase encoding of the 64-byte Ed25519 signature.

#### Canonicalisation note (deliberate spec deviation)

The Ed25519Signature2020 W3C suite specifies RDF Dataset Canonicalisation (URDNA2015) over the JSON-LD body. AR's v1.1 implementation **reuses the existing `canonicaliseJSON` algorithm** (a sorted-keys serializer in [`apps/gateway/src/lib/trust-card/canonical.ts`](../../apps/gateway/src/lib/trust-card/canonical.ts) and [`packages/verify/src/index.ts`](../../packages/verify/src/index.ts)) over the card body with `proof` removed, encoded as UTF-8 bytes. Trade-off:

- **Pro:** byte-identical hashing across gateway + verifier (no JSON-LD processor or RDF library required), single algorithm shared with `cardHash`.
- **Con:** does not interoperate with off-the-shelf Ed25519Signature2020 verifiers that expect URDNA2015. Any third-party verifier that wants to verify the Ed25519 proof must use `@agent-resources/verify` (or replicate `canonicaliseJSON`).

We accept this divergence to keep the verifier dependency-light. Cards remain a valid VC v2 document; only the second-proof verification path is custom.

### 11.3 `credentialSubject.operator.tosAccepted` (new optional block)

When the agent's controlling wallet has accepted the latest `tos_acceptances` row, v1.1 cards include:

```json
"credentialSubject": {
  "agentWallet": "0x...",
  "operator": {
    "tosAccepted": {
      "wallet": "0x...",
      "tosVersion": "1.0",
      "aoaVersion": "1.0",
      "chainId": 8453,
      "acceptedAt": "2026-11-01T12:00:00Z",
      "signature": "0x..."
    }
  }
}
```

When no acceptance exists, the field is `null` (still emitted, so the canonical hash is stable).

### 11.4 Issuer DID document

Verifiers fetch `https://agentresources.xyz/.well-known/did.json` (proxied by the apex Next.js app to the gateway's `/.well-known/did.json` route). The document publishes:

- `verificationMethod[0]` — id `did:web:agentresources.xyz#key-1`, type `EcdsaSecp256k1RecoveryMethod2020`, `blockchainAccountId: "eip155:8453:<EIP-712-signer-address>"`.
- `verificationMethod[1]` — id `did:web:agentresources.xyz#key-2`, type `Ed25519VerificationKey2020`, `publicKeyMultibase` (`z`-prefix base58btc, multicodec 0xed01 + 32-byte raw pubkey).
- `assertionMethod` — both ids.
- `service` — a `TrustCardEndpoint` pointing at `https://api.agentresources.xyz/.well-known/trust-card/`.

The route returns 503 `application/problem+json` if neither issuer key is configured. Cache 300 s. Content-Type `application/did+ld+json`.

### 11.5 Verifier behaviour (`@agent-resources/verify` ≥ 0.2)

- Accepts `proof` as a single object **or** an array. At least one `EthereumEip712Signature2021` proof is required.
- New optional `VerifyOptions` fields:
  - `ed25519IssuerPublicKeyMultibase` — pin the issuer key explicitly (skips DID resolution).
  - `disableDidWebResolution` — fail closed instead of fetching `did.json`.
- New check name: `ed25519SignatureValid` — `pass` / `fail` / `skipped` (skipped when no Ed25519 proof is present, or no key was supplied and DID resolution is disabled).
- All v1 checks (`structure`, `notExpired`, `cardHashMatches`, `signatureValid`, `issuerAllowed`, `telemetryAnchor`) are unchanged.

### 11.6 Environment

| Variable                                          | Purpose                                                                                     |
| ------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| `AR_TRUST_CARD_SIGNER_KEY` / `ERC8004_SIGNER_KEY` | EIP-712 secp256k1 issuer key (v1, required)                                                 |
| `AR_TRUST_CARD_ED25519_KEY`                       | 32-byte hex Ed25519 issuer seed (v1.1, optional). When unset, gateway emits v1-shape cards. |
| `AR_TRUST_CARD_ED25519_VERIFICATION_METHOD`       | Override for the Ed25519 verificationMethod URI. Defaults to `<ISSUER_DID>#key-2`.          |

---

_AR publishes the Trust Card Protocol as a public good. Fork, embed, extend, and hold us to it._

---

## 12. Changelog: v1.1 → v1.1 + Phase 19 (evidence pack + scoped cards)

Phase 19 extends Trust Card v1.1 with two **additive** features. Cards emitted before Phase 19 remain valid; verifiers that ignore the new fields continue to pass.

### 12.1 `credentialSubject.evidence` (always present)

Every card now carries an `evidence` block summarising the agent's most recent telemetry-relevant activity:

```json
"credentialSubject": {
  "agentWallet": "0x...",
  "evidence": {
    "windowStart": "2025-05-01T00:00:00Z",
    "windowEnd":   "2025-06-01T00:00:00Z",
    "telemetryRoot": null,
    "telemetryRootPending": {
      "reason": "phase_2_merkle_anchor_deferred",
      "spec":   "Documentation/06-Specifications/TRUST_CARD_PROTOCOL.md#11-changelog-v1--v11-phase-18"
    },
    "scans": [
      { "scanId": "...", "status": "complete", "score": 92.4, "completedAt": "..." }
    ]
  }
}
```

- `windowEnd` equals the card's `issuanceDate`. `windowStart` is `windowEnd - 30d`.
- `telemetryRoot` stays `null` until Phase 2 lands; `telemetryRootPending` is identical in spirit to the existing `telemetryAnchorPending` field at the top of `credentialSubject` and exists for forward-compat.
- `scans` is the most-recent **5** scans (id, status, numeric score, completedAt). Empty array when none.

The block is fully covered by `cardHash`, so any tamper invalidates the issuer EIP-712 signature.

### 12.2 Scoped Trust Card (`POST /.well-known/trust-card/:wallet/scope`)

Scoped cards bind a card to a single audience + use-case combination, signed by the agent itself. They are intended for delegation flows where the agent presents a Trust Card to a specific marketplace, validator, or counterparty.

**Request** (JSON body):

```json
{
  "audience": "marketplace.example",
  "useCase": "skill-listing",
  "scopeIssuedAt": 1717200000,
  "scopeValidUntil": 1717203600,
  "signature": "0x..."
}
```

The agent signs the EIP-712 tuple under a dedicated domain so the scope signature can never be replayed as an issuer card signature:

- **Domain:** `{name:"AgentResources-TrustCardScope", version:"1", chainId:8453}`
- **Primary type:** `TrustCardScope`
- **Fields:** `agentWallet:address`, `audience:string`, `useCase:string`, `scopeIssuedAt:uint256`, `scopeValidUntil:uint256`

**Validation rules** (gateway):

- `audience` and `useCase` are non-empty strings ≤256 bytes.
- `scopeValidUntil > scopeIssuedAt`.
- Lifetime ≤ 24h (`MAX_SCOPE_LIFETIME_SECONDS = 86400`).
- `|scopeIssuedAt − wallClock| ≤ 5min` (`SCOPE_ISSUED_SKEW_SECONDS = 300`).
- The recovered EIP-712 signer **must equal** the path `:wallet`.

**Response (200):** the same v1.1 card body the GET endpoint would have produced, plus:

1. `credentialSubject.scope = { audience, useCase, scopeIssuedAt, scopeValidUntil, presenter }` — fully covered by `cardHash`.
2. A third `proof` object: an `EthereumEip712Signature2021` with `proofPurpose: "authentication"`, `primaryType: "TrustCardScope"`, signer = the agent wallet, and `verificationMethod = did:pkh:eip155:8453:<wallet>#blockchainAccountId`.

Headers:

```
Content-Type:           application/vc+ld+json; charset=utf-8
Cache-Control:          no-store
AR-Trust-Card-Version:  1.1   (or 1 when Ed25519 key is not configured)
AR-Trust-Card-Scope:    true
```

Scoped cards MUST NOT be cached — each presentation is bearer-bound to one audience. `Cache-Control: no-store` enforces this at the edge.

**Error codes:**

- `400` invalid wallet, missing/non-hex signature, invalid fields, invalid window
- `401` recovered signer ≠ path wallet
- `404` unknown agent wallet
- `503` issuer signing key not configured
- `500` internal

### 12.3 Verifier additions (`@agent-resources/verify`)

The verifier gains a new check `presentationValid` (`pass | fail | skipped`):

- **skipped** when `credentialSubject.scope` is absent (regular cards).
- **pass** when `scope` is present, a `TrustCardScope` `EthereumEip712Signature2021` proof with `proofPurpose: "authentication"` exists, the proof's `signer` and `message.agentWallet` both equal `credentialSubject.agentWallet`, and the EIP-712 signature is valid.
- **fail** otherwise.

The issuer signature continues to cover the entire body including `scope` and `evidence`, so all tampering is caught by the existing `cardHashMatches` and `signatureValid` checks; `presentationValid` exists to assert the **agent's intent** to delegate to that specific audience.

---

## 13. Decision-review updates (locked 2026-05-03)

### 13.1. Ecosystem-agnostic positioning (D1, D7.a)

Trust Cards are **not Base-native**. The attestation NFT (ERC-8004) lives on Base mainnet (chainId 8453), but a Trust Card can be issued for any agent with an off-chain identifier (DID, public key, UUID) by binding the agent's signing key to the card's `credentialSubject.id`. Blockchain infrastructure (ERC-8004, Merkle anchor) proves additional guarantees but is not required for card issuance.

AR is the **cryptographic trust layer** above LLM routing, payment rails, and frameworks. Trust Cards work in any ecosystem that can fetch a URL and verify an EIP-712 signature.

### 13.2. New Phase 16+ claim fields (D8.c)

The following optional fields are added to `credentialSubject` in Phase 16:

```json
"credentialSubject": {
  "quality_gates_count": 3,
  "data_locality": "local | gateway | cloud",
  "memoryProvenanceVerified": true
}
```

| Field                      | Type                    | Added in | Notes                                                                                                      |
| -------------------------- | ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------- |
| `quality_gates_count`      | integer                 | Phase 16 | Count of `quality_gates` entries declared across all installed AR skills for this agent.                   |
| `data_locality`            | `local\|gateway\|cloud` | Phase 16 | Most permissive data-locality mode of any installed skill. `local` = best; `cloud` = least restrictive.    |
| `memoryProvenanceVerified` | boolean                 | Phase 16 | `true` when the agent's memory schema (§3 of MEMORY.md) is fully wired and CRON-046 has run at least once. |

### 13.3. Anchor status fields (D3.1.2)

The `telemetryAnchor` block adds two fields:

```json
"telemetryAnchor": {
  "lastAnchorAt": "...",
  "lastAnchorMerkleRoot": "0x...",
  "anchorStatus": "pending | anchored",
  "anchorBy": "2026-04-21T03:00:00Z"
}
```

| Field          | Values                  | Semantics                                                                                                                                        |
| -------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `anchorStatus` | `pending` \| `anchored` | `pending` = current day's telemetry is not yet anchored (CRON-040 runs at 03:00 UTC); `anchored` = last anchor is complete and root is on-chain. |
| `anchorBy`     | ISO-8601 timestamp      | SLA by which the next `pending` batch will be anchored. Always next 03:00 UTC window.                                                            |

### 13.4. Planned Phase 17+ extensions

These fields are NOT yet emitted. Spec additions for planning purposes.

| Field path                                    | Type         | Decision | Notes                                                                                                                           |
| --------------------------------------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `credentialSubject.runtime`                   | object       | D22.b    | Optional `{name, version, security_layers}`. Populated when the agent owner declares the runtime via `HAND.toml` or direct API. |
| `credentialSubject.agentsMdUrl`               | string (URL) | D32.c    | URL to the agent owner's `AGENTS.md` file. Populated on registration when provided.                                             |
| `credentialSubject.metadata.mcp-registry-url` | string (URL) | D33.e    | URL to the agent's registered MCP server entry at `registry.modelcontextprotocol.io`. Optional.                                 |
| `credentialSubject.capability_gates`          | array        | D22.a    | Derived from `HAND.toml` capability mapping — a declared list of tool categories the agent can invoke.                          |

### 13.5. ERC-8183 evaluator attestation (D39)

When ERC-8183 (evaluator attestation standard) reaches mainnet deployment, AR will support a `credentialSubject.evaluatorAttestations` array. Each entry references a third-party evaluator's on-chain attestation of the agent's capability or safety posture. ERC-8183 is not yet deployed; this is a forward-compat placeholder.

---

_AR publishes the Trust Card Protocol as a public good. Fork, embed, extend, and hold us to it._
