# EEP llms-full.txt — Comprehensive Knowledge Base (v0.1) # Generated: 2026-04-15T19:27:21Z This file concatenates the normative specification, key guides, compliance tooling, and examples. Use file headers for RAG context. === FILE: EEP/README.md === # Entity Engagement Protocol (EEP) > **An open standard for push-based, verifiable communication between digital entities and the clients that follow them.** [![EEP Version](https://img.shields.io/badge/EEP-v0.1-blue)](./docs/current/SPECIFICATION.md) [![CloudEvents](https://img.shields.io/badge/CloudEvents-v1.0.2-orange)](https://cloudevents.io) [![License](https://img.shields.io/badge/License-Apache%202.0-green)](./LICENSE) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](./CODE_OF_CONDUCT.md) ## Stability (v0.1) The specification and reference packages are **v0.1**: the spec, schemas, CI and libraries here are meant to be implemented against, but **breaking changes can still happen** while the ecosystem is small. Pin versions in production and read [CHANGELOG.md](./CHANGELOG.md) before upgrades. Governance details: [GOVERNANCE.md](./GOVERNANCE.md). **Community and safety:** [Code of Conduct](./CODE_OF_CONDUCT.md) · [Security](./SECURITY.md) (reports: **hello@eep.dev** with `[Security]` in the subject) · [Releasing](./RELEASING.md) (maintainers) ## Official repositories - Protocol and reference code: [github.com/eep-dev/EEP](https://github.com/eep-dev/EEP) - Landing site: [github.com/eep-dev/eep-site](https://github.com/eep-dev/eep-site) ## In this repository If you are deciding whether to star, fork, or integrate, here is what is actually here: | Artifact | Where | |----------|--------| | Normative protocol (v0.1) | [docs/current/SPECIFICATION.md](./docs/current/SPECIFICATION.md) | | JSON Schemas | [schemas/v0.1/](./schemas/v0.1/) | | TypeScript libraries (`@eep-dev/*`) | [packages/@eep-dev/](./packages/@eep-dev/) | | Python ports (`eep-*`) | [packages/eep-*-python/](./packages/) (same scope names, Python packaging) | | Conformance runner | [`@eep-dev/compliance-cli`](./packages/@eep-dev/compliance-cli/) | | MCP bridge (tool runtime ↔ EEP) | [`@eep-dev/mcp-bridge`](./packages/@eep-dev/mcp-bridge/) + [`eep-mcp-bridge-python`](./packages/eep-mcp-bridge-python/) | | HTTP middleware for existing APIs | [`@eep-dev/middleware`](./packages/@eep-dev/middleware/) + [`eep-middleware-python`](./packages/eep-middleware-python/) | | Project wizard (`init` / `inject` / `apply` / `verify`) | [`@eep-dev/setup-cli`](./packages/@eep-dev/setup-cli/) | | Docker reference stack (Node + Python + Postgres + Redis) | [examples/eep-reference-implementation/](./examples/eep-reference-implementation/) | | Scripted “Old Web vs EEP” terminal demo | [realworld-simulation/](./realworld-simulation/) (`npm run demo`) | | LangGraph/Claude agent example | [examples/langgraph-eep-agent/](./examples/langgraph-eep-agent/) | | Interactive playground (browser) | [eep.dev/playground](https://eep.dev/playground) — event validation + HMAC signing | | How to run tests | [TESTING.md](./TESTING.md) | Nothing here promises a particular ranking, traffic, or business outcome. It does promise a **documented wire format**, **libraries you can import** and **commands you can run** to check behavior. ## What is EEP? The Entity Engagement Protocol (EEP) describes how digital entities (people, organizations, products, agents) **publish state changes** and how **authorized subscribers** receive them **as events**, with optional **access gates** (identity, credentials, payment, agreements) and **signatures** so subscribers can tell real traffic from forgery. Much of the web still relies on polling or bespoke feeds, so clients often see stale data or one-off integrations. EEP standardizes **discovery**, **subscription**, **delivery** (SSE and webhooks at minimum) and optional **WebSocket** negotiation so integrations look the same across publishers. ## The triple protocol EEP defines three transport layers for different jobs: | Layer | Protocol | Role | |-------|----------|------| | **State resolution** | REST (HTTP) | Discover entities, read capabilities, resolve DID documents | | **Signal stream** | SSE + webhooks | Push lifecycle and content events to subscribers | | **Network pulse** | WebSockets | Low-latency commands and agent-to-agent work | Implementations must provide the **signal stream**. State resolution and network pulse are optional add-ons. ## Why it exists Automated clients (mobile apps, backends, or agents) repeatedly hit the same problems: knowing **when** something changed, subscribing **without** a custom protocol per publisher and checking that an event **really** came from that entity. EEP combines shared discovery, push delivery and cryptographic checks. **Publishers and strategists:** structured discovery, manifests versus sitemaps and *generative engine optimization* (GEO) are discussed as **industry context** in the [Whitepaper](docs/WHITEPAPER.tex) and non-normative spec notes. GEO is **not** a conformance test for EEP. ## Protocol positioning EEP is the contract for **agent ↔ entity** engagement: discovery, realtime streams, gate proofs and payment-aware access. It sits next to, not in place of, other stacks. | Protocol | Primary scope | Interaction | What it standardizes | |----------|----------------|---------------|----------------------| | **EEP** | Entity engagement | agent ↔ entity | discovery, streams, gates, commerce handshakes | | **MCP** | Tool use | agent ↔ tool/server | tool and resource calls for model runtimes | | **A2A** | Agent collaboration | agent ↔ agent | delegation and lifecycle | | **ANP** | Decentralized agent networking | agent ↔ agent | DID-centric coordination | See [eep-positioning-complementary.md](./docs/guides/eep-positioning-complementary.md) for a short comparison. ## Quick start ### Bootstrap (contributors and CI) ```bash bash scripts/bootstrap.sh ``` Run the full test matrix: [TESTING.md](./TESTING.md) (`bash test.sh` after bootstrap). ### For subscribers (sketch) ```bash # Subscribe to an entity stream (webhook delivery) curl -X POST https://api.example.com/eep/subscribe \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "source_did": "did:web:example.com:u:acme-corp", "event_types": ["com.example.entity.updated", "com.example.trust.changed"], "delivery_method": "webhook", "delivery_url": "https://your-agent.example.com/hooks/eep" }' # Or open an SSE stream (no webhook) curl -N "https://api.example.com/eep/stream?source=acme-corp" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### For platforms (dispatchers) [How to dispatch](./docs/guides/how-to-dispatch.md) walks through emitting EEP events from your own stack. ### Setup CLI (`init`, `inject`, `apply`) Use [`@eep-dev/setup-cli`](./packages/@eep-dev/setup-cli/) to scaffold a new config (`init`) or analyze an existing service (`inject`), then generate artifacts (`apply`) and validate (`verify`, `doctor`, `status`, `rotate-secrets`). After `apply`, you still **mount routes** in your app: [After setup-cli: wire EEP into your app](./docs/guides/integrate-eep-after-setup-cli.md). ```bash cd packages/@eep-dev/setup-cli npm install npm run build # optional; otherwise use npx tsx below node dist/index.js init --preset exchange --out ./eep-setup.json # same as: npx eep-setup init … (after build, from this package directory) # or: npx tsx src/index.ts init --preset exchange --out ./eep-setup.json npx tsx src/index.ts inject --project /path/to/existing-api --out /path/to/existing-api/eep-setup.json npx tsx src/index.ts apply --config /path/to/existing-api/eep-setup.json --dry-run npx tsx src/index.ts apply --config /path/to/existing-api/eep-setup.json --output /path/to/existing-api/eep-generated npx tsx src/index.ts verify --output /path/to/existing-api/eep-generated npx tsx src/index.ts doctor --output /path/to/existing-api/eep-generated npx tsx src/index.ts status --output /path/to/existing-api/eep-generated npx tsx src/index.ts rotate-secrets --env /path/to/existing-api/.env ``` Runtime integration: Node [`@eep-dev/middleware`](./packages/@eep-dev/middleware/README.md), Python [`eep-middleware-python`](./packages/eep-middleware-python/README.md). ### WebSocket (network pulse) ```javascript // Bidirectional channel for negotiation-style work const ws = new WebSocket('wss://api.example.com/eep/pulse', { headers: { Authorization: `Bearer ${API_KEY}` } }); ws.onopen = () => ws.send(JSON.stringify({ v: 1, type: 'system', action: 'subscribe', data: { source_did: 'did:web:example.com:u:acme-corp' } })); ws.onmessage = (e) => { const msg = JSON.parse(e.data); console.log(`[${msg.type}] ${msg.action} (seq: ${msg.seq})`); }; ``` ## Repository layout ```text EEP/ ├── docs/ # Spec, guides, ops baselines │ ├── index.md │ ├── current/ # SPECIFICATION.md, MONETIZATION.md, security, delivery_guarantees │ ├── ops/ # SLO, incidents, webhooks, observability │ └── guides/ # Subscribe, dispatch, testing, enterprise, agents, setup-cli, … ├── schemas/v0.1/ # JSON Schemas for v0.1 ├── packages/ │ ├── @eep-dev/{signer,validator,gates,compliance-cli,discovery,mcp-bridge,middleware,setup-cli} │ └── eep-*-python/ # Python ports (naming: eep-gates, eep-signer, …) ├── tests/ # Schema tests, benchmarks, parity tests │ └── cross-impl/ # Pytest suite against any EEP publisher (see README there) ├── realworld-simulation/ # Next.js + Express “Old Web vs EEP” demo ├── scripts/ # bootstrap.sh, smoke tests, coverage helpers ├── examples/ │ ├── eep-reference-implementation/# Docker: Node + Python APIs + Postgres + Redis │ ├── eep-middleware-express-mini/ # Minimal middleware wiring │ ├── node-express-subscriber/ │ ├── node-gate-publisher/ │ ├── python-fastapi-subscriber/ │ ├── python-gate-subscriber/ │ └── cross-impl/ # Legacy interoperability harness (see its README) ├── test.sh # Aggregated test entry └── TESTING.md # Detailed test commands ``` ## Packages (summary) Shipped as npm packages (TypeScript, Node 18+ where noted) with Python counterparts for the same roles: - **`@eep-dev/signer`** / **`eep-signer`**: HMAC-SHA256 webhook signing and verification ([Standard Webhooks](https://www.standardwebhooks.com/) aligned usage). - **`@eep-dev/validator`** / **`eep-validator`**: SSRF checks on subscriber URLs and event-type pattern matching before you call out. - **`@eep-dev/gates`** / **`eep-gates`**: gate configs, access resolution, HTTP 402 helpers, commerce transitions. - **`@eep-dev/compliance-cli`** / **`eep-compliance-cli`**: point at a live base URL and run conformance probes (Node CLI targets Node 22+). - **`@eep-dev/discovery`** / **`eep-discovery`**: manifest validation, `Link` headers, DNS TXT. - **`@eep-dev/mcp-bridge`** / **`eep-mcp-bridge`**: bridge MCP tool traffic with EEP. - **`@eep-dev/middleware`** / **`eep-middleware-python`**: drop-in HTTP adapters (Express, Fastify, Hono, Koa; FastAPI, Flask, Django). - **`@eep-dev/setup-cli`**: project detection, codegen, verify/doctor/watch. ### [@eep-dev/signer](./packages/@eep-dev/signer/) ```typescript import { EEPSigner, verifyEEPWebhook } from '@eep-dev/signer'; const sig = new EEPSigner(secret).sign(webhookId, timestamp, body); const ok = verifyEEPWebhook(rawBody, req.headers, secret); ``` ### [@eep-dev/validator](./packages/@eep-dev/validator/) ```typescript import { validateSSRF, matchesAnyPattern } from '@eep-dev/validator'; await validateSSRF(deliveryUrl); // throws if unsafe const match = matchesAnyPattern('com.example.entity.updated', ['com.example.entity.*']); ``` ### [@eep-dev/compliance-cli](./packages/@eep-dev/compliance-cli/) ```bash npx @eep-dev/compliance-cli --target https://api.yourplatform.com --api-key sk_... --entity u/test ``` Probes cover discovery, subscription, WebSub verification, signatures, CloudEvents envelopes, SSE and rate-limit headers. Use `--report-json` / `--report-md` for CI artifacts. ### [@eep-dev/discovery](./packages/@eep-dev/discovery/) Manifest validation, `Link` header parsing and DNS TXT parsing for discovery documents. ### [@eep-dev/gates](./packages/@eep-dev/gates/) ```typescript import { parseGateConfig, resolveAccess, build402Response, transition, ProofVerifierRegistry } from '@eep-dev/gates'; const config = parseGateConfig(entityGateJson); const registry = new ProofVerifierRegistry(); registry.register({ supportedTypes: ['payment'], verify: async (proof) => Boolean((proof as { token?: string }).token), }); const result = await resolveAccess(agentProofs, config, 'content.papers.full_text', registry); if (!result.granted) { const body = await build402Response(config, 'content.papers.full_text', agentProofs); } const t = transition('open', 'accept'); // { valid: true, to: 'accepted' } ``` Tier types include payment, trust, identity, credential, connection, capability, allowlist, reciprocal, custom `x-*` and combined tiers (see spec and tests for exact rules). ## Reference deployment The **eep-api** reference stack lives in [examples/eep-reference-implementation/](./examples/eep-reference-implementation/): - Node service: `examples/eep-reference-implementation/node` - Python (FastAPI): `examples/eep-reference-implementation/python` - Compose file: `examples/eep-reference-implementation/compose.yml` (build context is the **EEP repo root** so local `packages/@eep-dev/*` paths resolve) Both implementations cover Layer 1 discovery, Layer 2 subscribe/stream, Layer 3 pulse and gate endpoints against shared parity fixtures. Smoke script from repo root: `bash scripts/eep-reference-smoke.sh` (see [Five-minute proof](./docs/guides/five-minute-proof.md)). ## Conformance levels | Level | Includes | |-------|-----------| | **Core** | Layer 1 (`/.well-known/eep.json`) + Layer 2 SSE + valid DID document + content negotiation | | **Standard** | Core + webhooks + credential/identity/payment gates + EEP version negotiation | | **Full** | Standard + Layer 3 WebSocket + commerce state machine + agreement + `data_request` gate + session persistence + W3C DPV-oriented fields | ```bash npx @eep-dev/compliance-cli --target https://api.yourplatform.com ``` Publishers should enforce per-subscriber **429** limits with `Retry-After` and `X-RateLimit-*`; numeric quotas stay implementation-defined. ## Governance and planning EEP uses a BDFN model for **0.x** and plans a steering committee at **v1.0**. Details: [GOVERNANCE.md](./GOVERNANCE.md). - [ROADMAP.md](./ROADMAP.md) — milestones for v0.2, v0.3, and v1.0 (TSC formation, IETF/W3C submission, foundation transition) - [MAINTAINERS.md](./MAINTAINERS.md) — current maintainer tiers and per-package ownership - [CHANGELOG.md](./CHANGELOG.md) — Keep-a-Changelog-style release notes - [eep-site sync checklist](./docs/guides/eep-site-sync-checklist.md) — keep landing-site copy in lockstep with the spec - [arXiv packaging notes](./docs/guides/arxiv-submission.md) — for the whitepaper - [ADOPTERS.md](./ADOPTERS.md) — optional public list; PRs welcome ## Roadmap and adoption Completed in-tree: - Python ports for gates, signer, validator, compliance CLI, discovery, MCP bridge and middleware (see `packages/eep-*-python/`). - Cross-implementation HTTP tests ([tests/cross-impl](./tests/cross-impl)). - Python gate subscriber example ([examples/python-gate-subscriber](./examples/python-gate-subscriber)). Further reading: - [How to use the Setup CLI](./docs/guides/how-to-setup-cli.md) - [After setup-cli: wire EEP into your app](./docs/guides/integrate-eep-after-setup-cli.md) - [Five-minute proof](./docs/guides/five-minute-proof.md) - [Realworld simulation](./docs/guides/realworld-simulation.md) and [realworld-simulation/README.md](./realworld-simulation/README.md) - [Enterprise implementation playbook](./docs/guides/enterprise-implementation-playbook.md) - [Agent onboarding](./docs/guides/agent-onboarding.md) Contributions: [CONTRIBUTING.md](./CONTRIBUTING.md). ## License Apache 2.0. See [LICENSE](./LICENSE). === FILE: EEP/docs/current/SPECIFICATION.md === # Entity engagement protocol (EEP) specification **Version:** 0.1-draft **Status:** Pre-Release **Editors:** EEP Core Team (see `GOVERNANCE.md`) **License:** Apache 2.0 --- ## Abstract The Entity Engagement Protocol (EEP) defines how digital entities publish real-time state change events and how authorized subscribers receive them. It uses three transport layers: state resolution (REST), signal stream (SSE and Webhooks), and network pulse (WebSockets). EEP supports the agentic web, where AI agents participate directly in digital interactions. **Informative context (non-normative):** Industry discussions of *generative engine optimization* (GEO) and machine-readable discovery for retrieval systems are motivation for publishers, not wire requirements here. The normative discovery surfaces in this specification are `Link` headers, DNS/`/.well-known/eep.json`, and related fields. Narrative background, citations, and GEO positioning appear in [`WHITEPAPER.tex`](../WHITEPAPER.tex) (Discovery and related sections). --- ## Table of contents 1. [Terminology](#1-terminology) 2. [Architecture overview](#2-architecture-overview) 3. [Layer 1: State resolution](#3-layer-1-state-resolution) 4. [Layer 2: Signal stream (SSE)](#4-layer-2-signal-stream-sse) 5. [Layer 2: Signal stream (Webhooks)](#5-layer-2-signal-stream-webhooks) 6. [Layer 3: Network pulse (WebSockets)](#6-layer-3-network-pulse-websockets) 7. [Event envelope format](#7-event-envelope-format) 8. [Event type naming convention](#8-event-type-naming-convention) 9. [Standard event catalog](#9-standard-event-catalog) 10. [Subscription lifecycle](#10-subscription-lifecycle) 11. [Authentication and authorization](#11-authentication-and-authorization) 12. [Discovery](#12-discovery) 13. [Rate limiting](#13-rate-limiting) 14. [Conformance levels](#14-conformance-levels) --- ## 1. Terminology - **Entity**: Any digital subject with a stable identity and state that can change over time (a person, business, AI agent, or product). - **Source**: The entity or platform originating an event, identified by a DID or URI. - **Publisher**: The platform responsible for emitting events on behalf of entities. - **Subscriber**: An agent, service, or system that has subscribed to receive events. - **Event**: A structured, immutable record of a state change that occurred at a specific point in time. - **Subscription**: A persistent, authorized relationship between a subscriber and a source's event stream. - **DID**: Decentralized Identifier (W3C standard), used to globally identify entities without central authority. - **HMAC**: Hash-based Message Authentication Code, used to sign webhook payloads. - **WebSub**: W3C Web Subscription protocol. EEP borrows its intent verification mechanism. - **MUST / SHOULD / MAY**: RFC 2119 requirement levels. --- ## 2. Architecture overview ``` ┌─────────────────────────────────┐ │ EEP PUBLISHER │ │ (any compliant EEP platform) │ └──────────┬──────────────────────┘ │ emits events ▼ ┌─────────────────────────────────┐ │ EEP EVENT BUS │ │ (Redis Streams / RabbitMQ) │ └──────────┬──────────────────────┘ ┌────────────────┼──────────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ SSE Stream │ │ Webhooks │ │ WebSockets │ │ (Layer 2a) │ │ (Layer 2b) │ │ (Layer 3) │ └──────┬───────┘ └──────┬───────┘ └──────────────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ AI Agent SSE │ │ Webhook recv │ │ Client │ │ endpoint │ └──────────────┘ └──────────────┘ ``` --- ## 3. Layer 1: state resolution State resolution allows agents to discover and read the current state of an entity. > **Whitepaper §2.1 — Access Spectrum Crosswalk.** The following table maps the six access pattern names from the Whitepaper to their EEP gate type implementation. This crosswalk is normative: agents implementing any of these patterns MUST use the corresponding gate type. | Whitepaper Access Pattern | EEP Gate Type | Description | |---|---|---| | public access | `public` | No gate requirement. Resource is freely accessible. | | trust-gated | `credential` | Agent presents a W3C Verifiable Presentation proving trust level. | | agreement-gated | `agreement` | Agent presents a signed document hash proving they accepted terms. | | data-exchange-gated | `data_request` | Agent presents a W3C VP over requested data claims (name, org_type, etc.). | | payment-gated | `payment` | Agent presents an on-chain transaction hash or x402 payment payload. | | combined | `combined` | Agent must satisfy multiple gate requirements simultaneously (e.g., credential + payment). | ### 3.1 Entity resolution endpoint ``` GET /:type/:username Accept: application/json | text/markdown | text/toon ``` A compliant publisher MUST serve at minimum: - **JSON**: structured entity profile with capabilities, trust score, DID document, and EEP endpoint discovery headers. - **Markdown**: human-readable representation for LLM consumption. ### 3.2 Required response headers ```http HTTP/1.1 200 OK Content-Type: application/json EEP-Version: 0.1 EEP-Entity-DID: did:web:example.com:u:acme-corp Link: ; rel="subscribe"; type="application/json" Link: ; rel="monitor" Link: ; rel="agent-card" ``` The `Link` header with `rel="subscribe"` MUST be present on all entity resolution responses. This is the primary EEP discovery mechanism. ### 3.2.2 Agent Request Headers When an agent accesses restricted entity resources (e.g., submitting proofs to a gate, or posting to a protected inbox), the agent MUST include specific `EEP-` prefixed HTTP headers to identify itself and securely sign the request. ```http EEP-Agent-DID: did:web:agent.example.com EEP-Signature: bd56...8f9a EEP-Nonce: 4893jd83hfb ``` - **`EEP-Agent-DID`**: The DID of the agent making the request (REQUIRED for authenticated requests). - **`EEP-Signature`**: A cryptographic signature (e.g., Ed25519) over the request payload and nonce, asserting control over the `EEP-Agent-DID` (REQUIRED for gated access). - **`EEP-Nonce`**: A unique, single-use random string (8-128 chars) to prevent replay attacks (REQUIRED if `EEP-Signature` is present). ### 3.3 Capability declaration Entities MUST declare their EEP capabilities in the JSON response: ```json { "eep": { "version": "0.1", "endpoint": "https://api.example.com/eep", "supported_delivery": ["webhook", "sse"], "supported_event_types": ["com.example.entity.*", "com.example.trust.*"], "identity": { "did": "did:web:example.com:u:acme-corp", "verification_endpoint": "https://api.example.com/did/acme-corp" }, "gated": true, "gates_url": "https://api.example.com/eep/gates/did:web:example.com:u:acme-corp", "commerce": true, "services_url": "https://api.example.com/eep/services/did:web:example.com:u:acme-corp" } } ``` The `gated`, `gates_url`, `commerce`, and `services_url` fields are OPTIONAL. They MUST be present if the entity uses gated access or offers services. ### 3.4 Gated access Entities MAY define **gates** to restrict access to resources. A gate configuration has entity-defined **tiers**, each with a list of **requirements** and a set of **access patterns** that tier opens up. Some ground rules: - The protocol defines requirement **types**, not **values**. Entity owners pick their own tier names, requirement combinations, and access patterns. - Tier names are up to the entity: `"academic"`, `"dao_members"`, `"vip"`. The protocol does not mandate any names. - The `default_tier` MUST have zero requirements (it is the publicly accessible baseline). #### 3.4.1 Gate configuration endpoint ``` GET /eep/gates/:entity_did Accept: application/json ``` Returns the entity's gate configuration conforming to `gate.config.json` schema. #### 3.4.2 Standard requirement types | Type | Description | Proof needed | |------|-------------|------| | `credential` | W3C Verifiable Credential from a named issuer DID | Encoded VC (JWT / LD-Proof / SD-JWT) | | `identity` | DID ownership proof — know-your-peer | Signed challenge response from agent's DID key | | `agreement` | Crypto signature over SHA-256 hash of a licence document | EdDSA signature + Verifiable Presentation | | `data_request` | Quid-pro-quo: agent provides named claims about itself/owner | Signed VP with W3C DPV purpose declaration | | `payment` | On-chain micropayment to publisher address | Verified transaction hash from compatible L1/L2 | | `combined` | AND/OR combination of any of the above gate types | All constituent proofs | | `x-*` | Custom/extension types (platform-specific) | Implementation-defined | > **Note:** The six core gate types above (`credential`, `identity`, `agreement`, `data_request`, `payment`, `combined`) are normative per Whitepaper Table 1. Additional extension types (`trust`, `connection`, `capability`, `allowlist`, `reciprocal`) are supported by EEP reference implementations but are not required for whitepaper conformance. **Informative (non-normative):** For `agreement` gates, the licence document whose hash is signed MAY encode human-readable obligations (for example attribution strings, canonical URLs, or constraints on reuse in generated summaries). The protocol proves acceptance of that document hash; it does **not** mandate how third-party user interfaces, search engines, or LLM products display citations or links. See [`WHITEPAPER.tex`](../WHITEPAPER.tex) for publisher-facing discussion. #### 3.4.3 Access restriction response (402) When an agent requests a resource that requires a higher tier, publishers MUST return HTTP `402` with a body conforming to `gate.402-response.json`: ```json { "error": "access_restricted", "resource": "content.papers.full_text", "current_tier": "public", "required_tier": "academic", "unmet_requirements": [ { "type": "credential", "resolution_hint": "Verifiable Credential required: AcademicAffiliation" } ], "available_tiers": { "academic": { "label": "Academic Access", "requirements": [{"type": "credential", "credential_type": "AcademicAffiliation"}], "access": ["profile.*", "content.papers.*"] } }, "gates_config_url": "https://api.example.com/eep/gates/did:web:example.com:u:alice" } ``` The response is machine-readable. Agents can parse it and decide what to do next without human help. #### 3.4.4 Proof validation Proof validation is two-step: 1. **Structural validation** (protocol): does the proof have the right fields? Is it fresh (not expired, not future-dated)? 2. **Semantic validation** (platform): is the payment token actually valid? Does the VC verify against the issuer? The protocol defines structural validation. Implementing platforms provide a `ProofVerifier` for semantic checks. --- ## 4. Layer 2: signal stream (SSE) ### 4.1 SSE endpoint ``` GET /eep/stream Authorization: Bearer {API_KEY} Accept: text/event-stream ``` **Query Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `source` | string | No | Filter by entity username or DID | | `events` | string | No | Comma-separated event type filter (e.g. `entity.updated,trust.changed`). Wildcards supported: `entity.*` | | `last_event_id` | string | No | Resume from this event ID (see §4.3) | ### 4.2 SSE event format Each event follows the standard `text/event-stream` format: ``` id: 01HN3QK7GX-1708123456000 event: com.example.entity.updated data: {"specversion":"1.0","id":"01HN3QK7GX-1708123456000","source":"did:web:example.com:u:acme-corp","type":"com.example.entity.updated","time":"2026-02-22T14:30:00Z","datacontenttype":"application/json","data":{"field":"bio","previous":"Old bio","current":"New bio"}} ``` *(Note: events are separated by a blank line, as per the EventSource spec.)* ### 4.3 Guaranteed delivery via Last-Event-ID A compliant EEP publisher MUST implement event replay. When a subscriber reconnects with the `Last-Event-ID` header (or `last_event_id` query parameter), the server MUST replay all events after that ID, up to a configurable retention window (minimum: 24 hours). ```http GET /eep/stream?source=acme-corp Last-Event-ID: 01HN3QK7GX-1708123456000 ``` The publisher responds by replaying all missed events since `01HN3QK7GX-1708123456000`, then continues with live events. Agent workflows often drop network connections. EEP requires replay so agents don't miss data permanently. ### 4.4 Heartbeat The publisher MUST send a comment heartbeat every 15 seconds to detect stale connections: ``` : heartbeat 2026-02-22T14:30:00Z ``` --- ## 5. Layer 2: signal stream (Webhooks) ### 5.1 Webhook subscription ```http POST /eep/subscribe Authorization: Bearer {API_KEY} Content-Type: application/json { "source_did": "did:web:example.com:u:acme-corp", "event_types": ["com.example.entity.updated", "com.example.trust.*"], "delivery_method": "webhook", "delivery_url": "https://agent.example.com/hooks/eep", "delivery_format": "cloudevents/v1.0", "metadata": { "description": "Monitor Acme Corp for trust changes" } } ``` **Successful Response:** ```json { "subscription_id": "sub_01HN3QK7GX", "status": "pending_verification", "source_did": "did:web:example.com:u:acme-corp", "event_types": ["com.example.entity.updated", "com.example.trust.*"], "delivery_url": "https://agent.example.com/hooks/eep", "created_at": "2026-02-22T14:30:00Z", "verification_expires_at": "2026-02-22T14:40:00Z" } ``` The subscription sits in the `pending_verification` status until WebSub intent verification completes (see §10). ### 5.2 Webhook delivery format The publisher MUST `POST` the following payload to the `delivery_url`: ```http POST https://agent.example.com/hooks/eep Content-Type: application/json webhook-id: msg_01HN3QK7GX webhook-timestamp: 1708123456 webhook-signature: v1,base64EncodedHMACSHA256Signature EEP-Version: 0.1 { "specversion": "1.0", "id": "01HN3QK7GX-1708123456000", "source": "did:web:example.com:u:acme-corp", "type": "com.example.entity.updated", "time": "2026-02-22T14:30:00Z", "datacontenttype": "application/json", "eep_version": "0.1", "eep_subscription_id": "sub_01HN3QK7GX", "data": { "entity_id": "acme-corp", "field": "bio", "previous": "Old bio", "current": "New bio" } } ``` ### 5.3 Webhook signature verification The `webhook-signature` header contains an HMAC-SHA256 signature over the concatenation of: ``` {webhook-id}.{webhook-timestamp}.{raw-body} ``` The key is the `delivery_secret` established at subscription time. **Receiving platforms MUST:** 1. Verify the signature using `crypto.timingSafeEqual()` (or equivalent constant-time comparison) to prevent timing attacks. 2. Reject requests where the `webhook-timestamp` is more than **60 seconds** in the past or future to prevent replay attacks. 3. Return HTTP `200` within 10 seconds, or the publisher will treat the delivery as failed. **Example verification (Node.js):** ```typescript import { createHmac, timingSafeEqual } from 'crypto'; function verifyWebhook( rawBody: string, webhookId: string, webhookTimestamp: string, webhookSignature: string, secret: string ): boolean { const signedContent = `${webhookId}.${webhookTimestamp}.${rawBody}`; const expected = createHmac('sha256', secret) .update(signedContent) .digest('base64'); const incoming = webhookSignature.replace('v1,', ''); return timingSafeEqual(Buffer.from(expected), Buffer.from(incoming)); } ``` ### 5.4 Retry policy (exponential backoff) If a webhook delivery fails (non-2xx response or timeout), the publisher MUST retry with exponential backoff: | Attempt | Delay | Max Total Time | |---------|-------|----------------| | 1 | Immediate | — | | 2 | 5 seconds | 5s | | 3 | 30 seconds | 35s | | 4 | 2 minutes | ~2m35s | | 5 | 15 minutes | ~17m35s | | 6 | 1 hour | ~1h17m | | 7 | 6 hours | ~7h17m | After 5 consecutive failures, the subscription MUST switch to `paused` and notify the subscriber. --- ## 6. Layer 3: network pulse (WebSockets) Network pulse handles bidirectional, interactive scenarios. ### 6.1 Connection establishment ``` GET /eep/pulse Upgrade: websocket Authorization: Bearer {API_KEY} ``` ### 6.2 Message format All messages are JSON with a `type` and `action` envelope: ```json { "v": 1, "type": "entity | a2a | system | chat | commerce", "action": "specific-action", "seq": 12345, "data": {} } ``` The `v` field denotes the protocol version. Clients MUST disconnect if they receive an unsupported version. ### 6.3 Message ordering across servers Cross-server messages (routed via Redis pub/sub) do not guarantee in-order delivery. Each message MUST include a monotonic `seq` field per channel. If a gap is detected, the client MUST request a replay: ```json { "v": 1, "type": "system", "action": "replay", "data": { "from_seq": 12340 } } ``` ### 6.3.1 Replay retention bounds (normative) `system`/`replay` catch-up is **not** an infinite server-side log. Publishers MUST cap how much per-channel history they retain for replay (message count and/or maximum age of the earliest retained `seq`). This complements slow-consumer close code `4000` (Whitepaper §13.6): back-pressure avoids unbounded RAM during live delivery; retention caps avoid unbounded replay work after reconnects. **Manifest fields (SHOULD):** publishers SHOULD advertise limits in `/.well-known/eep.json`: | Field | Type | Meaning | |-------|------|---------| | `pulse_replay_max_messages` | integer | Maximum number of past messages retained per channel for replay. | | `pulse_replay_max_age_seconds` | integer | Maximum age of the earliest retained `seq` relative to wall clock. | **Behavior:** if a client requests `from_seq` older than the retained window, the server MUST NOT fabricate history. It MUST close with code `4009` (replay window exceeded) or return an explicit `system` error envelope with the same semantics so clients snapshot or reconcile from Layer 1 instead of assuming unbounded buffers. ### 6.4 JWT re-authentication JWT tokens can expire during long-lived connections. The protocol uses a re-authentication flow: ``` Server → Client: { "type": "system", "action": "auth_expiring", "data": { "expires_in": 300 } } Client → Server: { "type": "system", "action": "auth_refresh", "data": { "token": "new-jwt" } } Server → Client: { "type": "system", "action": "auth_refreshed", "data": { "expires_at": "..." } } ``` If the client fails to refresh within 60 seconds, the server MUST close the connection with code `4001`. ### 6.5 WebSocket close codes EEP defines the following application-level WebSocket close codes (4000-range). Implementations MUST use these codes consistently to allow agents to distinguish error types without parsing error messages: | Code | Name | Meaning | |---|---|---| | `4000` | Back-pressure / Slow consumer | The subscriber is consuming messages too slowly. The publisher terminated the connection rather than buffering indefinitely. Per Whitepaper §13.6. The agent SHOULD reconnect with a slower subscription filter or reduce its subscription scope. | | `4001` | Session expired | The agent's session token or API key expired and was not refreshed within the grace period. The agent MUST re-authenticate from scratch. | | `4002` | Version mismatch | The client sent a message with a `v` field the server does not support. The agent MUST negotiate a supported version using the `eep_versions` manifest field. | | `4003` | Nonce expired / Replay detected | The nonce in the agent's authentication message was already consumed or the `iat` window (60 seconds) was exceeded. The agent MUST obtain a new nonce and retry. | | `4008` | Invalid negotiation transition | The agent attempted an illegal commerce state machine transition (e.g., `bid` after `close`). The agent MUST reset its local state and re-open a new RFP. | | `4009` | Replay window exceeded | The client requested a `system`/`replay` `from_seq` (or equivalent) older than the publisher's retained history (see §6.3.1). The agent MUST reconcile from Layer 1 state or a durable client snapshot; the server does not hold an unbounded log. | ### 6.6 Chat messages The `chat` message type enables persistent messaging between authenticated users and entity owners. Messages are stored in PostgreSQL and fanned out via Redis pub/sub. **Actions:** | Action | Direction | Description | |--------|-----------|-------------| | `send` | Client → Server | Send a message (max 4096 chars). Server persists and broadcasts. | | `history` | Client → Server | Request message history with cursor-based pagination (max 100 per page). | | `read` | Client → Server | Mark messages as read by message ID or mark all as read for an entity. | ```json // Send { "v": 1, "type": "chat", "action": "send", "data": { "entity_did": "...", "message": "Hello" } } // History (cursor pagination) { "v": 1, "type": "chat", "action": "history", "data": { "entity_did": "...", "limit": 50, "before": "msg_id" } } // Mark as read { "v": 1, "type": "chat", "action": "read", "data": { "entity_did": "...", "message_id": "msg_id" } } ``` --- ## 7. Event envelope format All EEP events MUST be valid CloudEvents v1.0.2 envelopes with EEP-specific extensions: ```json { "specversion": "1.0", "id": "unique-event-id", "source": "did:web:example.com:u:acme-corp", "type": "com.example.entity.updated", "time": "2026-02-22T14:30:00Z", "datacontenttype": "application/json", "eep_version": "0.1", "eep_subscription_id": "sub_01HN3QK7GX", "eep_trust_score": 87, "eep_actor_type": "human | agent | system | cron", "data": {} } ``` **EEP extension attributes:** | Attribute | Type | Required | Description | |-----------|------|----------|-------------| | `eep_version` | string | MUST | EEP spec version that generated this event | | `eep_subscription_id` | string | SHOULD | ID of the subscription this was delivered to | | `eep_trust_score` | integer | SHOULD | Snapshot of entity's trust score at event time | | `eep_actor_type` | string | SHOULD | Who triggered the event (human/agent/system/cron) | | `eep_reputation_score` | integer | MAY | On-chain ERC-8004 reputation score at event time (0–100) | | `eep_on_chain_did` | string | MAY | On-chain DID linked to the entity (e.g. via ERC-8004 NFT token) | --- ## 8. Event type naming convention EEP event types follow a reverse-domain dot notation pattern: ``` {reverse-domain}.{entity-type}.{action} {reverse-domain}.{entity-type}.{sub-domain}.{action} ``` **Structure:** - `{reverse-domain}`: The publisher's domain in reverse (e.g., `com.example` for `example.com`) - `{entity-type}`: The noun affected (`entity`, `trust`, `content`, `connection`, `agent`) - `{action}`: The verb (`created`, `updated`, `deleted`, `changed`, `published`) **Examples:** - `com.example.entity.updated` — entity update event from a publisher at `example.com` - `com.acme.product.price_changed` — product price change event from `acme.com` **Wildcard matching:** - `com.example.entity.*` matches all entity events from example.com - `com.example.*` matches all events from example.com - `*.entity.updated` is NOT supported (prefix matching only) --- ## 9. Standard event catalog ### Entity lifecycle | Event Type | Description | |------------|-------------| | `com.example.entity.created` | A new entity profile was created | | `com.example.entity.updated` | One or more profile fields changed | | `com.example.entity.deleted` | An entity was permanently deleted | | `com.example.entity.activated` | A deactivated entity was reactivated | | `com.example.entity.deactivated` | An entity was temporarily deactivated | ### Trust and identity | Event Type | Description | |------------|-------------| | `com.example.trust.changed` | Trust score changed (includes `previous` and `current`) | | `com.example.trust.signal.added` | A positive or negative trust signal was recorded | | `com.example.identity.verified` | Domain, email, or credential verification completed | | `com.example.identity.did_updated` | The entity's DID document updated | ### Content | Event Type | Description | |------------|-------------| | `com.example.content.published` | A new page or post was published | | `com.example.content.updated` | Existing content was modified | | `com.example.content.deleted` | Content was deleted | ### Connections | Event Type | Description | |------------|-------------| | `com.example.connection.followed` | An entity gained a new follower | | `com.example.connection.unfollowed` | A follower disconnected | ### Agent events | Event Type | Description | |------------|-------------| | `com.example.agent.access.read` | An AI agent read this entity's profile | | `com.example.agent.access.search` | An AI agent found this entity via search | | `com.example.agent.task.received` | An A2A task was submitted to this entity | | `com.example.agent.task.completed` | An A2A task completed successfully | | `com.example.agent.task.failed` | An A2A task failed | ### Commerce and marketplace | Event Type | Description | |------------|-------------| | `com.example.commerce.offer` | A new price offer was made | | `com.example.commerce.counter` | A counter-offer was made | | `com.example.commerce.accepted` | A negotiation was accepted | | `com.example.commerce.rejected` | A negotiation was rejected | | `com.example.commerce.invoiced` | An invoice was generated | | `com.example.commerce.paid` | Payment was confirmed | | `com.example.commerce.completed` | A commerce transaction completed | | `com.example.commerce.disputed` | A dispute was raised | | `com.example.service.listed` | A new service was published | | `com.example.service.updated` | A service listing was updated | | `com.example.service.delisted` | A service was removed | | `com.example.gate.config_changed` | Gate configuration was updated | | `com.example.gate.access_granted` | An agent was granted access to a new tier | | `com.example.session.revoked` | Publisher revoked an active subscriber session | --- ## 10. Subscription lifecycle ``` POST /subscribe │ ▼ [pending_verification] │ │ Publisher sends GET challenge to delivery_url ▼ [Challenge Response from Subscriber] │ Success ──────────────────► [active] │ │ Failure event delivery ▼ │ [rejected] 5 consecutive failures ▼ [paused] │ POST /subscriptions/:id/resume ▼ [active] ``` ### WebSub intent verification When creating a webhook subscription, the publisher MUST perform intent verification: 1. Publisher sends a `GET` request to `delivery_url` with query string: ``` ?hub.mode=subscribe &hub.topic=did:web:example.com:u:acme-corp &hub.challenge=random_secure_string_32_chars &hub.lease_seconds=2592000 ``` 2. The subscriber endpoint MUST respond with HTTP `200` and a body containing perfectly matched `hub.challenge` value. 3. If the subscriber does not respond within 10 seconds, the subscription changes to `rejected`. Intent verification prevents malicious actors from registering unauthorized URLs to bounce traffic through the publisher. --- ## 11. Authentication and authorization ### API key authentication Subscription endpoints require an API key: ```http Authorization: Bearer {API_KEY} ``` ### Scopes | Scope | Description | |-------|-------------| | `read:subscriptions` | List own subscriptions | | `write:subscriptions` | Create and manage subscriptions | | `read:events` | Access the SSE stream | | `read:gates` | Read gate configurations | | `write:gates` | Modify gate configurations | | `commerce:negotiate` | Participate in commerce negotiations | | `read:services` | Browse service listings | | `write:services` | Publish and manage service listings | | `write:reviews` | Submit service reviews | ### Public events vs. private events Events can have access control: - **Public events** (like `entity.updated` on a public profile) can be accessed by any authenticated subscriber. - **Private events** (like agent access analytics) require the subscriber to be the entity owner. ### 11.5 Proof-of-Intent (PoI) PoI is a defence mechanism against two AI-specific attack classes: - **Confused Deputy**: an agent is tricked into using its elevated privileges to perform an action on behalf of a malicious second party. - **Logic Prompt Control Injection (LPCI)**: injected prompts cause the agent to take actions outside the scope that the human operator intended. For commerce transactions above a configurable threshold, or any resource marked as `high_risk`, publishers SHOULD require a `proof_of_intent` gate proof. #### Intent Document ```json { "type": "proof_of_intent", "intent_document": { "intent_id": "intent_01HXK", "agent_did": "did:web:my-agent.example.com", "principal_did": "did:web:alice.example.com", "action": "Purchase Bloomberg financial data feed — daily briefing", "scope": { "max_amount": 250, "currency": "USDC", "allowed_resources": ["data.finance.*", "events.market.*"], "expires_at": "2026-03-05T06:00:00Z" }, "principal_signature": "0xdeadbeef...", "created_at": "2026-03-05T05:00:00Z" } } ``` **Structural validation** (protocol-level, implemented by `@eep-dev/gates` `poi-validator.ts`): - All required fields present - `agent_did` matches the requesting agent's authenticated DID - `scope.expires_at` is in the future (not expired) - `created_at` is not in the future (replay protection) - `principal_signature` is a valid hex or base64 signature string **Semantic validation** (platform-level): - Verify the `principal_signature` against the `principal_did`'s DID Document public key - Confirm `scope.max_amount` and `allowed_resources` cover the current request #### Scope Checking Before executing any high-risk action, the publisher MUST check that both the `resource` and `amount` (if applicable) fall within the PoI scope using the `isWithinScope()` function from `@eep-dev/gates`. | Check | Failure Behaviour | |-------|------------------| | `resource` not in `allowed_resources` | Return 403 with `unmet: proof_of_intent` | | `amount > max_amount` | Return 402 with `unmet: proof_of_intent` | | PoI expired | Return 401 with `error: intent_expired` | ### 11.6 Post-Quantum Cryptography (PQC) Readiness EEP nodes that advertise `pqc_ready: true` in their `/.well-known/eep.json` manifest MUST support at least one of the NIST FIPS 203/204/205 primitive sets: | NIST Standard | Algorithm | Use | |---------------|-----------|-----| | FIPS 203 | ML-KEM-768 | Key encapsulation / TLS hybrid | | FIPS 204 | ML-DSA-65 | Digital signatures | | FIPS 205 | SLH-DSA-128s | Hash-based signatures (stateless) | Nodes SHOULD advertise supported algorithms in the `pqc_algorithms` array of the manifest. Nodes that are not yet PQC-ready MUST set `pqc_ready: false` (not omit the field). ### 11.7 Signing Algorithm Negotiation (Crypto-Agility) EEP is designed for a protocol lifetime exceeding a decade. To avoid a hard migration cutover when PQC algorithms become mandatory, EEP supports **signing algorithm negotiation** per Whitepaper §13.11. Publishers declare their supported signing algorithms in the `signing_algorithms` array of their `/.well-known/eep.json` manifest, in order from most preferred to least preferred: ```json { "signing_algorithms": [ "hybrid-EdDSA-ML-DSA-65", "EdDSA", "ES256K" ] } ``` **Negotiation rules:** 1. When an agent submits a proof, it MUST sign using the **strongest mutually supported algorithm**: the publisher's highest-preference algorithm that the agent also supports. 2. If the agent cannot support any algorithm in the publisher's list, it MUST abort and return a descriptive error rather than sending an unverifiable proof. 3. Publishers MUST verify only the algorithm they selected (reject proofs signed with unlisted algorithms). 4. If `signing_algorithms` is absent from the manifest, agents MUST default to `EdDSA` (Ed25519). **Algorithm identifiers** (valid `signing_algorithms` values): | Identifier | Algorithm | Standard | |---|---|---| | `EdDSA` | Ed25519 | RFC 8037 | | `ES256K` | secp256k1 ECDSA | RFC 8812 | | `ES256` | P-256 ECDSA | RFC 7518 | | `ML-DSA-65` | CRYSTALS-Dilithium Level 3 | FIPS 204 | | `ML-DSA-87` | CRYSTALS-Dilithium Level 5 | FIPS 204 | | `SLH-DSA-128s` | SPHINCS+-SHA2-128s | FIPS 205 | | `hybrid-EdDSA-ML-DSA-65` | Ed25519 + ML-DSA-65 (dual signature) | FIPS 204 + RFC 8037 | | `hybrid-EdDSA-ML-DSA-87` | Ed25519 + ML-DSA-87 (dual signature) | FIPS 204 + RFC 8037 | **Hybrid signatures:** When both `EdDSA` and `ML-DSA` are present in the same signed payload, the proof object carries both `proofValue` (EdDSA) and `mldsaProofValue` (ML-DSA). Either individual signature is valid for classical verifiers; post-quantum verifiers MUST validate both. This enables incremental migration without a flag-day switchover. ```json { "type": "DataIntegrityProof", "cryptosuite": "hybrid-eddsa-mldsa-2022", "verificationMethod": "did:web:agent.example.com#key-1", "proofPurpose": "assertionMethod", "proofValue": "z3K2nRgW...", "mldsaProofValue": "zABC123..." } ``` **Resource-constrained agents (IoT / embedded):** hybrid proofs increase CPU time and payload size versus EdDSA-only. Such deployments SHOULD default to classical algorithms for routine traffic and use PQ-hybrid only where policy or tier requires it (Whitepaper §13.11). ### 11.8 DID resolution caching and resolver outages DID methods that resolve over HTTPS (e.g. `did:web`) depend on infrastructure that can be temporarily unavailable. **Caching:** implementations MAY cache resolved DID Documents. Cache entries MUST have a bounded TTL (`did_cache_ttl_seconds` in operator policy or manifest metadata). Cached documents MUST NOT bypass revocation: before accepting high-assurance gate proofs, publishers SHOULD refresh when the cache age exceeds policy. **Resolver failure:** if authoritative resolution fails and freshness cannot be established, implementations SHOULD **fail closed** (reject the proof) for high-assurance gates rather than accept possibly stale keys. Low-risk surfaces MAY retry with exponential backoff per operator policy. --- ## 12. Discovery **Informative (non-normative):** Classic web discovery for crawlers often uses HTML links and XML `sitemap.xml` to enumerate URLs. The EEP manifest at `/.well-known/eep.json` is a **machine-readable declaration of protocol surfaces** (DIDs, layers, gates, content negotiation), complementary to sitemaps rather than a drop-in replacement. Retrieval-oriented and publisher strategy context (including GEO as discussed in research and industry reporting) is documented in [`WHITEPAPER.tex`](../WHITEPAPER.tex), Section 4 (*Discovery and the EEP Registry*). Subscribers discover EEP endpoints through three mechanisms: ### 12.1 HTTP link header (primary) Every entity resolution response MUST include: ```http Link: ; rel="subscribe" Link: ; rel="monitor" ``` ### 12.2 Agent card extension (A2A v0.3 + W3C ANP) The entity's A2A agent card MUST include the `x-eep` extension. Fields marked **SHOULD** improve discoverability by W3C AI Agent Protocol (ANP) clients and EU AI Act compliance tooling: ```json { "x-eep": { "subscribe_url": "https://api.example.com/eep/subscribe", "stream_url": "https://api.example.com/eep/stream", "source_did": "did:web:example.com:u:acme-corp", "supported_events": ["com.example.entity.*", "com.example.trust.*"], "anp_compatible": true, "dpv_purpose": "https://w3id.org/dpv#ServiceProvision", "dpv_retention": "https://w3id.org/dpv#TemporalDuration" } } ``` | Field | Required | Description | |-------|----------|-------------| | `subscribe_url` | MUST | Webhook subscription endpoint | | `stream_url` | MUST | SSE stream URL | | `source_did` | MUST | Entity's DID | | `supported_events` | SHOULD | Supported event type patterns | | `anp_compatible` | SHOULD | W3C ANP semantic compatibility flag | | `dpv_purpose` | SHOULD | W3C DPV data processing purpose URI | | `dpv_retention` | SHOULD | W3C DPV data retention policy URI | ### 12.3 Well-known document ``` GET /.well-known/eep.json ``` Returns the platform-level EEP capabilities document conforming to `schemas/v0.1/eep-manifest.json`. **Example manifest:** ```json { "did": "did:web:api.example.com:u:acme-corp", "eep_version": "0.1", "layers": { "layer1": "https://api.example.com/u/acme-corp", "layer2_sse": "https://api.example.com/eep/stream", "layer2_webhook": "https://api.example.com/eep/subscribe", "layer3_ws": "wss://api.example.com/eep/pulse" }, "supported_content_types": ["application/json", "text/markdown", "text/toon"], "gates_url": "https://api.example.com/eep/gates/did:web:api.example.com:u:acme-corp", "services_url": "https://api.example.com/eep/services/did:web:api.example.com:u:acme-corp", "capabilities_query_url": "https://api.example.com/eep/capabilities/did:web:api.example.com:u:acme-corp", "reputation": { "contract": "0xC5a3dD3EF9b961c5c52218af7023e6F7A5e2e67F", "chain": "ethereum", "scan_url": "https://8004scan.io/0xC5a3dD3EF9b961c5c52218af7023e6F7A5e2e67F" }, "pqc_ready": false, "pqc_algorithms": [], "x402_enabled": true, "x402": { "facilitator_url": "https://x402.org/facilitator", "payment_rails": ["x402/usdc"], "network": "base" }, "compliance": { "eu_ai_act": true, "gdpr": true, "anp_compatible": true, "dpv_purpose": "https://w3id.org/dpv#ServiceProvision" }, "updated_at": "2026-03-05T05:00:00Z" } ``` ### 12.4 Dynamic Capability Discovery For entities with large data catalogs or frequently changing capabilities, static manifests become stale. Publishers MAY expose a paginated capability query endpoint: ``` GET /.well-known/eep.json/capabilities ?query=financial+data &category=finance &gate_type=payment &page=1 &limit=20 ``` The URL is advertised in the manifest's `capabilities_query_url` field. **Response format:** ```json { "items": [ { "id": "cap_bloomberg_daily", "name": "Bloomberg Daily Briefing", "category": "finance", "gate_types": ["payment", "credential"], "access_patterns": ["data.finance.bloomberg.*"] } ], "total": 142, "page": 1, "limit": 20, "next_page_url": "https://api.example.com/eep/capabilities/acme-corp?page=2&limit=20" } ``` This allows agents to search for specific capabilities without downloading the entire catalog. --- ## 13. Rate limiting Publishers MUST enforce rate limits and return standard headers: ```http X-RateLimit-Limit: 100 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1708168200 Retry-After: 120 ``` Recommended default limits per subscriber: | Action | Limit | |--------|-------| | Subscription creation | 100/day | | SSE connections | 5 concurrent | | Webhook deliveries received | 10,000/day | | Event stream history queries | 60/hour | ### 13.1 Cold-start DID trust progression (normative) New or unproven DIDs start in a **restricted** rate bucket (tighter limits, optional proof-of-payment or proof-of-work challenge on `429` responses via `X-EEP-RL-Challenge`). Agents MAY graduate to standard limits by: 1. **Proof-of-payment:** Successful micropayment or stake tied to the DID (recorded in audit or on-chain reputation). 2. **Genesis proof:** Verifiable completion of a registry- or publisher-issued challenge (VC attestation `EEPColdStartGraduation` or equivalent). 3. **Trust Anchor VC:** Presentation of a valid trust credential from a federated registry. Publishers SHOULD document decay (e.g. trust score cooldown) and MUST NOT permanently trap good-faith agents: graduation paths MUST be machine-testable where advertised. --- ## 14. Conformance levels EEP defines three conformance tiers aligned with Whitepaper §10.2 (Table 2). Each tier is associated with a distinct **EEP Conformance Credential** type issued by `eep.dev`'s DID. Agents MUST only filter by conformance level after verifying the credential's `proof` and `validUntil`. ### 14.1 Core Suitable for: read-only publishers, IoT sensors, knowledge bases. - [x] `/.well-known/eep.json` manifest endpoint (must pass schema validation against `eep-manifest.json`) - [x] Layer 1 REST state endpoint with `Accept` header content negotiation (JSON, Markdown, TOON) - [x] `rel="subscribe"` Link header on all Layer 1 responses - [x] Layer 2 SSE stream endpoint with event type filtering (`?events=type1,type2`) - [x] `Last-Event-ID` replay with a minimum 24h event retention window - [x] CloudEvents v1.0 envelope format on all emitted events - [x] EEP extension attributes (`eep_version`, `eep_subscription_id`) on all emitted events - [x] Rate limit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `Retry-After`) on all responses - [x] Discovery via HTTP `Link` headers and/or DNS TXT record `_eep.` **Credential type:** `EEPConformanceCredential_Core` --- ### 14.2 Standard Superset of Core. Suitable for: B2B data APIs, financial feeds, subscription services. - [x] All Core requirements above, plus: - [x] Webhook subscription endpoint (`POST /eep/subscribe`) with full lifecycle (create/pause/resume/delete) - [x] WebSub intent verification before activating any webhook subscription - [x] HMAC-SHA256 signature on all webhook deliveries (`X-EEP-Signature` header) - [x] Exponential backoff retry policy for failed webhook deliveries (min 5 attempts, max 24h window) - [x] `credential` gate: W3C VC 2.0 presentation verification from named issuer DID - [x] `payment` gate: on-chain transaction hash verification with configurable confirmation threshold - [x] `identity` gate: DID ownership proof challenge-response - [x] HTTP `402 Payment Required` structured response (`gate.402-response.json`) - [x] HTTP `403 Forbidden` structured response (`gate.403-response.json`) - [x] HTTP `451 Unavailable For Legal Reasons` structured response (`gate.451-response.json`) - [x] Version negotiation: `EEP-Version` request/response headers + HTTP 505 fallback - [x] Session tokens (signed JWT-like) with `exp`, `refresh_threshold`, `context_id` per §6 - [x] `ERC-8004` reputation field in `/.well-known/eep.json` manifest (optional; SHOULD for on-chain entities) - [x] x402 payment rail support in `PaymentRequirement.x402` and `PaymentProof.x402_payload` - [x] PQC readiness declaration (`pqc_ready` + `pqc_algorithms`) in manifest - [x] `signing_algorithms` field in manifest declaring supported DID signing algorithms (crypto-agility) **Credential type:** `EEPConformanceCredential_Standard` --- ### 14.3 Full Superset of Standard. Suitable for: agent commerce platforms, regulated industries, multi-party data exchanges. - [x] All Standard requirements above, plus: - [x] Layer 3 WebSocket endpoint with `type`/`action`/`seq` JSON envelope format - [x] JWT re-authentication in WebSocket connections (session token presented on upgrade) - [x] Commerce message type (`commerce.*`) in WebSocket with full state machine enforcement - [x] `offer → counter → accept → invoice → paid` transitions validated - [x] `commerce.rfp.open / commerce.rfp.bid / commerce.rfp.closed` auction events via Layer 2 - [x] Signed Allocation Receipt VC issued to winning bidder - [x] Negotiation state machine enforcement (invalid transitions return `4008` close code) - [x] `agreement` gate: EdDSA signature over SHA-256 document hash verified as Verifiable Presentation - [x] `data_request` gate: W3C DPV purpose declaration + specific named claims + `retention_days` - [x] `combined` gate: AND/OR logic across any combination of gate types - [x] Session persistence: `Last-Event-ID` associated per session token for zero-loss reconnect - [x] `session.revoked` event emitted on active subscriber streams on publisher-initiated revocation - [x] Proof-of-Intent (`proof_of_intent`) structural and scope validation for high-risk commerce - [x] W3C DPV (`dpv_purpose`, `dpv_retention`) in data_request gates and Agent Card `x-eep` extension - [x] ANP compatibility flag (`anp_compatible: true`) in Agent Card `x-eep` extension - [x] `data.withdrawal` WebSocket message + `DELETE /data/claims/:claim_id` REST endpoint - [x] Operator Privacy Policy Profile machine-readable schema (`operator.privacy-policy.json`) - [x] Operator Spending Policy Profile machine-readable schema (`operator.spending-policy.json`) - [x] Service listing endpoints (Layer 1 state + `service.listing.json` schema) - [x] Review and rating system (aggregated rating in `service.listing.json`) - [x] End-to-end delivery audit log API (`GET /eep/audit-log`, response: `audit-log.json`) - [x] Cross-server message ordering via Redis pub/sub or equivalent ordered message broker - [x] Forward Secrecy enforced for all WS/SSE connections (`forward_secrecy_enforced: true` in manifest) - [x] mTLS support (`tls_mode: "mTLS"` or `"mTLS-required"` in manifest) **Credential type:** `EEPConformanceCredential_Full` --- ### 14.4 EEP Conformance Credential A publisher that passes the full conformance test suite at `eep.dev/conformance` receives a time-bounded **EEP Conformance Credential**: a W3C Verifiable Credential 2.0 issued by `did:web:eep.dev`, which can be embedded in the `/.well-known/eep.json` manifest under the `conformance_credential` field. ```json { "@context": ["https://www.w3.org/ns/credentials/v2"], "type": ["VerifiableCredential", "EEPConformanceCredential_Full"], "issuer": "did:web:eep.dev", "validFrom": "2026-03-01T00:00:00Z", "validUntil": "2027-03-01T00:00:00Z", "credentialSubject": { "id": "did:web:api.example.com", "conformanceTier": "Full", "testedAt": "2026-03-01T00:00:00Z", "passedChecks": 47, "totalChecks": 47, "manifestUrl": "https://api.example.com/.well-known/eep.json" }, "proof": { "type": "DataIntegrityProof", "cryptosuite": "eddsa-rdfc-2022", "created": "2026-03-01T00:00:00Z", "verificationMethod": "did:web:eep.dev#key-1", "proofPurpose": "assertionMethod", "proofValue": "z3K2nRgWAZf..." } } ``` Agents MUST verify: 1. `proof.verificationMethod` resolves to a key in `did:web:eep.dev`'s DID Document 2. `validUntil` is in the future (credential expires annually) 3. `conformanceTier` matches the tier declared in the publisher's manifest 4. The DID in `credentialSubject.id` matches the publisher's `entity_did` See `schemas/v0.1/conformance.credential.json` for the full JSON Schema. --- ### 14.5 Audit Log Requirement (Full Tier) Full-tier publishers MUST expose a delivery audit log endpoint: ``` GET /eep/audit-log ``` **Query parameters:** | Parameter | Type | Description | |-----------|------|-------------| | `actor_did` | string | Filter by agent DID | | `event_type` | string | Filter by audit event type | | `from` | date-time | Start of time range (ISO8601) | | `to` | date-time | End of time range (ISO8601) | | `outcome` | string | `success`, `failure`, `partial`, `pending` | | `page` | integer | Page number (default: 1) | | `per_page` | integer | Entries per page (default: 20, max: 1000) | | `sort` | string | `desc` (default) or `asc` | **Example response** (schema: `audit-log.json`): ```json { "entries": [ { "entry_id": "d290f1ee-6c54-4b01-90e6-d701748f0851", "event_type": "gate.proof.accepted", "actor_did": "did:web:agent.example.com", "publisher_did": "did:web:api.example.com", "timestamp": "2026-03-05T10:00:00Z", "outcome": "success", "resource": "premium", "gate_type": "payment", "nonce": "nonce_abc123", "signature": "z3K2nRgW...", "metadata": { "tx_hash": "0xdeadbeef", "chain": "base" } } ], "total": 142, "page": 1, "per_page": 20, "publisher_did": "did:web:api.example.com" } ``` Each entry is **individually signed** by the publisher's DID key, making tampering cryptographically detectable. This satisfies: - **DORA Art. 8** — ICT incident and event logging for financial services - **EU AI Act Art. 12** — High-risk AI system decision logging - **GDPR Art. 5(2)** — Accountability principle (signed exchange log as on-chain record) ### §3.4.3 Access restriction responses Publishers use three HTTP status codes for gate failures: | Status | Error Code | Trigger | |--------|------------|---------| | `402 Payment Required` | `access_restricted` | Payment gate not met | | `403 Forbidden` | `access_forbidden` | Credential, identity, allowlist, reciprocal gate not met | | `451 Unavailable For Legal Reasons` | `legally_restricted` | Resource restricted by law (EU AI Act, DORA, GDPR Art.17, judicial order) | **402 Response** (`gate.402-response.json`): ```json { "error": "access_restricted", "resource": "content.papers.full_text", "current_tier": "public", "required_tier": "academic", "unmet_requirements": [{"type": "credential", "resolution_hint": "AcademicAffiliation VC required"}], "available_tiers": { "academic": { "requirements": [...] } } } ``` **403 Response** (`gate.403-response.json`): ```json { "error": "access_forbidden", "resource": "analytics.agent.tracking", "current_tier": "public", "required_tier": "verified_agent", "unmet_requirements": [{"type": "identity", "resolution_hint": "DID verification required"}] } ``` **451 Response** (`gate.451-response.json`): ```json { "error": "legally_restricted", "resource": "ai.highRiskSystem.inference", "reason": "EU AI Act Annex III prohibits unregistered high-risk AI system access", "legal_basis": "EU AI Act Art. 6 Annex III", "jurisdiction": "EU", "contact": "legal@example.com" } ``` --- ## 15. Service discovery and marketplace Entities MAY publish a **service catalog** of their offerings. The catalog is machine-readable, so agents can find, compare, and purchase services without manual browsing. ### 15.1 Service catalog endpoint ``` GET /eep/services/:entity_did Accept: application/json ``` Returns a `service.listing.json`-conformant response with the entity's service catalog. ### 15.2 Service listing fields Each service in the catalog includes: - **id**: Unique service identifier (pattern: `svc_[a-zA-Z0-9_]+`) - **name**: Human-readable name - **category**: Freeform category string for classification - **tags**: Entity-defined tags for search and discovery - **pricing**: Uses the same pricing model schema as commerce negotiations - **delivery**: How the service is delivered (`realtime`, `async`, `scheduled`, `sse`, `webhook`, `download`, `a2a_task`) - **availability**: Schedule, slot limits, or on-demand - **negotiable**: Whether the entity accepts counter-offers - **gate_requirements**: Additional non-payment requirements ### 15.3 Pricing models The protocol defines standard pricing models. Custom models use the `x-` prefix. | Model | Description | |-------|-------------| | `fixed` | One-time flat price | | `per_request` | Charge per API request | | `per_event` | Charge per event delivered | | `subscription` | Recurring charge with a billing period | | `metered` | Usage-based billing (rate × units consumed) | | `tiered_volume` | Volume discounts with tier brackets | | `free` | No charge | | `x-*` | Custom pricing models | ### 15.4 Commerce negotiation When a service has `negotiable: true`, agents can negotiate pricing over the WebSocket `commerce` message type. The negotiation follows a state machine: ``` offer → [open] → counter → [countered] → accept → [accepted] → reject → [rejected] → expire → [expired] [accepted] → invoice → [invoiced] → receipt → [paid] → complete → [completed] Any active state → dispute → [disputed] → accept/reject/complete ``` Terminal states: `rejected`, `expired`, `completed`. #### 15.4.1 M2M dispute resolution (normative) After `paid` or `completed`, if the publisher fails SLA (e.g. stops streaming, withholds agreed data), the subscriber agent MAY open a dispute without human intervention where policy allows. **Layer 3:** Publishers MUST support `commerce.dispute.open` and related `commerce.dispute.*` actions on the WebSocket envelope (see `schemas/v0.1/ws-message.json`). Payloads include `negotiation_id`, `reason_code` (machine-readable), `evidence` (hashes or URIs), and optional `requested_remedy` (`refund` \| `service_resume` \| `reputation_penalty`). **Outcomes:** Resolution is implementation-defined on-chain or off-chain, but publishers MUST emit terminal commerce events (`commerce.dispute.resolved` with `outcome`: `refunded` \| `rejected` \| `penalty_applied` \| `dismissed`) and SHOULD adjust publisher trust score or escrow release per `terms.sla` when present. ### 15.5 Reviews After a transaction completes, subscribers MAY leave a review: - **score**: 1-5 integer - **comment**: Optional text (max 2048 chars) - **reviewer_did**: DID of the reviewing agent Reviews are collected into a `rating` object on the service listing. --- ## 16. Compliance and Audit Trails EEP publishers serving regulated environments (EU AI Act, DORA, GDPR) SHOULD expose a compliance audit log endpoint. The log provides a cryptographically verifiable record of all agent interactions. ### 16.1 Audit log endpoint ``` GET /eep/audit ?entity_did=did:web:example.com:u:acme-corp &from=2026-03-01T00:00:00Z &to=2026-03-05T23:59:59Z &type=agent.access&type=commerce.paid &page=1 &limit=100 Authorization: Bearer {OWNER_API_KEY} ``` **Response:** ```json { "entries": [ { "entry_id": "audit_01HXK", "timestamp": "2026-03-05T05:00:00Z", "entity_did": "did:web:example.com:u:acme-corp", "actor_did": "did:web:my-agent.example.com", "actor_type": "agent", "event_type": "com.example.commerce.paid", "resource": "services.consultation_30", "tier": "premium", "amount": 75, "currency": "USDC", "outcome": "success", "signature": "base64EncodedEd25519Signature" } ], "total": 2341, "page": 1, "limit": 100 } ``` ### 16.2 Entry signing Each audit entry MUST be signed by the publisher using an Ed25519 key. The signature covers the concatenation of: ``` {entry_id}.{timestamp}.{entity_did}.{actor_did}.{event_type}.{outcome} ``` This allows auditors (compliance officers, EU AI Act notified bodies) to verify the log has not been tampered with. ### 16.3 Retention requirements | Regulation | Minimum Retention | |------------|-------------------| | EU AI Act Art. 12 | 10 years (high-risk systems) | | DORA Art. 9 | 5 years | | GDPR Art. 30 | Duration of processing + 3 years | Publishers MUST declare their retention period in the manifest's `compliance` object. ### 16.4 Regulatory Alignment Table (G23) The following table maps EEP protocol features to their corresponding regulatory obligations: | Regulation | EEP Feature | How It Helps | |---|---|---| | **EU AI Act Art. 9** (risk management) | `trust` gate, ERC-8004 reputation | Verified agent identity and behavioral scoring | | **EU AI Act Art. 12** (record-keeping) | Audit Trail API (`GET /eep/audit`), signed log entries | Tamper-evident, long-term audit logs | | **EU AI Act Art. 13** (transparency) | `eep.json` manifest, TOON format | Machine-readable and human-readable disclosures | | **GDPR Art. 5** (purpose limitation) | `data_request` gate with W3C DPV purpose | Prevents data use outside declared purpose | | **GDPR Art. 7** (consent) | `data_request` gate, Operator Privacy Policy | Structured, withdrawable consent | | **GDPR Art. 17** (right to erasure) | `data.withdrawal` WebSocket message | Standardized data withdrawal request protocol | | **DORA Art. 9** (ICT risk) | `compliance.dora: true` flag, audit retention | Registry-level ICT risk compliance declaration | | **eIDAS 2.0 / EU 2024/1183** | `agreement` gate (W3C VC), Delegation Proof VC | Wallet-aligned credential stack; cross-border identity | | **CCPA §1798.100** | Operator Privacy Policy, `data_request` gate | Agent-side privacy preference enforcement | | **W3C ANP** | `compliance.anp_compatible`, A2A `x-eep` fields | Semantic interoperability with agent network protocols | --- ## §3.1.1 Version Negotiation (G21) Clients MUST include an `EEP-Version` header on every request: ``` EEP-Version: 0.1 ``` If the server does not support the requested version, it MUST respond with HTTP **505 EEP Version Not Supported**: ```json { "error": "eep_version_not_supported", "requested_version": "0.1", "supported_versions": ["1.0"], "preferred_version": "1.0" } ``` Publishers declare all supported versions in `eep_versions[]` and their preference in `preferred_version` in `eep.json`. --- ## §3.4.4 `data_request` Gate Type (G13) ```json { "type": "data_request", "requested_claims": [ { "claim": "org_type", "required": true }, { "claim": "industry_sector", "required": false } ], "purpose": "dpv:ResearchAndDevelopment", "retention_days": 30, "shareable": false, "policy_url": "https://publisher.example/privacy", "policy_hash": "sha256:a3b4c5..." } ``` **Proof:** Agent submits a W3C Verifiable Presentation containing the requested claims, signed by the agent's DID key. ```json { "type": "data_request", "verifiable_presentation": "eyJhbGciOiJFZERTQSJ9...", "claimed_fields": ["org_type", "industry_sector"] } ``` **Purpose values** MUST use W3C DPV vocabulary (e.g., `dpv:ServiceProvision`, `dpv:ResearchAndDevelopment`, `dpv:Optimization`). **Agent behavior:** Before sharing data, the agent checks its Operator Privacy Policy Profile (§10.1) to determine which claims it may share autonomously vs. which require human confirmation. --- ## §3.4.5 `agreement` Gate Type (G14) Requires the agent to digitally sign a specific document (license agreement, ToS, data processing agreement) using EdDSA. ```json { "type": "agreement", "document_hash": "sha256:4b227777d4dd1fc61c6f884f48641d02b4d121d3fd328cb0cd4af7d9c7d72a5a", "document_url": "https://publisher.example/terms/v2.pdf", "document_title": "API Terms of Service v2.0", "signature_algo": "EdDSA" } ``` **Proof:** ```json { "type": "agreement", "document_hash": "sha256:4b227777...", "signature": "base64url_encoded_eddsa_signature", "signer_did": "did:web:agent.acme.ai", "signature_algo": "EdDSA" } ``` The agent signs `document_hash` using its DID private key. Publishers MUST verify the signature using the agent's DID document verification key. --- ## §6.5.3 Auction / RFP Pricing Mode (G19) When `pricing_mode: "auction"` in the manifest, the publisher accepts bids for time-limited resource allocations (e.g., premium compute, exclusive data access, priority API slots). ### Auction Flow 1. **Publisher** emits `commerce.rfp.open` CloudEvent with auction parameters 2. **Agents** submit bids via `commerce.rfp.bid.submit` before `close_time` 3. **Publisher** closes the auction, emits `commerce.rfp.closed` with winner info 4. **Winner** receives an **AllocationReceipt** VC granting time-bounded access ### Auction Configuration (in `commerce.negotiation` message) ```json { "negotiation_id": "neg_01abc2def3", "service": "compute.gpu.h100", "pricing_mode": "auction", "auction": { "mechanism": "first_price", "close_time": "2026-03-06T12:00:00Z", "reserve_price": 50.00, "currency": "usd", "rfp_id": "rfp_01xyz789" } } ``` ### AllocationReceipt VC Issued to the auction winner as a W3C Verifiable Credential: ```json { "@context": ["https://www.w3.org/2018/credentials/v1", "https://eep.dev/contexts/v0.1"], "type": ["VerifiableCredential", "EEPAllocationReceipt"], "issuer": "did:web:publisher.example", "issuanceDate": "2026-03-06T12:01:00Z", "credentialSubject": { "id": "did:web:winner.agent.ai", "allocation_id": "alloc_abc123", "winning_bid": 75.00, "currency": "usd", "valid_from": "2026-03-06T12:01:00Z", "valid_until": "2026-03-07T12:01:00Z" }, "proof": { "type": "Ed25519Signature2020", "verificationMethod": "did:web:publisher.example#key-1", "proofValue": "z..." } } ``` --- ## §9.x Data Withdrawal Events (G17) ### `data.withdrawal.requested` Emitted by the agent via WebSocket `action: data_withdrawal`: ```json { "v": 1, "type": "a2a", "action": "data_withdrawal", "data": { "claim_id": "claim_abc123", "agent_did": "did:web:agent.acme.ai", "reason": "dpv:WithdrawConsent", "signed_request": "base64url_eddsa_signature" } } ``` ### `data.withdrawal.confirmed` Publisher acknowledges the withdrawal within 24h (GDPR Art. 17 compliance): ```json { "v": 1, "type": "system", "action": "event", "data": { "event_type": "data.withdrawal.confirmed", "claim_id": "claim_abc123", "deleted_at": "2026-03-05T12:00:00Z" } } ``` **REST alternative:** `DELETE /data/claims/:claim_id` with bearer token returns `204 No Content` or `202 Accepted` (async deletion). --- ## §10.1 Operator Policy Profiles (G18) See full guide: [`docs/guides/OPERATOR-POLICY-PROFILES.md`](../guides/OPERATOR-POLICY-PROFILES.md) **Privacy Policy Profile** — Controls which claims the agent may share autonomously vs. requiring human confirmation. Signed by `operator_did`. **Spending Policy Profile** — Defines per-transaction, per-hour, and per-day spending limits; approved chains; minimum recipient conformance level. Signed by `operator_did`. Both profiles are stored locally by the agent and consulted before any gate interaction. --- ## §11.7 Session Token / EEP-Session Header (G15) After meeting gate requirements, the publisher issues a **Session Token** — a signed JSON document that caches the agent's access grant. **Token structure** (schema: `schemas/v0.1/session.token.json`): ```json { "agent_did": "did:web:agent.acme.ai", "issuer_did": "did:web:publisher.example", "tiers": ["pro", "api_v2"], "iat": 1741219200, "exp": 1741305600, "refresh_threshold": 1741302000, "context_id": "ctx_a1b2c3d4", "gate_version": "2026-03-01", "signature": "EdDSA_base64url_signature" } ``` **Usage:** Agents present the encoded token in subsequent requests: ``` Authorization: EEP-Session ``` **Renewal:** When the current timestamp exceeds `refresh_threshold`, agents SHOULD proactively request a new token. Publishers MUST reject tokens where `exp` has passed. --- ## §11.8 Delegation Proof Verifiable Credential (G16) Delegation Proofs allow an owner DID to authorize an agent DID to act on its behalf within explicit scope constraints. **Credential structure** (schema: `schemas/v0.1/delegation.proof.json`): ```json { "@context": ["https://www.w3.org/2018/credentials/v1", "https://eep.dev/contexts/v0.1"], "type": ["VerifiableCredential", "EEPDelegationProof"], "issuer": "did:web:owner.acme.ai", "issuanceDate": "2026-03-01T00:00:00Z", "expirationDate": "2026-04-01T00:00:00Z", "credentialSubject": { "id": "did:web:agent.bot.ai", "permitted_actions": ["gate:payment", "subscribe:sse"], "permitted_endpoints": ["https://api.publisher.example/*"], "max_payment_amount": 100.00, "currency_code": "USD", "operator_privacy_policy_hash": "sha256:...", "allowed_dpv_purposes": ["dpv:ServiceProvision"], "max_retention_days": 30 }, "proof": { "type": "Ed25519Signature2020", "verificationMethod": "did:web:owner.acme.ai#key-1", "proofValue": "z..." } } ``` **Privacy propagation:** Sub-agents MUST remain cryptographically bound to the delegator's **Operator Privacy Policy** (or equivalent). Delegation VCs MUST include `operator_privacy_policy_hash` (SHA-256 of the canonical policy document) and SHOULD include `allowed_dpv_purposes` and `max_retention_days`. When evaluating `data_request` gates for a delegated agent, publishers MUST verify that requested claims and DPV purposes are a subset of the delegation's allowed set; otherwise the proof MUST be rejected. **Security:** Publishers MUST verify the delegation VC signature AND check `expirationDate` before accepting a delegated agent. Delegation VCs without explicit `permitted_actions` MUST be rejected. --- ## §12.3.1 Extended Manifest Fields (G21/G22) The following fields are available in `eep.json` in addition to those defined in §12.3: | Field | Type | Description | |---|---|---| | `eep_versions` | `string[]` | All EEP versions this entity supports | | `preferred_version` | `string` | Preferred version for version negotiation | | `data_residency` | `string` | Data residency constraint (e.g., `EU-only`, `DE`) | | `payment_networks` | `object[]` | Multi-chain payment config: `chain`, `address`, `min_confirmations` | | `pricing_mode` | `"fixed" \| "negotiable" \| "auction"` | Pricing discovery mode for the entity | | `compliance.dora` | `boolean` | EU DORA (2022/2554) compliance declaration | | `compliance.eidas2` | `boolean` | eIDAS 2.0 (EU 2024/1183) VC architecture alignment | **Example multi-chain payment networks:** ```json "payment_networks": [ { "chain": "base", "address": "0xABC...123", "min_confirmations": 1 }, { "chain": "solana", "address": "8xGt...ZkQ", "min_confirmations": 32 } ] ``` --- ## §12.5 DNS TXT Record Discovery (G20) Agents MAY verify that a domain is a legitimate EEP participant by checking its DNS TXT record: ``` _eep.publisher.example. IN TXT "v=EEP1 did=did:web:publisher.example" ``` **Format:** `v=EEP1 did=`. Agents SHOULD treat absence of this record as a trust signal downgrade but MUST NOT treat it as an outright rejection (DNS deployment takes time). --- ## §12.6 Registry Federation Protocol (G20) Federated registries allow vertical-market or regional registries to integrate with eep.dev while maintaining their own trust criteria. **Discovery:** Federation registries publish `/.well-known/eep-registry.json` (schema: `schemas/v0.1/eep-registry.json`). **Trust model:** 1. eep.dev issues a **Federation Credential** VC to each verified federated registry 2. The registry's `federation_credential_url` points to this VC 3. Agents verify the Federation Credential before trusting registry lookups 4. Cross-registry resolution is available via `cross_registry_resolution_url` **Example `eep-registry.json`:** ```json { "did": "did:web:registry.eep.eu", "registry_name": "EEP European Financial Registry", "scope": { "geography": ["EU"], "sectors": ["financial_services"] }, "trust_criteria": { "did_verification": true, "additional_checks": ["eidas_identity_verification", "financial_license_check"] }, "conformance_tier_required": "Full", "federation_credential_url": "https://registry.eep.eu/.well-known/eep-federation-credential.json" } ``` ### §12.6.1 Registry operator economics (normative) Federation registry operators incur ongoing cost (APIs, databases, verification labor). The protocol does **not** mandate a single business model, but **MUST** expose machine-readable economics metadata so agents and integrators can reason about sustainability. **`economics` object (optional in `eep-registry.json`; SHOULD for public production registries):** | Field | Type | Description | |-------|------|-------------| | `registration_fee` | `object` | One-time or recurring fee to list or verify an entity (currency, amount, `per`: `once` \| `year`). | | `query_quota` | `object` | Free tier for discovery/capability query APIs, then paid: `free_requests_per_day`, `paid_tier_url` (URI to pricing). | | `staking_or_challenge` | `object` | Anti-Sybil policy: `mode` (`none` \| `micro_stake` \| `proof_of_payment` \| `proof_of_work_challenge`) and optional `min_amount`, `currency`, `challenge_endpoint`. | Registries MAY combine models (e.g. free quota + paid API + optional stake). Agents MUST NOT assume registry infrastructure is volunteer-only when `economics` is absent; absence is a trust downgrade signal, not a protocol error. === FILE: EEP/docs/guides/how-to-setup-cli.md === # How to use the EEP Setup CLI (`@eep-dev/setup-cli`) This guide walks through **two adoption paths**: 1. **Greenfield** — create a new EEP setup configuration and generated artifacts in an empty or new folder. 2. **Brownfield** — point the CLI at an **existing** API repository, detect stack signals, then generate the same artifacts next to your code. The CLI binary is named **`eep-setup`**. ### What you see on the terminal vs. what lands on disk Every command ends with **one line of JSON** on stdout. That line is the **machine-readable result** (for scripts and exit-code automation). It is **not** the only output of the workflow. | Step | On disk (the real deliverable) | On stdout | |------|--------------------------------|-----------| | `init` / `inject` | **`eep-setup.json`** (or `--out` path) — full setup config | Progress text, then **`Wrote setup config: …`**, then JSON | | `apply` | **`eep-generated/`** (or `--output`) — manifests, OpenAPI, gates, etc. | `Applied N artifacts to …`, then JSON | | `verify` | **`setup-report.json`** and **`setup-report.md`** under the output dir | JSON summary line | If you only glance at the last JSON line, you might think “nothing was generated.” **Always open the directory** you passed as `--out` / `--output`, or run `ls` after each command. The JSON `details.output_file` / `details.output_dir` fields echo those paths. **Interactive prompts:** pass **`--interactive`** to `init` or `inject` on a TTY to fill **identity** fields (org, hostname, base URL, DID). In CI or non-TTY environments, prompts are skipped — use **`--answers`** for non-interactive overrides. Set **`EEP_SETUP_CI=1`** to force non-interactive behavior. **Template alias:** **`--template`** is an alias for **`--preset`** (same preset names: `exchange`, `saas`, …). **Production apply:** use **`apply --production`** to refuse placeholder identities (`example.com`, `did:web:example.com`, etc.) before writing artifacts. --- ## Prerequisites - **Node.js** 18+ (for running the CLI). - From the **EEP monorepo**, install and build the package once: ```bash cd EEP/packages/@eep-dev/setup-cli npm install npm run build ``` After build, you can invoke: - `node dist/index.js ...` from that directory, or - `npx tsx src/index.ts ...` if you prefer running TypeScript directly (same flags). When the package is published to npm, you will also be able to run `npx @eep-dev/setup-cli` / `eep-setup` without cloning the repo. ### Install path: EEP monorepo vs published npm | Situation | What to run | |-----------|-------------| | **You cloned `eep-dev/EEP`** | `cd packages/@eep-dev/setup-cli && npm install && npm run build`, then `node dist/index.js …` or `npx tsx src/index.ts …` from that package directory (paths in examples assume this layout). | | **Published package** (when released) | `npx @eep-dev/setup-cli@latest …` or install globally / in CI: `eep-setup` from the package `bin`. Same flags; no need to build TypeScript locally. | | **CI / automation** | Prefer a **pinned** npm version and non-interactive flags: `--answers` for `init`/`inject`, optional `--no-interactive` where supported. | After artifacts exist, wire your HTTP app using **[integrate-eep-after-setup-cli.md](./integrate-eep-after-setup-cli.md)** and the runtime libraries [`@eep-dev/middleware`](../../packages/@eep-dev/middleware/README.md) / [`eep-middleware-python`](../../packages/eep-middleware-python/README.md). --- ## Command overview | Command | Purpose | |--------|---------| | `init` | Create **`eep-setup.json`** (optional **`--preset`** / **`--template`**, **`--interactive`**, **`--answers`**). | | `inject` | Scan **`--project`** and write **`eep-setup.json`** (optional **`--interactive`**, **`--answers`**). | | `apply` | Generate artifacts from `--config` and **write** them (**`--dry-run`** preview; **`--production`** blocks placeholder identity). | | `verify` | Check expected files under `--output` and write JSON/Markdown reports. | | `doctor` / `status` | Inspect generated output for issues and readiness. | | `upgrade` | Bump `setup_schema_version` in the config file. | | `watch` | Runs `apply` in one cycle; **`--dry-run`** previews, **`--once`** marks a single run (see command `details.watch_mode`). | | `rotate-secrets` | Rotate webhook HMAC secrets in an `.env` file safely. | --- ## Presets (`init` and `inject`) Built-in presets (see `src/prompts/presets.ts`) include: - `exchange` - `marketplace` - `saas` - `data-provider` - `iot-publisher` Unknown preset names fall back to **`saas`**. Optional **`--answers path/to/answers.json`**: a JSON object merged on top of the preset (non-interactive overrides). --- ## Path A — Greenfield (from scratch) **Goal:** produce `eep-setup.json` and a folder of generated EEP artifacts without an existing API codebase. ### 1. Create the setup config From a directory where you want the config file (e.g. a new `my-eep/` folder): ```bash cd EEP/packages/@eep-dev/setup-cli # or use global path to dist/index.js node dist/index.js init --preset exchange --out /absolute/path/to/my-eep/eep-setup.json ``` Use another preset if it fits your product (`marketplace`, `data-provider`, etc.). ### 2. (Optional) Override fields with answers Create `answers.json` with partial overrides (structure must match mergeable fields in `EEPSetupConfig`), then: ```bash node dist/index.js init --preset saas --answers /absolute/path/to/answers.json --out /absolute/path/to/my-eep/eep-setup.json ``` ### 3. Generate and write artifacts ```bash # Preview only (no writes) node dist/index.js apply --config /absolute/path/to/my-eep/eep-setup.json --dry-run # Write files under eep-generated/ (must stay under current working directory unless you use --unsafe-paths) cd /absolute/path/to/my-eep node /path/to/setup-cli/dist/index.js apply --config ./eep-setup.json --output ./eep-generated ``` By default, **`apply` refuses** output directories that escape the current working directory (path traversal protection). Use **`--unsafe-paths`** only when you explicitly need to write outside `cwd`. ### 4. Verify and operate ```bash node /path/to/setup-cli/dist/index.js verify --output ./eep-generated node /path/to/setup-cli/dist/index.js doctor --output ./eep-generated node /path/to/setup-cli/dist/index.js status --output ./eep-generated ``` `verify` writes **`setup-report.json`** and **`setup-report.md`** under the output dir (override with `--report-json` / `--report-md`). ### 5. Secrets If you maintain webhook signing secrets in `.env`: ```bash node /path/to/setup-cli/dist/index.js rotate-secrets --env /absolute/path/to/my-eep/.env ``` When a secret already exists, the previous value is kept as **`EEP_WEBHOOK_SECRET_PREVIOUS`** for overlap rotation. --- ## Path B — Existing project (integrate EEP) **Goal:** keep your application repo unchanged except for new config and generated artifacts, then wire HTTP behavior using official middleware packages. ### 1. Run `inject` against your API root Point `--project` at the folder that contains `package.json`, `go.mod`, `pyproject.toml`, etc.: ```bash cd EEP/packages/@eep-dev/setup-cli node dist/index.js inject --project /absolute/path/to/your-api --out /absolute/path/to/your-api/eep-setup.json ``` The CLI runs **project detection** (language, framework, infra hints). The result is stored in the generated config metadata (`detected_profile` in command `details` when run via JSON output). Optional: combine with **`--preset`** and **`--answers`** the same way as `init`. ### 2. Apply artifacts next to your code ```bash cd /absolute/path/to/your-api node /path/to/setup-cli/dist/index.js apply --config ./eep-setup.json --output ./eep-generated ``` Choose `./eep-generated` (or another name) and add it to **`.gitignore`** if generated files should not be committed. ### 3. Verify ```bash node /path/to/setup-cli/dist/index.js verify --output ./eep-generated ``` Fix any missing files reported before deploying. ### 4. Wire runtime: Node (`@eep-dev/middleware`) Add the middleware package to your API (path or workspace as appropriate for your monorepo): - Package: **`EEP/packages/@eep-dev/middleware`** - Provides **`EEPServer`**, Express/Fastify/Hono/Koa adapters, and adapter interfaces for auth, persistence, and event bus. Mount routes and middleware according to your framework’s pattern, using **`adapter-config.json`** and other generated files under `eep-generated/` as the source of truth for EEP-specific wiring. ### 5. Wire runtime: Python (`eep-middleware-python`) - Package: **`EEP/packages/eep-middleware-python`** - FastAPI router helpers and Flask/Django integration points; same conceptual split as the Node package. ### 6. Ongoing lifecycle - **`upgrade --config eep-setup.json --to-version …`** — when the setup schema evolves. - **`watch`** — local dev: regenerate artifacts when `eep-setup.json` changes. - **`doctor` / `status`** — before releases or after config edits. --- ## Security checklist 1. **Do not** commit production secrets; use env vars and `rotate-secrets` for HMAC keys. 2. Treat **`--unsafe-paths`** as a last resort; prefer keeping generated output under the project root. 3. Store **`verify`** reports in CI artifacts for audit trails (JSON + Markdown). --- ## Related documentation - Short reference: [quick-setup-cli.md](./quick-setup-cli.md) - **After CLI — wire middleware and deploy:** [integrate-eep-after-setup-cli.md](./integrate-eep-after-setup-cli.md) - **Fast paths:** [five-minute-proof.md](./five-minute-proof.md) - **CI / verify reports:** [eep-ready-verification.md](./eep-ready-verification.md) - **Runtime matrix:** [implementation-matrix.md](./implementation-matrix.md) - **Positioning (MCP/A2A):** [eep-positioning-complementary.md](./eep-positioning-complementary.md) - **Adoption metrics (internal):** [adoption-metrics.md](./adoption-metrics.md) - Reference deployment (Docker, dual Node/Python API): [reference-deployment-eep-api.md](./reference-deployment-eep-api.md) - Dispatch and delivery: [how-to-dispatch.md](./how-to-dispatch.md) --- ## Troubleshooting | Symptom | What to check | |--------|----------------| | `apply blocked unsafe output path` | Run `apply` with `cwd` such that `--output` resolves under it, or pass `--unsafe-paths` deliberately. | | `verify` reports missing files | Re-run `apply` with the same `--config` and `--output` (omit `--dry-run`). | | Preset seems wrong | Pass an explicit `--preset` or use `--answers` to override identity/conformance fields. | For framework-specific mounting issues, use the detector output from `inject` and align with **`@eep-dev/middleware`** or **`eep-middleware-python`** adapter docs in the repository. --- ## When is EEP “fully implemented”? The CLI gets you to a **verified artifact bundle** (config + generated files + `verify` / `doctor` / `status` green). **Production EEP** still requires: 1. **Serve generated HTTP surfaces** — e.g. host `.well-known/eep.json` and any routes described in `openapi-eep.json` at URLs consistent with `identity.base_url` in `eep-setup.json`. 2. **Wire runtime middleware** — mount **`@eep-dev/middleware`** (Node) or **`eep-middleware-python`** using `adapter-config.json` and your auth/DB/event adapters. 3. **Secrets and env** — configure webhook signing (`rotate-secrets`), API keys, and deployment-specific values; keep secrets out of git. 4. **Optional: reference stack** — for a full dual-runtime example, see [reference-deployment-eep-api.md](./reference-deployment-eep-api.md) and `examples/eep-reference-implementation/`. **Definition of done (CLI + integration):** `apply` (without `--dry-run`) succeeds, `verify` reports no missing files, `status` is healthy, and your API process actually serves the EEP endpoints using the middleware package — not only the generated static files on disk. === FILE: EEP/docs/guides/integrate-eep-after-setup-cli.md === # After `setup-cli`: wire EEP into your application This guide picks up where **[how-to-setup-cli.md](./how-to-setup-cli.md)** ends. The CLI produces **`eep-setup.json`** and **`eep-generated/`**; this document describes what integrators should do next. ## What the CLI already guarantees - A consistent **setup config** and **artifact bundle** (`verify` / `status` can pass). - **`adapter-config.json`** aligned with `inject` detection (framework, auth/DB/event defaults). ## What still requires engineering work | Area | Why | |------|-----| | **Identity & URLs** | `identity.domain`, `base_url`, `did` are often still placeholders until you set real values. | | **HTTP surface** | Static files under `eep-generated/` are not automatically served by your process; you must mount routes or deploy them behind a gateway. | | **Persistence & messaging** | Defaults assume patterns (e.g. Postgres + Redis); you provide connections and adapter implementations where you move beyond in-memory defaults. | | **Secrets** | Webhook signing and API keys belong in env / secret stores, not in git. | --- ## Recommended order of operations ### 1. Customize `eep-setup.json` Edit (or regenerate with **`--answers`**) at least: - `identity.org_name`, `identity.domain`, `identity.base_url`, `identity.did` - `conformance.environment` when you promote toward production Then run **`apply`** again so **`eep-generated/`** stays in sync. ### 2. Add the runtime library for your language - **Node:** `@eep-dev/middleware` (from this monorepo or your package registry when published). - **Python:** `eep-middleware-python`. Install paths depend on your repo layout (workspace `file:`, `npm link`, or published version). ### 3. Construct `EEPServerOptions` (Node) The middleware core is **`EEPServer`**; options are **`EEPServerOptions`**: - **`baseUrl`**: must match how clients reach your API (same origin as `identity.base_url` in normal setups). - **`did`**: your deployment DID (same as `identity.did` in config). - **`gateConfig`**: optional; use **`parseGateConfig`** from `@eep-dev/gates` with JSON parsed from **`eep-generated/gate-config.json`** if the schema matches your gates package version (adjust field names if your generator and parser drift). - **`services`**: optional; align with **`eep-generated/service-catalog.json`** shape. - **`authAdapter` / `dbAdapter` / `eventBusAdapter`**: start with defaults for a smoke test; swap for **`JWTAuthAdapter`**, **`PostgresDBAdapter`**, **`RedisEventBusAdapter`**, etc., when wiring real infrastructure. See package exports in **`packages/@eep-dev/middleware/src/index.ts`**. ### 4. Mount routes (Express example) `createEEPRouter` returns **route bindings**, not a ready-made Express `Router`. Register each binding on your `app` (method + path + handler that forwards to `execute` with the incoming request shape). Conceptually: ```typescript import { createEEPRouter } from "@eep-dev/middleware"; import { parseGateConfig } from "@eep-dev/gates"; import { readFileSync } from "node:fs"; import express from "express"; const app = express(); const gateRaw = JSON.parse(readFileSync("eep-generated/gate-config.json", "utf8")); const { routes } = createEEPRouter({ baseUrl: process.env.EEP_BASE_URL ?? "https://api.example.com", did: process.env.EEP_DID ?? "did:web:example.com", gateConfig: parseGateConfig(gateRaw), }); for (const route of routes) { app[route.method](route.path, async (req, res) => { const out = await route.execute({ method: req.method, path: req.path, headers: req.headers as Record, query: req.query as Record, params: req.params as Record, body: req.body, }); res.status(out.status); for (const [k, v] of Object.entries(out.headers ?? {})) { res.setHeader(k, v as string); } res.send(out.body ?? ""); }); } ``` Adapt paths if you mount under a sub-prefix; keep public URLs consistent with **`openapi-eep.json`** and **`.well-known/eep.json`**. ### 5. Validate behavior - Hit **`GET /.well-known/eep.json`** and compare to **`eep-generated/.well-known/eep.json`** (or serve that file statically in dev). - Run **`eep-generated/eep-contract-tests/basic.hurl`** (or equivalent) against your base URL. - Use **[testing-and-validation.md](./testing-and-validation.md)** and your compliance runner for tier targets. ### 6. Deploy and operate - **[reference-deployment-eep-api.md](./reference-deployment-eep-api.md)** — Docker Compose layout for the **reference** stack (Node + Python + infra). - **[how-to-dispatch.md](./how-to-dispatch.md)** — event delivery semantics. - **[runbook-webhook-delivery.md](../ops/runbook-webhook-delivery.md)** — webhook operations. --- ## Relationship to `examples/eep-reference-implementation` The reference Node service demonstrates protocol behavior (gates, SSE, subscriptions, optional Postgres/Redis) but **does not** mount **`@eep-dev/middleware`**’s `createEEPRouter`; it uses a custom HTTP server. Treat it as a **behavioral reference**, and use **`@eep-dev/middleware`** when you want the packaged route table inside Express/Fastify/Hono/Koa. --- ## See also - [five-minute-proof.md](./five-minute-proof.md) — fastest paths to a running surface - [eep-ready-verification.md](./eep-ready-verification.md) — CI and `verify` reports - [examples/eep-middleware-express-mini](../../examples/eep-middleware-express-mini/README.md) — minimal Express + middleware --- ## Documentation completeness (honest checklist) | Topic | Where it lives | Status | |-------|----------------|--------| | CLI: `init` / `inject` / `apply` / `verify` | [how-to-setup-cli.md](./how-to-setup-cli.md) | Documented | | Post-CLI wiring (this page) | This guide | Use this after CLI | | Middleware API surface | [packages/@eep-dev/middleware/README.md](../../packages/@eep-dev/middleware/README.md) + source | Quickstart + exports | | Runnable dual API + compose | [reference-deployment-eep-api.md](./reference-deployment-eep-api.md) + `examples/eep-reference-implementation/` | Documented | | Enterprise rollout | [enterprise-implementation-playbook.md](./enterprise-implementation-playbook.md) | Broader than CLI | If something is missing for your stack, open an issue or PR against **`docs/guides/`** with the framework-specific snippet you needed. === FILE: EEP/docs/guides/five-minute-proof.md === # Five-minute proof (EEP) Goal: go from **clone** to **working HTTP surface** and a **verification command** in a few minutes. ## Path A — Reference stack (Node + Python + infra) 1. From the **EEP repo root**, start the reference deployment (Docker required): ```bash cd examples/eep-reference-implementation docker compose up --build -d ``` 2. Wait until **`node-api`** is healthy (port **3100** by default). 3. From the **EEP repo root**, run the smoke script: ```bash bash scripts/eep-reference-smoke.sh ``` Override base URL if needed: ```bash EEP_SMOKE_BASE_URL=http://127.0.0.1:3100 bash scripts/eep-reference-smoke.sh ``` 4. Read **[reference-deployment-eep-api.md](./reference-deployment-eep-api.md)** for what is implemented and how to extend it. ## Path B — `setup-cli` on a sample repo 1. Build the CLI: `cd packages/@eep-dev/setup-cli && npm install && npm run build` 2. In a **clone of an API project**: ```bash node dist/index.js inject --project /path/to/api --out /path/to/api/eep-setup.json node dist/index.js apply --config /path/to/api/eep-setup.json --output /path/to/api/eep-generated node dist/index.js verify --output /path/to/api/eep-generated ``` 3. Wire runtime using **[integrate-eep-after-setup-cli.md](./integrate-eep-after-setup-cli.md)**. ## Path C — Minimal Express + middleware (copy/paste) 1. Run the tiny example server: ```bash cd examples/eep-middleware-express-mini npm install PORT=3333 npm start ``` 2. In another shell: ```bash curl -sSf http://127.0.0.1:3333/healthz curl -sSf http://127.0.0.1:3333/.well-known/eep.json | head ``` This uses **`@eep-dev/middleware`** directly — best for “how do I mount routes?” questions. ## What “done” means here - **Path A:** smoke script exits 0; manifests and gates/services respond. - **Path B:** `verify` exits 0 (artifacts present); then you still wire your app. - **Path C:** `healthz` and `/.well-known/eep.json` return 200 from the Express process. For production readiness, add **`apply --production`**, real **`identity`** values, and operational runbooks under `docs/ops/`. ## See also - **[realworld-simulation.md](./realworld-simulation.md)** — deterministic terminal demo contrasting Next.js HTML scraping with EEP gates (`npm run demo` under `realworld-simulation/`). === FILE: EEP/docs/guides/testing-and-validation.md === # Testing and validating your EEP implementation > This guide explains how to test any platform's conformance with the EEP specification using the `@eep-dev/compliance-cli`. --- ## Quick start ```bash npx @eep-dev/compliance-cli --target https://api.yourplatform.com --api-key YOUR_KEY --entity u/your-entity ``` For automated scoring/reporting: ```bash npx @eep-dev/compliance-cli \ --target https://api.yourplatform.com \ --api-key YOUR_KEY \ --entity u/your-entity \ --level full \ --report-json ./eep-audit-report.json \ --report-md ./eep-audit-report.md ``` The CLI starts a temporary local HTTP server, triggers test events, and checks for: - EEP endpoint discovery via HTTP `Link` headers - Subscription creation and WebSub intent verification - Webhook delivery within 5 seconds - HMAC-SHA256 signature correctness - CloudEvents v1.0 envelope format - EEP extension attributes It also prints a normalized audit score and can emit machine-readable findings for remediation workflows. After the main conformance blocks, the CLI runs an additional **v0.1 reference capabilities** section (always best-effort): - `GET /.well-known/eep-registry.json` — checks for an `economics` object (registration fee, query quota, or staking/challenge fields). - `GET /eep/trust-status?agent_did=…` — cold-start trust state probe. - `POST /eep/delegation/verify` — delegation privacy binding probe. These endpoints are optional on production platforms; reference stacks (`examples/eep-reference-implementation`) implement them for demos. Use `--report-json` / `--report-md` to capture results. ### What the compliance CLI does **not** validate The CLI exercises **wire behavior**, schemas, and selected policy probes. It does **not** assess: - **Generative engine optimization (GEO)** outcomes, search or answer-engine ranking, or whether your content is cited in third-party LLM interfaces. - **Legal or editorial semantics** inside licence documents (for example attribution wording); structural `agreement` gate checks do not replace counsel. - **HTML / XML sitemap parity** with the EEP manifest, or general SEO quality. For publisher strategy and GEO as *informative* context, see [`docs/WHITEPAPER.tex`](../WHITEPAPER.tex). For normative discovery requirements, see [`docs/current/SPECIFICATION.md`](../current/SPECIFICATION.md) §12. --- ## Conformance levels Run with `--level core|standard|full` to test specific levels. ### Core (minimum EEP-compliant) ```bash npx @eep-dev/compliance-cli --target https://api.yourplatform.com --level core ``` Tests: basic reachability, subscription creation, webhook delivery, and HMAC signing. ### Standard (recommended minimum for production) ```bash npx @eep-dev/compliance-cli --target https://api.yourplatform.com --level standard ``` Tests: core features plus the SSE endpoint, `Last-Event-ID` replay, rate limit headers, credential/identity/payment gates, and EEP version negotiation. ### Full (commerce, advanced gates + marketplace) > **Note:** The compliance CLI provides **partial** automation for `--level full` (manifest + selected policy probes). Full-tier capabilities such as WebSocket commerce flows, PoI cryptographic validation, and sector-specific extensions still require manual validation. Full adds advanced capabilities on top of Standard: - Commerce messages over WebSocket follow the state machine - Agreement and data_request gates are enforced - Session persistence and W3C DPV compliance - Service catalog endpoint returns valid `service.listing.json` - Review submission and rating aggregation work correctly --- ## Manual testing checklist ### 1. Verify HMAC signing Deliver a test webhook to yourself and verify the signature: ```bash # Generate a test signature node -e " const { createHmac } = require('crypto'); const id = 'test-id'; const ts = Math.floor(Date.now()/1000).toString(); const body = JSON.stringify({ specversion: '1.0', id: '1', source: 'test', type: 'test.event', time: new Date().toISOString(), datacontenttype: 'application/json', data: {} }); const sig = createHmac('sha256', 'your_secret').update(id+'.'+ts+'.'+body).digest('base64'); console.log('webhook-signature: v1,' + sig); " ``` ### 2. Test WebSub verification manually ```bash # Simulate the intent verification call curl "https://your-webhook-url.com/hooks/eep?hub.mode=subscribe&hub.topic=did:web:...&hub.challenge=test123" # Expected: response body should be exactly: test123 ``` ### 3. Test SSRF block Your platform must block these URLs when subscribing: ```bash # These should all return an error (not deliver events) POST /eep/subscribe with delivery_url: - http://localhost:3000/hook - http://192.168.1.1/admin - http://169.254.169.254/latest/meta-data - http://10.0.0.1/internal ``` ### 4. Test Last-Event-ID replay ```bash # Connect to SSE, note the last event ID curl -N "https://api.yourplatform.com/eep/stream?source=entity" \ -H "Authorization: Bearer key" # ... receive a few events, note their IDs, then close # Reconnect with Last-Event-ID - should receive all events since that ID curl -N "https://api.yourplatform.com/eep/stream?source=entity" \ -H "Authorization: Bearer key" \ -H "Last-Event-ID: {your_last_event_id}" ``` ### 5. Test gate 402 response ```bash # Request a gated resource without proofs — should return 402 curl -s https://api.yourplatform.com/eep/content/did:web:example.com:u:alice/content.papers.full_text | jq . # Expected: { "error": "access_restricted", "resource": "...", "unmet_requirements": [...] } ``` ### 6. Test gate config endpoint ```bash # Should return valid gate configuration curl -s https://api.yourplatform.com/eep/gates/did:web:example.com:u:alice | jq . # Validate against schema npx ajv validate -s schemas/v0.1/gate.config.json -d response.json ``` ### 7. Test gated subscription ```bash # Subscribe with a tier that requires proofs — should fail without proofs curl -X POST https://api.yourplatform.com/eep/subscribe \ -H "Content-Type: application/json" \ -d '{ "source_did": "did:web:example.com:u:alice", "event_types": ["com.example.entity.*"], "delivery_method": "sse", "tier": "premium" }' # Expected: 402 with unmet requirements ``` --- ## CI integration Add EEP compliance testing to your CI/CD pipeline: ```yaml # .github/workflows/eep-compliance.yml (template for your own repository) name: EEP Compliance Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Start platform run: docker compose up -d - name: Run EEP compliance tests run: | npx @eep-dev/compliance-cli \ --target http://localhost:3000 \ --api-key ${{ secrets.TEST_API_KEY }} \ --entity u/test-entity \ --level standard ``` === FILE: EEP/docs/guides/langgraph-eep-agent.md === # LangGraph/Claude + EEP Integration Guide This guide walks through building an AI agent (using [LangGraph](https://github.com/langchain-ai/langgraph) and Claude) that interacts with EEP publishers: discovering entities, subscribing to event streams, handling gate challenges, and processing events through an LLM pipeline. ## Why LangGraph + EEP? LangGraph provides a graph-based orchestration framework for LLM agents. EEP provides the event infrastructure those agents consume. Together, they enable agents that react to real-time entity state changes with structured reasoning. | Concern | Handled by | |---------|-----------| | Entity discovery, subscription, delivery | EEP (Layer 1 + Layer 2) | | Gate proofs (auth, payment, agreements) | `eep-gates-python` | | Webhook signature verification | `eep-signer-python` | | Event envelope validation | `eep-validator-python` | | Event reasoning, summarization, actions | LangGraph + Claude | ## Architecture ``` Publisher ──Layer 2 webhook──▶ Agent webhook server │ ┌───────┴───────┐ │ LangGraph │ │ ┌──────────┐ │ │ │ validate │ │ ← CloudEvents + EEP checks │ │ verify │ │ ← HMAC-SHA256 │ │ summarize │ │ ← Claude (langchain-anthropic) │ │ act │ │ ← route by event type │ └──────────┘ │ └───────────────┘ ``` ## Quick start ```bash cd EEP/examples/langgraph-eep-agent python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt export EEP_TARGET=http://localhost:3100 # reference impl or realworld-simulation export ANTHROPIC_API_KEY=sk-ant-... python agent.py ``` The agent will: 1. `GET /u/acme-corp` to discover the entity and its `Link: rel="subscribe"` URL. 2. `POST /eep/subscribe` with a webhook delivery URL pointing to the local server. 3. Wait for incoming events and process each through the validate/summarize/act pipeline. ## Gate handling When the agent encounters a gated resource: - **402 Payment Required**: reads `gate_type` and payment requirements, constructs a proof (x402 or tx hash), retries. - **403 Agreement Required**: fetches the agreement, signs its hash with the agent DID key, retries. - **403 Credential Required**: presents a Verifiable Presentation from the agent's credential store. These flows use the `eep_gates` Python package. See [Agent Wallet Guide](./AGENT-WALLET-GUIDE.md) for wallet and spending policy configuration. ## Event processing pipeline Each webhook event flows through three nodes: 1. **validate**: checks CloudEvents required fields (`specversion`, `id`, `source`, `type`, `time`) and EEP extensions (`eep_version`). 2. **summarize**: sends the event to Claude for a one-sentence summary (falls back to a template if no API key). 3. **act**: routes by event type suffix to an action (`alert:trust_change`, `revoke_local_session`, `sync_entity_cache`, `record_payment`, etc.). ## Extending the agent - Add nodes for MCP tool calls via `eep-mcp-bridge-python` (see [MCP-EEP Bridge Guide](./EEP-MCP-BRIDGE.md)). - Add Layer 3 WebSocket negotiation for commerce disputes. - Use LangGraph's `StateGraph` for more complex routing (conditional edges, parallel branches). ## Related resources - [Example code](../../examples/langgraph-eep-agent/) - [EEP Specification](../current/SPECIFICATION.md) - [Agent Onboarding Guide](./agent-onboarding.md) - [MCP-EEP Bridge Guide](./EEP-MCP-BRIDGE.md) - [Realworld Simulation](./realworld-simulation.md) - [Interactive Playground](https://eep.dev/playground) (validate events and signatures in the browser) === FILE: EEP/docs/guides/mcp-eep-bridge.md === # MCP <-> EEP Bridge Guide ## Purpose The bridge converts MCP tool/resource surfaces into EEP-native discovery, service, and gate artifacts without changing MCP server internals. ## Implementations - Node: `packages/@eep-dev/mcp-bridge` - Python: `packages/eep-mcp-bridge-python` ## What the bridge exposes 1. `/.well-known/eep.json` manifest synthesized from MCP introspection. 2. `/eep/services` service catalog derived from MCP tools. 3. `/eep/gates` gate config synthesized from annotations and overrides. 4. `/mcp/tools/call` guarded call facade with fail-closed 402 behavior. ## Security posture - Strict tool-name validation (`^[a-zA-Z0-9._:-]{1,128}$`) - Unknown tool rejection - Fail-closed gate enforcement - Redteam coverage: - `packages/@eep-dev/mcp-bridge/src/security.test.ts` - `packages/eep-mcp-bridge-python/tests/test_bridge.py` ## Coverage and parity - Node bridge: 100% threshold enforced via `vitest.config.ts` - Python bridge: 100% threshold enforced via `pytest.ini` - Shared fixture parity: `tests/parity/mcp-bridge-fixtures.json` === FILE: EEP/packages/@eep-dev/compliance-cli/README.md === # @eep-dev/compliance-cli > **End-to-end conformance testing CLI for any EEP-compatible platform.** [![EEP](https://img.shields.io/badge/EEP-v0.1-blue)](../../../docs/current/SPECIFICATION.md) [![Node](https://img.shields.io/badge/Node-%E2%89%A522-green)](https://nodejs.org) [![License](https://img.shields.io/badge/License-Apache%202.0-green)](../../../LICENSE) --- ## Overview `@eep-dev/compliance-cli` is a zero-dependency test harness that verifies whether a platform correctly implements the Entity Engagement Protocol. It simulates an agent subscriber — creating subscriptions, receiving webhook deliveries, and validating every aspect of the EEP specification. ### What It Tests The CLI runs tests across **three conformance levels**: | Level | Tests | What's Verified | |-------|-------|----------------| | 🥉 **Core** | Platform reachability, EEP discovery (Link headers), subscription creation, WebSub intent verification, webhook delivery, Standard Webhooks headers, HMAC-SHA256 signature, CloudEvents envelope | Signal stream basics | | 🥈 **Standard** | All Core tests + SSE stream endpoint, rate limit headers | SSE + rate limiting | | 🏆 **Full** | All Standard tests + manifest/policy probes + extended probes (Layer 1 content negotiation, 402 payment gate, WebSocket pulse, CloudEvents/EEP helper validation) | Advanced baseline checks (partial full-tier automation) | > `--level full` currently performs **partial** full-tier automation. WebSocket commerce state machine, PoI cryptographic verification, and some sector-specific checks still require manual/stack-specific validation. --- ## Requirements - **Node.js ≥ 22** (uses `node:util/parseArgs` and `--experimental-strip-types`) - **Network access** to the target platform - **An API key** for authenticated endpoints - A **publicly reachable port** for the webhook receiver (or use `host.docker.internal` for Docker environments) --- ## Usage ### Quick Start ```bash # Run against any EEP-compatible platform npx @eep-dev/compliance-cli --target https://api.example.com --api-key sk_... --entity u/acme-corp # Test only core conformance npx @eep-dev/compliance-cli --target https://api.example.com --api-key sk_... --entity u/test --level core # Use a custom port for the local webhook receiver npx @eep-dev/compliance-cli --target https://localhost:3000 --api-key sk_... --entity u/test --port 9999 # Emit structured audit reports npx @eep-dev/compliance-cli \ --target https://api.example.com \ --api-key sk_... \ --entity u/acme-corp \ --level full \ --report-json ./eep-audit-report.json \ --report-md ./eep-audit-report.md \ --report-html ./eep-audit-report.html ``` ### From the Monorepo ```bash cd packages/@eep-dev/compliance-cli node --experimental-strip-types src/index.ts \ --target https://api.example.com \ --api-key sk_... \ --entity u/test ``` --- ## CLI Options | Flag | Short | Type | Default | Description | |------|-------|------|---------|-------------| | `--target` | `-t` | `string` | — | **Required.** Platform base URL | | `--api-key` | `-k` | `string` | — | API key for authenticated requests | | `--entity` | `-e` | `string` | — | Entity DID or `{prefix}/{username}` to subscribe to | | `--level` | `-l` | `string` | `standard` | Conformance level: `core`, `standard`, `full` | | `--port` | `-p` | `string` | `9876` | Local port for the test webhook receiver | | `--report-json` | — | `string` | — | Write machine-readable audit report JSON | | `--report-md` | — | `string` | — | Write human-readable audit report markdown | | `--report-html` | — | `string` | — | Write self-contained HTML audit report | | `--help` | `-h` | `boolean` | — | Show help message | --- ## How It Works ``` ┌──────────────────┐ ┌───────────────────┐ │ compliance-cli │ │ Target Platform │ │ │ │ │ │ 1. POST /subscribe ───► │ Creates sub │ │ │ │ │ │ 2. ◄── WebSub challenge │ Intent verify │ │ (GET ?hub.challenge) │ │ │ │ │ │ │ 3. POST /test ────────► │ Triggers event │ │ │ │ │ │ 4. ◄── POST /hook │ Delivers webhook │ │ (Verify HMAC) │ │ │ │ │ │ │ 5. Check SSE ──────────►│ Stream endpoint │ │ │ │ │ │ 📊 Report Results │ │ └──────────────────┘ └───────────────────┘ ``` ### Step-by-Step Flow 1. **Health check** — Verifies the platform is reachable 2. **EEP discovery** — Checks for `Link: <...>; rel="subscribe"` header on entity pages 3. **Subscription creation** — Creates a webhook subscription via `POST /eep/subscribe` 4. **WebSub Intent Verification** — Waits for the platform to send a GET challenge to the local webhook receiver 5. **Webhook delivery** — Triggers a test event and waits for the webhook to be delivered 6. **Signature verification** — Validates HMAC-SHA256 using the `delivery_secret` 7. **CloudEvents validation** — Checks `specversion`, `id`, `source`, and `eep_version` fields 8. **SSE stream** (Standard+) — Opens an SSE connection and verifies `Content-Type: text/event-stream` 9. **Rate limit headers** (Standard+) — Checks for `X-RateLimit-*` headers --- ## Example Output ``` 🔬 EEP Compliance Test — Level: STANDARD Target: https://api.example.com Entity: u/acme-corp ──────────────────────────────────────────────────────── 📋 CORE CONFORMANCE ✅ Platform is reachable (HTTP 200) ✅ EEP discovery via Link header (rel="subscribe" found) ✅ Subscription creation (ID: sub_abc123) ✅ WebSub Intent Verification (challenge/response completed within 10s) ✅ Webhook delivery received (event type: com.example.entity.test) ✅ Standard Webhooks headers present (webhook-id, webhook-timestamp, webhook-signature) ✅ HMAC-SHA256 signature is valid (Standard Webhooks v1) ✅ CloudEvents specversion is 1.0 ✅ Event id field present ✅ Event source field present ✅ EEP extension attributes present (eep_version: 0.1) 📋 STANDARD CONFORMANCE ✅ SSE stream endpoint (Content-Type: text/event-stream) ✅ Rate limit headers present (X-RateLimit-* headers found) ──────────────────────────────────────────────────────── 📊 Results: 13 passed | 0 failed | 0 skipped Audit score: 100/100 🥈 Standard EEP Compliant ``` ## Verification & Scoring Workflow The CLI can act as an automated verifier for projects claiming EEP compliance: 1. Run conformance checks against the target. 2. Compute a normalized score (`score_100`) over evaluated checks. 3. Emit per-check failures with actionable recommendations. 4. Share the generated JSON/markdown report with the target project. This enables repeatable, automatable audit loops for migration and transition programs. --- ## Architecture The CLI is a single TypeScript file (~360 lines) with **zero runtime dependencies**. It uses: - `node:util/parseArgs` — CLI argument parsing - `node:http/createServer` — Local webhook receiver (receives both WebSub challenges and webhook deliveries) - `node:crypto` — HMAC-SHA256 signature verification with `timingSafeEqual` - `fetch` — HTTP requests (built into Node.js 22+) The local webhook receiver runs on `localhost:9876` (configurable) and handles: - **GET requests** — WebSub intent verification (echoes `hub.challenge` parameter) - **POST requests** — Webhook delivery capture and header recording --- ## Network Configuration The CLI starts a local HTTP server to receive webhooks. The target platform must be able to reach this server. | Scenario | `delivery_url` | |----------|---------------| | Same machine | `http://localhost:9876/hook` | | Docker → host | `http://host.docker.internal:9876/hook` | | Cloud dev | Use a tunnel (e.g., `ngrok http 9876`) | The CLI defaults to `http://host.docker.internal:${port}/hook` for Docker environments. --- ## Exit Codes | Code | Meaning | |------|---------| | `0` | All tests passed — platform is compliant at the requested level | | `1` | One or more tests failed, or `--help` was invoked without `--target` | --- ## Unit Tests The CLI's helper functions are thoroughly tested with **34 unit tests** covering: | Area | Tests | What's Covered | |------|-------|----------------| | Test Runner | 11 | pass/fail/skip tracking, summary computation, conformance labels (all 3 levels + failures) | | Argument Validation | 7 | Missing target, invalid level, port validation (range + NaN) | | Target Normalization | 4 | Trailing slash removal, multi-slash, path URLs | | CloudEvents Validation | 5 | Required fields, specversion check, multiple missing fields | | EEP Extensions | 2 | eep_version presence | | Webhook Headers | 4 | Standard Webhooks header detection, undefined handling | ```bash cd packages/@eep-dev/compliance-cli && npx vitest run ``` --- ## Specification Reference - [EEP SPECIFICATION.md](../../../docs/current/SPECIFICATION.md) — The formal specification - [EEP security.md](../../../docs/current/security.md) — Security model - [EEP delivery_guarantees.md](../../../docs/current/delivery_guarantees.md) — Retry and backoff requirements - [CloudEvents v1.0.2](https://cloudevents.io) — Event envelope format - [Standard Webhooks](https://www.standardwebhooks.com/) — Signature specification --- ## License Apache 2.0 — See [LICENSE](../../../LICENSE) === FILE: EEP/examples/README.md === # Examples - **`eep-reference-implementation/`** — Dual-runtime (Node + Python) EEP publisher with Docker Compose, Postgres, and Redis. See that directory’s README for ports and smoke checks. From the repo root: `bash scripts/eep-reference-smoke.sh` (with the stack running). - **`eep-middleware-express-mini/`** — Minimal Express app wiring for `@eep-dev/middleware`. - **`node-gate-publisher/`** — Hono gate publisher used by CI and by `tests/cross-impl` (starts on port **3002** by default). - **`node-express-subscriber/`**, **`python-fastapi-subscriber/`**, **`python-gate-subscriber/`** — Subscriber and 402/proof examples. - **`langgraph-eep-agent/`** — LangGraph + Claude agent that subscribes to EEP events, handles 402/403 gates, verifies HMAC signatures, and processes events through a Claude-powered pipeline. See [integration guide](../docs/guides/langgraph-eep-agent.md). - **`cross-impl/`** — **Legacy** interoperability harness kept for history. Active protocol tests live under **`../tests/cross-impl/`** (see that README). === FILE: EEP/docs/guides/realworld-simulation.md === # Realworld simulation (HTML vs EEP) This guide points to the **deterministic** “current web vs EEP” demo in the monorepo. It is for **talks, onboarding, and side-by-side comparison** — not a production deployment template. ## What you get - **Scenario A — Current web:** a Next.js HTML surface with paywalls; a Python agent uses **Playwright** to scrape embedded JSON (high bytes, simulated human steps). - **Scenario B — EEP:** the same fictional publisher exposes **`@eep-dev/gates`** on HTTP (**402** + structured proofs); the agent signs an NDA hash, submits a mock payment proof, and receives **JSON** without HTML parsing. Orchestration uses **Google ADK**-shaped agents but **does not call a hosted LLM** — runs are reproducible. ## Run it From the package directory (see [realworld-simulation/README.md](../../realworld-simulation/README.md) for prerequisites and layout): ```bash cd realworld-simulation npm run demo ``` That bootstraps Node + Python, starts **:3401** (Next.js) and **:3402** (EEP Express), runs both scenarios, then prints a **comparison** table. If servers are already running: ```bash cd realworld-simulation/agent PYTHONPATH=. SKIP_SERVER_START=1 .venv/bin/python run_demo.py ``` ## When to use this vs other paths | Path | Use when | |------|----------| | [Five-minute proof](./five-minute-proof.md) | You want the **reference stack**, **setup-cli**, or **minimal Express** in minutes. | | **Realworld simulation** | You want a **narrated terminal story** contrasting legacy HTML scraping with gate-based JSON. | | [Reference deployment](./reference-deployment-eep-api.md) | You need **Dockerized** Node + Python APIs and infra patterns. | ## Tunables (summary) Full list and defaults: **[realworld-simulation/README.md](../../realworld-simulation/README.md)**. Commonly adjusted: | Variable | Role | |----------|------| | `DEMO_SPLIT_SCREEN` | Parallel **left/right** panes (wide terminal). | | `DEMO_PHASE_PAUSE_SEC` | Pause between major beats. | | `DEMO_EXPORT_SECTION_PAUSE_SEC` | Pause between KPI / segments / JSON blocks (Scenario A exports). | | `DEMO_COMPARISON_DELAY_SEC` | Pause before the final comparison table. | | `DEMO_VIEWPORT_STEP_SEC` / `DEMO_HTML_VIEWPORT_STEP_SEC` / `DEMO_JSON_VIEWPORT_STEP_SEC` | Scroll animation speed. | ## Source layout | Path | Contents | |------|----------| | `realworld-simulation/provider/` | Next.js “CorpX” app + `eep-server/` Express publisher | | `realworld-simulation/agent/` | `run_demo.py`, Scenario A (Playwright), Scenario B (EEP client) | ## License Apache-2.0, same as the EEP repository. # End of llms-full.txt — see SPECIFICATION.md for normative wire format, schemas/v0.1/ for JSON contracts, and CHANGELOG.md for updates.