@private.me/xbind 3.0.3 → 3.1.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/MIGRATING.md +205 -0
- package/README.md +91 -28
- package/dist-standalone/cjs/split-channel.js +1 -1
- package/dist-standalone/cjs/transport.js +1 -1
- package/dist-standalone/split-channel.d.ts +1 -1
- package/dist-standalone/split-channel.js +1 -1
- package/dist-standalone/transport.d.ts +1 -1
- package/dist-standalone/transport.js +1 -1
- package/package.json +2 -1
- package/share1.dat +0 -0
- package/README.md.backup +0 -2121
package/README.md.backup
DELETED
|
@@ -1,2121 +0,0 @@
|
|
|
1
|
-
# @private.me/xbind
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
5
|
-

|
|
6
|
-

|
|
7
|
-

|
|
8
|
-
|
|
9
|
-
**Authenticated agent-to-agent messaging with post-quantum cryptographic identity.**
|
|
10
|
-
|
|
11
|
-
Build AI agents that communicate securely using ML-DSA-65 DID identity, ML-KEM-768 + AES-256-GCM encryption, and information-theoretic split-channel delivery (XorIDA). Every message is signed and encrypted. No API keys, no rotation, no sprawl.
|
|
12
|
-
|
|
13
|
-
Part of the **Private.Me** platform—where APIs have keys, but ACIs have identity.
|
|
14
|
-
|
|
15
|
-
**Version 3.0.3** — **Major Features:** LoopbackTransport export for testing (GAP-CORE-2), describeSecurityModeStructured export (GAP-API-3), Agent.quickstart() signature fixes. Full Control IP Protection (PLAN-13) - Vault Store architecture with payment-gated algorithm delivery. Store Front (npm) contains Share 1 only, Vault Store (EC2) contains Share 2 (payment-gated). Runtime crypto loading, 4-layer security (DID auth + usage quotas + rate limiting + audit logging). Usage-based model: Free tier 100K ops/month (includes vault access), Pro tier unlimited. Previous v3.0.2: Full Control IP Protection launch. Previous v1.4.2: Runtime compatibility, API enhancements.
|
|
16
|
-
|
|
17
|
-
## Install
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
# Node.js / TypeScript
|
|
21
|
-
npm install @private.me/xbind
|
|
22
|
-
|
|
23
|
-
# Python
|
|
24
|
-
pip install private-me-xbind
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**Distribution Model:** xBind uses Full Control IP protection (2-share XorIDA). Share 1 (Store Front) is distributed via npm registry. Share 2 (Vault Store) is served via `/api/full-control/share2/:package/:version` and requires payment verification and xBind authentication.
|
|
28
|
-
|
|
29
|
-
[Python SDK documentation](./python/README.md) • [Complete docs](./docs/README.md) • [White paper](https://private.me/docs/xbind.html)
|
|
30
|
-
|
|
31
|
-
## Security Notice
|
|
32
|
-
|
|
33
|
-
**Post-Quantum Cryptography:** xBind uses `mldsa-wasm@0.0.4` for post-quantum digital signatures (ML-DSA-65/FIPS 204). This package is pre-1.0 beta software. While based on audited upstream cryptography ([PQCA mldsa](https://github.com/dajiaji/mldsa)), it has not been independently audited.
|
|
34
|
-
|
|
35
|
-
**Risk Acceptance:** We have accepted this risk for the following reasons:
|
|
36
|
-
- Based on NIST FIPS 204 standardized algorithm
|
|
37
|
-
- Zero production dependencies (minimal supply chain risk)
|
|
38
|
-
- No known CVEs
|
|
39
|
-
- Version pinned (not using semver range) for stability
|
|
40
|
-
|
|
41
|
-
**Migration Plan:** We plan to migrate to [@noble/post-quantum](https://www.npmjs.com/package/@noble/post-quantum) in Q4 2026 (xBind v2.0.0), which offers broader ecosystem support and maturity.
|
|
42
|
-
|
|
43
|
-
For production deployments requiring formal cryptographic assurance, please contact contact@private.me for enterprise options.
|
|
44
|
-
|
|
45
|
-
## Secure Key Storage
|
|
46
|
-
|
|
47
|
-
**⚠️ CRITICAL SECURITY WARNING:** All post-quantum cryptography in xBind is undermined if seeds/keys are stored in plaintext.
|
|
48
|
-
|
|
49
|
-
### ❌ NEVER Store Keys in Plaintext
|
|
50
|
-
|
|
51
|
-
**Dangerous practices that expose your identity:**
|
|
52
|
-
|
|
53
|
-
<!-- ANTI-PATTERN -->
|
|
54
|
-
```typescript
|
|
55
|
-
// ❌ WRONG: Plaintext file storage
|
|
56
|
-
const seed = agent.exportSeeds();
|
|
57
|
-
fs.writeFileSync('seed.txt', seed); // Readable by any process
|
|
58
|
-
fs.writeFileSync('.env', `XBIND_SEED=${seed}`); // Committed to git by accident
|
|
59
|
-
localStorage.setItem('seed', seed); // Accessible to XSS attacks
|
|
60
|
-
|
|
61
|
-
// ❌ WRONG: Hardcoded in source code
|
|
62
|
-
const agent = await Agent.fromSeed('0123456789abcdef...'); // Visible in repository
|
|
63
|
-
|
|
64
|
-
// ❌ WRONG: Unencrypted database
|
|
65
|
-
await db.run('INSERT INTO config VALUES (?, ?)', ['seed', seed]); // SQL injection risk
|
|
66
|
-
```
|
|
67
|
-
<!-- /ANTI-PATTERN -->
|
|
68
|
-
|
|
69
|
-
**Why this is critical:**
|
|
70
|
-
- **Identity Theft**: Attacker gains your DID and can impersonate your agent
|
|
71
|
-
- **Message Decryption**: All past and future messages can be decrypted
|
|
72
|
-
- **Billing Fraud**: Attacker can exhaust your quota or make unauthorized charges
|
|
73
|
-
- **Post-Quantum Broken**: ML-KEM and ML-DSA offer no protection if seed is leaked
|
|
74
|
-
|
|
75
|
-
### ✅ Use OS-Level Keystore APIs
|
|
76
|
-
|
|
77
|
-
**Recommended secure storage by platform:**
|
|
78
|
-
|
|
79
|
-
#### macOS: Keychain Services
|
|
80
|
-
|
|
81
|
-
<!-- SNIPPET -->
|
|
82
|
-
```typescript
|
|
83
|
-
import { exec } from 'node:child_process';
|
|
84
|
-
import { promisify } from 'node:util';
|
|
85
|
-
const execAsync = promisify(exec);
|
|
86
|
-
|
|
87
|
-
// Store seed in macOS Keychain
|
|
88
|
-
async function storeSeed(seed: string): Promise<void> {
|
|
89
|
-
await execAsync(
|
|
90
|
-
`security add-generic-password -a xbind -s "xBind Agent Seed" -w "${seed}" -U`
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Retrieve seed from macOS Keychain
|
|
95
|
-
async function getSeed(): Promise<string> {
|
|
96
|
-
const { stdout } = await execAsync(
|
|
97
|
-
'security find-generic-password -a xbind -s "xBind Agent Seed" -w'
|
|
98
|
-
);
|
|
99
|
-
return stdout.trim();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Create agent from keychain
|
|
103
|
-
import { Agent, HttpTrustRegistry, HttpsTransportAdapter } from '@private.me/xbind';
|
|
104
|
-
|
|
105
|
-
const seed = await getSeed();
|
|
106
|
-
const result = await Agent.fromSeed(Buffer.from(seed, 'hex'), {
|
|
107
|
-
registry: new HttpTrustRegistry({ baseUrl: 'https://private.me/registry' }),
|
|
108
|
-
transport: new HttpsTransportAdapter({ baseUrl: 'https://private.me/relay' }),
|
|
109
|
-
postQuantumSig: false
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
if (!result.ok) {
|
|
113
|
-
throw new Error(`Failed to create agent: ${result.error.message}`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const agent = result.value;
|
|
117
|
-
```
|
|
118
|
-
<!-- /SNIPPET -->
|
|
119
|
-
|
|
120
|
-
#### Windows: Credential Manager (DPAPI)
|
|
121
|
-
|
|
122
|
-
<!-- SNIPPET -->
|
|
123
|
-
```typescript
|
|
124
|
-
// Using keytar package for cross-platform keychain access
|
|
125
|
-
import keytar from 'keytar';
|
|
126
|
-
|
|
127
|
-
// Store seed in Windows Credential Manager
|
|
128
|
-
await keytar.setPassword('xbind', 'agent-seed', seed);
|
|
129
|
-
|
|
130
|
-
// Retrieve seed from Windows Credential Manager
|
|
131
|
-
import { Agent, HttpTrustRegistry, HttpsTransportAdapter } from '@private.me/xbind';
|
|
132
|
-
|
|
133
|
-
const seed = await keytar.getPassword('xbind', 'agent-seed');
|
|
134
|
-
if (!seed) throw new Error('Seed not found in credential store');
|
|
135
|
-
|
|
136
|
-
const result = await Agent.fromSeed(Buffer.from(seed, 'hex'), {
|
|
137
|
-
registry: new HttpTrustRegistry({ baseUrl: 'https://private.me/registry' }),
|
|
138
|
-
transport: new HttpsTransportAdapter({ baseUrl: 'https://private.me/relay' }),
|
|
139
|
-
postQuantumSig: false
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
if (!result.ok) {
|
|
143
|
-
throw new Error(`Failed to create agent: ${result.error.message}`);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const agent = result.value;
|
|
147
|
-
```
|
|
148
|
-
<!-- /SNIPPET -->
|
|
149
|
-
|
|
150
|
-
#### Linux: Secret Service API (gnome-keyring, KWallet)
|
|
151
|
-
|
|
152
|
-
<!-- SNIPPET -->
|
|
153
|
-
```typescript
|
|
154
|
-
import keytar from 'keytar';
|
|
155
|
-
|
|
156
|
-
// Store seed in Secret Service (libsecret)
|
|
157
|
-
await keytar.setPassword('xbind', 'agent-seed', seed);
|
|
158
|
-
|
|
159
|
-
// Retrieve seed from Secret Service
|
|
160
|
-
import { Agent, HttpTrustRegistry, HttpsTransportAdapter } from '@private.me/xbind';
|
|
161
|
-
|
|
162
|
-
const seed = await keytar.getPassword('xbind', 'agent-seed');
|
|
163
|
-
if (!seed) throw new Error('Seed not found in Secret Service');
|
|
164
|
-
|
|
165
|
-
const result = await Agent.fromSeed(Buffer.from(seed, 'hex'), {
|
|
166
|
-
registry: new HttpTrustRegistry({ baseUrl: 'https://private.me/registry' }),
|
|
167
|
-
transport: new HttpsTransportAdapter({ baseUrl: 'https://private.me/relay' }),
|
|
168
|
-
postQuantumSig: false
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
if (!result.ok) {
|
|
172
|
-
throw new Error(`Failed to create agent: ${result.error.message}`);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const agent = result.value;
|
|
176
|
-
```
|
|
177
|
-
<!-- /SNIPPET -->
|
|
178
|
-
|
|
179
|
-
**Cross-platform library:**
|
|
180
|
-
```bash
|
|
181
|
-
npm install keytar # Unified API for macOS/Windows/Linux keystores
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
### 🏢 Production: Hardware Security Modules (HSM)
|
|
185
|
-
|
|
186
|
-
For production deployments with compliance requirements (PCI-DSS, HIPAA, SOC 2):
|
|
187
|
-
|
|
188
|
-
<!-- SNIPPET -->
|
|
189
|
-
```typescript
|
|
190
|
-
// Using AWS CloudHSM or Azure Key Vault
|
|
191
|
-
import { KMSClient, DecryptCommand } from '@aws-sdk/client-kms';
|
|
192
|
-
|
|
193
|
-
const kms = new KMSClient({ region: 'us-west-2' });
|
|
194
|
-
|
|
195
|
-
// Encrypt seed with KMS (one-time setup)
|
|
196
|
-
const encryptedSeed = await kms.send(new EncryptCommand({
|
|
197
|
-
KeyId: 'arn:aws:kms:us-west-2:...',
|
|
198
|
-
Plaintext: Buffer.from(seed)
|
|
199
|
-
}));
|
|
200
|
-
|
|
201
|
-
// Store encrypted seed in database (safe)
|
|
202
|
-
await db.run('INSERT INTO config VALUES (?, ?)', ['seed', encryptedSeed.CiphertextBlob]);
|
|
203
|
-
|
|
204
|
-
// Decrypt seed with KMS at runtime
|
|
205
|
-
import { Agent, HttpTrustRegistry, HttpsTransportAdapter } from '@private.me/xbind';
|
|
206
|
-
|
|
207
|
-
const decryptedSeed = await kms.send(new DecryptCommand({
|
|
208
|
-
CiphertextBlob: encryptedSeedFromDB
|
|
209
|
-
}));
|
|
210
|
-
|
|
211
|
-
const result = await Agent.fromSeed(Buffer.from(decryptedSeed.Plaintext), {
|
|
212
|
-
registry: new HttpTrustRegistry({ baseUrl: 'https://private.me/registry' }),
|
|
213
|
-
transport: new HttpsTransportAdapter({ baseUrl: 'https://private.me/relay' }),
|
|
214
|
-
postQuantumSig: false
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
if (!result.ok) {
|
|
218
|
-
throw new Error(`Failed to create agent: ${result.error.message}`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const agent = result.value;
|
|
222
|
-
```
|
|
223
|
-
<!-- /SNIPPET -->
|
|
224
|
-
|
|
225
|
-
**HSM Benefits:**
|
|
226
|
-
- **FIPS 140-2 Level 3** certified hardware
|
|
227
|
-
- **Tamper-evident**: Keys destroyed if physical breach detected
|
|
228
|
-
- **Audit logging**: All key access operations logged
|
|
229
|
-
- **Access control**: IAM policies restrict who can decrypt
|
|
230
|
-
|
|
231
|
-
### 📋 Key Storage Best Practices
|
|
232
|
-
|
|
233
|
-
1. **Encrypt at Rest**: If storing in database/filesystem, use AES-256-GCM with a separate encryption key
|
|
234
|
-
2. **Least Privilege**: Only the agent process should have access to the seed
|
|
235
|
-
3. **Rotation**: Plan for key rotation (see Succession API section)
|
|
236
|
-
4. **Backup**: Encrypted backups to separate storage (3-2-1 rule)
|
|
237
|
-
5. **Monitoring**: Alert on unauthorized seed access attempts
|
|
238
|
-
6. **Destruction**: Securely wipe seeds when decommissioning agents
|
|
239
|
-
|
|
240
|
-
### 🔒 Environment Variable Security
|
|
241
|
-
|
|
242
|
-
If you MUST use environment variables (not recommended):
|
|
243
|
-
|
|
244
|
-
```bash
|
|
245
|
-
# ✅ Better: Encrypted environment variable (AWS Secrets Manager)
|
|
246
|
-
export XBIND_SEED=$(aws secretsmanager get-secret-value --secret-id xbind-seed --query SecretString --output text)
|
|
247
|
-
|
|
248
|
-
# ❌ Avoid: Plaintext in shell history
|
|
249
|
-
export XBIND_SEED="0123456789abcdef..." # Visible in ~/.bash_history
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
**Limitations of environment variables:**
|
|
253
|
-
- Visible to all processes (ps, /proc/PID/environ)
|
|
254
|
-
- Logged by process managers (systemd, Docker logs)
|
|
255
|
-
- Inherited by child processes
|
|
256
|
-
- Difficult to rotate without restart
|
|
257
|
-
|
|
258
|
-
### 🚨 Incident Response
|
|
259
|
-
|
|
260
|
-
**If your seed is compromised:**
|
|
261
|
-
|
|
262
|
-
1. **Revoke immediately**: Use the Succession API to rotate to a new identity
|
|
263
|
-
2. **Audit access**: Check all messages sent/received during exposure window
|
|
264
|
-
3. **Notify recipients**: Inform peers to distrust the old DID
|
|
265
|
-
4. **Update registry**: Register new DID, revoke old DID
|
|
266
|
-
5. **Forensics**: Determine how seed was leaked to prevent recurrence
|
|
267
|
-
|
|
268
|
-
**Contact contact@private.me for incident assistance** (24-hour SLA for Pro/VIP tiers).
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## Dependencies
|
|
273
|
-
|
|
274
|
-
xBind requires the following runtime dependencies for cryptographic operations and network communication:
|
|
275
|
-
|
|
276
|
-
### Post-Quantum Cryptography
|
|
277
|
-
|
|
278
|
-
- **mlkem** — Post-quantum key encapsulation mechanism (ML-KEM-768, FIPS 203)
|
|
279
|
-
- Purpose: Quantum-resistant key agreement for message encryption
|
|
280
|
-
- Security: NIST-approved lattice-based cryptography, 192-bit security level
|
|
281
|
-
- Usage: Establishes shared secrets between agents resistant to quantum attacks
|
|
282
|
-
|
|
283
|
-
- **mldsa-wasm@0.0.4** — Post-quantum digital signatures (ML-DSA-65, FIPS 204)
|
|
284
|
-
- Purpose: Quantum-resistant DID identity and message signing
|
|
285
|
-
- Security: NIST-approved lattice-based signatures, 192-bit security level
|
|
286
|
-
- Usage: Signs all agent messages and verifies peer identity
|
|
287
|
-
|
|
288
|
-
### Network Communication
|
|
289
|
-
|
|
290
|
-
- **bonjour-service** — mDNS service discovery (Peer Discovery model)
|
|
291
|
-
- Purpose: Zero-configuration local network device pairing
|
|
292
|
-
- Security: LAN-only discovery with user confirmation and cryptographic verification
|
|
293
|
-
- Usage: Enables IoT devices and offline pairing without internet connectivity
|
|
294
|
-
|
|
295
|
-
- **nodemailer@8.0.7** — Email transport for invitation delivery
|
|
296
|
-
- Purpose: Delivers single-use invite codes for customer onboarding
|
|
297
|
-
- Security: 6-character codes with 24-hour TTL, rate-limited generation
|
|
298
|
-
- Usage: Supports Invite Code connection model for remote agent pairing
|
|
299
|
-
|
|
300
|
-
### Internal Dependencies (Bundled)
|
|
301
|
-
|
|
302
|
-
The following @private.me/* packages are bundled into xBind's distribution and do not require separate installation:
|
|
303
|
-
|
|
304
|
-
- **@private.me/shared** — Core types and Result<T,E> error handling primitives
|
|
305
|
-
- **@private.me/crypto** — XorIDA threshold sharing, HMAC verification, cryptographic primitives
|
|
306
|
-
- **@private.me/xchange** — Transport envelope formatting and message serialization
|
|
307
|
-
- **@private.me/ux-helpers** — Abuse prevention and rate limiting utilities
|
|
308
|
-
- **@private.me/xregistry** — Trust registry interface and DID resolution
|
|
309
|
-
|
|
310
|
-
These dependencies are compiled into `dist-standalone/` with relative import paths. Users install xBind as a single package - no separate installation of building blocks required.
|
|
311
|
-
|
|
312
|
-
All cryptographic dependencies are production-grade implementations. No test or mock crypto is used in production builds.
|
|
313
|
-
|
|
314
|
-
## Setup & Configuration
|
|
315
|
-
|
|
316
|
-
### Environment Variables
|
|
317
|
-
|
|
318
|
-
#### FULL_CONTROL_MASTER_KEY (Required)
|
|
319
|
-
|
|
320
|
-
**Critical for Production:** This key is required for Share 2 decryption in the Full Control vault store. Without it, the package cannot access proprietary XorIDA algorithms.
|
|
321
|
-
|
|
322
|
-
```bash
|
|
323
|
-
# Generate a new key (one-time setup)
|
|
324
|
-
openssl rand -base64 32
|
|
325
|
-
|
|
326
|
-
# Set in your environment
|
|
327
|
-
export FULL_CONTROL_MASTER_KEY="<generated-key-here>"
|
|
328
|
-
|
|
329
|
-
# Verify length (should be 44 characters)
|
|
330
|
-
echo ${#FULL_CONTROL_MASTER_KEY}
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
**Key Details:**
|
|
334
|
-
- **Purpose:** Master key for Share 2 decryption in Full Control vault store
|
|
335
|
-
- **Format:** 32-byte random value, base64-encoded (44 characters)
|
|
336
|
-
- **When Required:**
|
|
337
|
-
- ✅ Required in production for Full Control operations
|
|
338
|
-
- ✅ Required for server health checks to pass
|
|
339
|
-
- ⚠️ Optional for basic testing (package will use fallback behavior)
|
|
340
|
-
- **Security:** Store in `.env` file with `chmod 600` permissions
|
|
341
|
-
- **Validation:** Server health check at `/aci/billing/health` validates this key
|
|
342
|
-
|
|
343
|
-
**Troubleshooting:**
|
|
344
|
-
|
|
345
|
-
If you see errors like `FULL_CONTROL_MASTER_KEY not configured` or `Share 2 decryption failed`:
|
|
346
|
-
1. Verify the key is set: `echo $FULL_CONTROL_MASTER_KEY`
|
|
347
|
-
2. Check the length is exactly 44 characters
|
|
348
|
-
3. Ensure `.env` file is loaded (if using dotenv)
|
|
349
|
-
4. Verify file permissions: `chmod 600 .env`
|
|
350
|
-
5. For production deployments, confirm the key is set in your deployment configuration
|
|
351
|
-
|
|
352
|
-
See [Configuration Guide](./docs/configuration.md) for complete setup instructions and advanced configuration options.
|
|
353
|
-
|
|
354
|
-
## Pricing
|
|
355
|
-
|
|
356
|
-
**Free tier available** — No credit card required.
|
|
357
|
-
|
|
358
|
-
See [pricing details](../../docs/pricing-reference.md) for current rates and tier comparison.
|
|
359
|
-
|
|
360
|
-
[Subscribe now](https://private.me/subscribe?product=xbind)
|
|
361
|
-
|
|
362
|
-
## Quick Start
|
|
363
|
-
|
|
364
|
-
**Complete setup in under 2 minutes:**
|
|
365
|
-
|
|
366
|
-
### Step 1: Email Verification (Required)
|
|
367
|
-
|
|
368
|
-
**ALL API calls are blocked until you verify your email address.** This links your usage to a verified contact for security notifications and billing.
|
|
369
|
-
|
|
370
|
-
```bash
|
|
371
|
-
npx xbind setup --email user@example.com
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
**What happens:**
|
|
375
|
-
1. **DID Generation**: Creates Ed25519 cryptographic identity (did:key:z6Mk...)
|
|
376
|
-
2. **DeploymentID Creation**: Generates persistent economic identity (DEP-202605-XXXXXXXXXX)
|
|
377
|
-
3. **Email Code Delivery**: Sends 6-digit verification code to your email
|
|
378
|
-
4. **Code Verification**: Enter code to link email to DeploymentID
|
|
379
|
-
5. **Identity Storage**: Saves to `~/.xbind/identity.json` (chmod 600)
|
|
380
|
-
6. **Ready to Use**: No additional configuration needed
|
|
381
|
-
|
|
382
|
-
**Dual-Mode Verification:**
|
|
383
|
-
- **CLI/Programmatic**: 6-digit code (this method)
|
|
384
|
-
- **Web/Browser**: Magic link (auto-verifies on click)
|
|
385
|
-
|
|
386
|
-
**Command Options:**
|
|
387
|
-
```bash
|
|
388
|
-
npx xbind setup --email user@example.com # Standard setup
|
|
389
|
-
npx xbind setup --email user@example.com --force # Overwrite existing identity
|
|
390
|
-
npx xbind setup --dev # Development mode (mock email provider)
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
**Security Notes:**
|
|
394
|
-
- Disposable email services blocked (Mailinator, Guerrilla Mail, etc.)
|
|
395
|
-
- Device fingerprinting active (100+ signals for abuse prevention)
|
|
396
|
-
- DID ≠ DeploymentID (see Identity Model section below)
|
|
397
|
-
|
|
398
|
-
---
|
|
399
|
-
|
|
400
|
-
### Identity Model: DID vs DeploymentID
|
|
401
|
-
|
|
402
|
-
**Two complementary identities for different purposes:**
|
|
403
|
-
|
|
404
|
-
#### DID (Decentralized Identifier)
|
|
405
|
-
- **Format**: `did:key:z6Mk...` (Ed25519 public key)
|
|
406
|
-
- **Purpose**: Cryptographic authentication (message signing)
|
|
407
|
-
- **Lifespan**: Ephemeral - can be rotated for security
|
|
408
|
-
- **Use case**: Proving "I sent this message"
|
|
409
|
-
- **Storage**: `~/.xbind/identity.json` (local only)
|
|
410
|
-
|
|
411
|
-
#### DeploymentID (Persistent Economic Identity)
|
|
412
|
-
- **Format**: `DEP-YYYYMM-XXXXXXXXXX` (month prefix + 10 hex digits)
|
|
413
|
-
- **Purpose**: Billing and usage tracking (persistent across DIDs)
|
|
414
|
-
- **Lifespan**: Permanent - never changes for your account
|
|
415
|
-
- **Use case**: "This deployment used 50K operations this month"
|
|
416
|
-
- **Prevents**: Economic state reset attacks (DID rotation to bypass usage limits)
|
|
417
|
-
|
|
418
|
-
**Why Both?**
|
|
419
|
-
- **Security**: Rotate DID without losing billing history
|
|
420
|
-
- **Privacy**: DID is pseudonymous, DeploymentID links to verified email
|
|
421
|
-
- **Billing**: Usage tracked by DeploymentID, even if DID changes
|
|
422
|
-
- **Attack Prevention**: Cannot reset free tier quota by generating new DID
|
|
423
|
-
|
|
424
|
-
**Example:**
|
|
425
|
-
```
|
|
426
|
-
User creates account:
|
|
427
|
-
- DID: did:key:z6MkABC123... (for signing messages)
|
|
428
|
-
- DeploymentID: DEP-202605-7F3A2B1C (for billing)
|
|
429
|
-
|
|
430
|
-
User rotates DID for security:
|
|
431
|
-
- DID: did:key:z6MkXYZ789... (NEW cryptographic identity)
|
|
432
|
-
- DeploymentID: DEP-202605-7F3A2B1C (SAME billing identity)
|
|
433
|
-
- Usage history: Preserved ✅
|
|
434
|
-
- Free tier quota: Cannot reset ✅
|
|
435
|
-
```
|
|
436
|
-
|
|
437
|
-
---
|
|
438
|
-
|
|
439
|
-
### Device Fingerprinting & Privacy
|
|
440
|
-
|
|
441
|
-
**xBind collects device fingerprints for abuse prevention:**
|
|
442
|
-
|
|
443
|
-
**What We Collect (100+ Signals):**
|
|
444
|
-
1. **Browser**: User agent, language, timezone, screen resolution
|
|
445
|
-
2. **OS**: Platform, CPU cores, memory (approximate)
|
|
446
|
-
3. **Hardware**: GPU vendor, audio context, canvas fingerprint
|
|
447
|
-
4. **Network**: IP address (hashed), connection type
|
|
448
|
-
5. **Behavior**: Timing patterns, interaction signals
|
|
449
|
-
6. **Fonts**: Installed font list (system fingerprint)
|
|
450
|
-
|
|
451
|
-
**Why We Collect:**
|
|
452
|
-
- Detect multi-accounting (creating unlimited free accounts)
|
|
453
|
-
- Identify coordinated abuse patterns
|
|
454
|
-
- Link DeploymentIDs across devices (same user, different machines)
|
|
455
|
-
- Risk scoring (0-100 scale, manual review ≥70)
|
|
456
|
-
|
|
457
|
-
**Privacy Protections:**
|
|
458
|
-
- **SHA-256 hashed**: Fingerprints stored as hashes, not raw data
|
|
459
|
-
- **No PII**: Individual signals don't identify you personally
|
|
460
|
-
- **GDPR compliant**: Right to access, deletion, opt-out
|
|
461
|
-
- **Minimization**: Only signals necessary for abuse detection
|
|
462
|
-
- **Retention**: 90 days for fingerprints, 30 days for raw signals
|
|
463
|
-
|
|
464
|
-
**Opt-Out:**
|
|
465
|
-
Email contact@private.me with subject "Fingerprint Opt-Out" and your DeploymentID. Note: Opting out may trigger manual review for new accounts.
|
|
466
|
-
|
|
467
|
-
**Transparency:**
|
|
468
|
-
Full fingerprinting source code available at `apps/server/src/device-fingerprinting.ts`
|
|
469
|
-
|
|
470
|
-
**Note:** Disposable email services (Mailinator, Guerrilla Mail, etc.) are blocked. Use a real email address.
|
|
471
|
-
|
|
472
|
-
### Step 2: Create Agent & Send Messages
|
|
473
|
-
|
|
474
|
-
```typescript
|
|
475
|
-
import { Agent } from '@private.me/xbind';
|
|
476
|
-
|
|
477
|
-
// Create agent (auto-generates cryptographic identity, throws on error)
|
|
478
|
-
const agent = await Agent.quickstart({ name: 'my-service' });
|
|
479
|
-
|
|
480
|
-
// Send authenticated message
|
|
481
|
-
const sendResult = await agent.send({
|
|
482
|
-
to: 'did:key:z6Mk...', // recipient DID
|
|
483
|
-
payload: { action: 'createCharge', amount: 100 },
|
|
484
|
-
scope: 'billing'
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
if (!sendResult.ok) {
|
|
488
|
-
console.error(`Failed: ${sendResult.error}`);
|
|
489
|
-
return;
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
console.log('Message sent with cryptographic identity');
|
|
493
|
-
console.log('Agent DID:', agent.did);
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
### Step 3: Understand Your Free Tier
|
|
497
|
-
|
|
498
|
-
- **100,000 operations/month** (free tier)
|
|
499
|
-
- **120,000 hard cap** (20% grace buffer)
|
|
500
|
-
- **Monthly reset:** 1st of each month at 00:00 UTC
|
|
501
|
-
- **Milestone emails:** Sent at 50%, 80%, 100%, 120% usage
|
|
502
|
-
|
|
503
|
-
**At 100K operations:** Email verification enforced (if not already verified)
|
|
504
|
-
**At 120K operations:** Hard cap reached. Upgrade to Pro for unlimited operations.
|
|
505
|
-
|
|
506
|
-
**Prerequisites:** The `FULL_CONTROL_MASTER_KEY` environment variable is required for Share 2 operations in production but optional for basic testing. See [Environment Variables](#environment-variables) for setup.
|
|
507
|
-
|
|
508
|
-
**JITR (Just-in-Time Registration):** Agents created with `Agent.fromSeed()` automatically register with the trust registry on first use. No manual registration scripts required. Includes all encryption keys (Ed25519, X25519, ML-KEM, ML-DSA) for zero-config encrypted messaging.
|
|
509
|
-
|
|
510
|
-
[More examples](./docs/examples.md) • [Python examples](./python/README.md)
|
|
511
|
-
|
|
512
|
-
## Programmatic Quickstart
|
|
513
|
-
|
|
514
|
-
**Complete, copy-paste ready examples** tested in clean environments:
|
|
515
|
-
|
|
516
|
-
### Example 1: Create Agent & Get DID
|
|
517
|
-
|
|
518
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
519
|
-
```typescript
|
|
520
|
-
import { Agent } from '@private.me/xbind';
|
|
521
|
-
|
|
522
|
-
// Create agent with automatic identity generation
|
|
523
|
-
const agent = await Agent.quickstart({ name: 'test-agent' });
|
|
524
|
-
|
|
525
|
-
console.log('Agent DID:', agent.did);
|
|
526
|
-
console.log('Agent name:', agent.name);
|
|
527
|
-
```
|
|
528
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
529
|
-
|
|
530
|
-
**Expected output:**
|
|
531
|
-
```
|
|
532
|
-
Agent DID: did:key:z6Mk...
|
|
533
|
-
Agent name: test-agent
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
### Example 2: Agent Identity Details
|
|
537
|
-
|
|
538
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
539
|
-
```typescript
|
|
540
|
-
import { Agent } from '@private.me/xbind';
|
|
541
|
-
|
|
542
|
-
// Create agent
|
|
543
|
-
const agent = await Agent.quickstart({ name: 'identity-test' });
|
|
544
|
-
|
|
545
|
-
// Access identity information
|
|
546
|
-
console.log('DID:', agent.did);
|
|
547
|
-
console.log('Has Ed25519 keys:', !!agent.identity.publicKey);
|
|
548
|
-
console.log('Has X25519 keys:', !!agent.identity.x25519PublicKey);
|
|
549
|
-
console.log('Has ML-KEM keys:', !!agent.identity.mlKemPublicKey);
|
|
550
|
-
```
|
|
551
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
552
|
-
|
|
553
|
-
**Expected output:**
|
|
554
|
-
```
|
|
555
|
-
DID: did:key:z6Mk...
|
|
556
|
-
Has Ed25519 keys: true
|
|
557
|
-
Has X25519 keys: true
|
|
558
|
-
Has ML-KEM keys: true
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
### Example 3: Registry & Transport Configuration
|
|
562
|
-
|
|
563
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
564
|
-
```typescript
|
|
565
|
-
import { Agent } from '@private.me/xbind';
|
|
566
|
-
|
|
567
|
-
// Quickstart uses defaults: MemoryRegistry + HttpsTransport
|
|
568
|
-
const agent = await Agent.quickstart({ name: 'config-test' });
|
|
569
|
-
|
|
570
|
-
// Check configuration
|
|
571
|
-
console.log('Registry type:', agent.registry.constructor.name);
|
|
572
|
-
console.log('Transports count:', agent.transports.length);
|
|
573
|
-
console.log('Transport type:', agent.transports[0].constructor.name);
|
|
574
|
-
```
|
|
575
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
576
|
-
|
|
577
|
-
**Expected output:**
|
|
578
|
-
```
|
|
579
|
-
Registry type: MemoryTrustRegistry
|
|
580
|
-
Transports count: 1
|
|
581
|
-
Transport type: HttpsTransportAdapter
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
**Note:** These examples work immediately after `npm install @private.me/xbind`. Email verification is NOT required for basic agent creation and local operations. Verification is enforced when:
|
|
585
|
-
- Sending messages to other agents
|
|
586
|
-
- Exceeding 100K operations/month
|
|
587
|
-
- Accessing production features
|
|
588
|
-
|
|
589
|
-
[More examples](./docs/examples.md) • [Python examples](./python/README.md)
|
|
590
|
-
|
|
591
|
-
## Post-Quantum Cryptography & Envelopes
|
|
592
|
-
|
|
593
|
-
**Complete examples for ML-DSA signatures, key export, and envelope operations:**
|
|
594
|
-
|
|
595
|
-
### Example 4: ML-DSA-65 Signing and Verification
|
|
596
|
-
|
|
597
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
598
|
-
```typescript
|
|
599
|
-
import { Agent, signMlDsa65, verifyMlDsa65 } from '@private.me/xbind';
|
|
600
|
-
|
|
601
|
-
// Create agent with post-quantum signatures enabled
|
|
602
|
-
const agent = await Agent.quickstart({
|
|
603
|
-
name: 'pq-test',
|
|
604
|
-
postQuantumSig: true
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
// Sign data with ML-DSA-65
|
|
608
|
-
const data = new TextEncoder().encode('Critical transaction data');
|
|
609
|
-
const mlDsaSecretKey = agent.identity.mlDsaSecretKey;
|
|
610
|
-
|
|
611
|
-
if (!mlDsaSecretKey) {
|
|
612
|
-
throw new Error('ML-DSA keys not available');
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
const signResult = await signMlDsa65(mlDsaSecretKey, data);
|
|
616
|
-
if (!signResult.ok) {
|
|
617
|
-
throw new Error(`Signing failed: ${signResult.error}`);
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
console.log('ML-DSA-65 signature length:', signResult.value.length); // 3309 bytes
|
|
621
|
-
|
|
622
|
-
// Verify signature
|
|
623
|
-
const mlDsaPublicKey = agent.identity.mlDsaPublicKey!;
|
|
624
|
-
const verifyResult = await verifyMlDsa65(mlDsaPublicKey, signResult.value, data);
|
|
625
|
-
|
|
626
|
-
if (verifyResult.ok && verifyResult.value) {
|
|
627
|
-
console.log('Post-quantum signature verified successfully');
|
|
628
|
-
} else {
|
|
629
|
-
console.error('Signature verification failed');
|
|
630
|
-
}
|
|
631
|
-
```
|
|
632
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
633
|
-
|
|
634
|
-
**Expected output:**
|
|
635
|
-
```
|
|
636
|
-
ML-DSA-65 signature length: 3309
|
|
637
|
-
Post-quantum signature verified successfully
|
|
638
|
-
```
|
|
639
|
-
|
|
640
|
-
### Example 5: Export Post-Quantum Keys
|
|
641
|
-
|
|
642
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
643
|
-
```typescript
|
|
644
|
-
import {
|
|
645
|
-
Agent,
|
|
646
|
-
exportMlDsaSecretKey,
|
|
647
|
-
exportMlDsaPublicKey,
|
|
648
|
-
exportMlKemSecretKey,
|
|
649
|
-
exportMlKemPublicKey
|
|
650
|
-
} from '@private.me/xbind';
|
|
651
|
-
|
|
652
|
-
// Create agent with post-quantum cryptography
|
|
653
|
-
const agent = await Agent.quickstart({
|
|
654
|
-
name: 'export-test',
|
|
655
|
-
postQuantumSig: true
|
|
656
|
-
});
|
|
657
|
-
|
|
658
|
-
// Export ML-DSA keys (signatures)
|
|
659
|
-
const mlDsaSecret = exportMlDsaSecretKey(agent.identity);
|
|
660
|
-
const mlDsaPublic = exportMlDsaPublicKey(agent.identity);
|
|
661
|
-
|
|
662
|
-
console.log('ML-DSA-65 secret key:', mlDsaSecret ? `${mlDsaSecret.length} bytes` : 'N/A');
|
|
663
|
-
console.log('ML-DSA-65 public key:', mlDsaPublic ? `${mlDsaPublic.length} bytes` : 'N/A');
|
|
664
|
-
|
|
665
|
-
// Export ML-KEM keys (encryption)
|
|
666
|
-
const mlKemSecret = exportMlKemSecretKey(agent.identity);
|
|
667
|
-
const mlKemPublic = exportMlKemPublicKey(agent.identity);
|
|
668
|
-
|
|
669
|
-
console.log('ML-KEM-768 secret key:', mlKemSecret ? `${mlKemSecret.length} bytes` : 'N/A');
|
|
670
|
-
console.log('ML-KEM-768 public key:', mlKemPublic ? `${mlKemPublic.length} bytes` : 'N/A');
|
|
671
|
-
```
|
|
672
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
673
|
-
|
|
674
|
-
**Expected output:**
|
|
675
|
-
```
|
|
676
|
-
ML-DSA-65 secret key: 32 bytes
|
|
677
|
-
ML-DSA-65 public key: 1952 bytes
|
|
678
|
-
ML-KEM-768 secret key: 2400 bytes
|
|
679
|
-
ML-KEM-768 public key: 1184 bytes
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
### Example 6: Key Rotation with Backward Compatibility
|
|
683
|
-
|
|
684
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
685
|
-
```typescript
|
|
686
|
-
import { Agent, rotateKeys } from '@private.me/xbind';
|
|
687
|
-
|
|
688
|
-
// Create agent
|
|
689
|
-
const agent = await Agent.quickstart({ name: 'rotation-test' });
|
|
690
|
-
|
|
691
|
-
// Store original X25519 public key
|
|
692
|
-
const originalX25519 = Buffer.from(agent.identity.rawX25519PublicKey).toString('hex');
|
|
693
|
-
|
|
694
|
-
// Rotate encryption keys (X25519 + ML-KEM)
|
|
695
|
-
const rotatedResult = await rotateKeys(agent.identity);
|
|
696
|
-
|
|
697
|
-
if (!rotatedResult.ok) {
|
|
698
|
-
throw new Error(`Key rotation failed: ${rotatedResult.error}`);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
const rotatedIdentity = rotatedResult.value;
|
|
702
|
-
|
|
703
|
-
// New keys are active
|
|
704
|
-
const newX25519 = Buffer.from(rotatedIdentity.rawX25519PublicKey).toString('hex');
|
|
705
|
-
console.log('Keys rotated successfully');
|
|
706
|
-
console.log('Original X25519:', originalX25519.substring(0, 16) + '...');
|
|
707
|
-
console.log('New X25519:', newX25519.substring(0, 16) + '...');
|
|
708
|
-
|
|
709
|
-
// Old keys preserved for decryption
|
|
710
|
-
console.log('Rotation history:', rotatedIdentity.rotatedKeys?.length ?? 0);
|
|
711
|
-
console.log('DID unchanged:', agent.identity.did === rotatedIdentity.did);
|
|
712
|
-
```
|
|
713
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
714
|
-
|
|
715
|
-
**Expected output:**
|
|
716
|
-
```
|
|
717
|
-
Keys rotated successfully
|
|
718
|
-
Original X25519: a1b2c3d4e5f6g7h8...
|
|
719
|
-
New X25519: 9i0j1k2l3m4n5o6p...
|
|
720
|
-
Rotation history: 1
|
|
721
|
-
DID unchanged: true
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### Example 7: Create V1 Envelope (Classical Crypto)
|
|
725
|
-
|
|
726
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
727
|
-
```typescript
|
|
728
|
-
import { Agent, createEnvelope, generateSharedKey } from '@private.me/xbind';
|
|
729
|
-
|
|
730
|
-
// Generate shared AES-256-GCM key
|
|
731
|
-
const sharedKey = await generateSharedKey();
|
|
732
|
-
|
|
733
|
-
// Create agent
|
|
734
|
-
const agent = await Agent.quickstart({ name: 'envelope-test' });
|
|
735
|
-
|
|
736
|
-
// Create encrypted envelope
|
|
737
|
-
const plaintext = new TextEncoder().encode(JSON.stringify({
|
|
738
|
-
action: 'transfer',
|
|
739
|
-
amount: 1000
|
|
740
|
-
}));
|
|
741
|
-
|
|
742
|
-
const envelopeResult = await createEnvelope({
|
|
743
|
-
senderDid: agent.did,
|
|
744
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
745
|
-
scope: 'billing:write',
|
|
746
|
-
plaintext,
|
|
747
|
-
privateKey: agent.identity.privateKey,
|
|
748
|
-
sharedKey
|
|
749
|
-
});
|
|
750
|
-
|
|
751
|
-
if (!envelopeResult.ok) {
|
|
752
|
-
throw new Error(`Envelope creation failed: ${envelopeResult.error}`);
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
const envelope = envelopeResult.value;
|
|
756
|
-
console.log('Envelope version:', envelope.v);
|
|
757
|
-
console.log('Algorithm:', envelope.alg);
|
|
758
|
-
console.log('Signature length:', envelope.signature.length);
|
|
759
|
-
console.log('Encrypted payload:', envelope.payload.substring(0, 32) + '...');
|
|
760
|
-
```
|
|
761
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
762
|
-
|
|
763
|
-
**Expected output:**
|
|
764
|
-
```
|
|
765
|
-
Envelope version: 1
|
|
766
|
-
Algorithm: Ed25519
|
|
767
|
-
Signature length: 88
|
|
768
|
-
Encrypted payload: aGVsbG8gd29ybGQgdGhpcyBpcyBhIHRl...
|
|
769
|
-
```
|
|
770
|
-
|
|
771
|
-
### Example 8: Create V2 Envelope (Hybrid KEM)
|
|
772
|
-
|
|
773
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
774
|
-
```typescript
|
|
775
|
-
import { Agent, createEnvelopeV2, generateSharedKey } from '@private.me/xbind';
|
|
776
|
-
import { createMlKem768 } from 'mlkem';
|
|
777
|
-
|
|
778
|
-
// Generate shared AES-256-GCM key
|
|
779
|
-
const sharedKey = await generateSharedKey();
|
|
780
|
-
|
|
781
|
-
// Generate ephemeral X25519 keypair
|
|
782
|
-
const x25519Pair = await crypto.subtle.generateKey(
|
|
783
|
-
{ name: 'X25519' },
|
|
784
|
-
true,
|
|
785
|
-
['deriveBits']
|
|
786
|
-
);
|
|
787
|
-
const ephemeralPub = new Uint8Array(
|
|
788
|
-
await crypto.subtle.exportKey('raw', x25519Pair.publicKey)
|
|
789
|
-
);
|
|
790
|
-
|
|
791
|
-
// Generate ML-KEM-768 ciphertext (mocked for example)
|
|
792
|
-
const mlkem = await createMlKem768();
|
|
793
|
-
const recipientMlKemPub = mlkem.generateKeyPair()[0]; // Mock recipient public key
|
|
794
|
-
const [kemCiphertext] = mlkem.encap(recipientMlKemPub);
|
|
795
|
-
|
|
796
|
-
const agent = await Agent.quickstart({ name: 'v2-envelope-test' });
|
|
797
|
-
|
|
798
|
-
const envelope = await createEnvelopeV2({
|
|
799
|
-
senderDid: agent.did,
|
|
800
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
801
|
-
scope: 'messaging',
|
|
802
|
-
plaintext: new TextEncoder().encode('Hybrid KEM message'),
|
|
803
|
-
privateKey: agent.identity.privateKey,
|
|
804
|
-
sharedKey,
|
|
805
|
-
ephemeralPublicKey: ephemeralPub,
|
|
806
|
-
kemCiphertext
|
|
807
|
-
});
|
|
808
|
-
|
|
809
|
-
if (envelope.ok) {
|
|
810
|
-
console.log('Envelope version:', envelope.value.v);
|
|
811
|
-
console.log('KEM mode:', envelope.value.kem);
|
|
812
|
-
console.log('ML-KEM ciphertext length:', envelope.value.kemCiphertext.length);
|
|
813
|
-
}
|
|
814
|
-
```
|
|
815
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
816
|
-
|
|
817
|
-
**Expected output:**
|
|
818
|
-
```
|
|
819
|
-
Envelope version: 2
|
|
820
|
-
KEM mode: X25519-MLKEM768
|
|
821
|
-
ML-KEM ciphertext length: 1452
|
|
822
|
-
```
|
|
823
|
-
|
|
824
|
-
### Example 9: Create V3 Envelope (Dual Signatures)
|
|
825
|
-
|
|
826
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
827
|
-
```typescript
|
|
828
|
-
import { Agent, createEnvelopeV3, generateSharedKey } from '@private.me/xbind';
|
|
829
|
-
import { createMlKem768 } from 'mlkem';
|
|
830
|
-
|
|
831
|
-
// Create agent with ML-DSA enabled
|
|
832
|
-
const agent = await Agent.quickstart({
|
|
833
|
-
name: 'v3-envelope-test',
|
|
834
|
-
postQuantumSig: true
|
|
835
|
-
});
|
|
836
|
-
|
|
837
|
-
if (!agent.identity.mlDsaSecretKey) {
|
|
838
|
-
throw new Error('ML-DSA keys required for V3 envelopes');
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
// Generate shared key and KEM materials
|
|
842
|
-
const sharedKey = await generateSharedKey();
|
|
843
|
-
const x25519Pair = await crypto.subtle.generateKey(
|
|
844
|
-
{ name: 'X25519' },
|
|
845
|
-
true,
|
|
846
|
-
['deriveBits']
|
|
847
|
-
);
|
|
848
|
-
const ephemeralPub = new Uint8Array(
|
|
849
|
-
await crypto.subtle.exportKey('raw', x25519Pair.publicKey)
|
|
850
|
-
);
|
|
851
|
-
|
|
852
|
-
const mlkem = await createMlKem768();
|
|
853
|
-
const recipientMlKemPub = mlkem.generateKeyPair()[0];
|
|
854
|
-
const [kemCiphertext] = mlkem.encap(recipientMlKemPub);
|
|
855
|
-
|
|
856
|
-
const envelope = await createEnvelopeV3({
|
|
857
|
-
senderDid: agent.did,
|
|
858
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
859
|
-
scope: 'high-security',
|
|
860
|
-
plaintext: new TextEncoder().encode('Dual-signature message'),
|
|
861
|
-
privateKey: agent.identity.privateKey,
|
|
862
|
-
sharedKey,
|
|
863
|
-
ephemeralPublicKey: ephemeralPub,
|
|
864
|
-
kemCiphertext,
|
|
865
|
-
mlDsaSecretKey: agent.identity.mlDsaSecretKey
|
|
866
|
-
});
|
|
867
|
-
|
|
868
|
-
if (envelope.ok) {
|
|
869
|
-
console.log('Envelope version:', envelope.value.v);
|
|
870
|
-
console.log('Signature scheme:', envelope.value.sig);
|
|
871
|
-
console.log('Ed25519 signature:', envelope.value.signature.substring(0, 16) + '...');
|
|
872
|
-
console.log('ML-DSA signature:', envelope.value.pqSignature.substring(0, 16) + '...');
|
|
873
|
-
}
|
|
874
|
-
```
|
|
875
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
876
|
-
|
|
877
|
-
**Expected output:**
|
|
878
|
-
```
|
|
879
|
-
Envelope version: 3
|
|
880
|
-
Signature scheme: Ed25519+MLDSA65
|
|
881
|
-
Ed25519 signature: SGVsbG8gd29ybGQ...
|
|
882
|
-
ML-DSA signature: cG9zdC1xdWFudHV...
|
|
883
|
-
```
|
|
884
|
-
|
|
885
|
-
### Example 10: Create V4 Envelope (Xchange Mode)
|
|
886
|
-
|
|
887
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
888
|
-
```typescript
|
|
889
|
-
import { Agent, createEnvelopeV4 } from '@private.me/xbind';
|
|
890
|
-
|
|
891
|
-
const agent = await Agent.quickstart({ name: 'xchange-test' });
|
|
892
|
-
|
|
893
|
-
// Xchange mode: Share data is the payload (no encryption layer)
|
|
894
|
-
const shareData = new TextEncoder().encode('XorIDA share data');
|
|
895
|
-
|
|
896
|
-
const envelope = await createEnvelopeV4({
|
|
897
|
-
senderDid: agent.did,
|
|
898
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
899
|
-
scope: 'xchange',
|
|
900
|
-
shareData,
|
|
901
|
-
privateKey: agent.identity.privateKey,
|
|
902
|
-
shareIndex: 0,
|
|
903
|
-
shareTotal: 3,
|
|
904
|
-
shareThreshold: 2,
|
|
905
|
-
shareGroupId: 'group-uuid-1234',
|
|
906
|
-
shareHmacKey: 'base64-hmac-key',
|
|
907
|
-
shareHmacSig: 'base64-hmac-sig'
|
|
908
|
-
});
|
|
909
|
-
|
|
910
|
-
if (envelope.ok) {
|
|
911
|
-
console.log('Envelope version:', envelope.value.v);
|
|
912
|
-
console.log('KEM mode:', envelope.value.kem);
|
|
913
|
-
console.log('Share index:', envelope.value.shareIndex);
|
|
914
|
-
console.log('Threshold:', `${envelope.value.shareThreshold}-of-${envelope.value.shareTotal}`);
|
|
915
|
-
}
|
|
916
|
-
```
|
|
917
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
918
|
-
|
|
919
|
-
**Expected output:**
|
|
920
|
-
```
|
|
921
|
-
Envelope version: 4
|
|
922
|
-
KEM mode: Xchange
|
|
923
|
-
Share index: 0
|
|
924
|
-
Threshold: 2-of-3
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
### Example 11: Decrypt Envelope Payload
|
|
928
|
-
|
|
929
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
930
|
-
```typescript
|
|
931
|
-
import {
|
|
932
|
-
Agent,
|
|
933
|
-
createEnvelope,
|
|
934
|
-
decryptPayload,
|
|
935
|
-
generateSharedKey
|
|
936
|
-
} from '@private.me/xbind';
|
|
937
|
-
|
|
938
|
-
// Create and encrypt envelope
|
|
939
|
-
const sharedKey = await generateSharedKey();
|
|
940
|
-
const agent = await Agent.quickstart({ name: 'decrypt-test' });
|
|
941
|
-
|
|
942
|
-
const originalMessage = 'Secret payment details';
|
|
943
|
-
const plaintext = new TextEncoder().encode(originalMessage);
|
|
944
|
-
|
|
945
|
-
const envelopeResult = await createEnvelope({
|
|
946
|
-
senderDid: agent.did,
|
|
947
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
948
|
-
scope: 'payments',
|
|
949
|
-
plaintext,
|
|
950
|
-
privateKey: agent.identity.privateKey,
|
|
951
|
-
sharedKey
|
|
952
|
-
});
|
|
953
|
-
|
|
954
|
-
if (!envelopeResult.ok) {
|
|
955
|
-
throw new Error('Envelope creation failed');
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
// Decrypt the payload
|
|
959
|
-
const decryptResult = await decryptPayload(envelopeResult.value, sharedKey);
|
|
960
|
-
|
|
961
|
-
if (!decryptResult.ok) {
|
|
962
|
-
throw new Error(`Decryption failed: ${decryptResult.error}`);
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
const decryptedMessage = new TextDecoder().decode(decryptResult.value);
|
|
966
|
-
console.log('Decrypted:', decryptedMessage);
|
|
967
|
-
console.log('Match:', decryptedMessage === originalMessage);
|
|
968
|
-
```
|
|
969
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
970
|
-
|
|
971
|
-
**Expected output:**
|
|
972
|
-
```
|
|
973
|
-
Decrypted: Secret payment details
|
|
974
|
-
Match: true
|
|
975
|
-
```
|
|
976
|
-
|
|
977
|
-
### Example 12: Serialize and Deserialize Envelope
|
|
978
|
-
|
|
979
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
980
|
-
```typescript
|
|
981
|
-
import {
|
|
982
|
-
Agent,
|
|
983
|
-
createEnvelope,
|
|
984
|
-
serializeEnvelope,
|
|
985
|
-
deserializeEnvelope,
|
|
986
|
-
generateSharedKey
|
|
987
|
-
} from '@private.me/xbind';
|
|
988
|
-
|
|
989
|
-
// Create envelope
|
|
990
|
-
const sharedKey = await generateSharedKey();
|
|
991
|
-
const agent = await Agent.quickstart({ name: 'serialize-test' });
|
|
992
|
-
|
|
993
|
-
const envelope = await createEnvelope({
|
|
994
|
-
senderDid: agent.did,
|
|
995
|
-
recipientDid: 'did:key:z6MkRecipient...',
|
|
996
|
-
scope: 'test',
|
|
997
|
-
plaintext: new TextEncoder().encode('Test message'),
|
|
998
|
-
privateKey: agent.identity.privateKey,
|
|
999
|
-
sharedKey
|
|
1000
|
-
});
|
|
1001
|
-
|
|
1002
|
-
if (!envelope.ok) {
|
|
1003
|
-
throw new Error('Envelope creation failed');
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
// Serialize to bytes
|
|
1007
|
-
const serialized = serializeEnvelope(envelope.value);
|
|
1008
|
-
console.log('Serialized length:', serialized.length, 'bytes');
|
|
1009
|
-
|
|
1010
|
-
// Deserialize back to envelope
|
|
1011
|
-
const deserialized = deserializeEnvelope(serialized);
|
|
1012
|
-
|
|
1013
|
-
if (deserialized.ok) {
|
|
1014
|
-
console.log('Deserialized version:', deserialized.value.v);
|
|
1015
|
-
console.log('Sender DID:', deserialized.value.sender.substring(0, 20) + '...');
|
|
1016
|
-
console.log('Round-trip successful');
|
|
1017
|
-
}
|
|
1018
|
-
```
|
|
1019
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1020
|
-
|
|
1021
|
-
**Expected output:**
|
|
1022
|
-
```
|
|
1023
|
-
Serialized length: 512 bytes
|
|
1024
|
-
Deserialized version: 1
|
|
1025
|
-
Sender DID: did:key:z6Mk...
|
|
1026
|
-
Round-trip successful
|
|
1027
|
-
```
|
|
1028
|
-
|
|
1029
|
-
### Example 13: Validate Envelope Structure
|
|
1030
|
-
|
|
1031
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1032
|
-
```typescript
|
|
1033
|
-
import { validateEnvelope } from '@private.me/xbind';
|
|
1034
|
-
|
|
1035
|
-
// Valid envelope structure
|
|
1036
|
-
const validEnvelope = {
|
|
1037
|
-
v: 1,
|
|
1038
|
-
alg: 'Ed25519',
|
|
1039
|
-
sender: 'did:key:z6MkSender...',
|
|
1040
|
-
recipient: 'did:key:z6MkRecipient...',
|
|
1041
|
-
timestamp: Date.now(),
|
|
1042
|
-
nonce: 'YmFzZTY0LW5vbmNl',
|
|
1043
|
-
scope: 'test',
|
|
1044
|
-
payload: 'ZW5jcnlwdGVkLXBheWxvYWQ=',
|
|
1045
|
-
signature: 'c2lnbmF0dXJlLWRhdGE='
|
|
1046
|
-
};
|
|
1047
|
-
|
|
1048
|
-
const validation = validateEnvelope(validEnvelope);
|
|
1049
|
-
|
|
1050
|
-
if (validation.ok) {
|
|
1051
|
-
console.log('Envelope valid');
|
|
1052
|
-
console.log('Version:', validation.value.v);
|
|
1053
|
-
console.log('Algorithm:', validation.value.alg);
|
|
1054
|
-
} else {
|
|
1055
|
-
console.error('Validation error:', validation.error);
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
// Invalid envelope (missing required field)
|
|
1059
|
-
const invalidEnvelope = {
|
|
1060
|
-
v: 1,
|
|
1061
|
-
alg: 'Ed25519',
|
|
1062
|
-
sender: 'did:key:z6MkSender...'
|
|
1063
|
-
// Missing recipient, timestamp, nonce, etc.
|
|
1064
|
-
};
|
|
1065
|
-
|
|
1066
|
-
const invalidValidation = validateEnvelope(invalidEnvelope);
|
|
1067
|
-
console.log('Invalid envelope error:', invalidValidation.ok ? 'N/A' : invalidValidation.error);
|
|
1068
|
-
```
|
|
1069
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1070
|
-
|
|
1071
|
-
**Expected output:**
|
|
1072
|
-
```
|
|
1073
|
-
Envelope valid
|
|
1074
|
-
Version: 1
|
|
1075
|
-
Algorithm: Ed25519
|
|
1076
|
-
Invalid envelope error: INVALID_FIELDS
|
|
1077
|
-
```
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
## Identity & CLI Operations
|
|
1081
|
-
|
|
1082
|
-
### CLI Initialization
|
|
1083
|
-
|
|
1084
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1085
|
-
```typescript
|
|
1086
|
-
import { initCommand } from '@private.me/xbind';
|
|
1087
|
-
|
|
1088
|
-
// Initialize xBind project with invite code
|
|
1089
|
-
await initCommand({
|
|
1090
|
-
invite: 'https://xbind.to/invite/XBD-abc123',
|
|
1091
|
-
name: 'my-xbind-app',
|
|
1092
|
-
runtime: 'node-typescript',
|
|
1093
|
-
yes: true // Skip interactive prompts
|
|
1094
|
-
});
|
|
1095
|
-
|
|
1096
|
-
// Or use CLI directly:
|
|
1097
|
-
// npx xbind-init --invite XBD-abc123 --name my-app --runtime node-typescript --yes
|
|
1098
|
-
```
|
|
1099
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1100
|
-
|
|
1101
|
-
### DID Conversions
|
|
1102
|
-
|
|
1103
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1104
|
-
```typescript
|
|
1105
|
-
import { generateIdentity, publicKeyToDid, didToPublicKeyBytes } from '@private.me/xbind';
|
|
1106
|
-
|
|
1107
|
-
// Generate identity and extract DID
|
|
1108
|
-
const result = await generateIdentity();
|
|
1109
|
-
if (!result.ok) throw new Error(result.error);
|
|
1110
|
-
|
|
1111
|
-
const identity = result.value;
|
|
1112
|
-
console.log('DID:', identity.did); // did:key:z6Mk...
|
|
1113
|
-
|
|
1114
|
-
// Convert public key to DID
|
|
1115
|
-
const did = publicKeyToDid(identity.rawPublicKey);
|
|
1116
|
-
console.log('Derived DID:', did);
|
|
1117
|
-
|
|
1118
|
-
// Convert DID back to public key bytes
|
|
1119
|
-
const keyResult = didToPublicKeyBytes(did);
|
|
1120
|
-
if (!keyResult.ok) throw new Error(keyResult.error);
|
|
1121
|
-
|
|
1122
|
-
console.log('Public key bytes:', keyResult.value); // Uint8Array(32)
|
|
1123
|
-
```
|
|
1124
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1125
|
-
|
|
1126
|
-
### PKCS8 Key Export
|
|
1127
|
-
|
|
1128
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1129
|
-
```typescript
|
|
1130
|
-
import { generateIdentity, exportPKCS8, exportX25519PKCS8 } from '@private.me/xbind';
|
|
1131
|
-
|
|
1132
|
-
const result = await generateIdentity();
|
|
1133
|
-
if (!result.ok) throw new Error(result.error);
|
|
1134
|
-
|
|
1135
|
-
const identity = result.value;
|
|
1136
|
-
|
|
1137
|
-
// Export Ed25519 private key as PKCS8 (for persistent storage)
|
|
1138
|
-
const ed25519Result = await exportPKCS8(identity.privateKey);
|
|
1139
|
-
if (!ed25519Result.ok) throw new Error(ed25519Result.error);
|
|
1140
|
-
|
|
1141
|
-
console.log('Ed25519 PKCS8:', ed25519Result.value); // Uint8Array(48)
|
|
1142
|
-
|
|
1143
|
-
// Export X25519 private key as PKCS8
|
|
1144
|
-
const x25519Result = await exportX25519PKCS8(identity.x25519PrivateKey);
|
|
1145
|
-
if (!x25519Result.ok) throw new Error(x25519Result.error);
|
|
1146
|
-
|
|
1147
|
-
console.log('X25519 PKCS8:', x25519Result.value); // Uint8Array(48)
|
|
1148
|
-
```
|
|
1149
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1150
|
-
|
|
1151
|
-
### PKCS8 Key Import
|
|
1152
|
-
|
|
1153
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1154
|
-
```typescript
|
|
1155
|
-
import { exportPKCS8, exportX25519PKCS8, importFromPKCS8, importIdentity } from '@private.me/xbind';
|
|
1156
|
-
|
|
1157
|
-
// Assume we have PKCS8 bytes from previous export
|
|
1158
|
-
const ed25519Pkcs8 = new Uint8Array(48); // From exportPKCS8()
|
|
1159
|
-
const x25519Pkcs8 = new Uint8Array(48); // From exportX25519PKCS8()
|
|
1160
|
-
|
|
1161
|
-
// Import Ed25519 identity (generates new X25519 keypair)
|
|
1162
|
-
const simpleResult = await importFromPKCS8(ed25519Pkcs8);
|
|
1163
|
-
if (!simpleResult.ok) throw new Error(simpleResult.error);
|
|
1164
|
-
|
|
1165
|
-
console.log('Restored DID:', simpleResult.value.did);
|
|
1166
|
-
|
|
1167
|
-
// Import full identity (preserves both Ed25519 + X25519 keys)
|
|
1168
|
-
const fullResult = await importIdentity(ed25519Pkcs8, x25519Pkcs8);
|
|
1169
|
-
if (!fullResult.ok) throw new Error(fullResult.error);
|
|
1170
|
-
|
|
1171
|
-
console.log('Full identity restored:', fullResult.value.did);
|
|
1172
|
-
console.log('Has X25519 keys:', !!fullResult.value.x25519PublicKey);
|
|
1173
|
-
```
|
|
1174
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1175
|
-
|
|
1176
|
-
### Deterministic Identity from Seed
|
|
1177
|
-
|
|
1178
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1179
|
-
```typescript
|
|
1180
|
-
import { identityFromSeed } from '@private.me/xbind';
|
|
1181
|
-
|
|
1182
|
-
// Generate 32-byte seed (high-entropy random bytes)
|
|
1183
|
-
const seed = crypto.getRandomValues(new Uint8Array(32));
|
|
1184
|
-
|
|
1185
|
-
// Derive deterministic identity (same seed = same DID)
|
|
1186
|
-
const result = await identityFromSeed(seed);
|
|
1187
|
-
if (!result.ok) throw new Error(result.error);
|
|
1188
|
-
|
|
1189
|
-
console.log('DID:', result.value.did);
|
|
1190
|
-
console.log('Has Ed25519 keys:', !!result.value.publicKey);
|
|
1191
|
-
console.log('Has X25519 keys:', !!result.value.x25519PublicKey);
|
|
1192
|
-
console.log('Has ML-KEM keys:', !!result.value.mlKemPublicKey);
|
|
1193
|
-
|
|
1194
|
-
// Same seed produces identical DID
|
|
1195
|
-
const result2 = await identityFromSeed(seed);
|
|
1196
|
-
if (!result2.ok) throw new Error(result2.error);
|
|
1197
|
-
|
|
1198
|
-
console.log('DIDs match:', result.value.did === result2.value.did); // true
|
|
1199
|
-
```
|
|
1200
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1201
|
-
|
|
1202
|
-
### Raw Key Extraction
|
|
1203
|
-
|
|
1204
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1205
|
-
```typescript
|
|
1206
|
-
import { exportPKCS8, exportX25519PKCS8, extractRawEd25519, extractRawX25519 } from '@private.me/xbind';
|
|
1207
|
-
import { generateIdentity } from '@private.me/xbind';
|
|
1208
|
-
|
|
1209
|
-
const identity = (await generateIdentity()).value!;
|
|
1210
|
-
|
|
1211
|
-
// Export PKCS8 format
|
|
1212
|
-
const ed25519Pkcs8 = (await exportPKCS8(identity.privateKey)).value!;
|
|
1213
|
-
const x25519Pkcs8 = (await exportX25519PKCS8(identity.x25519PrivateKey)).value!;
|
|
1214
|
-
|
|
1215
|
-
// Extract raw 32-byte private keys
|
|
1216
|
-
const ed25519Raw = extractRawEd25519(ed25519Pkcs8);
|
|
1217
|
-
if (!ed25519Raw.ok) throw new Error(ed25519Raw.error);
|
|
1218
|
-
|
|
1219
|
-
console.log('Ed25519 raw key:', ed25519Raw.value); // Uint8Array(32)
|
|
1220
|
-
|
|
1221
|
-
const x25519Raw = extractRawX25519(x25519Pkcs8);
|
|
1222
|
-
if (!x25519Raw.ok) throw new Error(x25519Raw.error);
|
|
1223
|
-
|
|
1224
|
-
console.log('X25519 raw key:', x25519Raw.value); // Uint8Array(32)
|
|
1225
|
-
```
|
|
1226
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1227
|
-
|
|
1228
|
-
### ML-KEM Key Export
|
|
1229
|
-
|
|
1230
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1231
|
-
```typescript
|
|
1232
|
-
import { generateIdentity, exportMlKemSecretKey, exportMlKemPublicKey } from '@private.me/xbind';
|
|
1233
|
-
|
|
1234
|
-
const result = await generateIdentity();
|
|
1235
|
-
if (!result.ok) throw new Error(result.error);
|
|
1236
|
-
|
|
1237
|
-
const identity = result.value;
|
|
1238
|
-
|
|
1239
|
-
// Export ML-KEM-768 secret key (2400 bytes)
|
|
1240
|
-
const secretKey = exportMlKemSecretKey(identity);
|
|
1241
|
-
if (secretKey) {
|
|
1242
|
-
console.log('ML-KEM secret key size:', secretKey.length); // 2400
|
|
1243
|
-
}
|
|
1244
|
-
|
|
1245
|
-
// Export ML-KEM-768 public key (1184 bytes)
|
|
1246
|
-
const publicKey = exportMlKemPublicKey(identity);
|
|
1247
|
-
if (publicKey) {
|
|
1248
|
-
console.log('ML-KEM public key size:', publicKey.length); // 1184
|
|
1249
|
-
}
|
|
1250
|
-
```
|
|
1251
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1252
|
-
|
|
1253
|
-
## Advanced Networking & Resilience
|
|
1254
|
-
|
|
1255
|
-
xBind provides production-grade retry strategies, replay prevention, and circuit breakers for fault-tolerant distributed systems.
|
|
1256
|
-
|
|
1257
|
-
### Replay Prevention with MemoryNonceStore
|
|
1258
|
-
|
|
1259
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1260
|
-
```typescript
|
|
1261
|
-
import { MemoryNonceStore } from '@private.me/xbind';
|
|
1262
|
-
|
|
1263
|
-
// Create in-memory nonce store (10-minute TTL, 60-second cleanup)
|
|
1264
|
-
const nonceStore = new MemoryNonceStore({
|
|
1265
|
-
ttlMs: 10 * 60 * 1000,
|
|
1266
|
-
cleanupIntervalMs: 60 * 1000,
|
|
1267
|
-
});
|
|
1268
|
-
|
|
1269
|
-
// Check nonce freshness (returns true if new, false if duplicate)
|
|
1270
|
-
const nonce1 = 'unique-nonce-abc123';
|
|
1271
|
-
const senderDid = 'did:key:z6Mk...';
|
|
1272
|
-
|
|
1273
|
-
const isNewNonce = await nonceStore.check(nonce1, senderDid);
|
|
1274
|
-
console.log('Nonce accepted:', isNewNonce); // true (first use)
|
|
1275
|
-
|
|
1276
|
-
const isDuplicate = await nonceStore.check(nonce1, senderDid);
|
|
1277
|
-
console.log('Nonce rejected:', !isDuplicate); // false (replay attack)
|
|
1278
|
-
|
|
1279
|
-
// Clean up
|
|
1280
|
-
nonceStore.dispose();
|
|
1281
|
-
```
|
|
1282
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1283
|
-
|
|
1284
|
-
### Redis Nonce Store (Multi-Node)
|
|
1285
|
-
|
|
1286
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1287
|
-
```typescript
|
|
1288
|
-
import { RedisNonceStore } from '@private.me/xbind';
|
|
1289
|
-
import Redis from 'ioredis';
|
|
1290
|
-
|
|
1291
|
-
// Create Redis client
|
|
1292
|
-
const redis = new Redis({ host: 'localhost', port: 6379 });
|
|
1293
|
-
|
|
1294
|
-
// Create Redis nonce store (distributed across all nodes)
|
|
1295
|
-
const nonceStore = new RedisNonceStore({
|
|
1296
|
-
client: {
|
|
1297
|
-
setNX: async (key, value, ttl) => {
|
|
1298
|
-
const result = await redis.set(key, value, 'EX', ttl, 'NX');
|
|
1299
|
-
return result === 'OK' ? 'OK' : null;
|
|
1300
|
-
},
|
|
1301
|
-
del: (key) => redis.del(key),
|
|
1302
|
-
quit: () => redis.quit(),
|
|
1303
|
-
},
|
|
1304
|
-
ttlSeconds: 600, // 10 minutes
|
|
1305
|
-
keyPrefix: 'xbind:nonce:',
|
|
1306
|
-
});
|
|
1307
|
-
|
|
1308
|
-
// Use nonce store (same API as MemoryNonceStore)
|
|
1309
|
-
const isNewNonce = await nonceStore.check('nonce-xyz', 'did:key:z6Mk...');
|
|
1310
|
-
console.log('Distributed nonce check:', isNewNonce);
|
|
1311
|
-
|
|
1312
|
-
// Clean up
|
|
1313
|
-
await nonceStore.dispose();
|
|
1314
|
-
```
|
|
1315
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1316
|
-
|
|
1317
|
-
### Exponential Backoff Retry
|
|
1318
|
-
|
|
1319
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1320
|
-
```typescript
|
|
1321
|
-
import { ExponentialBackoffStrategy, executeWithRetry } from '@private.me/xbind';
|
|
1322
|
-
import { err, ok } from '@private.me/shared';
|
|
1323
|
-
|
|
1324
|
-
// Create exponential backoff strategy (3 attempts, 1s → 2s → 4s)
|
|
1325
|
-
const retryStrategy = new ExponentialBackoffStrategy({
|
|
1326
|
-
maxAttempts: 3,
|
|
1327
|
-
initialDelayMs: 1000,
|
|
1328
|
-
maxDelayMs: 30000,
|
|
1329
|
-
multiplier: 2,
|
|
1330
|
-
jitter: true,
|
|
1331
|
-
});
|
|
1332
|
-
|
|
1333
|
-
// Simulate flaky operation
|
|
1334
|
-
let attemptCount = 0;
|
|
1335
|
-
async function flakyOperation() {
|
|
1336
|
-
attemptCount++;
|
|
1337
|
-
console.log(`Attempt ${attemptCount}`);
|
|
1338
|
-
|
|
1339
|
-
if (attemptCount < 3) {
|
|
1340
|
-
return err('NETWORK_ERROR' as const);
|
|
1341
|
-
}
|
|
1342
|
-
return ok({ data: 'Success after retries' });
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
// Execute with retry
|
|
1346
|
-
const result = await executeWithRetry(flakyOperation, retryStrategy);
|
|
1347
|
-
|
|
1348
|
-
if (result.ok) {
|
|
1349
|
-
console.log('Operation succeeded:', result.value.data);
|
|
1350
|
-
} else {
|
|
1351
|
-
console.error('Operation failed:', result.error);
|
|
1352
|
-
}
|
|
1353
|
-
```
|
|
1354
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1355
|
-
|
|
1356
|
-
### Linear Backoff Strategy
|
|
1357
|
-
|
|
1358
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1359
|
-
```typescript
|
|
1360
|
-
import { LinearBackoffStrategy, executeWithRetry } from '@private.me/xbind';
|
|
1361
|
-
import { err, ok } from '@private.me/shared';
|
|
1362
|
-
|
|
1363
|
-
// Create linear backoff strategy (delays: 1s, 2s, 3s, 4s)
|
|
1364
|
-
const retryStrategy = new LinearBackoffStrategy({
|
|
1365
|
-
maxAttempts: 4,
|
|
1366
|
-
initialDelayMs: 1000,
|
|
1367
|
-
delayIncrementMs: 1000,
|
|
1368
|
-
maxDelayMs: 10000,
|
|
1369
|
-
jitter: true,
|
|
1370
|
-
});
|
|
1371
|
-
|
|
1372
|
-
// Simulate operation
|
|
1373
|
-
async function operation() {
|
|
1374
|
-
return ok({ message: 'Linear backoff demo' });
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
const result = await executeWithRetry(operation, retryStrategy);
|
|
1378
|
-
console.log('Result:', result.ok ? result.value.message : result.error);
|
|
1379
|
-
```
|
|
1380
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1381
|
-
|
|
1382
|
-
### Fixed Delay Strategy
|
|
1383
|
-
|
|
1384
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1385
|
-
```typescript
|
|
1386
|
-
import { FixedDelayStrategy, executeWithRetry } from '@private.me/xbind';
|
|
1387
|
-
import { err, ok } from '@private.me/shared';
|
|
1388
|
-
|
|
1389
|
-
// Create fixed delay strategy (constant 2s delay between retries)
|
|
1390
|
-
const retryStrategy = new FixedDelayStrategy({
|
|
1391
|
-
maxAttempts: 3,
|
|
1392
|
-
delayMs: 2000,
|
|
1393
|
-
jitter: false,
|
|
1394
|
-
});
|
|
1395
|
-
|
|
1396
|
-
// Simulate operation
|
|
1397
|
-
async function operation() {
|
|
1398
|
-
return ok({ message: 'Fixed delay demo' });
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
const result = await executeWithRetry(operation, retryStrategy);
|
|
1402
|
-
console.log('Result:', result.ok ? result.value.message : result.error);
|
|
1403
|
-
```
|
|
1404
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1405
|
-
|
|
1406
|
-
### No Retry Strategy
|
|
1407
|
-
|
|
1408
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1409
|
-
```typescript
|
|
1410
|
-
import { NoRetryStrategy, executeWithRetry } from '@private.me/xbind';
|
|
1411
|
-
import { err } from '@private.me/shared';
|
|
1412
|
-
|
|
1413
|
-
// Create no-retry strategy (fail immediately)
|
|
1414
|
-
const retryStrategy = new NoRetryStrategy();
|
|
1415
|
-
|
|
1416
|
-
// Simulate failing operation
|
|
1417
|
-
async function operation() {
|
|
1418
|
-
return err('NETWORK_ERROR' as const);
|
|
1419
|
-
}
|
|
1420
|
-
|
|
1421
|
-
const result = await executeWithRetry(operation, retryStrategy);
|
|
1422
|
-
console.log('Failed immediately:', !result.ok);
|
|
1423
|
-
console.log('Error:', result.ok ? null : result.error);
|
|
1424
|
-
```
|
|
1425
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1426
|
-
|
|
1427
|
-
### Circuit Breaker Pattern
|
|
1428
|
-
|
|
1429
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1430
|
-
```typescript
|
|
1431
|
-
import { CircuitBreaker } from '@private.me/xbind';
|
|
1432
|
-
|
|
1433
|
-
// Create circuit breaker (5 failures → open, 60s reset, 2 successes → close)
|
|
1434
|
-
const breaker = new CircuitBreaker({
|
|
1435
|
-
failureThreshold: 5,
|
|
1436
|
-
resetTimeoutMs: 60000,
|
|
1437
|
-
successThreshold: 2,
|
|
1438
|
-
windowMs: 60000,
|
|
1439
|
-
});
|
|
1440
|
-
|
|
1441
|
-
// Simulate failures to trip circuit
|
|
1442
|
-
for (let i = 0; i < 5; i++) {
|
|
1443
|
-
breaker.recordFailure();
|
|
1444
|
-
}
|
|
1445
|
-
|
|
1446
|
-
console.log('Circuit state after 5 failures:', breaker.getStats().state); // OPEN
|
|
1447
|
-
|
|
1448
|
-
// Attempt request while circuit is open
|
|
1449
|
-
const canProceed = breaker.allowRequest();
|
|
1450
|
-
console.log('Request allowed:', canProceed); // false
|
|
1451
|
-
|
|
1452
|
-
// Get circuit statistics
|
|
1453
|
-
const stats = breaker.getStats();
|
|
1454
|
-
console.log('Stats:', {
|
|
1455
|
-
state: stats.state,
|
|
1456
|
-
totalFailures: stats.totalFailures,
|
|
1457
|
-
consecutiveFailures: stats.consecutiveFailures,
|
|
1458
|
-
});
|
|
1459
|
-
```
|
|
1460
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1461
|
-
|
|
1462
|
-
### Retry with Circuit Breaker
|
|
1463
|
-
|
|
1464
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1465
|
-
```typescript
|
|
1466
|
-
import {
|
|
1467
|
-
ExponentialBackoffStrategy,
|
|
1468
|
-
CircuitBreaker,
|
|
1469
|
-
executeWithRetry,
|
|
1470
|
-
} from '@private.me/xbind';
|
|
1471
|
-
import { err, ok } from '@private.me/shared';
|
|
1472
|
-
|
|
1473
|
-
// Create retry strategy and circuit breaker
|
|
1474
|
-
const retryStrategy = new ExponentialBackoffStrategy({
|
|
1475
|
-
maxAttempts: 3,
|
|
1476
|
-
initialDelayMs: 1000,
|
|
1477
|
-
});
|
|
1478
|
-
|
|
1479
|
-
const circuitBreaker = new CircuitBreaker({
|
|
1480
|
-
failureThreshold: 2,
|
|
1481
|
-
resetTimeoutMs: 5000,
|
|
1482
|
-
});
|
|
1483
|
-
|
|
1484
|
-
// Simulate operation that succeeds after circuit recovery
|
|
1485
|
-
let callCount = 0;
|
|
1486
|
-
async function operation() {
|
|
1487
|
-
callCount++;
|
|
1488
|
-
if (callCount === 1) {
|
|
1489
|
-
return err('NETWORK_ERROR' as const);
|
|
1490
|
-
}
|
|
1491
|
-
return ok({ data: `Success on attempt ${callCount}` });
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
// Execute with retry + circuit breaker
|
|
1495
|
-
const result = await executeWithRetry(operation, retryStrategy, circuitBreaker);
|
|
1496
|
-
|
|
1497
|
-
console.log('Operation result:', result.ok ? result.value.data : result.error);
|
|
1498
|
-
console.log('Circuit state:', circuitBreaker.getStats().state);
|
|
1499
|
-
```
|
|
1500
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1501
|
-
|
|
1502
|
-
### RetryTransportAdapter (Automatic Retry)
|
|
1503
|
-
|
|
1504
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1505
|
-
```typescript
|
|
1506
|
-
import { RetryTransportAdapter, HttpsTransportAdapter, Agent } from '@private.me/xbind';
|
|
1507
|
-
|
|
1508
|
-
// Create base transport
|
|
1509
|
-
const baseTransport = new HttpsTransportAdapter({
|
|
1510
|
-
baseUrl: 'https://gateway.private.me',
|
|
1511
|
-
});
|
|
1512
|
-
|
|
1513
|
-
// Wrap with retry decorator (exponential backoff, 3 attempts)
|
|
1514
|
-
const retryTransport = new RetryTransportAdapter(baseTransport, {
|
|
1515
|
-
maxAttempts: 3,
|
|
1516
|
-
initialDelayMs: 1000,
|
|
1517
|
-
maxDelayMs: 10000,
|
|
1518
|
-
strategy: 'exponential',
|
|
1519
|
-
});
|
|
1520
|
-
|
|
1521
|
-
// Create agent with retry transport
|
|
1522
|
-
const agent = await Agent.quickstart({
|
|
1523
|
-
name: 'retry-demo',
|
|
1524
|
-
transports: [retryTransport],
|
|
1525
|
-
});
|
|
1526
|
-
|
|
1527
|
-
console.log('Agent created with retry transport');
|
|
1528
|
-
console.log('Transport type:', agent.transports[0].constructor.name);
|
|
1529
|
-
```
|
|
1530
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1531
|
-
|
|
1532
|
-
### Shared Key Generation
|
|
1533
|
-
|
|
1534
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1535
|
-
```typescript
|
|
1536
|
-
import { generateSharedKey } from '@private.me/xbind';
|
|
1537
|
-
|
|
1538
|
-
// Generate random AES-256-GCM shared key
|
|
1539
|
-
const sharedKeyResult = await generateSharedKey();
|
|
1540
|
-
|
|
1541
|
-
if (!sharedKeyResult.ok) {
|
|
1542
|
-
throw new Error(`Failed to generate key: ${sharedKeyResult.error}`);
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
const sharedKey = sharedKeyResult.value;
|
|
1546
|
-
|
|
1547
|
-
// Export key material for inspection
|
|
1548
|
-
const keyMaterial = await crypto.subtle.exportKey('raw', sharedKey);
|
|
1549
|
-
console.log('Shared key generated (256 bits):', keyMaterial.byteLength * 8);
|
|
1550
|
-
console.log('Key algorithm:', sharedKey.algorithm.name);
|
|
1551
|
-
console.log('Key usages:', sharedKey.usages);
|
|
1552
|
-
```
|
|
1553
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1554
|
-
|
|
1555
|
-
### Signed Envelopes
|
|
1556
|
-
|
|
1557
|
-
<!-- RUNNABLE-EXAMPLE -->
|
|
1558
|
-
```typescript
|
|
1559
|
-
import { createSignedEnvelope, openSignedEnvelope, Agent } from '@private.me/xbind';
|
|
1560
|
-
|
|
1561
|
-
// Create agents
|
|
1562
|
-
const sender = await Agent.quickstart({ name: 'sender' });
|
|
1563
|
-
const recipient = await Agent.quickstart({ name: 'recipient' });
|
|
1564
|
-
|
|
1565
|
-
// Create signed envelope
|
|
1566
|
-
const payload = { action: 'transfer', amount: 100 };
|
|
1567
|
-
const envelopeResult = await createSignedEnvelope(
|
|
1568
|
-
sender.identity,
|
|
1569
|
-
recipient.did,
|
|
1570
|
-
payload,
|
|
1571
|
-
'billing'
|
|
1572
|
-
);
|
|
1573
|
-
|
|
1574
|
-
if (!envelopeResult.ok) {
|
|
1575
|
-
throw new Error(`Failed to create envelope: ${envelopeResult.error}`);
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
const envelope = envelopeResult.value;
|
|
1579
|
-
console.log('Envelope created with signature');
|
|
1580
|
-
console.log('Sender DID:', envelope.sender);
|
|
1581
|
-
console.log('Recipient DID:', envelope.recipient);
|
|
1582
|
-
console.log('Signature length:', envelope.signature.length);
|
|
1583
|
-
|
|
1584
|
-
// Verify and open envelope
|
|
1585
|
-
const openResult = await openSignedEnvelope(envelope, sender.identity.publicKey);
|
|
1586
|
-
|
|
1587
|
-
if (!openResult.ok) {
|
|
1588
|
-
throw new Error(`Failed to open envelope: ${openResult.error}`);
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
console.log('Envelope verified and opened');
|
|
1592
|
-
console.log('Payload:', openResult.value);
|
|
1593
|
-
```
|
|
1594
|
-
<!-- /RUNNABLE-EXAMPLE -->
|
|
1595
|
-
|
|
1596
|
-
## Python SDK
|
|
1597
|
-
|
|
1598
|
-
Complete Python bindings for agent identity and messaging:
|
|
1599
|
-
|
|
1600
|
-
```python
|
|
1601
|
-
from private_me.xbind import Agent
|
|
1602
|
-
|
|
1603
|
-
# Create agent from private key
|
|
1604
|
-
agent = Agent.from_private_key(private_key_bytes)
|
|
1605
|
-
|
|
1606
|
-
# Make authenticated call
|
|
1607
|
-
result = agent.call('stripe:createCharge', {
|
|
1608
|
-
'amount': 100,
|
|
1609
|
-
'currency': 'usd',
|
|
1610
|
-
'description': 'AI agent purchase'
|
|
1611
|
-
})
|
|
1612
|
-
|
|
1613
|
-
if result['ok']:
|
|
1614
|
-
print(f"Charge ID: {result['data']['id']}")
|
|
1615
|
-
print(f"Agent DID: {result['audit']['agent']}")
|
|
1616
|
-
else:
|
|
1617
|
-
print(f"Error: {result['error']['message']}")
|
|
1618
|
-
```
|
|
1619
|
-
|
|
1620
|
-
See [Python SDK documentation](./python/README.md) for complete API reference and examples.
|
|
1621
|
-
|
|
1622
|
-
## Why xBind?
|
|
1623
|
-
|
|
1624
|
-
Zero key management, zero cascade failures, zero bearer credentials. Cryptographic identity replaces API keys. See [white paper](https://private.me/docs/xbind.html) for architecture details and benchmarks.
|
|
1625
|
-
|
|
1626
|
-
## Getting Started
|
|
1627
|
-
|
|
1628
|
-
**[Guide](../../docs/xbind-integrations/getting-started/index.md)** — Concepts, migration
|
|
1629
|
-
**[Quickstart](../../docs/xbind-integrations/getting-started/quickstart.md)** — 15-second setup
|
|
1630
|
-
|
|
1631
|
-
## Features
|
|
1632
|
-
|
|
1633
|
-
**Zero-config JITR:** Just-in-Time Registration auto-registers agents with trust registry on first use (AWS IoT JITR, OAuth DCR, MCP 2025 standards).
|
|
1634
|
-
|
|
1635
|
-
### Core Security
|
|
1636
|
-
- **Post-quantum cryptography:** ML-KEM-768 key encapsulation, ML-DSA-65 digital signatures (FIPS 203/204)
|
|
1637
|
-
- **Hybrid key agreement:** X-Wing combiner (IETF draft-10) with 6-parameter domain separation
|
|
1638
|
-
- **XorIDA split-channel delivery:** Information-theoretic threshold sharing (2-of-2, 2-of-3, 3-of-5)
|
|
1639
|
-
- **Cryptographic request signing:** Ed25519 signatures prevent DID header forgery
|
|
1640
|
-
- **Key rotation:** ML-KEM + X25519 rotation with fallback decryption (10 rotation history)
|
|
1641
|
-
- **Proof-of-Possession:** Ed25519 signature verification prevents DID spoofing
|
|
1642
|
-
- **Share-aware nonce deduplication:** Prevents replay attacks with composite keys
|
|
1643
|
-
|
|
1644
|
-
### Runtime Compatibility (4 Platforms)
|
|
1645
|
-
- **Browser:** WebCrypto API, IndexedDB/localStorage adapters, WASM support, service workers
|
|
1646
|
-
- **React Native:** AsyncStorage, Buffer polyfills, crypto detection, iOS/Android platform support
|
|
1647
|
-
- **Edge Runtime:** Cloudflare Workers, Vercel Edge, Deno Deploy, KV storage, <1MB optimization
|
|
1648
|
-
- **Node.js:** Native crypto module, filesystem storage, full feature set
|
|
1649
|
-
|
|
1650
|
-
### Operations Patterns
|
|
1651
|
-
- **Health checks:** Startup/liveness/readiness probes, Kubernetes-compatible, Express/Fastify middleware
|
|
1652
|
-
- **Circuit breakers:** 3-state machine (closed/open/half-open), registry/gateway/S3 presets, automatic recovery
|
|
1653
|
-
- **Graceful degradation:** QoS tiers, intelligent caching, service health tracking, fallback strategies
|
|
1654
|
-
- **Performance benchmarks:** Latency histograms with baselines for key ops (ML-KEM, ML-DSA, encryption)
|
|
1655
|
-
- **Structured logging:** 4 levels (DEBUG/INFO/WARN/ERROR), automatic sensitive data redaction, correlation IDs
|
|
1656
|
-
- **Telemetry:** Prometheus-compatible metrics (counters, histograms, gauges), operation latency tracking
|
|
1657
|
-
|
|
1658
|
-
### Security Audit Preparation
|
|
1659
|
-
- **STRIDE threat modeling:** 66 threats analyzed across 6 categories
|
|
1660
|
-
- **Crypto claims documentation:** 41 cryptographic claims documented with evidence
|
|
1661
|
-
- **Known limitations disclosure:** 24 limitations disclosed for auditor transparency
|
|
1662
|
-
- **Audit-ready:** NCC Group / Trail of Bits preparation ($100K-$150K, 12-week timeline)
|
|
1663
|
-
|
|
1664
|
-
### API Enhancements
|
|
1665
|
-
- **Batch operations:** 6-8x speedup for parallel operations with single network round-trip
|
|
1666
|
-
- **Async iterators:** `for await...of` syntax support for streaming message processing
|
|
1667
|
-
- **Plugin/middleware system:** 6-phase lifecycle hooks with 3 built-in plugins
|
|
1668
|
-
- **Event emitters:** Type-safe events with 5 event types, priority execution, bubbling
|
|
1669
|
-
- **Cancellation tokens:** AbortController integration with timeout support
|
|
1670
|
-
- **Progress callbacks:** 4 specialized trackers (operation, transfer, share, encryption)
|
|
1671
|
-
- **Retry strategies:** 4 strategies (exponential, linear, immediate, jittered) + circuit breaker integration
|
|
1672
|
-
- **Request timeouts:** Per-operation config with inheritance and cancellation
|
|
1673
|
-
- **Connection pooling:** 60-70% latency reduction with keep-alive and metrics
|
|
1674
|
-
- **Serialization formats:** JSON/MessagePack/CBOR support with auto-detection and negotiation
|
|
1675
|
-
- **Configuration validation:** Comprehensive validation with clear error messages
|
|
1676
|
-
- **Debug mode:** Performance profiling, network/crypto tracing, state inspection
|
|
1677
|
-
- **SDK version info:** Capability detection, deprecation warnings, compatibility checking
|
|
1678
|
-
|
|
1679
|
-
### Developer Experience
|
|
1680
|
-
- **Type safety:** `Result<T, E>` error handling with 96+ error codes
|
|
1681
|
-
- **TypeScript strict mode:** Zero type errors, complete type coverage
|
|
1682
|
-
- **Python SDK:** Complete bindings for identity, messaging, and encryption
|
|
1683
|
-
- **User-friendly errors:** 75+ errors with actionable recovery hints
|
|
1684
|
-
- **Complete API docs:** 2,587 lines with 50+ usage examples
|
|
1685
|
-
- **CHANGELOG generation:** Automated Keep a Changelog format with semver discipline
|
|
1686
|
-
- **Dependency audit:** Weekly Dependabot scans, 5-layer vulnerability scanning
|
|
1687
|
-
- **Crypto license compliance:** Automated MIT/MIT-0 validation with GPL/AGPL detection
|
|
1688
|
-
|
|
1689
|
-
### Enterprise Features
|
|
1690
|
-
- **Version negotiation:** Explicit SDK version fields prevent "404 Route not found" in mixed fleets
|
|
1691
|
-
- **Multi-device session resume:** AES-256-GCM encrypted session state sync with PBKDF2 (100k iterations)
|
|
1692
|
-
- **Encrypted backup/restore:** Password-protected identity export with PBKDF2-SHA256 (310k iterations)
|
|
1693
|
-
- **Offline sync:** Message queueing for offline devices (max 1000 messages, 24-hour TTL)
|
|
1694
|
-
- **Registry expiration:** TTL support with cleanup (default 7 days)
|
|
1695
|
-
- **Server-side spending limits:** Redis-backed enforcement with deployment-level aggregation
|
|
1696
|
-
- **Rate limiting:** Three-tier protection (per-DID, per-IP, global)
|
|
1697
|
-
- **Full Control IP protection:** Store Front (npm) + Vault Store (EC2) with payment verification
|
|
1698
|
-
|
|
1699
|
-
### Testing & Quality
|
|
1700
|
-
- **2,762 tests:** Comprehensive coverage (96.6% passing)
|
|
1701
|
-
- **End-to-end integration:** Full message flow tests (Agent A → Gateway → Agent B)
|
|
1702
|
-
- **Gateway concurrency:** 100 concurrent sends, race condition detection
|
|
1703
|
-
- **Network partition recovery:** Disconnect/reconnect cycles with retry logic
|
|
1704
|
-
- **PLAN-3 hybrid signatures:** Bilateral authorization with composite verification
|
|
1705
|
-
|
|
1706
|
-
## Bundle Size Optimization (Tree-Shaking)
|
|
1707
|
-
|
|
1708
|
-
**New in v3.0.3:** LoopbackTransport export (testing workflow), describeSecurityModeStructured export (white paper examples), Agent.quickstart() signature fixes (README correctness). Full Control IP Protection (v3.0.2) - cryptographic algorithms delivered via payment-gated Vault Store. Share 1 in npm (useless alone), Share 2 in EC2 (completes algorithm). Information-theoretic security for proprietary IP.
|
|
1709
|
-
|
|
1710
|
-
### Full Import (Convenience)
|
|
1711
|
-
|
|
1712
|
-
```typescript
|
|
1713
|
-
import { Agent, generateIdentity } from '@private.me/xbind';
|
|
1714
|
-
|
|
1715
|
-
// Bundle size: ~450 KB
|
|
1716
|
-
```
|
|
1717
|
-
|
|
1718
|
-
### Granular Import (Optimized)
|
|
1719
|
-
|
|
1720
|
-
```typescript
|
|
1721
|
-
import { Agent } from '@private.me/xbind/agent';
|
|
1722
|
-
import { generateIdentity } from '@private.me/xbind/identity';
|
|
1723
|
-
|
|
1724
|
-
// Bundle size: ~180 KB (60% reduction)
|
|
1725
|
-
```
|
|
1726
|
-
|
|
1727
|
-
### Available Entry Points
|
|
1728
|
-
|
|
1729
|
-
| Entry Point | Exports | Bundle Impact |
|
|
1730
|
-
|-------------|---------|---------------|
|
|
1731
|
-
| `@private.me/xbind` | All exports | Full package (~450 KB) |
|
|
1732
|
-
| `@private.me/xbind/agent` | `Agent`, `AgentOptions` | ~180 KB |
|
|
1733
|
-
| `@private.me/xbind/identity` | `generateIdentity`, `Identity` | ~120 KB |
|
|
1734
|
-
| `@private.me/xbind/trust-registry` | Registry classes | ~200 KB |
|
|
1735
|
-
| `@private.me/xbind/key-agreement` | Key exchange functions | ~90 KB |
|
|
1736
|
-
| `@private.me/xbind/errors` | Error types | 0 KB (types only) |
|
|
1737
|
-
|
|
1738
|
-
**Bundler Support:** Works with webpack 5+, Rollup, esbuild, and Vite. Tree-shaking is automatic in production mode.
|
|
1739
|
-
|
|
1740
|
-
**See:** [Tree-Shaking Guide](./docs/packaging/tree-shaking.md) for detailed usage and configuration.
|
|
1741
|
-
|
|
1742
|
-
## Automatic XorIDA Split-Channel Protection
|
|
1743
|
-
|
|
1744
|
-
xBind automatically activates information-theoretic XorIDA threshold sharing for high-risk operations. No code changes required—security is transparent.
|
|
1745
|
-
|
|
1746
|
-
### Risk Tags (Recommended for Crypto)
|
|
1747
|
-
|
|
1748
|
-
For cryptocurrency transactions (BTC, ETH, etc.), use explicit risk tags in your payload:
|
|
1749
|
-
|
|
1750
|
-
```typescript
|
|
1751
|
-
// Low risk: 2-of-2 threshold
|
|
1752
|
-
await agent.send({
|
|
1753
|
-
to: recipientDid,
|
|
1754
|
-
payload: { amount: 0.5, currency: 'BTC', risk: 'low' }
|
|
1755
|
-
});
|
|
1756
|
-
|
|
1757
|
-
// Medium risk: 2-of-3 threshold
|
|
1758
|
-
await agent.send({
|
|
1759
|
-
to: recipientDid,
|
|
1760
|
-
payload: { amount: 5.0, currency: 'ETH', risk: 'medium' }
|
|
1761
|
-
});
|
|
1762
|
-
|
|
1763
|
-
// High risk: 3-of-5 threshold
|
|
1764
|
-
await agent.send({
|
|
1765
|
-
to: recipientDid,
|
|
1766
|
-
payload: { amount: 50, currency: 'BTC', risk: 'high' }
|
|
1767
|
-
});
|
|
1768
|
-
|
|
1769
|
-
// Critical risk: 3-of-5 threshold
|
|
1770
|
-
await agent.send({
|
|
1771
|
-
to: recipientDid,
|
|
1772
|
-
payload: { amount: 100, currency: 'BTC', risk: 'critical' }
|
|
1773
|
-
});
|
|
1774
|
-
```
|
|
1775
|
-
|
|
1776
|
-
### Fiat Currency Auto-Detection
|
|
1777
|
-
|
|
1778
|
-
For fiat currencies (USD, EUR, GBP), xBind uses numeric thresholds:
|
|
1779
|
-
|
|
1780
|
-
```typescript
|
|
1781
|
-
// Automatically triggers 2-of-3 (amount >= $100,000)
|
|
1782
|
-
await agent.send({
|
|
1783
|
-
to: recipientDid,
|
|
1784
|
-
payload: { amount: 500000, currency: 'USD', action: 'transfer' }
|
|
1785
|
-
});
|
|
1786
|
-
|
|
1787
|
-
// Automatically triggers 3-of-5 (amount >= $1,000,000)
|
|
1788
|
-
await agent.send({
|
|
1789
|
-
to: recipientDid,
|
|
1790
|
-
payload: { amount: 2500000, currency: 'USD', action: 'transfer' }
|
|
1791
|
-
});
|
|
1792
|
-
```
|
|
1793
|
-
|
|
1794
|
-
### Manual Security Override
|
|
1795
|
-
|
|
1796
|
-
Override automatic detection with explicit security levels:
|
|
1797
|
-
|
|
1798
|
-
```typescript
|
|
1799
|
-
// Force 2-of-3 regardless of amount/risk
|
|
1800
|
-
await agent.send({
|
|
1801
|
-
to: recipientDid,
|
|
1802
|
-
payload: data,
|
|
1803
|
-
security: 'high'
|
|
1804
|
-
});
|
|
1805
|
-
|
|
1806
|
-
// Force 3-of-5 for maximum security
|
|
1807
|
-
await agent.send({
|
|
1808
|
-
to: recipientDid,
|
|
1809
|
-
payload: data,
|
|
1810
|
-
security: 'critical'
|
|
1811
|
-
});
|
|
1812
|
-
|
|
1813
|
-
// Disable XorIDA (standard encrypted transport)
|
|
1814
|
-
await agent.send({
|
|
1815
|
-
to: recipientDid,
|
|
1816
|
-
payload: data,
|
|
1817
|
-
security: 'standard'
|
|
1818
|
-
});
|
|
1819
|
-
```
|
|
1820
|
-
|
|
1821
|
-
### Threshold Schemes
|
|
1822
|
-
|
|
1823
|
-
| Risk Tag / Threshold | Shares | Required | Security Level |
|
|
1824
|
-
|---------------------|--------|----------|----------------|
|
|
1825
|
-
| `low` | 2 | 2 | 2-of-2 threshold |
|
|
1826
|
-
| `medium` / $100k-$1M | 3 | 2 | 2-of-3 threshold |
|
|
1827
|
-
| `high` / `critical` / >$1M | 5 | 3 | 3-of-5 threshold |
|
|
1828
|
-
| No tag / <$100k | — | — | Standard encrypted transport |
|
|
1829
|
-
|
|
1830
|
-
**Key Insight:** XorIDA is information-theoretically secure. Any K-1 shares reveal zero information about the secret, even with unlimited computing power. Quantum computers cannot break XorIDA.
|
|
1831
|
-
|
|
1832
|
-
## Billing & Metering
|
|
1833
|
-
|
|
1834
|
-
xBind includes usage-based billing with automated milestone notifications:
|
|
1835
|
-
|
|
1836
|
-
- **Free Tier:** Generous monthly limits (no email verification required upfront)
|
|
1837
|
-
- **Grace Buffer:** Additional operations available after email verification
|
|
1838
|
-
- **Pro Tier:** Usage-based billing with unlimited operations
|
|
1839
|
-
- **Monthly Reset:** 1st of each month at 00:00 UTC
|
|
1840
|
-
|
|
1841
|
-
See [pricing](../../docs/pricing-reference.md) for current rates and tier details.
|
|
1842
|
-
|
|
1843
|
-
### Milestone Notifications
|
|
1844
|
-
|
|
1845
|
-
Automated email notifications at usage thresholds with progress bars and CTAs for upgrades.
|
|
1846
|
-
|
|
1847
|
-
**Email verification:** Required at free tier limit to access grace buffer.
|
|
1848
|
-
|
|
1849
|
-
**Implementation:**
|
|
1850
|
-
- Metering logic: `apps/server/src/customer-metering.ts`
|
|
1851
|
-
- Milestone system: `apps/server/src/usage-milestone-notifications.ts`
|
|
1852
|
-
- Tier pattern: See `docs/gold-package.md` section 7.6.5
|
|
1853
|
-
|
|
1854
|
-
## Gateway
|
|
1855
|
-
|
|
1856
|
-
Non-authoritative coordination for discovery, relay, push notifications, and state checkpoints. Cannot forge identity or decide trust. See [Gateway Architecture](./docs/gateway-architecture.md).
|
|
1857
|
-
|
|
1858
|
-
## Connection Models
|
|
1859
|
-
|
|
1860
|
-
xBind provides four connection models for entity-to-entity authentication: Invite Code (email-based onboarding), QR Code (physical proximity pairing), Trust Registry (pre-authorized enterprise), and Peer Discovery (mDNS local network). All use cryptographic DIDs.
|
|
1861
|
-
|
|
1862
|
-
| Model | Security | UX | Best For |
|
|
1863
|
-
|-------|----------|-----|----------|
|
|
1864
|
-
| Invite Code | Single-use, 24h TTL | 6-char code | Customer onboarding |
|
|
1865
|
-
| QR Code | Physical proximity, 60s TTL | Scan & tap | Mobile/desktop pairing |
|
|
1866
|
-
| Trust Registry | Admin pre-auth, scoped | Zero (automated) | Enterprise/CI/CD |
|
|
1867
|
-
| Peer Discovery | LAN proximity, user confirm | Scan & confirm | IoT devices, offline |
|
|
1868
|
-
|
|
1869
|
-
See [Entity-to-Entity Connection UX Guide](../../docs/ENTITY-TO-ENTITY-CONNECTION-UX.md) for implementation patterns and code examples.
|
|
1870
|
-
|
|
1871
|
-
## Configuration
|
|
1872
|
-
|
|
1873
|
-
### Basic Setup
|
|
1874
|
-
|
|
1875
|
-
```typescript
|
|
1876
|
-
import { HttpTrustRegistry } from '@private.me/xbind';
|
|
1877
|
-
|
|
1878
|
-
// Documentation example - use your actual gateway URL
|
|
1879
|
-
const registry = new HttpTrustRegistry({
|
|
1880
|
-
baseUrl: 'https://gateway.private.me'
|
|
1881
|
-
});
|
|
1882
|
-
```
|
|
1883
|
-
|
|
1884
|
-
### Advanced Features
|
|
1885
|
-
|
|
1886
|
-
Checkpoints, sequence numbers, subscription proofs, XorIDA configuration, key backup (2-of-3 default), DID succession. See [Configuration Guide](./docs/configuration.md) and [Examples](./docs/examples.md).
|
|
1887
|
-
|
|
1888
|
-
## Type Safety
|
|
1889
|
-
|
|
1890
|
-
xbind returns `Result<T, E>` types for type-safe error handling.
|
|
1891
|
-
|
|
1892
|
-
<!-- SNIPPET -->
|
|
1893
|
-
```typescript
|
|
1894
|
-
import { call, type CallResult } from '@private.me/xbind';
|
|
1895
|
-
|
|
1896
|
-
interface User { id: number; name: string; email: string; }
|
|
1897
|
-
|
|
1898
|
-
const result: CallResult<User> = await call('getUser', { id: 123 });
|
|
1899
|
-
if (result.ok) {
|
|
1900
|
-
console.log(result.value.data.name);
|
|
1901
|
-
console.log(result.value.audit.signature);
|
|
1902
|
-
} else {
|
|
1903
|
-
console.error(result.error.message);
|
|
1904
|
-
}
|
|
1905
|
-
```
|
|
1906
|
-
<!-- /SNIPPET -->
|
|
1907
|
-
|
|
1908
|
-
Error types: `ConnectionError`, `AuthenticationError`, `ValidationError`, `RateLimitError`, `ServerError`
|
|
1909
|
-
|
|
1910
|
-
## Documentation
|
|
1911
|
-
|
|
1912
|
-
- **[API Reference](./docs/api-reference.md)** — Complete API documentation
|
|
1913
|
-
- **[Configuration Guide](./docs/configuration.md)** — All configuration options
|
|
1914
|
-
- **[Examples](./docs/examples.md)** — Common usage patterns
|
|
1915
|
-
- **[Troubleshooting](./docs/troubleshooting.md)** — Common issues and solutions
|
|
1916
|
-
- **[Advanced Guide](./docs/advanced.md)** — Multi-backend failover, retry strategies
|
|
1917
|
-
- **[White Paper](https://private.me/docs/xbind.html)** — Architecture and design
|
|
1918
|
-
- **[AGENTS.md](./AGENTS.md)** — AI agent patterns
|
|
1919
|
-
- **[SECURITY.md](./SECURITY.md)** — Threat model
|
|
1920
|
-
|
|
1921
|
-
## Testing
|
|
1922
|
-
|
|
1923
|
-
**1,245/1,245 tests passing** — Comprehensive coverage including post-quantum cryptography (ML-KEM-768, ML-DSA-65), hybrid signature verification, DID generation, message encryption, transport layer, multi-agent coordination, error handling, Python SDK bindings, and Full Control protection.
|
|
1924
|
-
|
|
1925
|
-
```bash
|
|
1926
|
-
pnpm test # All tests
|
|
1927
|
-
pnpm test:coverage # Coverage report
|
|
1928
|
-
pnpm test:watch # Watch mode
|
|
1929
|
-
```
|
|
1930
|
-
|
|
1931
|
-
## Full Control IP Protection
|
|
1932
|
-
|
|
1933
|
-
xBind uses **Full Control** (2-share XorIDA) to protect proprietary cryptographic algorithms while maintaining a seamless developer experience.
|
|
1934
|
-
|
|
1935
|
-
### Architecture: Store Front + Vault Store
|
|
1936
|
-
|
|
1937
|
-
**Store Front (npm registry):**
|
|
1938
|
-
- Contains wrapper code, types, and non-proprietary utilities
|
|
1939
|
-
- Includes Share 1 (`share1.dat`) — useless alone, safe to distribute publicly
|
|
1940
|
-
- Installed via standard `npm install @private.me/xbind`
|
|
1941
|
-
|
|
1942
|
-
**Vault Store (private.me gateway):**
|
|
1943
|
-
- Contains Share 2 (encrypted, payment-gated)
|
|
1944
|
-
- Delivered via `/api/vault-store/crypto` endpoint
|
|
1945
|
-
- Requires xBind DID authentication + usage quota verification
|
|
1946
|
-
- AES-256-GCM encrypted with `FULL_CONTROL_MASTER_KEY`
|
|
1947
|
-
|
|
1948
|
-
When combined, Share 1 + Share 2 reconstruct the complete XorIDA algorithm at runtime.
|
|
1949
|
-
|
|
1950
|
-
### Usage-Based Access Model
|
|
1951
|
-
|
|
1952
|
-
**IMPORTANT:** Full Control uses **usage-based metering**, NOT feature-gating.
|
|
1953
|
-
|
|
1954
|
-
**All tiers** can access the Vault Store (crypto algorithms + Share 2) **within their usage quota**:
|
|
1955
|
-
|
|
1956
|
-
- **Free Tier:** 100,000 operations/month
|
|
1957
|
-
- Grace buffer: 120,000 hard cap (includes 20% overage)
|
|
1958
|
-
- Email verification required
|
|
1959
|
-
- Vault access included (no additional payment needed)
|
|
1960
|
-
- At 120K ops: 402 Quota Exceeded → Upgrade prompt
|
|
1961
|
-
|
|
1962
|
-
- **Pro Tier:** Unlimited operations
|
|
1963
|
-
- $5 per 100,000 operations (after first 100K free)
|
|
1964
|
-
- No quota checks
|
|
1965
|
-
- Vault access unlimited
|
|
1966
|
-
- Example: 400K ops = $15/month (100K free + 300K @ $5/100K)
|
|
1967
|
-
|
|
1968
|
-
- **VIP Tier:** Custom limits per account
|
|
1969
|
-
- Bronze: 200K, Silver: 500K, Gold: 1M, Platinum: Unlimited
|
|
1970
|
-
- Vault access within custom quota
|
|
1971
|
-
|
|
1972
|
-
### Upgrade to Pro
|
|
1973
|
-
|
|
1974
|
-
If you exceed the free tier quota, upgrade to Pro for unlimited operations:
|
|
1975
|
-
|
|
1976
|
-
```bash
|
|
1977
|
-
# Visit the upgrade page
|
|
1978
|
-
https://private.me/subscribe?product=xbind&tier=pro
|
|
1979
|
-
|
|
1980
|
-
# Or upgrade programmatically via xBind API
|
|
1981
|
-
const result = await agent.send({
|
|
1982
|
-
to: 'did:key:z6MkBillingService...',
|
|
1983
|
-
payload: { action: 'upgradeTier', tier: 'pro' }
|
|
1984
|
-
});
|
|
1985
|
-
```
|
|
1986
|
-
|
|
1987
|
-
### 4-Layer Security
|
|
1988
|
-
|
|
1989
|
-
1. **DID Authentication:** Ed25519 signature verification (cryptographic proof of identity)
|
|
1990
|
-
2. **Usage Quota Verification:** Monthly operation count checked against tier limits
|
|
1991
|
-
3. **Rate Limiting:** Free: 100 req/hour, Pro: 1000 req/hour, VIP: 5000 req/hour
|
|
1992
|
-
4. **Audit Logging:** Every vault access logged with DID, timestamp, IP, and success status
|
|
1993
|
-
|
|
1994
|
-
### Runtime Flow
|
|
1995
|
-
|
|
1996
|
-
```typescript
|
|
1997
|
-
// 1. Install package (includes Share 1)
|
|
1998
|
-
// npm install @private.me/xbind
|
|
1999
|
-
|
|
2000
|
-
// 2. Create agent (auto-fetches Share 2 on first use)
|
|
2001
|
-
const agent = await Agent.create(seed);
|
|
2002
|
-
|
|
2003
|
-
// 3. Vault Store loader detects missing crypto
|
|
2004
|
-
// 4. POST /api/vault-store/crypto
|
|
2005
|
-
// - Auth: DID signature
|
|
2006
|
-
// - Verify: Usage quota (Free: <120K, Pro: unlimited)
|
|
2007
|
-
// - Response: { cryptoBundle, share2, version }
|
|
2008
|
-
|
|
2009
|
-
// 5. Load crypto dynamically (Share 1 + Share 2 = complete algorithm)
|
|
2010
|
-
// 6. Cache in memory (session-only, 7-day expiration)
|
|
2011
|
-
// 7. Use reconstructed XorIDA algorithm
|
|
2012
|
-
|
|
2013
|
-
await agent.send({
|
|
2014
|
-
to: recipientDid,
|
|
2015
|
-
payload: { amount: 100, currency: 'BTC' },
|
|
2016
|
-
security: 'high' // Uses XorIDA (2-of-3 threshold)
|
|
2017
|
-
});
|
|
2018
|
-
```
|
|
2019
|
-
|
|
2020
|
-
### Why This Matters
|
|
2021
|
-
|
|
2022
|
-
**Without Full Control:**
|
|
2023
|
-
- Complete XorIDA algorithm exposed in npm tarball
|
|
2024
|
-
- Anyone can download and use without payment
|
|
2025
|
-
- Patent protection (US 11,972,000) defeated
|
|
2026
|
-
- Revenue model bypassed
|
|
2027
|
-
|
|
2028
|
-
**With Full Control:**
|
|
2029
|
-
- Share 1 alone is mathematically useless (information-theoretic security)
|
|
2030
|
-
- Share 2 requires usage-based quota verification
|
|
2031
|
-
- Patent-protected algorithms delivered only to paying users (or within free tier quota)
|
|
2032
|
-
- Reverse engineering requires breaking AES-256-GCM encryption
|
|
2033
|
-
|
|
2034
|
-
**Revenue Protection:**
|
|
2035
|
-
- Free tier: 100K ops/month (generous for experimentation)
|
|
2036
|
-
- Pro tier: Usage-based billing scales with value delivered
|
|
2037
|
-
- DeploymentID tracking prevents quota reset attacks (DID rotation doesn't bypass limits)
|
|
2038
|
-
|
|
2039
|
-
See [IP Protection Documentation](./docs/ip-protection.md) for complete technical details.
|
|
2040
|
-
|
|
2041
|
-
## Data Collection
|
|
2042
|
-
|
|
2043
|
-
xBind makes network connections for three purposes, each with different security and privacy characteristics:
|
|
2044
|
-
|
|
2045
|
-
### 1. Local Network Discovery (Peer Discovery Model Only)
|
|
2046
|
-
|
|
2047
|
-
**When:** Only when using the Peer Discovery connection model for IoT devices and offline pairing.
|
|
2048
|
-
|
|
2049
|
-
**What:** Sends mDNS (multicast DNS) broadcast messages on your local network to discover nearby xBind-compatible devices.
|
|
2050
|
-
|
|
2051
|
-
**Data transmitted:**
|
|
2052
|
-
- Device DID (cryptographic identity, public key)
|
|
2053
|
-
- Device type identifier
|
|
2054
|
-
- Service announcement (port, protocol version)
|
|
2055
|
-
|
|
2056
|
-
**Security:** Broadcast messages are visible to all devices on the local network. Does NOT transmit private keys, message content, or personal data. Recipients cannot impersonate your device without the private key.
|
|
2057
|
-
|
|
2058
|
-
**Privacy:** Other connection models (Invite Code, QR Code, Trust Registry) do NOT use local network discovery.
|
|
2059
|
-
|
|
2060
|
-
### 2. Gateway Communication (gateway.private.me)
|
|
2061
|
-
|
|
2062
|
-
**When:** During message delivery, Share 2 retrieval, and connection establishment.
|
|
2063
|
-
|
|
2064
|
-
**What:** Encrypted communication with gateway.private.me for coordination and IP protection.
|
|
2065
|
-
|
|
2066
|
-
**Data transmitted:**
|
|
2067
|
-
- **Share 2 delivery:** Encrypted share required for Full Control vault store reconstruction (payment-gated)
|
|
2068
|
-
- **Usage metrics:** Operation counts, error codes, latency (anonymized, no message content)
|
|
2069
|
-
- **Connection metadata:** DID identifiers, sequence numbers, checkpoints (for message ordering)
|
|
2070
|
-
- **Push notifications:** Delivery receipts, presence signals (encrypted, no content)
|
|
2071
|
-
|
|
2072
|
-
**Security:** All communication uses TLS 1.3. Gateway is non-authoritative and cannot forge identity or decrypt messages. See [Gateway Architecture](./docs/gateway-architecture.md).
|
|
2073
|
-
|
|
2074
|
-
**Privacy:** No message content, API credentials, or plaintext data transmitted. DIDs are pseudonymous identifiers.
|
|
2075
|
-
|
|
2076
|
-
### 3. Full Control Share Retrieval
|
|
2077
|
-
|
|
2078
|
-
**When:** During initial setup and algorithm reconstruction.
|
|
2079
|
-
|
|
2080
|
-
**What:** Downloads Share 2 (Vault Store) from gateway.private.me after payment verification.
|
|
2081
|
-
|
|
2082
|
-
**Data transmitted:**
|
|
2083
|
-
- Payment proof (Stripe subscription ID)
|
|
2084
|
-
- xBind authentication token (cryptographic proof of identity)
|
|
2085
|
-
- Package identifier and version
|
|
2086
|
-
|
|
2087
|
-
**Security:** Share 2 is AES-256-GCM encrypted with FULL_CONTROL_MASTER_KEY. Without both Share 1 (npm) and Share 2 (gateway), the algorithm cannot execute.
|
|
2088
|
-
|
|
2089
|
-
**Privacy:** Payment verification uses Stripe (see [Stripe Privacy](https://stripe.com/privacy)). xBind does not store credit card data.
|
|
2090
|
-
|
|
2091
|
-
### Data Retention
|
|
2092
|
-
|
|
2093
|
-
- **Usage metrics:** 90 days (aggregated, anonymized)
|
|
2094
|
-
- **Connection metadata:** 30 days (sequence numbers, checkpoints)
|
|
2095
|
-
- **Share 2 downloads:** Access logs retained per payment verification requirements
|
|
2096
|
-
|
|
2097
|
-
### Opt-Out
|
|
2098
|
-
|
|
2099
|
-
**Local network discovery:** Disable by not using Peer Discovery connection model.
|
|
2100
|
-
|
|
2101
|
-
**Gateway communication:** Required for message delivery. Self-hosted gateway option available for enterprise (contact contact@private.me).
|
|
2102
|
-
|
|
2103
|
-
**Usage metrics:** Cannot be disabled (required for billing and abuse prevention).
|
|
2104
|
-
|
|
2105
|
-
For complete privacy details, see [Privacy Policy](https://private.me/privacy).
|
|
2106
|
-
|
|
2107
|
-
## Legal
|
|
2108
|
-
|
|
2109
|
-
[Terms of Service](https://private.me/terms) • [Privacy Policy](https://private.me/privacy) • [License](./LICENSE.md)
|
|
2110
|
-
|
|
2111
|
-
## Export Control Notice
|
|
2112
|
-
|
|
2113
|
-
This package contains cryptographic software. Export restrictions may apply. Users are responsible for compliance with U.S. Export Administration Regulations (EAR) and jurisdiction-specific export control requirements.
|
|
2114
|
-
|
|
2115
|
-
---
|
|
2116
|
-
|
|
2117
|
-
**License:** Proprietary
|
|
2118
|
-
|
|
2119
|
-
---
|
|
2120
|
-
|
|
2121
|
-
**Questions?** [Documentation](./docs/README.md) • [White paper](https://private.me/docs/xbind.html) • [Issues](https://github.com/xail-io/xail/issues)
|