@emilia-protocol/sdk 0.1.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +810 -0
- package/dist/client.d.ts +540 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +740 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +512 -189
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +317 -139
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +508 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +35 -0
- package/dist/types.js.map +1 -0
- package/package.json +28 -11
- package/src/client.ts +920 -0
- package/src/index.ts +932 -0
- package/src/types.ts +640 -0
package/README.md
ADDED
|
@@ -0,0 +1,810 @@
|
|
|
1
|
+
# @emilia-protocol/sdk
|
|
2
|
+
|
|
3
|
+
**Trust before high-risk action.**
|
|
4
|
+
|
|
5
|
+
The official TypeScript SDK for the [EMILIA Protocol](https://emiliaprotocol.ai) — the protocol-grade trust substrate for high-risk action enforcement across AI agents, enterprise systems, government workflows, and financial operations.
|
|
6
|
+
|
|
7
|
+
EMILIA maps to six design pillars: **E**vidence, **M**ediation, **I**dentity, **L**ineage, **I**nvocation, **A**ppeals.
|
|
8
|
+
|
|
9
|
+
> Constitutional principle: **trust must never be more powerful than appeal.**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Installation](#installation)
|
|
16
|
+
- [Quick Start](#quick-start)
|
|
17
|
+
- [Environment Variables](#environment-variables)
|
|
18
|
+
- [Core Concepts](#core-concepts)
|
|
19
|
+
- [API Reference](#api-reference)
|
|
20
|
+
- [Trust Profile](#trust-profile)
|
|
21
|
+
- [Trust Evaluation](#trust-evaluation)
|
|
22
|
+
- [Trust Gate](#trust-gate)
|
|
23
|
+
- [Domain Scores](#domain-scores)
|
|
24
|
+
- [Pre-Action Enforcement (experimental)](#install-preflight)
|
|
25
|
+
- [Entities](#entities)
|
|
26
|
+
- [Receipts](#receipts)
|
|
27
|
+
- [Disputes & Due Process](#disputes--due-process)
|
|
28
|
+
- [Delegation](#delegation)
|
|
29
|
+
- [Identity Continuity](#identity-continuity)
|
|
30
|
+
- [Policies](#policies)
|
|
31
|
+
- [System](#system)
|
|
32
|
+
- [Error Handling](#error-handling)
|
|
33
|
+
- [TypeScript Usage](#typescript-usage)
|
|
34
|
+
- [Links](#links)
|
|
35
|
+
- [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install @emilia-protocol/sdk
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Requires Node.js 18 or later (native `fetch` is used).
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Quick Start
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
import { EPClient } from '@emilia-protocol/sdk';
|
|
53
|
+
|
|
54
|
+
const ep = new EPClient({ apiKey: process.env.EP_API_KEY });
|
|
55
|
+
|
|
56
|
+
const profile = await ep.trustProfile('merchant-xyz');
|
|
57
|
+
console.log(profile.current_confidence); // "confident"
|
|
58
|
+
console.log(profile.trust_profile?.behavioral?.completion_rate); // 97.2
|
|
59
|
+
|
|
60
|
+
const evaluation = await ep.trustEvaluate('merchant-xyz', 'strict');
|
|
61
|
+
if (evaluation.decision !== 'allow') throw new Error(`Trust check failed: ${evaluation.reasons?.join(', ')}`);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Environment Variables
|
|
67
|
+
|
|
68
|
+
| Variable | Description | Default |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| `EP_API_KEY` | Your EP API key (`ep_live_...`). Required for write operations. | — |
|
|
71
|
+
| `EP_BASE_URL` | Override the API base URL (useful for local dev). | `https://emiliaprotocol.ai` |
|
|
72
|
+
|
|
73
|
+
You can also pass these directly to the constructor:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const ep = new EPClient({
|
|
77
|
+
apiKey: 'ep_live_...',
|
|
78
|
+
baseUrl: 'http://localhost:3000', // local dev
|
|
79
|
+
timeout: 10_000, // 10 seconds (default: 30s)
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Core Concepts
|
|
86
|
+
|
|
87
|
+
### Trust Profile
|
|
88
|
+
|
|
89
|
+
The trust profile is the canonical EP read surface. It aggregates behavioral rates, signal scores, provenance breakdown, consistency, anomaly detection, and dispute history into a single structured object. Always start here.
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
profile.current_confidence → "pending" | "insufficient" | "provisional" | "emerging" | "confident"
|
|
93
|
+
profile.trust_profile.behavioral.completion_rate → float (0-100)
|
|
94
|
+
profile.trust_profile.signals.delivery_accuracy → float (0-100)
|
|
95
|
+
profile.trust_profile.provenance.bilateral_rate → float (0-100)
|
|
96
|
+
profile.anomaly → present only when anomaly detected
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Receipts
|
|
100
|
+
|
|
101
|
+
Receipts are the atomic unit of evidence in EP. Every interaction between principals generates a receipt. Receipts are:
|
|
102
|
+
|
|
103
|
+
- **Append-only** — cannot be edited or deleted
|
|
104
|
+
- **Cryptographically hashed** — SHA-256 of the canonical payload
|
|
105
|
+
- **Chain-linked** — each receipt references the previous hash for the entity
|
|
106
|
+
- **Anchored** — periodically committed to a Merkle root for external verification
|
|
107
|
+
|
|
108
|
+
The `agent_behavior` field is the strongest Phase 1 signal. Always set it.
|
|
109
|
+
|
|
110
|
+
### Policy Evaluation
|
|
111
|
+
|
|
112
|
+
Policies define trust thresholds. EP ships 8 named policies:
|
|
113
|
+
|
|
114
|
+
| Policy | Family | Use case |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `strict` | core | High-value transactions, sensitive data |
|
|
117
|
+
| `standard` | core | Normal commerce, default |
|
|
118
|
+
| `permissive` | core | Low-risk interactions |
|
|
119
|
+
| `discovery` | core | Allow unevaluated entities to participate |
|
|
120
|
+
| `mcp_server_safe_v1` | software | MCP server installation |
|
|
121
|
+
| `npm_buildtime_safe_v1` | software | npm package installation in CI |
|
|
122
|
+
| `browser_extension_safe_v1` | software | Browser extension installation |
|
|
123
|
+
| `github_private_repo_safe_v1` | software | GitHub App with private repo access |
|
|
124
|
+
|
|
125
|
+
### Trust Gate
|
|
126
|
+
|
|
127
|
+
The trust gate is a pre-action decision surface that combines trust evaluation with delegation verification. Call it before any high-stakes autonomous action. It returns `allow | review | deny` with appeal paths for non-allow decisions.
|
|
128
|
+
|
|
129
|
+
### Due Process
|
|
130
|
+
|
|
131
|
+
EP enforces a mandatory due process pipeline for every negative trust event:
|
|
132
|
+
|
|
133
|
+
1. **Dispute** — any affected party can challenge a receipt
|
|
134
|
+
2. **Response** — the receipt submitter has 7 days to respond
|
|
135
|
+
3. **Resolution** — EP resolves with rationale (`upheld | reversed | dismissed`)
|
|
136
|
+
4. **Appeal** — participants can appeal the resolution
|
|
137
|
+
5. **Human Report** — no auth required; any human can report trust issues
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## API Reference
|
|
142
|
+
|
|
143
|
+
### Trust Profile
|
|
144
|
+
|
|
145
|
+
#### `ep.trustProfile(entityId)`
|
|
146
|
+
|
|
147
|
+
Get an entity's full trust profile. This is the canonical EP read surface.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
const profile = await ep.trustProfile('merchant-xyz');
|
|
151
|
+
|
|
152
|
+
console.log(profile.entity_id); // "merchant-xyz"
|
|
153
|
+
console.log(profile.display_name); // "Merchant XYZ"
|
|
154
|
+
console.log(profile.current_confidence); // "confident"
|
|
155
|
+
console.log(profile.historical_establishment); // true
|
|
156
|
+
console.log(profile.effective_evidence_current); // 42
|
|
157
|
+
console.log(profile.receipt_count); // 57
|
|
158
|
+
console.log(profile.unique_submitters); // 12
|
|
159
|
+
|
|
160
|
+
// Behavioral rates
|
|
161
|
+
const b = profile.trust_profile?.behavioral;
|
|
162
|
+
console.log(b?.completion_rate); // 97.2
|
|
163
|
+
console.log(b?.retry_rate); // 1.8
|
|
164
|
+
console.log(b?.abandon_rate); // 0.5
|
|
165
|
+
console.log(b?.dispute_rate); // 0.5
|
|
166
|
+
|
|
167
|
+
// Signal scores
|
|
168
|
+
const s = profile.trust_profile?.signals;
|
|
169
|
+
console.log(s?.delivery_accuracy); // 96.1
|
|
170
|
+
console.log(s?.product_accuracy); // 94.8
|
|
171
|
+
console.log(s?.price_integrity); // 99.2
|
|
172
|
+
console.log(s?.return_processing); // 88.0
|
|
173
|
+
|
|
174
|
+
// Provenance
|
|
175
|
+
const prov = profile.trust_profile?.provenance;
|
|
176
|
+
console.log(prov?.breakdown); // { bilateral: 0.6, self_attested: 0.4 }
|
|
177
|
+
console.log(prov?.bilateral_rate); // 60
|
|
178
|
+
|
|
179
|
+
// Disputes
|
|
180
|
+
console.log(profile.disputes?.total); // 2
|
|
181
|
+
console.log(profile.disputes?.active); // 0
|
|
182
|
+
console.log(profile.disputes?.reversed); // 1
|
|
183
|
+
|
|
184
|
+
// Anomaly detection (only present when triggered)
|
|
185
|
+
if (profile.anomaly) {
|
|
186
|
+
console.warn(profile.anomaly.alert); // "Sudden drop: 23 points in 7 days"
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Legacy score (fallback only — prefer trust_profile for decisions)
|
|
190
|
+
console.log(profile.compat_score); // 91
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Trust Evaluation
|
|
196
|
+
|
|
197
|
+
#### `ep.trustEvaluate(entityId, policy?, context?)`
|
|
198
|
+
|
|
199
|
+
Evaluate an entity against a named trust policy.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
// Basic evaluation — returns a canonical TrustDecision
|
|
203
|
+
const result = await ep.trustEvaluate('merchant-xyz', 'standard');
|
|
204
|
+
console.log(result.decision); // "allow"
|
|
205
|
+
console.log(result.confidence); // "confident"
|
|
206
|
+
|
|
207
|
+
// With context for context-aware evaluation
|
|
208
|
+
const strict = await ep.trustEvaluate('merchant-xyz', 'strict', {
|
|
209
|
+
category: 'furniture',
|
|
210
|
+
geo: 'US-CA',
|
|
211
|
+
value_band: 'high',
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (strict.decision !== 'allow') {
|
|
215
|
+
console.error('Reasons:', strict.reasons);
|
|
216
|
+
// e.g. ["insufficient_evidence_current", "dispute_rate_too_high"]
|
|
217
|
+
console.warn('Warnings:', strict.warnings);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Check which policy was applied (useful when policies cascade)
|
|
221
|
+
console.log(strict.policy_used); // "strict"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
### Trust Gate
|
|
227
|
+
|
|
228
|
+
#### `ep.trustGate(options)`
|
|
229
|
+
|
|
230
|
+
Pre-action trust check. Combines trust evaluation with delegation verification.
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const gate = await ep.trustGate({
|
|
234
|
+
entityId: 'payment-agent-v2',
|
|
235
|
+
action: 'execute_payment',
|
|
236
|
+
policy: 'strict',
|
|
237
|
+
valueUsd: 750,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// gate.decision: "allow" | "review" | "deny"
|
|
241
|
+
if (gate.decision === 'allow') {
|
|
242
|
+
// Proceed with action
|
|
243
|
+
} else {
|
|
244
|
+
console.error('Gate denied:', gate.reasons);
|
|
245
|
+
console.log('Appeal path:', gate.appeal_path);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// With delegation verification
|
|
249
|
+
const gateWithDelegation = await ep.trustGate({
|
|
250
|
+
entityId: 'acme-payment-agent',
|
|
251
|
+
action: 'purchase',
|
|
252
|
+
policy: 'standard',
|
|
253
|
+
valueUsd: 200,
|
|
254
|
+
delegationId: 'ep_del_abc123',
|
|
255
|
+
});
|
|
256
|
+
console.log(gateWithDelegation.delegation_verified); // true
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
### Domain Scores
|
|
262
|
+
|
|
263
|
+
#### `ep.domainScore(entityId, domains?)`
|
|
264
|
+
|
|
265
|
+
Get trust scores broken down by domain. Useful when you need trust context scoped to a specific action category.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
// All domains
|
|
269
|
+
const all = await ep.domainScore('agent-v2');
|
|
270
|
+
console.log(all.domains.financial?.confidence); // "confident"
|
|
271
|
+
console.log(all.domains.code_execution?.confidence); // "provisional"
|
|
272
|
+
|
|
273
|
+
// Filtered to specific domains
|
|
274
|
+
const relevant = await ep.domainScore('agent-v2', ['financial', 'delegation']);
|
|
275
|
+
console.log(relevant.domains.financial?.completion_rate); // 98.1
|
|
276
|
+
console.log(relevant.domains.delegation?.dispute_rate); // 0.2
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
### Install Preflight
|
|
282
|
+
|
|
283
|
+
#### `ep.installPreflight(entityId, policy?, context?)`
|
|
284
|
+
|
|
285
|
+
EP-SX: Software pre-action enforcement check (experimental). Use before installing any plugin, package, extension, MCP server, or marketplace app.
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
// MCP server
|
|
289
|
+
const mcp = await ep.installPreflight(
|
|
290
|
+
'mcp-server-acme-v1',
|
|
291
|
+
'mcp_server_safe_v1',
|
|
292
|
+
{ host: 'claude-desktop', permission_class: 'bounded_external_access' },
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
console.log(mcp.decision); // "allow" | "review" | "deny"
|
|
296
|
+
console.log(mcp.confidence); // "confident"
|
|
297
|
+
console.log(mcp.reasons); // present for review/deny
|
|
298
|
+
console.log(mcp.software_meta?.publisher_verified); // true
|
|
299
|
+
console.log(mcp.software_meta?.permission_class); // "bounded_external_access"
|
|
300
|
+
|
|
301
|
+
if (mcp.decision === 'deny') throw new Error('Installation blocked by EP trust policy');
|
|
302
|
+
if (mcp.decision === 'review') console.warn('Manual review recommended before installing');
|
|
303
|
+
|
|
304
|
+
// npm package
|
|
305
|
+
const pkg = await ep.installPreflight(
|
|
306
|
+
'npm:acme-build-plugin',
|
|
307
|
+
'npm_buildtime_safe_v1',
|
|
308
|
+
{ execution_mode: 'build_only' },
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
// Browser extension
|
|
312
|
+
const ext = await ep.installPreflight(
|
|
313
|
+
'chrome_extension:acme-helper',
|
|
314
|
+
'browser_extension_safe_v1',
|
|
315
|
+
{ data_sensitivity: 'low' },
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// GitHub App
|
|
319
|
+
const app = await ep.installPreflight(
|
|
320
|
+
'github_app:acme/code-review',
|
|
321
|
+
'github_private_repo_safe_v1',
|
|
322
|
+
{ install_scope: 'private_repos' },
|
|
323
|
+
);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
### Entities
|
|
329
|
+
|
|
330
|
+
#### `ep.registerEntity(options)`
|
|
331
|
+
|
|
332
|
+
Register a new entity. Public endpoint — no API key required. Save the returned `api_key` securely; it will not be shown again.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
const { entity, api_key } = await ep.registerEntity({
|
|
336
|
+
entityId: 'acme-payment-agent',
|
|
337
|
+
displayName: 'Acme Payment Agent',
|
|
338
|
+
entityType: 'agent',
|
|
339
|
+
description: 'Handles autonomous payment flows for Acme Corp.',
|
|
340
|
+
capabilities: ['payment', 'refund', 'dispute_resolution'],
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
console.log(entity.entity_id); // "acme-payment-agent"
|
|
344
|
+
console.log(api_key); // "ep_live_..." — store this securely!
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### `ep.searchEntities(query, entityType?, minConfidence?)`
|
|
348
|
+
|
|
349
|
+
Search for entities by name, capability, or category.
|
|
350
|
+
|
|
351
|
+
```typescript
|
|
352
|
+
const { entities } = await ep.searchEntities('payment', 'agent', 'confident');
|
|
353
|
+
|
|
354
|
+
for (const e of entities) {
|
|
355
|
+
console.log(`${e.display_name} (${e.entity_id}): ${e.confidence}`);
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### `ep.leaderboard(limit?, entityType?)`
|
|
360
|
+
|
|
361
|
+
Get the leaderboard of top-trusted entities.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
// Top 5 merchants
|
|
365
|
+
const { leaderboard } = await ep.leaderboard(5, 'merchant');
|
|
366
|
+
leaderboard.forEach(e => console.log(`#${e.rank} ${e.display_name} — ${e.confidence}`));
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
### Receipts
|
|
372
|
+
|
|
373
|
+
#### `ep.submitReceipt(input)`
|
|
374
|
+
|
|
375
|
+
Submit a single transaction receipt. Requires an API key.
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
const { receipt } = await ep.submitReceipt({
|
|
379
|
+
entity_id: 'merchant-xyz',
|
|
380
|
+
transaction_ref: 'order-8821', // Required — must be unique per entity
|
|
381
|
+
transaction_type: 'purchase',
|
|
382
|
+
agent_behavior: 'completed', // Strongest signal — always set this
|
|
383
|
+
delivery_accuracy: 98,
|
|
384
|
+
product_accuracy: 95,
|
|
385
|
+
price_integrity: 100,
|
|
386
|
+
return_processing: 88,
|
|
387
|
+
claims: {
|
|
388
|
+
delivered: true,
|
|
389
|
+
on_time: true,
|
|
390
|
+
price_honored: true,
|
|
391
|
+
as_described: true,
|
|
392
|
+
},
|
|
393
|
+
context: {
|
|
394
|
+
category: 'electronics',
|
|
395
|
+
geo: 'US-NY',
|
|
396
|
+
value_band: 'medium',
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
console.log(receipt.receipt_id); // "ep_rcpt_..."
|
|
401
|
+
console.log(receipt.receipt_hash); // SHA-256 hash
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
#### `ep.batchSubmit(receipts)`
|
|
405
|
+
|
|
406
|
+
Submit up to 50 receipts in a single atomic call. Partial success is possible.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
const result = await ep.batchSubmit([
|
|
410
|
+
{
|
|
411
|
+
entity_id: 'merchant-a',
|
|
412
|
+
transaction_ref: 'tx-001',
|
|
413
|
+
transaction_type: 'purchase',
|
|
414
|
+
agent_behavior: 'completed',
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
entity_id: 'merchant-b',
|
|
418
|
+
transaction_ref: 'tx-002',
|
|
419
|
+
transaction_type: 'service',
|
|
420
|
+
agent_behavior: 'completed',
|
|
421
|
+
},
|
|
422
|
+
]);
|
|
423
|
+
|
|
424
|
+
result.results.forEach(r => {
|
|
425
|
+
if (r.success) console.log(`${r.entity_id}: receipt ${r.receipt_id}`);
|
|
426
|
+
else console.error(`${r.entity_id}: ${r.error}`);
|
|
427
|
+
});
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
#### `ep.confirmReceipt(receiptId, confirm)`
|
|
431
|
+
|
|
432
|
+
Bilateral confirmation — counterparty confirms or rejects a receipt within 48 hours. Confirmed receipts receive a higher provenance tier.
|
|
433
|
+
|
|
434
|
+
```typescript
|
|
435
|
+
// Confirm as the counterparty
|
|
436
|
+
await ep.confirmReceipt('ep_rcpt_abc123', true);
|
|
437
|
+
|
|
438
|
+
// Reject (triggers dispute-like flow)
|
|
439
|
+
await ep.confirmReceipt('ep_rcpt_abc123', false);
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### `ep.verifyReceipt(receiptId)`
|
|
443
|
+
|
|
444
|
+
Verify receipt hash integrity and Merkle root anchoring.
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
const { verified, anchored, receipt_hash } = await ep.verifyReceipt('ep_rcpt_abc123');
|
|
448
|
+
|
|
449
|
+
if (!verified) console.error('Receipt integrity check FAILED — possible tampering');
|
|
450
|
+
if (!anchored) console.log('Receipt not yet anchored — check back after next anchor cycle');
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### Disputes & Due Process
|
|
456
|
+
|
|
457
|
+
#### `ep.fileDispute(options)`
|
|
458
|
+
|
|
459
|
+
File a dispute against a receipt. Any affected party can challenge.
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
const dispute = await ep.fileDispute({
|
|
463
|
+
receiptId: 'ep_rcpt_abc123',
|
|
464
|
+
reason: 'inaccurate_signals', // See DisputeReason type for all options
|
|
465
|
+
description: 'Delivery accuracy was reported as 98 but item arrived damaged.',
|
|
466
|
+
evidence: { photo_url: 'https://cdn.example.com/damage-photo.jpg' },
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
console.log('Dispute ID:', dispute.dispute_id);
|
|
470
|
+
console.log('Respond by:', dispute.response_deadline); // 7-day window
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
Valid `reason` values: `fraudulent_receipt` | `inaccurate_signals` | `identity_dispute` | `context_mismatch` | `duplicate_transaction` | `coerced_receipt` | `other`
|
|
474
|
+
|
|
475
|
+
#### `ep.disputeStatus(disputeId)`
|
|
476
|
+
|
|
477
|
+
Check dispute status. Public — transparency is a protocol value.
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
const dispute = await ep.disputeStatus('ep_disp_xyz789');
|
|
481
|
+
|
|
482
|
+
console.log(dispute.status); // "pending" | "responded" | "upheld" | "reversed" | "dismissed"
|
|
483
|
+
console.log(dispute.reason); // "inaccurate_signals"
|
|
484
|
+
console.log(dispute.entity?.entity_id); // "merchant-xyz"
|
|
485
|
+
console.log(dispute.response); // submitter's response (if provided)
|
|
486
|
+
console.log(dispute.resolution); // resolution decision (if resolved)
|
|
487
|
+
console.log(dispute.resolution_rationale);
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
#### `ep.respondToDispute(options)`
|
|
491
|
+
|
|
492
|
+
Respond to a dispute filed against one of your receipts.
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
await ep.respondToDispute({
|
|
496
|
+
disputeId: 'ep_disp_xyz789',
|
|
497
|
+
response: 'The accuracy score reflects carrier handoff state, confirmed by tracking log.',
|
|
498
|
+
evidence: { tracking_log: 'https://carrier.example.com/track/8821' },
|
|
499
|
+
});
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
#### `ep.withdrawDispute(disputeId)`
|
|
503
|
+
|
|
504
|
+
Withdraw an open dispute before resolution.
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
await ep.withdrawDispute('ep_disp_xyz789');
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
#### `ep.appealDispute(options)`
|
|
511
|
+
|
|
512
|
+
Appeal a dispute resolution. Only dispute participants may appeal. The dispute must be in `upheld`, `reversed`, or `dismissed` state. Appeal decisions are final.
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
await ep.appealDispute({
|
|
516
|
+
disputeId: 'ep_disp_xyz789',
|
|
517
|
+
reason: 'The carrier log submitted in the response was from a different shipment.',
|
|
518
|
+
evidence: { corrected_manifest: 'https://...' },
|
|
519
|
+
});
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
#### `ep.reportTrustIssue(options)`
|
|
523
|
+
|
|
524
|
+
Human appeal channel. No authentication required.
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
// No API key needed
|
|
528
|
+
const report = await ep.reportTrustIssue({
|
|
529
|
+
entityId: 'merchant-xyz',
|
|
530
|
+
reportType: 'harmed_by_trusted_entity',
|
|
531
|
+
description: 'Paid for an item marked delivered but never received. Order #8821.',
|
|
532
|
+
contactEmail: 'jane@example.com', // Optional — for EP follow-up
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
console.log(report.report_id); // "ep_report_..."
|
|
536
|
+
console.log(report._principle); // "Trust must never be more powerful than appeal."
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Valid `reportType` values: `wrongly_downgraded` | `harmed_by_trusted_entity` | `fraudulent_entity` | `inaccurate_profile` | `other`
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
### Delegation
|
|
544
|
+
|
|
545
|
+
#### `ep.createDelegation(options)`
|
|
546
|
+
|
|
547
|
+
Create a delegation record authorizing an agent to act on behalf of a principal.
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
const delegation = await ep.createDelegation({
|
|
551
|
+
principalId: 'ep_principal_acme',
|
|
552
|
+
agentEntityId: 'acme-payment-agent',
|
|
553
|
+
scope: ['purchase', 'refund'],
|
|
554
|
+
maxValueUsd: 1000,
|
|
555
|
+
expiresAt: '2026-12-31T23:59:59Z',
|
|
556
|
+
constraints: { require_confirmation_above_usd: 500 },
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
console.log('Delegation ID:', delegation.delegation_id);
|
|
560
|
+
console.log('Status:', delegation.status); // "active"
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
#### `ep.verifyDelegation(delegationId, actionType?)`
|
|
564
|
+
|
|
565
|
+
Verify a delegation is valid and covers a specific action.
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
const result = await ep.verifyDelegation('ep_del_abc123', 'purchase');
|
|
569
|
+
|
|
570
|
+
console.log(result.valid); // true
|
|
571
|
+
console.log(result.action_permitted); // true
|
|
572
|
+
console.log(result.status); // "active"
|
|
573
|
+
console.log(result.expires_at); // "2026-12-31T23:59:59Z"
|
|
574
|
+
|
|
575
|
+
if (!result.valid) throw new Error(`Delegation invalid: ${result.reason}`);
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
### Identity Continuity
|
|
581
|
+
|
|
582
|
+
#### `ep.principalLookup(principalId)`
|
|
583
|
+
|
|
584
|
+
Look up a principal — the enduring actor behind one or more entities.
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
const result = await ep.principalLookup('ep_principal_acme');
|
|
588
|
+
|
|
589
|
+
console.log(result.principal.display_name); // "Acme Corp"
|
|
590
|
+
console.log(result.principal.principal_type); // "organization"
|
|
591
|
+
console.log(result.principal.bootstrap_verified); // true
|
|
592
|
+
|
|
593
|
+
// Controlled entities
|
|
594
|
+
result.entities?.forEach(e => {
|
|
595
|
+
console.log(`${e.display_name} (${e.entity_type}): ${e.entity_id}`);
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
// Identity bindings (e.g. domain, GitHub org)
|
|
599
|
+
result.bindings?.forEach(b => {
|
|
600
|
+
console.log(`${b.binding_type}: ${b.binding_target} [${b.status}]`);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// Continuity history
|
|
604
|
+
result.continuity_claims?.forEach(c => {
|
|
605
|
+
console.log(`${c.old_entity_id} → ${c.new_entity_id} (${c.reason}) [${c.status}]`);
|
|
606
|
+
});
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### `ep.lineage(entityId)`
|
|
610
|
+
|
|
611
|
+
View entity lineage — predecessors and successors. Use to detect reputation laundering.
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
const lineage = await ep.lineage('merchant-xyz');
|
|
615
|
+
|
|
616
|
+
// Check for suspicious predecessor gaps
|
|
617
|
+
if (lineage.predecessors?.some(p => p.status === 'disputed')) {
|
|
618
|
+
console.warn('Entity has disputed predecessor — investigate before transacting');
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
lineage.predecessors?.forEach(p => {
|
|
622
|
+
console.log(`← ${p.from} (${p.reason}) [${p.status}] transfer: ${p.transfer_policy}`);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
lineage.successors?.forEach(s => {
|
|
626
|
+
console.log(`→ ${s.to} (${s.reason}) [${s.status}]`);
|
|
627
|
+
});
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
### Policies
|
|
633
|
+
|
|
634
|
+
#### `ep.listPolicies()`
|
|
635
|
+
|
|
636
|
+
List all available trust policies.
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
const { policies } = await ep.listPolicies();
|
|
640
|
+
|
|
641
|
+
policies.forEach(p => {
|
|
642
|
+
console.log(`${p.name} [${p.family}]`);
|
|
643
|
+
console.log(` ${p.description}`);
|
|
644
|
+
if (p.min_confidence) console.log(` min confidence: ${p.min_confidence}`);
|
|
645
|
+
});
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
### System
|
|
651
|
+
|
|
652
|
+
#### `ep.stats()`
|
|
653
|
+
|
|
654
|
+
Public proof metrics.
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
const stats = await ep.stats();
|
|
658
|
+
console.log(`${stats.total_entities} entities`);
|
|
659
|
+
console.log(`${stats.trust_policies} trust policies`);
|
|
660
|
+
console.log(`${stats.mcp_tools} MCP tools`);
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
#### `ep.health()`
|
|
664
|
+
|
|
665
|
+
Health check.
|
|
666
|
+
|
|
667
|
+
```typescript
|
|
668
|
+
const health = await ep.health();
|
|
669
|
+
console.log(health.status); // "ok"
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
#### `ep.legacyScore(entityId)` (deprecated)
|
|
673
|
+
|
|
674
|
+
Returns the 0-100 legacy compatibility score. Prefer `trustProfile()` for all new code.
|
|
675
|
+
|
|
676
|
+
```typescript
|
|
677
|
+
const { score } = await ep.legacyScore('merchant-xyz');
|
|
678
|
+
console.log(score); // 91
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## Error Handling
|
|
684
|
+
|
|
685
|
+
All methods throw `EPError` on failure. `EPError` extends `Error` with `status` (HTTP status code) and `code` (API error code).
|
|
686
|
+
|
|
687
|
+
```typescript
|
|
688
|
+
import { EPClient, EPError } from '@emilia-protocol/sdk';
|
|
689
|
+
|
|
690
|
+
const ep = new EPClient({ apiKey: process.env.EP_API_KEY });
|
|
691
|
+
|
|
692
|
+
try {
|
|
693
|
+
const profile = await ep.trustProfile('unknown-entity');
|
|
694
|
+
} catch (err) {
|
|
695
|
+
if (err instanceof EPError) {
|
|
696
|
+
console.error(`EP error ${err.status}: ${err.message}`);
|
|
697
|
+
// err.status === 404 → entity not found
|
|
698
|
+
// err.status === 401 → missing or invalid API key
|
|
699
|
+
// err.status === 429 → rate limited
|
|
700
|
+
// err.code === 'timeout' → request timed out
|
|
701
|
+
// err.code === 'network_error' → network failure
|
|
702
|
+
} else {
|
|
703
|
+
throw err; // unexpected error — re-throw
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
### Common status codes
|
|
709
|
+
|
|
710
|
+
| Status | Meaning |
|
|
711
|
+
|---|---|
|
|
712
|
+
| `401` | Missing or invalid API key |
|
|
713
|
+
| `403` | Insufficient permissions for this operation |
|
|
714
|
+
| `404` | Entity, receipt, or dispute not found |
|
|
715
|
+
| `409` | Conflict (e.g. duplicate transaction_ref) |
|
|
716
|
+
| `422` | Validation error — check request body |
|
|
717
|
+
| `429` | Rate limited |
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## TypeScript Usage
|
|
722
|
+
|
|
723
|
+
The SDK is fully typed. All types are exported from the package root.
|
|
724
|
+
|
|
725
|
+
```typescript
|
|
726
|
+
import {
|
|
727
|
+
EPClient,
|
|
728
|
+
EPError,
|
|
729
|
+
// Enumerations
|
|
730
|
+
type EntityType,
|
|
731
|
+
type TrustPolicy,
|
|
732
|
+
type AgentBehavior,
|
|
733
|
+
type TransactionType,
|
|
734
|
+
type DisputeReason,
|
|
735
|
+
type TrustDomain,
|
|
736
|
+
type ConfidenceTier,
|
|
737
|
+
// Response types
|
|
738
|
+
type EntityTrustProfile,
|
|
739
|
+
type TrustEvaluation,
|
|
740
|
+
type TrustGateResult,
|
|
741
|
+
type InstallPreflightResult,
|
|
742
|
+
type Receipt,
|
|
743
|
+
type Dispute,
|
|
744
|
+
type DelegationRecord,
|
|
745
|
+
// Input types
|
|
746
|
+
type SubmitReceiptInput,
|
|
747
|
+
type TrustContext,
|
|
748
|
+
type EPClientOptions,
|
|
749
|
+
} from '@emilia-protocol/sdk';
|
|
750
|
+
|
|
751
|
+
// Type-safe client construction
|
|
752
|
+
const options: EPClientOptions = {
|
|
753
|
+
apiKey: process.env.EP_API_KEY,
|
|
754
|
+
timeout: 15_000,
|
|
755
|
+
};
|
|
756
|
+
const ep = new EPClient(options);
|
|
757
|
+
|
|
758
|
+
// Type-safe receipt submission
|
|
759
|
+
const input: SubmitReceiptInput = {
|
|
760
|
+
entity_id: 'merchant-xyz',
|
|
761
|
+
transaction_ref: `order-${Date.now()}`,
|
|
762
|
+
transaction_type: 'purchase',
|
|
763
|
+
agent_behavior: 'completed',
|
|
764
|
+
delivery_accuracy: 98,
|
|
765
|
+
};
|
|
766
|
+
const { receipt } = await ep.submitReceipt(input);
|
|
767
|
+
|
|
768
|
+
// Type-safe context
|
|
769
|
+
const context: TrustContext = {
|
|
770
|
+
category: 'electronics',
|
|
771
|
+
geo: 'US-CA',
|
|
772
|
+
value_band: 'high',
|
|
773
|
+
};
|
|
774
|
+
const evaluation = await ep.trustEvaluate('merchant-xyz', 'strict', context);
|
|
775
|
+
|
|
776
|
+
// Narrowing on confidence tier
|
|
777
|
+
function isHighConfidence(confidence: ConfidenceTier): boolean {
|
|
778
|
+
return confidence === 'confident' || confidence === 'emerging';
|
|
779
|
+
}
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
### Using with custom fetch (e.g. for testing)
|
|
783
|
+
|
|
784
|
+
```typescript
|
|
785
|
+
import { EPClient } from '@emilia-protocol/sdk';
|
|
786
|
+
|
|
787
|
+
const mockFetch: typeof fetch = async (url, init) => {
|
|
788
|
+
// Return mock responses for testing
|
|
789
|
+
return new Response(JSON.stringify({ entity_id: 'test', current_confidence: 'confident' }));
|
|
790
|
+
};
|
|
791
|
+
|
|
792
|
+
const ep = new EPClient({ fetchImpl: mockFetch });
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
---
|
|
796
|
+
|
|
797
|
+
## Links
|
|
798
|
+
|
|
799
|
+
- [emiliaprotocol.ai](https://emiliaprotocol.ai)
|
|
800
|
+
- [EP Core RFC](https://github.com/emiliaprotocol/emilia-protocol/blob/main/docs/EP-CORE-RFC.md)
|
|
801
|
+
- [OpenAPI Specification](https://github.com/emiliaprotocol/emilia-protocol/blob/main/openapi.yaml)
|
|
802
|
+
- [MCP Server](https://github.com/emiliaprotocol/emilia-protocol/tree/main/mcp-server)
|
|
803
|
+
- [Conformance Vectors](https://github.com/emiliaprotocol/emilia-protocol/tree/main/conformance)
|
|
804
|
+
- [Issues](https://github.com/emiliaprotocol/emilia-protocol/issues)
|
|
805
|
+
|
|
806
|
+
---
|
|
807
|
+
|
|
808
|
+
## License
|
|
809
|
+
|
|
810
|
+
Apache 2.0 — see [LICENSE](../../LICENSE).
|