@youam/sdk 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +149 -7
- package/dist/cli/index.cjs +2633 -0
- package/dist/index.cjs +2244 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +892 -0
- package/dist/index.d.ts +892 -0
- package/dist/index.js +2218 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -14
- package/index.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sdk/dns-verifier.ts","../src/index.ts","../src/protocol/index.ts","../src/protocol/types.ts","../src/protocol/errors.ts","../src/protocol/address.ts","../src/protocol/crypto.ts","../src/protocol/envelope.ts","../src/protocol/contact.ts","../src/sdk/config.ts","../src/sdk/key-manager.ts","../src/sdk/contact-book.ts","../src/sdk/handshake.ts","../src/sdk/tier3.ts","../src/sdk/resolver.ts","../src/sdk/transport/base.ts","../src/sdk/transport/http.ts","../src/sdk/transport/websocket.ts","../src/sdk/transport/index.ts","../src/sdk/agent.ts","../src/sdk/webhook-verify.ts","../src/sdk/index.ts"],"sourcesContent":["/**\n * DNS domain verification for UAM Tier 2 addresses (DNS-01, DNS-03).\n *\n * Provides TXT record parsing, HTTPS .well-known fallback resolution,\n * and helper functions for domain ownership verification.\n *\n * TXT record format (at `_uam.{domain}`):\n *\n * v=uam1; key=ed25519:<base64-pubkey>; relay=<relay-url>\n *\n * Matches Python dns_verifier.py API surface.\n */\n\nimport { resolveTxt as dnsResolveTxt } from \"node:dns/promises\";\n\n/**\n * Parse a UAM TXT record value into tag-value pairs.\n *\n * Format: `v=uam1; key=ed25519:<base64>; relay=https://...`\n *\n * Tag names are lowercased for case-insensitive matching.\n * Unknown tags are preserved (forward compatibility).\n */\nexport function parseUamTxt(txtValue: string): Record<string, string> {\n const tags: Record<string, string> = {};\n for (const part of txtValue.split(\";\")) {\n const trimmed = part.trim();\n if (!trimmed) continue;\n const eqIdx = trimmed.indexOf(\"=\");\n if (eqIdx !== -1) {\n const tag = trimmed.slice(0, eqIdx).trim().toLowerCase();\n const value = trimmed.slice(eqIdx + 1).trim();\n tags[tag] = value;\n }\n }\n return tags;\n}\n\n/**\n * Extract the base64 public key from parsed UAM TXT tags.\n *\n * Strips the `ed25519:` prefix. Returns `null` if the key\n * tag is missing or does not have the expected prefix.\n */\nexport function extractPublicKey(\n tags: Record<string, string>\n): string | null {\n const keyValue = tags[\"key\"] ?? \"\";\n if (keyValue.startsWith(\"ed25519:\")) {\n return keyValue.slice(\"ed25519:\".length);\n }\n return null;\n}\n\n/**\n * Query `_uam.{domain}` for UAM TXT records.\n *\n * Returns a list of TXT record values that start with `v=uam1`.\n * Returns an empty list if no matching records are found or on any\n * DNS error.\n */\nexport async function queryUamTxt(\n domain: string,\n timeout?: number\n): Promise<string[]> {\n // Node dns/promises does not support per-call timeout natively.\n // We use AbortController for cancellation.\n const controller = new AbortController();\n const timer =\n timeout != null\n ? setTimeout(() => controller.abort(), timeout)\n : undefined;\n\n try {\n const records = await dnsResolveTxt(`_uam.${domain}`);\n\n // Each record is an array of strings (multi-part TXT).\n // Concatenate parts and filter for v=uam1.\n const results: string[] = [];\n for (const parts of records) {\n const txtValue = parts.join(\"\");\n if (txtValue.trim().startsWith(\"v=uam1\")) {\n results.push(txtValue);\n }\n }\n return results;\n } catch {\n // NXDOMAIN, SERVFAIL, etc. -- return empty\n return [];\n } finally {\n if (timer != null) clearTimeout(timer);\n }\n}\n\n/**\n * Resolve an agent's public key from `.well-known/uam.json` HTTPS fallback.\n *\n * Returns the base64 public key string, or `null` if the agent is not\n * found or the request fails.\n */\nexport async function resolveKeyViaHttps(\n agentName: string,\n domain: string,\n timeout?: number\n): Promise<string | null> {\n const url = `https://${domain}/.well-known/uam.json`;\n\n try {\n const resp = await fetch(url, {\n signal: AbortSignal.timeout(timeout ?? 10000),\n });\n if (!resp.ok) return null;\n\n const data = (await resp.json()) as Record<string, unknown>;\n if (data[\"v\"] !== \"uam1\") return null;\n\n const agents = (data[\"agents\"] ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n const entry = agents[agentName];\n if (!entry) return null;\n\n let keyValue = (entry[\"key\"] as string) ?? \"\";\n if (keyValue.startsWith(\"ed25519:\")) {\n keyValue = keyValue.slice(\"ed25519:\".length);\n }\n return keyValue || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Generate the TXT record value an agent should publish at `_uam.{domain}`.\n *\n * Returns a formatted string like:\n * `v=uam1; key=ed25519:<publicKey>; relay=<relayUrl>`\n */\nexport function generateTxtRecord(\n publicKey: string,\n relayUrl: string\n): string {\n return `v=uam1; key=ed25519:${publicKey}; relay=${relayUrl}`;\n}\n","/**\n * UAM -- Universal Agent Messaging.\n *\n * Top-level package exports: Agent, ReceivedMessage, protocol.\n */\n\nexport { Agent } from \"./sdk/index.js\";\nexport type { ReceivedMessage } from \"./sdk/index.js\";\nexport * as protocol from \"./protocol/index.js\";\n","/**\n * UAM Protocol -- Universal Agent Messaging protocol library.\n *\n * Public API re-exports for the protocol layer.\n */\n\n// Types\nexport {\n UAM_VERSION,\n MAX_ENVELOPE_SIZE,\n MessageType,\n b64Encode,\n b64Decode,\n utcTimestamp,\n} from \"./types.js\";\n\n// Errors\nexport {\n UAMError,\n InvalidAddressError,\n InvalidEnvelopeError,\n EnvelopeTooLargeError,\n SignatureError,\n SignatureVerificationError,\n EncryptionError,\n DecryptionError,\n InvalidContactCardError,\n KeyPinningError,\n} from \"./errors.js\";\n\n// Address\nexport { type Address, parseAddress } from \"./address.js\";\n\n// Crypto\nexport {\n sodiumReady,\n type SigningKey,\n type VerifyKey,\n type Seed,\n type Keypair,\n generateKeypair,\n serializeSigningKey,\n deserializeSigningKey,\n serializeVerifyKey,\n deserializeVerifyKey,\n publicKeyFingerprint,\n canonicalize,\n signMessage,\n verifySignature,\n generateNonce,\n encryptPayload,\n decryptPayload,\n encryptPayloadAnonymous,\n decryptPayloadAnonymous,\n} from \"./crypto.js\";\n\n// Envelope\nexport {\n type MessageEnvelope,\n createEnvelope,\n verifyEnvelope,\n toWireDict,\n fromWireDict,\n validateEnvelopeSize,\n} from \"./envelope.js\";\n\n// Contact\nexport {\n type ContactCard,\n createContactCard,\n verifyContactCard,\n contactCardToDict,\n contactCardFromDict,\n} from \"./contact.js\";\n","/**\n * Core types, constants, and utility functions for UAM protocol.\n */\n\n/** Protocol version. */\nexport const UAM_VERSION = \"0.1\";\n\n/** Maximum envelope size in bytes (64 KB). */\nexport const MAX_ENVELOPE_SIZE = 65536;\n\n/** All UAM message types. */\nexport enum MessageType {\n MESSAGE = \"message\",\n HANDSHAKE_REQUEST = \"handshake.request\",\n HANDSHAKE_ACCEPT = \"handshake.accept\",\n HANDSHAKE_DENY = \"handshake.deny\",\n RECEIPT_DELIVERED = \"receipt.delivered\",\n RECEIPT_READ = \"receipt.read\",\n RECEIPT_FAILED = \"receipt.failed\",\n SESSION_REQUEST = \"session.request\",\n SESSION_ACCEPT = \"session.accept\",\n SESSION_DECLINE = \"session.decline\",\n SESSION_END = \"session.end\",\n}\n\n/**\n * URL-safe base64 encode, stripping padding.\n */\nexport function b64Encode(data: Uint8Array): string {\n return Buffer.from(data).toString(\"base64url\");\n}\n\n/**\n * URL-safe base64 decode, tolerating missing padding.\n */\nexport function b64Decode(s: string): Uint8Array {\n return new Uint8Array(Buffer.from(s, \"base64url\"));\n}\n\n/**\n * Return a canonical UTC timestamp: YYYY-MM-DDTHH:MM:SS.mmmZ\n */\nexport function utcTimestamp(): string {\n return new Date().toISOString();\n}\n","/**\n * UAM exception hierarchy.\n *\n * All protocol-specific errors inherit from UAMError.\n */\n\n/** Base error for all UAM protocol errors. */\nexport class UAMError extends Error {\n constructor(message?: string) {\n super(message);\n this.name = \"UAMError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Raised when an address string fails validation. */\nexport class InvalidAddressError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"InvalidAddressError\";\n }\n}\n\n/** Raised when an envelope fails schema validation. */\nexport class InvalidEnvelopeError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"InvalidEnvelopeError\";\n }\n}\n\n/** Raised when an envelope exceeds the maximum allowed size. */\nexport class EnvelopeTooLargeError extends InvalidEnvelopeError {\n constructor(message?: string) {\n super(message);\n this.name = \"EnvelopeTooLargeError\";\n }\n}\n\n/** Raised on signing failures. */\nexport class SignatureError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"SignatureError\";\n }\n}\n\n/** Raised when a cryptographic signature cannot be verified. */\nexport class SignatureVerificationError extends SignatureError {\n constructor(message?: string) {\n super(message);\n this.name = \"SignatureVerificationError\";\n }\n}\n\n/** Raised on encryption failures. */\nexport class EncryptionError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"EncryptionError\";\n }\n}\n\n/** Raised on decryption failures. */\nexport class DecryptionError extends EncryptionError {\n constructor(message?: string) {\n super(message);\n this.name = \"DecryptionError\";\n }\n}\n\n/** Raised when a contact card fails validation. */\nexport class InvalidContactCardError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"InvalidContactCardError\";\n }\n}\n\n/** Raised when a pinned contact's public key doesn't match the resolved key. */\nexport class KeyPinningError extends UAMError {\n constructor(message?: string) {\n super(message);\n this.name = \"KeyPinningError\";\n Object.setPrototypeOf(this, KeyPinningError.prototype);\n }\n}\n","/**\n * UAM address parsing and validation.\n *\n * A UAM address has the form `agent::domain` (e.g. `alice::youam.network`).\n */\n\nimport { InvalidAddressError } from \"./errors.js\";\n\n/**\n * A parsed UAM address (always lowercase).\n */\nexport interface Address {\n readonly agent: string;\n readonly domain: string;\n readonly full: string;\n}\n\n// Agent: 1-64 chars, lowercase alphanumeric + hyphen + underscore.\n// Cannot start or end with hyphen.\n// Domain: standard DNS-style, 1-255 chars.\nconst ADDRESS_RE =\n /^(?<agent>[a-z0-9][a-z0-9_-]{0,62}[a-z0-9]|[a-z0-9])::(?<domain>[a-z0-9](?:[a-z0-9.-]{0,253}[a-z0-9])?)$/;\n\nconst MAX_AGENT_LEN = 64;\nconst MAX_ADDRESS_LEN = 128;\n\n/**\n * Parse and validate a UAM address string.\n *\n * Strips whitespace, lowercases, and validates format.\n * Enforces max lengths: agent <= 64 chars, full address <= 128 chars.\n *\n * @throws {InvalidAddressError} If `raw` is not a valid `agent::domain` address.\n */\nexport function parseAddress(raw: string): Address {\n const normalized = raw.trim().toLowerCase();\n if (normalized.length > MAX_ADDRESS_LEN) {\n throw new InvalidAddressError(\n `Address exceeds ${MAX_ADDRESS_LEN} characters: ${JSON.stringify(raw)}`\n );\n }\n const m = ADDRESS_RE.exec(normalized);\n if (!m || !m.groups) {\n throw new InvalidAddressError(\n `Invalid UAM address: ${JSON.stringify(raw)}`\n );\n }\n const agent = m.groups.agent;\n if (agent.length > MAX_AGENT_LEN) {\n throw new InvalidAddressError(\n `Agent name exceeds ${MAX_AGENT_LEN} characters: ${JSON.stringify(raw)}`\n );\n }\n return {\n agent,\n domain: m.groups.domain,\n get full() {\n return `${this.agent}::${this.domain}`;\n },\n };\n}\n","/**\n * Cryptographic primitives for UAM protocol.\n *\n * Wraps libsodium-wrappers for Ed25519 signing, Curve25519 key exchange,\n * NaCl Box (authenticated encryption), and NaCl SealedBox (anonymous encryption).\n *\n * This module never hand-rolls crypto -- every operation delegates to libsodium.\n */\n\nimport sodium from \"libsodium-wrappers\";\nimport { createHash } from \"node:crypto\";\n\nimport {\n DecryptionError,\n EncryptionError,\n SignatureVerificationError,\n} from \"./errors.js\";\nimport { b64Decode, b64Encode } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Sodium initialization\n// ---------------------------------------------------------------------------\n\n/**\n * Promise that resolves when libsodium is ready.\n * Callers must await this before first use of any crypto function.\n */\nexport const sodiumReady: Promise<void> = sodium.ready;\n\n// ---------------------------------------------------------------------------\n// Key type aliases\n// ---------------------------------------------------------------------------\n\n/** 64-byte Ed25519 secret key (seed + public). */\nexport type SigningKey = Uint8Array;\n\n/** 32-byte Ed25519 public key. */\nexport type VerifyKey = Uint8Array;\n\n/** 32-byte seed. */\nexport type Seed = Uint8Array;\n\n// ---------------------------------------------------------------------------\n// Key generation and serialization\n// ---------------------------------------------------------------------------\n\nexport interface Keypair {\n signingKey: Uint8Array;\n verifyKey: Uint8Array;\n seed: Uint8Array;\n}\n\n/**\n * Generate an Ed25519 keypair.\n */\nexport function generateKeypair(): Keypair {\n const seed = sodium.randombytes_buf(32);\n const kp = sodium.crypto_sign_seed_keypair(seed);\n return {\n signingKey: kp.privateKey,\n verifyKey: kp.publicKey,\n seed,\n };\n}\n\n/**\n * Serialize a signing key to URL-safe base64 (32-byte seed).\n *\n * Matches Python: PyNaCl's SigningKey.encode() returns the 32-byte seed.\n */\nexport function serializeSigningKey(seed: Uint8Array): string {\n return b64Encode(seed);\n}\n\n/**\n * Restore a signing key from its base64-encoded seed.\n */\nexport function deserializeSigningKey(s: string): Keypair {\n const seed = b64Decode(s);\n const kp = sodium.crypto_sign_seed_keypair(seed);\n return {\n signingKey: kp.privateKey,\n verifyKey: kp.publicKey,\n seed,\n };\n}\n\n/**\n * Serialize a verify (public) key to URL-safe base64.\n */\nexport function serializeVerifyKey(key: Uint8Array): string {\n return b64Encode(key);\n}\n\n/**\n * Restore a verify key from its base64 encoding.\n */\nexport function deserializeVerifyKey(s: string): Uint8Array {\n return b64Decode(s);\n}\n\n/**\n * Return the SHA-256 hex digest of the verify key bytes.\n *\n * This 64-character string serves as the agent's identity fingerprint.\n */\nexport function publicKeyFingerprint(verifyKey: Uint8Array): string {\n return createHash(\"sha256\").update(Buffer.from(verifyKey)).digest(\"hex\");\n}\n\n// ---------------------------------------------------------------------------\n// Canonical JSON\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively sort all object keys and produce compact JSON.\n *\n * Matches Python: json.dumps(data, sort_keys=True, separators=(',',':'), ensure_ascii=True)\n */\nfunction sortedStringify(value: unknown): string {\n if (value === null || value === undefined) {\n return \"null\";\n }\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => sortedStringify(v));\n return \"[\" + items.join(\",\") + \"]\";\n }\n if (typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n const keys = Object.keys(obj).sort();\n const pairs = keys.map((k) => JSON.stringify(k) + \":\" + sortedStringify(obj[k]));\n return \"{\" + pairs.join(\",\") + \"}\";\n }\n return String(value);\n}\n\n/**\n * Produce deterministic JSON bytes for signing.\n *\n * - Excludes the \"signature\" key.\n * - Excludes keys whose value is null or undefined.\n * - Sorts keys, uses compact separators, ensures ASCII encoding.\n */\nexport function canonicalize(data: Record<string, unknown>): Uint8Array {\n const filtered: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(data)) {\n if (k !== \"signature\" && v !== null && v !== undefined) {\n filtered[k] = v;\n }\n }\n const json = sortedStringify(filtered);\n return new TextEncoder().encode(json);\n}\n\n// ---------------------------------------------------------------------------\n// Signing and verification\n// ---------------------------------------------------------------------------\n\n/**\n * Sign data with the Ed25519 signing key.\n *\n * @returns The 64-byte signature as a URL-safe base64 string.\n */\nexport function signMessage(data: Uint8Array, signingKey: Uint8Array): string {\n const signature = sodium.crypto_sign_detached(data, signingKey);\n return b64Encode(signature);\n}\n\n/**\n * Verify an Ed25519 signature.\n *\n * @throws {SignatureVerificationError} If the signature is invalid.\n */\nexport function verifySignature(\n data: Uint8Array,\n signatureB64: string,\n verifyKey: Uint8Array\n): void {\n try {\n const sigBytes = b64Decode(signatureB64);\n const valid = sodium.crypto_sign_verify_detached(sigBytes, data, verifyKey);\n if (!valid) {\n throw new SignatureVerificationError(\"Signature verification failed\");\n }\n } catch (err) {\n if (err instanceof SignatureVerificationError) {\n throw err;\n }\n throw new SignatureVerificationError(\n err instanceof Error ? err.message : String(err)\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Nonce generation\n// ---------------------------------------------------------------------------\n\n/**\n * Generate 24 cryptographically random bytes, returned as base64.\n */\nexport function generateNonce(): string {\n return b64Encode(sodium.randombytes_buf(24));\n}\n\n// ---------------------------------------------------------------------------\n// NaCl Box encryption (authenticated, both parties known)\n// ---------------------------------------------------------------------------\n\n/**\n * Encrypt plaintext using NaCl Box (authenticated encryption).\n *\n * Both parties are known; the sender signs implicitly via key exchange.\n * Format: nonce (24 bytes) || ciphertext, matching PyNaCl Box.encrypt() output.\n *\n * @returns Base64-encoded ciphertext (nonce prepended).\n * @throws {EncryptionError} On any libsodium error.\n */\nexport function encryptPayload(\n plaintext: Uint8Array,\n senderSigningKey: Uint8Array,\n recipientVerifyKey: Uint8Array\n): string {\n try {\n const senderCurve = sodium.crypto_sign_ed25519_sk_to_curve25519(senderSigningKey);\n const recipientCurve = sodium.crypto_sign_ed25519_pk_to_curve25519(recipientVerifyKey);\n const nonce = sodium.randombytes_buf(sodium.crypto_box_NONCEBYTES);\n const encrypted = sodium.crypto_box_easy(plaintext, nonce, recipientCurve, senderCurve);\n // Concatenate nonce || ciphertext (matching PyNaCl format)\n const combined = new Uint8Array(nonce.length + encrypted.length);\n combined.set(nonce, 0);\n combined.set(encrypted, nonce.length);\n return b64Encode(combined);\n } catch (err) {\n if (err instanceof EncryptionError) throw err;\n throw new EncryptionError(err instanceof Error ? err.message : String(err));\n }\n}\n\n/**\n * Decrypt NaCl Box ciphertext.\n *\n * @returns The original plaintext bytes.\n * @throws {DecryptionError} On any libsodium error (wrong keys, tampered data).\n */\nexport function decryptPayload(\n ciphertextB64: string,\n recipientSigningKey: Uint8Array,\n senderVerifyKey: Uint8Array\n): Uint8Array {\n try {\n const combined = b64Decode(ciphertextB64);\n const nonce = combined.slice(0, sodium.crypto_box_NONCEBYTES);\n const ciphertext = combined.slice(sodium.crypto_box_NONCEBYTES);\n const recipientCurve = sodium.crypto_sign_ed25519_sk_to_curve25519(recipientSigningKey);\n const senderCurve = sodium.crypto_sign_ed25519_pk_to_curve25519(senderVerifyKey);\n return sodium.crypto_box_open_easy(ciphertext, nonce, senderCurve, recipientCurve);\n } catch (err) {\n if (err instanceof DecryptionError) throw err;\n throw new DecryptionError(err instanceof Error ? err.message : String(err));\n }\n}\n\n// ---------------------------------------------------------------------------\n// NaCl SealedBox encryption (anonymous sender)\n// ---------------------------------------------------------------------------\n\n/**\n * Encrypt plaintext using NaCl SealedBox (anonymous sender).\n *\n * Only the recipient's public key is required; no sender authentication.\n *\n * @returns Base64-encoded ciphertext.\n */\nexport function encryptPayloadAnonymous(\n plaintext: Uint8Array,\n recipientVerifyKey: Uint8Array\n): string {\n const recipientCurve = sodium.crypto_sign_ed25519_pk_to_curve25519(recipientVerifyKey);\n const ciphertext = sodium.crypto_box_seal(plaintext, recipientCurve);\n return b64Encode(ciphertext);\n}\n\n/**\n * Decrypt NaCl SealedBox ciphertext.\n *\n * @returns The original plaintext bytes.\n * @throws {DecryptionError} On any libsodium error.\n */\nexport function decryptPayloadAnonymous(\n ciphertextB64: string,\n recipientSigningKey: Uint8Array\n): Uint8Array {\n try {\n const ciphertext = b64Decode(ciphertextB64);\n const recipientCurveSk = sodium.crypto_sign_ed25519_sk_to_curve25519(recipientSigningKey);\n // Extract the public key from the signing key (last 32 bytes of the 64-byte Ed25519 secret key)\n const recipientVerifyKey = recipientSigningKey.slice(32);\n const recipientCurvePk = sodium.crypto_sign_ed25519_pk_to_curve25519(recipientVerifyKey);\n return sodium.crypto_box_seal_open(ciphertext, recipientCurvePk, recipientCurveSk);\n } catch (err) {\n if (err instanceof DecryptionError) throw err;\n throw new DecryptionError(err instanceof Error ? err.message : String(err));\n }\n}\n","/**\n * UAM message envelope -- creation, signing, verification, wire format.\n *\n * An envelope wraps every UAM message with cryptographic signatures and\n * encrypted payloads, using fromAddress/toAddress naming internally\n * (\"from\"/\"to\" on the wire).\n */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport { parseAddress } from \"./address.js\";\nimport {\n canonicalize,\n encryptPayload,\n encryptPayloadAnonymous,\n generateNonce,\n signMessage,\n verifySignature,\n} from \"./crypto.js\";\nimport { EnvelopeTooLargeError, InvalidEnvelopeError } from \"./errors.js\";\nimport { MAX_ENVELOPE_SIZE, MessageType, UAM_VERSION, utcTimestamp } from \"./types.js\";\n\n/**\n * Required wire-format field names (using \"from\"/\"to\").\n */\nconst REQUIRED_WIRE_FIELDS = new Set([\n \"uam_version\",\n \"message_id\",\n \"from\",\n \"to\",\n \"timestamp\",\n \"type\",\n \"nonce\",\n \"payload\",\n \"signature\",\n]);\n\n/**\n * A signed, encrypted UAM message envelope.\n */\nexport interface MessageEnvelope {\n // Required fields\n readonly uamVersion: string;\n readonly messageId: string;\n readonly fromAddress: string;\n readonly toAddress: string;\n readonly timestamp: string;\n readonly type: string;\n readonly nonce: string;\n readonly payload: string;\n readonly signature: string;\n\n // Optional fields\n readonly threadId?: string;\n readonly replyTo?: string;\n readonly expires?: string;\n readonly mediaType?: string;\n readonly metadata?: Record<string, unknown>;\n\n // v1.1 fields -- NOT in signature scope\n readonly attachments?: Array<Record<string, unknown>>;\n}\n\n/**\n * Build the dict used for signature computation.\n *\n * Maps TypeScript names to wire names (fromAddress -> \"from\").\n * Excludes signature and any optional field that is undefined.\n */\nfunction buildSignableDict(\n envelope: MessageEnvelope\n): Record<string, unknown> {\n const d: Record<string, unknown> = {\n uam_version: envelope.uamVersion,\n message_id: envelope.messageId,\n from: envelope.fromAddress,\n to: envelope.toAddress,\n timestamp: envelope.timestamp,\n type: envelope.type,\n nonce: envelope.nonce,\n payload: envelope.payload,\n };\n if (envelope.threadId !== undefined) d[\"thread_id\"] = envelope.threadId;\n if (envelope.replyTo !== undefined) d[\"reply_to\"] = envelope.replyTo;\n if (envelope.expires !== undefined) d[\"expires\"] = envelope.expires;\n if (envelope.mediaType !== undefined) d[\"media_type\"] = envelope.mediaType;\n if (envelope.metadata !== undefined) d[\"metadata\"] = envelope.metadata;\n return d;\n}\n\n/**\n * Convert an envelope to a wire-format dict.\n *\n * Maps fromAddress -> \"from\" and toAddress -> \"to\".\n * Excludes undefined-valued optional fields.\n */\nexport function toWireDict(\n envelope: MessageEnvelope\n): Record<string, unknown> {\n const d = buildSignableDict(envelope);\n d[\"signature\"] = envelope.signature;\n if (envelope.attachments !== undefined) {\n d[\"attachments\"] = envelope.attachments;\n }\n return d;\n}\n\n/**\n * Restore an envelope from a wire-format dict.\n *\n * @throws {InvalidEnvelopeError} If any required field is missing.\n */\nexport function fromWireDict(\n d: Record<string, unknown>\n): MessageEnvelope {\n const keys = new Set(Object.keys(d));\n const missing: string[] = [];\n for (const field of REQUIRED_WIRE_FIELDS) {\n if (!keys.has(field)) missing.push(field);\n }\n if (missing.length > 0) {\n missing.sort();\n throw new InvalidEnvelopeError(\n `Missing required fields: ${JSON.stringify(missing)}`\n );\n }\n\n return Object.freeze({\n uamVersion: d[\"uam_version\"] as string,\n messageId: d[\"message_id\"] as string,\n fromAddress: d[\"from\"] as string,\n toAddress: d[\"to\"] as string,\n timestamp: d[\"timestamp\"] as string,\n type: d[\"type\"] as string,\n nonce: d[\"nonce\"] as string,\n payload: d[\"payload\"] as string,\n signature: d[\"signature\"] as string,\n threadId: d[\"thread_id\"] as string | undefined,\n replyTo: d[\"reply_to\"] as string | undefined,\n expires: d[\"expires\"] as string | undefined,\n mediaType: d[\"media_type\"] as string | undefined,\n metadata: d[\"metadata\"] as Record<string, unknown> | undefined,\n attachments: d[\"attachments\"] as Array<Record<string, unknown>> | undefined,\n });\n}\n\n/**\n * Check that the serialized envelope does not exceed MAX_ENVELOPE_SIZE.\n *\n * @throws {EnvelopeTooLargeError} If the wire JSON exceeds 64 KB.\n */\nexport function validateEnvelopeSize(envelope: MessageEnvelope): void {\n const wire = toWireDict(envelope);\n const json = JSON.stringify(wire);\n const size = new TextEncoder().encode(json).length;\n if (size > MAX_ENVELOPE_SIZE) {\n throw new EnvelopeTooLargeError(\n `Envelope size ${size} bytes exceeds maximum ${MAX_ENVELOPE_SIZE} bytes`\n );\n }\n}\n\n/**\n * Create a signed, encrypted message envelope.\n *\n * @throws {InvalidAddressError} If either address is invalid.\n * @throws {EnvelopeTooLargeError} If the serialized envelope exceeds 64 KB.\n */\nexport async function createEnvelope(\n fromAddress: string,\n toAddress: string,\n messageType: MessageType | string,\n payloadPlaintext: Uint8Array,\n signingKey: Uint8Array,\n recipientVerifyKey: Uint8Array,\n options?: {\n threadId?: string;\n replyTo?: string;\n expires?: string;\n mediaType?: string;\n metadata?: Record<string, unknown>;\n attachments?: Array<Record<string, unknown>>;\n }\n): Promise<MessageEnvelope> {\n // Normalize message type\n const typeValue =\n typeof messageType === \"string\"\n ? messageType\n : (messageType as string);\n\n // Step 1: Validate addresses\n parseAddress(fromAddress);\n parseAddress(toAddress);\n\n // Step 2: Generate identifiers\n const messageId = randomUUID();\n const nonce = generateNonce();\n const timestamp = utcTimestamp();\n\n // Step 3: Encrypt payload\n let encryptedPayload: string;\n if (typeValue === MessageType.HANDSHAKE_REQUEST) {\n encryptedPayload = encryptPayloadAnonymous(payloadPlaintext, recipientVerifyKey);\n } else {\n encryptedPayload = encryptPayload(\n payloadPlaintext,\n signingKey,\n recipientVerifyKey\n );\n }\n\n // Build temporary envelope without signature\n const tempEnvelope: MessageEnvelope = {\n uamVersion: UAM_VERSION,\n messageId,\n fromAddress,\n toAddress,\n timestamp,\n type: typeValue,\n nonce,\n payload: encryptedPayload,\n signature: \"\",\n threadId: options?.threadId,\n replyTo: options?.replyTo,\n expires: options?.expires,\n mediaType: options?.mediaType,\n metadata: options?.metadata,\n attachments: options?.attachments,\n };\n\n // Step 4: Build signable dict, canonicalize, and sign\n const signable = buildSignableDict(tempEnvelope);\n const signature = signMessage(canonicalize(signable), signingKey);\n\n // Step 5: Build final envelope\n const finalEnvelope: MessageEnvelope = Object.freeze({\n uamVersion: UAM_VERSION,\n messageId,\n fromAddress,\n toAddress,\n timestamp,\n type: typeValue,\n nonce,\n payload: encryptedPayload,\n signature,\n threadId: options?.threadId,\n replyTo: options?.replyTo,\n expires: options?.expires,\n mediaType: options?.mediaType,\n metadata: options?.metadata,\n attachments: options?.attachments,\n });\n\n // Step 6: Validate size\n validateEnvelopeSize(finalEnvelope);\n\n return finalEnvelope;\n}\n\n/**\n * Verify the cryptographic signature on an envelope.\n *\n * @throws {SignatureVerificationError} If the signature is invalid.\n */\nexport function verifyEnvelope(\n envelope: MessageEnvelope,\n senderVerifyKey: Uint8Array\n): void {\n const signable = buildSignableDict(envelope);\n verifySignature(canonicalize(signable), envelope.signature, senderVerifyKey);\n}\n","/**\n * UAM contact cards -- self-signed agent identity documents.\n *\n * A contact card advertises an agent's address, public key, relay endpoint,\n * and optional metadata. The card is signed by the agent's own signing key\n * so that any recipient can verify authenticity using the embedded public key.\n */\n\nimport { parseAddress } from \"./address.js\";\nimport {\n canonicalize,\n deserializeVerifyKey,\n publicKeyFingerprint,\n serializeVerifyKey,\n signMessage,\n verifySignature,\n} from \"./crypto.js\";\nimport { InvalidContactCardError } from \"./errors.js\";\nimport { UAM_VERSION } from \"./types.js\";\n\n/**\n * A self-signed agent identity card.\n */\nexport interface ContactCard {\n readonly version: string;\n readonly address: string;\n readonly displayName: string;\n readonly description?: string;\n readonly system?: string;\n readonly connectionEndpoint?: string;\n readonly relay: string;\n readonly publicKey: string;\n readonly signature: string;\n readonly verifiedDomain?: string;\n readonly payloadFormats?: string[];\n readonly fingerprint?: string;\n /** CARD-04: Multi-relay support. Outside signature scope. */\n readonly relays?: string[];\n}\n\n/**\n * Build the dict used for signature computation.\n *\n * Includes all fields except signature, payload_formats, fingerprint, relays.\n * Excludes undefined-valued optional fields.\n */\nfunction buildSignableDict(card: ContactCard): Record<string, unknown> {\n const d: Record<string, unknown> = {\n version: card.version,\n address: card.address,\n display_name: card.displayName,\n relay: card.relay,\n public_key: card.publicKey,\n };\n if (card.description !== undefined) d[\"description\"] = card.description;\n if (card.system !== undefined) d[\"system\"] = card.system;\n if (card.connectionEndpoint !== undefined) {\n d[\"connection_endpoint\"] = card.connectionEndpoint;\n }\n if (card.verifiedDomain !== undefined) {\n d[\"verified_domain\"] = card.verifiedDomain;\n }\n return d;\n}\n\n/**\n * Serialize a contact card to a plain dict.\n *\n * Uses snake_case names on the wire, excludes undefined-valued optional fields.\n */\nexport function contactCardToDict(\n card: ContactCard\n): Record<string, unknown> {\n const d = buildSignableDict(card);\n d[\"signature\"] = card.signature;\n if (card.payloadFormats !== undefined) {\n d[\"payload_formats\"] = card.payloadFormats;\n }\n if (card.fingerprint !== undefined) {\n d[\"fingerprint\"] = card.fingerprint;\n }\n if (card.relays !== undefined) {\n d[\"relays\"] = card.relays;\n }\n return d;\n}\n\n/**\n * Deserialize a contact card from a dict.\n *\n * When verify is true (the default), the card's signature is checked\n * immediately after deserialization.\n *\n * @throws {InvalidContactCardError} If required fields are missing.\n * @throws {SignatureVerificationError} If verify is true and the signature is invalid.\n */\nexport function contactCardFromDict(\n d: Record<string, unknown>,\n options?: { verify?: boolean }\n): ContactCard {\n const verify = options?.verify ?? true;\n\n const required = new Set([\n \"version\",\n \"address\",\n \"display_name\",\n \"relay\",\n \"public_key\",\n \"signature\",\n ]);\n const keys = new Set(Object.keys(d));\n const missing: string[] = [];\n for (const field of required) {\n if (!keys.has(field)) missing.push(field);\n }\n if (missing.length > 0) {\n missing.sort();\n throw new InvalidContactCardError(\n `Missing required fields: ${JSON.stringify(missing)}`\n );\n }\n\n const card: ContactCard = Object.freeze({\n version: d[\"version\"] as string,\n address: d[\"address\"] as string,\n displayName: d[\"display_name\"] as string,\n description: d[\"description\"] as string | undefined,\n system: d[\"system\"] as string | undefined,\n connectionEndpoint: d[\"connection_endpoint\"] as string | undefined,\n relay: d[\"relay\"] as string,\n publicKey: d[\"public_key\"] as string,\n signature: d[\"signature\"] as string,\n verifiedDomain: d[\"verified_domain\"] as string | undefined,\n payloadFormats: d[\"payload_formats\"] as string[] | undefined,\n fingerprint: d[\"fingerprint\"] as string | undefined,\n relays: d[\"relays\"] as string[] | undefined,\n });\n\n if (verify) {\n verifyContactCard(card);\n }\n\n return card;\n}\n\n/**\n * Create a self-signed contact card.\n *\n * payloadFormats defaults to [\"text/plain\", \"text/markdown\"] when not specified.\n * The fingerprint is always auto-computed as the SHA-256 hex digest of the\n * Ed25519 public key bytes.\n *\n * @throws {InvalidAddressError} If address is not valid.\n */\nexport async function createContactCard(\n address: string,\n displayName: string,\n relay: string,\n signingKey: Uint8Array,\n options?: {\n description?: string;\n system?: string;\n connectionEndpoint?: string;\n verifiedDomain?: string;\n payloadFormats?: string[];\n relays?: string[];\n }\n): Promise<ContactCard> {\n // Validate address\n parseAddress(address);\n\n // Derive public key and fingerprint\n // The verify key is the last 32 bytes of the 64-byte signing key\n const verifyKey = signingKey.slice(32);\n const pubKeyB64 = serializeVerifyKey(verifyKey);\n const fp = publicKeyFingerprint(verifyKey);\n\n // Default payload formats\n const payloadFormats = options?.payloadFormats ?? [\n \"text/plain\",\n \"text/markdown\",\n ];\n\n // Build temporary card without signature\n const tempCard: ContactCard = {\n version: UAM_VERSION,\n address,\n displayName,\n description: options?.description,\n system: options?.system,\n connectionEndpoint: options?.connectionEndpoint,\n relay,\n publicKey: pubKeyB64,\n signature: \"\",\n verifiedDomain: options?.verifiedDomain,\n payloadFormats,\n fingerprint: fp,\n relays: options?.relays,\n };\n\n // Sign (payload_formats, fingerprint, relays are NOT in signable dict)\n const signable = buildSignableDict(tempCard);\n const signature = signMessage(canonicalize(signable), signingKey);\n\n // Return final card\n return Object.freeze({\n version: UAM_VERSION,\n address,\n displayName,\n description: options?.description,\n system: options?.system,\n connectionEndpoint: options?.connectionEndpoint,\n relay,\n publicKey: pubKeyB64,\n signature,\n verifiedDomain: options?.verifiedDomain,\n payloadFormats,\n fingerprint: fp,\n relays: options?.relays,\n });\n}\n\n/**\n * Verify a contact card's signature using its embedded public key.\n *\n * @throws {InvalidContactCardError} If the address is invalid.\n * @throws {SignatureVerificationError} If the signature is invalid.\n */\nexport function verifyContactCard(card: ContactCard): void {\n // Validate address format\n try {\n parseAddress(card.address);\n } catch (err) {\n throw new InvalidContactCardError(\n `Invalid address in contact card: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n\n // Deserialize the embedded public key\n const vk = deserializeVerifyKey(card.publicKey);\n\n // Verify signature\n const signable = buildSignableDict(card);\n verifySignature(canonicalize(signable), card.signature, vk);\n}\n","/**\n * SDK configuration (matching Python config.py).\n *\n * Priority (highest wins): constructor arg > env var > default.\n * TOML config file support is Python-only for now (unnecessary complexity for TS MVP).\n */\n\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nconst DEFAULT_RELAY_URL = \"https://relay.youam.network\";\n\nconst VALID_POLICIES = new Set([\n \"auto-accept\",\n \"approval-required\",\n \"allowlist-only\",\n \"require_verify\",\n]);\n\nexport class SDKConfig {\n readonly name: string;\n readonly relayUrl: string;\n readonly relayWsUrl: string;\n readonly keyDir: string;\n readonly dataDir: string;\n readonly displayName: string;\n readonly transportType: string;\n readonly trustPolicy: string;\n readonly relayDomain: string;\n\n constructor(options: {\n name: string;\n relayUrl?: string | null;\n relayWsUrl?: string | null;\n keyDir?: string | null;\n dataDir?: string | null;\n displayName?: string | null;\n transportType?: string;\n trustPolicy?: string;\n relayDomain?: string;\n }) {\n this.name = options.name;\n\n // Relay URL: constructor arg > env var > default\n this.relayUrl =\n options.relayUrl ?? process.env[\"UAM_RELAY_URL\"] ?? DEFAULT_RELAY_URL;\n\n // Derive relayWsUrl from relayUrl if not explicitly set\n if (options.relayWsUrl) {\n this.relayWsUrl = options.relayWsUrl;\n } else {\n let wsUrl = this.relayUrl\n .replace(\"https://\", \"wss://\")\n .replace(\"http://\", \"ws://\");\n if (!wsUrl.endsWith(\"/ws\")) {\n wsUrl = wsUrl.replace(/\\/+$/, \"\") + \"/ws\";\n }\n this.relayWsUrl = wsUrl;\n }\n\n // Derive relayDomain: env var > constructor arg > URL hostname\n const envDomain = process.env[\"UAM_RELAY_DOMAIN\"];\n if (envDomain) {\n this.relayDomain = envDomain;\n } else if (options.relayDomain) {\n this.relayDomain = options.relayDomain;\n } else {\n // Extract hostname from relayUrl\n try {\n const parsed = new URL(this.relayUrl);\n this.relayDomain = parsed.hostname || \"localhost\";\n } catch {\n // Fallback for malformed URLs\n const afterScheme = this.relayUrl.split(\"://\").pop() || \"\";\n this.relayDomain = afterScheme.split(\"/\")[0] || \"localhost\";\n }\n }\n\n // Default key_dir and data_dir.\n // UAM_HOME env var overrides ~/.uam (useful for testing / isolation).\n const uamHome = process.env[\"UAM_HOME\"];\n const defaultHome = uamHome || join(homedir(), \".uam\");\n\n this.keyDir = options.keyDir ?? join(defaultHome, \"keys\");\n this.dataDir = options.dataDir ?? defaultHome;\n\n // Display name defaults to agent name\n this.displayName = options.displayName ?? this.name;\n\n // Transport type\n this.transportType = options.transportType ?? \"websocket\";\n\n // Trust policy: constructor arg > env var > default\n let policy = options.trustPolicy ?? \"auto-accept\";\n const envPolicy = process.env[\"UAM_TRUST_POLICY\"];\n if (envPolicy) {\n policy = envPolicy;\n }\n\n if (!VALID_POLICIES.has(policy)) {\n throw new Error(\n `Invalid trust_policy '${policy}'. ` +\n `Must be one of: ${JSON.stringify([...VALID_POLICIES].sort())}`\n );\n }\n\n this.trustPolicy = policy;\n }\n}\n","/**\n * Ed25519 key generation, storage, loading, and token persistence.\n *\n * Matches Python key_manager.py: stores 32-byte seed (not 64-byte secret key),\n * uses same file format so keys are cross-language compatible.\n */\n\nimport {\n chmodSync,\n mkdirSync,\n readFileSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { platform } from \"node:os\";\n\nimport {\n type Keypair,\n type SigningKey,\n type VerifyKey,\n type Seed,\n generateKeypair,\n serializeSigningKey,\n deserializeSigningKey,\n serializeVerifyKey,\n} from \"../protocol/index.js\";\n\nconst DEFAULT_KEY_DIR = join(homedir(), \".uam\", \"keys\");\n\nexport class KeyManager {\n private _keyDir: string;\n private _keypair: Keypair | null = null;\n\n constructor(keyDir?: string | null) {\n this._keyDir = keyDir ?? DEFAULT_KEY_DIR;\n }\n\n /** The 64-byte Ed25519 signing key. Throws if not loaded. */\n get signingKey(): SigningKey {\n if (this._keypair === null) {\n throw new Error(\"No keypair loaded. Call loadOrGenerate() first.\");\n }\n return this._keypair.signingKey;\n }\n\n /** The 32-byte Ed25519 verify (public) key. Throws if not loaded. */\n get verifyKey(): VerifyKey {\n if (this._keypair === null) {\n throw new Error(\"No keypair loaded. Call loadOrGenerate() first.\");\n }\n return this._keypair.verifyKey;\n }\n\n /** The 32-byte seed. Throws if not loaded. */\n get seed(): Seed {\n if (this._keypair === null) {\n throw new Error(\"No keypair loaded. Call loadOrGenerate() first.\");\n }\n return this._keypair.seed;\n }\n\n /**\n * Load existing keypair or generate a new one.\n *\n * Checks UAM_SIGNING_KEY env var first (base64-encoded Ed25519 seed).\n * Falls back to file-based storage at {keyDir}/{name}.key.\n * Generates a new keypair if neither source exists.\n */\n loadOrGenerate(name: string): void {\n // 1. Check environment variable\n const envKey = process.env[\"UAM_SIGNING_KEY\"];\n if (envKey) {\n this._keypair = deserializeSigningKey(envKey.trim());\n return;\n }\n\n // 2. File-based storage\n mkdirSync(this._keyDir, { recursive: true });\n const keyPath = join(this._keyDir, `${name}.key`);\n const pubPath = join(this._keyDir, `${name}.pub`);\n\n if (existsSync(keyPath)) {\n // Returning user: load existing keys\n this._checkPermissions(keyPath);\n const seedB64 = readFileSync(keyPath, \"utf-8\").trim();\n this._keypair = deserializeSigningKey(seedB64);\n } else {\n // First-run: generate new keypair\n this._keypair = generateKeypair();\n writeFileSync(keyPath, serializeSigningKey(this._keypair.seed));\n writeFileSync(pubPath, serializeVerifyKey(this._keypair.verifyKey));\n this._setPermissions(keyPath);\n }\n }\n\n /**\n * Store the relay token alongside the keypair.\n */\n saveToken(name: string, token: string): void {\n mkdirSync(this._keyDir, { recursive: true });\n const tokenPath = join(this._keyDir, `${name}.token`);\n writeFileSync(tokenPath, token);\n this._setPermissions(tokenPath);\n }\n\n /**\n * Load a previously saved token, or return null.\n *\n * Checks UAM_TOKEN env var first, then file-based storage,\n * then legacy .api_key files for backward compatibility.\n */\n loadToken(name: string): string | null {\n // 1. Check environment variable\n const envToken = process.env[\"UAM_TOKEN\"];\n if (envToken) {\n return envToken.trim();\n }\n\n // 2. File-based storage\n const tokenPath = join(this._keyDir, `${name}.token`);\n if (existsSync(tokenPath)) {\n return readFileSync(tokenPath, \"utf-8\").trim();\n }\n // Backward compatibility: check for legacy .api_key file\n const legacyPath = join(this._keyDir, `${name}.api_key`);\n if (existsSync(legacyPath)) {\n return readFileSync(legacyPath, \"utf-8\").trim();\n }\n return null;\n }\n\n /** Set file permissions to 0o600 (owner read/write only). */\n private _setPermissions(path: string): void {\n if (platform() !== \"win32\") {\n chmodSync(path, 0o600);\n }\n }\n\n /** Warn if key file permissions are too permissive. */\n private _checkPermissions(path: string): void {\n if (platform() === \"win32\") {\n return; // Cannot reliably check on Windows\n }\n try {\n const mode = statSync(path).mode & 0o777;\n if (mode !== 0o600) {\n console.warn(\n `Key file ${path} has permissions ${mode.toString(8)} (expected 600). ` +\n `Run: chmod 600 ${path}`\n );\n }\n } catch {\n // Ignore stat errors\n }\n }\n}\n","/**\n * SQLite-backed local contact storage (HAND-03).\n *\n * Stores known contacts with their public keys and trust state.\n * Provides fast in-memory caches for isKnown() and isBlocked() checks.\n *\n * Uses better-sqlite3 for synchronous SQLite (simpler than Python's aiosqlite).\n */\n\nimport { mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport Database from \"better-sqlite3\";\n\n/**\n * A row returned from listContacts().\n */\nexport interface ContactRow {\n address: string;\n displayName: string | null;\n trustState: string;\n firstSeen: string;\n lastSeen: string;\n}\n\n/**\n * A pending handshake entry.\n */\nexport interface PendingEntry {\n address: string;\n contactCard: string;\n receivedAt: string;\n}\n\n/**\n * A blocked pattern entry.\n */\nexport interface BlockedEntry {\n pattern: string;\n blockedAt: string;\n}\n\nexport class ContactBook {\n private _dbPath: string;\n private _db: Database.Database | null = null;\n private _knownAddresses: Set<string> = new Set();\n private _blockedExact: Set<string> = new Set();\n private _blockedDomains: Set<string> = new Set();\n\n constructor(dataDir: string) {\n this._dbPath = join(dataDir, \"contacts\", \"contacts.db\");\n }\n\n /**\n * Open the database, create tables, run migrations, load caches.\n */\n open(): void {\n mkdirSync(dirname(this._dbPath), { recursive: true });\n this._db = new Database(this._dbPath);\n this._db.pragma(\"journal_mode = WAL\");\n\n // Create tables with all columns upfront (no migrations needed for new DB)\n this._db.exec(`\n CREATE TABLE IF NOT EXISTS contacts (\n address TEXT PRIMARY KEY,\n public_key TEXT NOT NULL,\n display_name TEXT,\n trust_state TEXT NOT NULL DEFAULT 'unknown',\n trust_source TEXT DEFAULT 'legacy-unknown',\n relay TEXT,\n relays_json TEXT,\n pinned_at TEXT,\n first_seen TEXT NOT NULL DEFAULT (datetime('now')),\n last_seen TEXT NOT NULL DEFAULT (datetime('now'))\n );\n\n CREATE TABLE IF NOT EXISTS pending_handshakes (\n address TEXT PRIMARY KEY,\n contact_card TEXT NOT NULL,\n received_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n\n CREATE TABLE IF NOT EXISTS blocked_patterns (\n pattern TEXT PRIMARY KEY,\n blocked_at TEXT NOT NULL DEFAULT (datetime('now'))\n );\n `);\n\n // Run migrations\n this._migrate();\n\n // Load all known addresses into memory for fast sync lookups\n const rows = this._db\n .prepare(\"SELECT address FROM contacts\")\n .all() as Array<{ address: string }>;\n this._knownAddresses = new Set(rows.map((r) => r.address));\n\n // Load blocked patterns into memory\n this._blockedExact.clear();\n this._blockedDomains.clear();\n const blocked = this._db\n .prepare(\"SELECT pattern FROM blocked_patterns\")\n .all() as Array<{ pattern: string }>;\n for (const row of blocked) {\n this._cacheBlockPattern(row.pattern);\n }\n }\n\n /**\n * Run schema migrations using PRAGMA user_version.\n */\n private _migrate(): void {\n if (!this._db) return;\n\n const versionRow = this._db\n .prepare(\"PRAGMA user_version\")\n .get() as { user_version: number };\n const version = versionRow.user_version;\n\n if (version < 2) {\n // For new DBs, tables are created with all columns upfront\n // (including pinned_at). Skip straight to version 3.\n this._db.exec(\"PRAGMA user_version = 3\");\n } else if (version < 3) {\n // Existing v2 database: add pinned_at column for key pinning lifecycle\n this._db.exec(\n \"ALTER TABLE contacts ADD COLUMN pinned_at TEXT\"\n );\n this._db.exec(\"PRAGMA user_version = 3\");\n }\n }\n\n /**\n * Close the database connection.\n */\n close(): void {\n if (this._db !== null) {\n this._db.close();\n this._db = null;\n }\n }\n\n /**\n * Check if an address is in the contact book (in-memory, no I/O).\n */\n isKnown(address: string): boolean {\n return this._knownAddresses.has(address);\n }\n\n /**\n * Check if an address matches any blocked pattern (O(1) set lookup).\n */\n isBlocked(address: string): boolean {\n if (this._blockedExact.has(address)) {\n return true;\n }\n // Extract domain from 'name::domain' format\n if (address.includes(\"::\")) {\n const domain = address.split(\"::\")[1];\n return this._blockedDomains.has(domain);\n }\n return false;\n }\n\n /**\n * Look up the public key for a known contact.\n */\n getPublicKey(address: string): string | null {\n if (this._db === null) return null;\n const row = this._db\n .prepare(\"SELECT public_key FROM contacts WHERE address = ?\")\n .get(address) as { public_key: string } | undefined;\n return row?.public_key ?? null;\n }\n\n /**\n * Return the relay URLs for a known contact (CARD-04).\n */\n getRelayUrls(address: string): string[] | null {\n if (this._db === null) return null;\n const row = this._db\n .prepare(\"SELECT relay, relays_json FROM contacts WHERE address = ?\")\n .get(address) as { relay: string | null; relays_json: string | null } | undefined;\n if (!row) return null;\n if (row.relays_json !== null) {\n return JSON.parse(row.relays_json) as string[];\n }\n if (row.relay !== null) {\n return [row.relay];\n }\n return null;\n }\n\n /**\n * Add or update a contact (upsert).\n */\n addContact(\n address: string,\n publicKey: string,\n options?: {\n displayName?: string | null;\n trustState?: string;\n trustSource?: string | null;\n relay?: string | null;\n relays?: string[] | null;\n }\n ): void {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n const displayName = options?.displayName ?? null;\n const trustState = options?.trustState ?? \"trusted\";\n const trustSource = options?.trustSource ?? null;\n const relay = options?.relay ?? null;\n const relaysJson =\n options?.relays !== undefined && options?.relays !== null\n ? JSON.stringify(options.relays)\n : null;\n\n this._db\n .prepare(\n `INSERT INTO contacts (address, public_key, display_name, trust_state, trust_source, relay, relays_json)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT(address) DO UPDATE SET\n public_key = excluded.public_key,\n display_name = excluded.display_name,\n trust_state = excluded.trust_state,\n trust_source = COALESCE(excluded.trust_source, contacts.trust_source),\n relay = COALESCE(excluded.relay, contacts.relay),\n relays_json = COALESCE(excluded.relays_json, contacts.relays_json),\n last_seen = datetime('now')`\n )\n .run(address, publicKey, displayName, trustState, trustSource, relay, relaysJson);\n\n this._knownAddresses.add(address);\n }\n\n /**\n * Return all contacts sorted by last_seen DESC.\n */\n listContacts(): ContactRow[] {\n if (this._db === null) return [];\n const rows = this._db\n .prepare(\n \"SELECT address, display_name, trust_state, first_seen, last_seen \" +\n \"FROM contacts ORDER BY last_seen DESC\"\n )\n .all() as Array<{\n address: string;\n display_name: string | null;\n trust_state: string;\n first_seen: string;\n last_seen: string;\n }>;\n return rows.map((r) => ({\n address: r.address,\n displayName: r.display_name,\n trustState: r.trust_state,\n firstSeen: r.first_seen,\n lastSeen: r.last_seen,\n }));\n }\n\n /**\n * Store a pending handshake request.\n */\n addPending(address: string, contactCardJson: string): void {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n this._db\n .prepare(\n `INSERT OR REPLACE INTO pending_handshakes (address, contact_card) VALUES (?, ?)`\n )\n .run(address, contactCardJson);\n }\n\n /**\n * Retrieve all pending handshake requests.\n */\n getPending(): PendingEntry[] {\n if (this._db === null) return [];\n const rows = this._db\n .prepare(\n \"SELECT address, contact_card, received_at FROM pending_handshakes\"\n )\n .all() as Array<{\n address: string;\n contact_card: string;\n received_at: string;\n }>;\n return rows.map((r) => ({\n address: r.address,\n contactCard: r.contact_card,\n receivedAt: r.received_at,\n }));\n }\n\n /**\n * Remove a pending handshake request.\n */\n removePending(address: string): void {\n if (this._db === null) return;\n this._db\n .prepare(\"DELETE FROM pending_handshakes WHERE address = ?\")\n .run(address);\n }\n\n /**\n * Return pending handshakes older than N days.\n */\n getExpiredPending(days: number = 7): PendingEntry[] {\n if (this._db === null) return [];\n const rows = this._db\n .prepare(\n `SELECT address, contact_card, received_at FROM pending_handshakes\n WHERE datetime(received_at, '+' || ? || ' days') < datetime('now')`\n )\n .all(String(days)) as Array<{\n address: string;\n contact_card: string;\n received_at: string;\n }>;\n return rows.map((r) => ({\n address: r.address,\n contactCard: r.contact_card,\n receivedAt: r.received_at,\n }));\n }\n\n /**\n * Return the trust_state for an address, or null if unknown.\n */\n getTrustState(address: string): string | null {\n if (this._db === null) return null;\n const row = this._db\n .prepare(\"SELECT trust_state FROM contacts WHERE address = ?\")\n .get(address) as { trust_state: string } | undefined;\n return row?.trust_state ?? null;\n }\n\n /**\n * Set the pinned_at timestamp and trust_state='pinned' for a contact (TOFU).\n */\n setPinnedAt(address: string): void {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n this._db\n .prepare(\n \"UPDATE contacts SET pinned_at = datetime('now'), trust_state = 'pinned' WHERE address = ?\"\n )\n .run(address);\n }\n\n /**\n * Remove a contact by address. Returns true if a contact was deleted.\n */\n removeContact(address: string): boolean {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n const result = this._db\n .prepare(\"DELETE FROM contacts WHERE address = ?\")\n .run(address);\n this._knownAddresses.delete(address);\n return result.changes > 0;\n }\n\n /**\n * Return true if the address has trust_state 'trusted', 'verified', or 'pinned'.\n *\n * Convenience helper for inbound message filtering (CARD-05, TOFU-02).\n */\n isTrustedOrVerified(address: string): boolean {\n const state = this.getTrustState(address);\n return state === \"trusted\" || state === \"verified\" || state === \"pinned\";\n }\n\n /**\n * Block an address or domain pattern (e.g., '*::evil.com').\n */\n addBlock(pattern: string): void {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n this._db\n .prepare(\"INSERT OR IGNORE INTO blocked_patterns (pattern) VALUES (?)\")\n .run(pattern);\n this._cacheBlockPattern(pattern);\n }\n\n /**\n * Remove a block pattern.\n */\n removeBlock(pattern: string): void {\n if (this._db === null) {\n throw new Error(\"ContactBook not open. Call open() first.\");\n }\n this._db\n .prepare(\"DELETE FROM blocked_patterns WHERE pattern = ?\")\n .run(pattern);\n this._uncacheBlockPattern(pattern);\n }\n\n /**\n * Return all blocked patterns with their timestamps.\n */\n listBlocked(): BlockedEntry[] {\n if (this._db === null) return [];\n const rows = this._db\n .prepare(\n \"SELECT pattern, blocked_at FROM blocked_patterns ORDER BY blocked_at DESC\"\n )\n .all() as Array<{ pattern: string; blocked_at: string }>;\n return rows.map((r) => ({\n pattern: r.pattern,\n blockedAt: r.blocked_at,\n }));\n }\n\n // -- Internal block caching ---------------------------------------------------\n\n private _cacheBlockPattern(pattern: string): void {\n if (pattern.startsWith(\"*::\")) {\n this._blockedDomains.add(pattern.slice(3));\n } else {\n this._blockedExact.add(pattern);\n }\n }\n\n private _uncacheBlockPattern(pattern: string): void {\n if (pattern.startsWith(\"*::\")) {\n this._blockedDomains.delete(pattern.slice(3));\n } else {\n this._blockedExact.delete(pattern);\n }\n }\n}\n","/**\n * First-contact handshake flow manager (HAND-01 through HAND-04).\n *\n * Handles the three-phase handshake:\n * 1. HANDSHAKE_REQUEST: sender sends contact card (encrypted with SealedBox)\n * 2. HANDSHAKE_ACCEPT: recipient stores contact and sends accept back\n * 3. HANDSHAKE_DENY: recipient rejects the handshake\n *\n * The HandshakeManager works with the ContactBook to persist trust decisions.\n */\n\nimport {\n MessageType,\n createEnvelope,\n createContactCard,\n verifyContactCard,\n contactCardToDict,\n contactCardFromDict,\n decryptPayloadAnonymous,\n serializeVerifyKey,\n toWireDict,\n type MessageEnvelope,\n type VerifyKey,\n} from \"../protocol/index.js\";\nimport type { ContactBook } from \"./contact-book.js\";\nimport type { ReceivedMessage } from \"./message.js\";\n\n// Forward reference type for Agent to avoid circular dependency\ninterface AgentLike {\n readonly address: string;\n readonly _config: {\n readonly displayName: string;\n readonly relayWsUrl: string;\n };\n readonly _keyManager: {\n readonly signingKey: Uint8Array;\n };\n readonly _transport: {\n send(envelope: Record<string, unknown>): Promise<void>;\n } | null;\n}\n\nexport class HandshakeManager {\n private _contactBook: ContactBook;\n readonly _trustPolicy: string;\n\n constructor(contactBook: ContactBook, trustPolicy: string) {\n this._contactBook = contactBook;\n this._trustPolicy = trustPolicy;\n }\n\n /**\n * Create a handshake request envelope with embedded contact card.\n *\n * The payload is the JSON-serialized contact card, encrypted with\n * SealedBox (anonymous encryption) to the recipient.\n *\n * Returns wire-format dict ready to send via transport.\n */\n async createHandshakeRequest(\n agent: AgentLike,\n toAddress: string,\n recipientVk: VerifyKey\n ): Promise<Record<string, unknown>> {\n // Create contact card for the sending agent\n const card = await createContactCard(\n agent.address,\n agent._config.displayName,\n agent._config.relayWsUrl,\n agent._keyManager.signingKey\n );\n const cardJson = JSON.stringify(contactCardToDict(card));\n\n // Create envelope -- createEnvelope auto-uses SealedBox for HANDSHAKE_REQUEST\n const envelope = await createEnvelope(\n agent.address,\n toAddress,\n MessageType.HANDSHAKE_REQUEST,\n new TextEncoder().encode(cardJson),\n agent._keyManager.signingKey,\n recipientVk\n );\n\n return toWireDict(envelope);\n }\n\n /**\n * Handle an inbound handshake message.\n *\n * Returns null -- handshake messages are not user-visible.\n */\n async handleInbound(\n agent: AgentLike,\n envelope: MessageEnvelope,\n senderVk: VerifyKey\n ): Promise<ReceivedMessage | null> {\n if (envelope.type === MessageType.HANDSHAKE_REQUEST) {\n await this._handleRequest(agent, envelope, senderVk);\n } else if (envelope.type === MessageType.HANDSHAKE_ACCEPT) {\n await this._handleAccept(envelope, senderVk);\n } else if (envelope.type === MessageType.HANDSHAKE_DENY) {\n // Handshake denied -- logged silently\n }\n return null;\n }\n\n /**\n * Process a handshake.request: decrypt contact card, apply trust policy.\n */\n private async _handleRequest(\n agent: AgentLike,\n envelope: MessageEnvelope,\n senderVk: VerifyKey\n ): Promise<void> {\n // Handshake requests are encrypted with SealedBox (anonymous)\n const plaintext = decryptPayloadAnonymous(\n envelope.payload,\n agent._keyManager.signingKey\n );\n const cardDict = JSON.parse(\n new TextDecoder().decode(plaintext)\n ) as Record<string, unknown>;\n const card = contactCardFromDict(cardDict);\n\n // Verify the contact card's self-signature\n verifyContactCard(card);\n\n if (this._trustPolicy === \"auto-accept\") {\n // Store the contact as provisional (TOFU: trust upgrades on accept)\n this._contactBook.addContact(card.address, card.publicKey, {\n displayName: card.displayName,\n trustState: \"provisional\",\n trustSource: \"auto-accepted-provisional\",\n });\n // Send handshake.accept back\n await this._sendAccept(agent, envelope.fromAddress, senderVk);\n } else if (this._trustPolicy === \"allowlist-only\") {\n // Auto-deny: only pre-approved contacts are allowed\n await this._sendDeny(agent, envelope.fromAddress, senderVk);\n } else {\n // approval-required: store in pending for manual review\n this._contactBook.addPending(\n envelope.fromAddress,\n JSON.stringify(cardDict)\n );\n }\n }\n\n /**\n * Process a handshake.accept: store the sender as pinned (TOFU).\n */\n private async _handleAccept(\n envelope: MessageEnvelope,\n senderVk: VerifyKey\n ): Promise<void> {\n const senderPkStr = serializeVerifyKey(senderVk);\n this._contactBook.addContact(envelope.fromAddress, senderPkStr, {\n trustState: \"pinned\",\n });\n this._contactBook.setPinnedAt(envelope.fromAddress);\n }\n\n /**\n * Send a handshake.accept envelope back to the requester.\n */\n async _sendAccept(\n agent: AgentLike,\n toAddress: string,\n recipientVk: VerifyKey\n ): Promise<void> {\n const card = await createContactCard(\n agent.address,\n agent._config.displayName,\n agent._config.relayWsUrl,\n agent._keyManager.signingKey\n );\n const acceptPayload = JSON.stringify({\n status: \"accepted\",\n contact_card: contactCardToDict(card),\n });\n\n const envelope = await createEnvelope(\n agent.address,\n toAddress,\n MessageType.HANDSHAKE_ACCEPT,\n new TextEncoder().encode(acceptPayload),\n agent._keyManager.signingKey,\n recipientVk\n );\n\n const wire = toWireDict(envelope);\n if (agent._transport) {\n await agent._transport.send(wire);\n }\n }\n\n /**\n * Send a handshake.deny envelope to the requester.\n */\n async _sendDeny(\n agent: AgentLike,\n toAddress: string,\n recipientVk: VerifyKey\n ): Promise<void> {\n const denyPayload = JSON.stringify({\n status: \"denied\",\n reason: \"allowlist-only\",\n });\n\n const envelope = await createEnvelope(\n agent.address,\n toAddress,\n MessageType.HANDSHAKE_DENY,\n new TextEncoder().encode(denyPayload),\n agent._keyManager.signingKey,\n recipientVk\n );\n\n const wire = toWireDict(envelope);\n if (agent._transport) {\n await agent._transport.send(wire);\n }\n }\n}\n","/**\n * Tier 3 resolver: on-chain namespace lookup via UAMNameRegistry (TSSDK-09).\n *\n * Uses viem for contract reads on Base Sepolia/Base L2.\n */\n\nimport { createPublicClient, http, type Address, defineChain } from \"viem\";\nimport { UAMError } from \"../protocol/index.js\";\nimport { parseAddress } from \"../protocol/address.js\";\nimport { AddressResolver } from \"./resolver.js\";\n\n// Default config\nconst DEFAULT_RPC_URL = \"https://sepolia.base.org\";\nconst DEFAULT_CHAIN_ID = 84532; // Base Sepolia\n\n// Cache TTL: 1 hour in milliseconds\nconst CACHE_TTL_MS = 3600 * 1000;\n\n// Minimal ABI for resolve() and available() -- inline to avoid file I/O\nconst REGISTRY_ABI = [\n {\n name: \"resolve\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"name\", type: \"string\" }],\n outputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"publicKey\", type: \"string\" },\n { name: \"relayUrl\", type: \"string\" },\n { name: \"expiry\", type: \"uint256\" },\n ],\n },\n {\n name: \"available\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"name\", type: \"string\" }],\n outputs: [{ name: \"\", type: \"bool\" }],\n },\n] as const;\n\ninterface CacheEntry {\n publicKey: string;\n expiresAt: number; // Date.now() + TTL\n}\n\nexport interface Tier3Config {\n contractAddress: string;\n rpcUrl?: string;\n chainId?: number;\n cacheTtlMs?: number;\n}\n\n/**\n * Build a minimal chain definition for viem.\n * Using defineChain avoids importing chain-specific types from viem/chains\n * which cause TypeScript compatibility issues with generic PublicClient.\n */\nfunction buildChain(chainId: number, rpcUrl: string) {\n return defineChain({\n id: chainId,\n name: `chain-${chainId}`,\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: { http: [rpcUrl] },\n },\n });\n}\n\n/**\n * Resolve agent addresses via on-chain UAMNameRegistry contract.\n *\n * Uses viem PublicClient to call resolve() on the contract.\n * Caches results for 1 hour to minimize RPC calls.\n */\nexport class Tier3Resolver extends AddressResolver {\n private _contractAddress: Address;\n private _client: ReturnType<typeof createPublicClient>;\n private _cacheTtlMs: number;\n private _cache: Map<string, CacheEntry> = new Map();\n\n constructor(config: Tier3Config) {\n super();\n this._contractAddress = config.contractAddress as Address;\n this._cacheTtlMs = config.cacheTtlMs ?? CACHE_TTL_MS;\n const rpcUrl = config.rpcUrl ?? DEFAULT_RPC_URL;\n const chainId = config.chainId ?? DEFAULT_CHAIN_ID;\n this._client = createPublicClient({\n chain: buildChain(chainId, rpcUrl),\n transport: http(rpcUrl),\n });\n }\n\n async resolvePublicKey(\n address: string,\n _token: string,\n _relayUrl: string\n ): Promise<string> {\n const parsed = parseAddress(address);\n const name = parsed.domain; // For Tier 3, domain IS the namespace\n\n // Check cache\n const cached = this._cache.get(name);\n if (cached && cached.expiresAt > Date.now()) {\n return cached.publicKey;\n }\n\n // Call contract\n try {\n const result = await this._client.readContract({\n address: this._contractAddress,\n abi: REGISTRY_ABI,\n functionName: \"resolve\",\n args: [name],\n });\n\n const [_owner, publicKey, _relayUrl2, _expiry] = result;\n\n if (!publicKey) {\n throw new UAMError(\n `Tier 3 name '${name}' has no public key registered`\n );\n }\n\n // Cache result\n this._cache.set(name, {\n publicKey,\n expiresAt: Date.now() + this._cacheTtlMs,\n });\n\n return publicKey;\n } catch (err) {\n if (err instanceof UAMError) throw err;\n const msg = err instanceof Error ? err.message : String(err);\n if (msg.includes(\"NameNotFound\") || msg.includes(\"revert\")) {\n throw new UAMError(`Tier 3 name not found on-chain: ${name}`);\n }\n throw new UAMError(`Tier 3 resolution failed for ${name}: ${msg}`);\n }\n }\n\n /**\n * Check if a name is available for registration.\n */\n async isAvailable(name: string): Promise<boolean> {\n try {\n const result = await this._client.readContract({\n address: this._contractAddress,\n abi: REGISTRY_ABI,\n functionName: \"available\",\n args: [name],\n });\n return result;\n } catch {\n return false;\n }\n }\n\n /**\n * Clear cache for a specific name or all names.\n */\n invalidateCache(name?: string): void {\n if (name) {\n this._cache.delete(name);\n } else {\n this._cache.clear();\n }\n }\n}\n","/**\n * Pluggable address resolver with Tier 1 relay lookup (SDK-08).\n *\n * Matches Python resolver.py: SmartResolver routes by domain format.\n */\n\nimport { UAMError } from \"../protocol/index.js\";\nimport { parseAddress } from \"../protocol/address.js\";\nimport { Tier3Resolver, type Tier3Config } from \"./tier3.js\";\nimport {\n queryUamTxt,\n parseUamTxt,\n extractPublicKey,\n resolveKeyViaHttps,\n} from \"./dns-verifier.js\";\n\n/**\n * Pluggable address resolver interface.\n */\nexport abstract class AddressResolver {\n /**\n * Resolve an agent address to its public key (base64).\n *\n * @throws {UAMError} If the address cannot be resolved.\n */\n abstract resolvePublicKey(\n address: string,\n token: string,\n relayUrl: string\n ): Promise<string>;\n}\n\n/**\n * Tier 1: resolve via relay HTTP API.\n *\n * Calls GET /api/v1/agents/{address}/public-key.\n */\nexport class Tier1Resolver extends AddressResolver {\n async resolvePublicKey(\n address: string,\n _token: string,\n relayUrl: string\n ): Promise<string> {\n const resp = await fetch(\n `${relayUrl}/api/v1/agents/${address}/public-key`\n );\n if (resp.status === 404) {\n throw new UAMError(`Agent not found: ${address}`);\n }\n if (!resp.ok) {\n throw new UAMError(\n `Resolver request failed: ${resp.status} ${resp.statusText}`\n );\n }\n const data = (await resp.json()) as Record<string, unknown>;\n return data[\"public_key\"] as string;\n }\n}\n\n/**\n * Tier 2: DNS TXT record resolution (DNS-01).\n *\n * Resolution order:\n * 1. Query _uam.{domain} TXT records for v=uam1 entries\n * 2. Fallback to HTTPS .well-known/uam.json\n * 3. Throw UAMError if both fail\n */\nexport class Tier2Resolver extends AddressResolver {\n async resolvePublicKey(\n address: string,\n _token: string,\n _relayUrl: string\n ): Promise<string> {\n const parsed = parseAddress(address);\n\n // 1. Try DNS TXT at _uam.{domain}\n const txtRecords = await queryUamTxt(parsed.domain);\n for (const txt of txtRecords) {\n const tags = parseUamTxt(txt);\n if (tags[\"v\"] === \"uam1\") {\n const key = extractPublicKey(tags);\n if (key) return key;\n }\n }\n\n // 2. Fallback to HTTPS .well-known\n const httpsKey = await resolveKeyViaHttps(parsed.agent, parsed.domain);\n if (httpsKey) return httpsKey;\n\n throw new UAMError(\n `Could not resolve public key for ${address} via DNS or HTTPS`\n );\n }\n}\n\n/**\n * Automatic tier-based resolver that routes by domain format (RESOLVE-01).\n *\n * Routing rules:\n * - domain == relayDomain -> Tier 1 (relay HTTP API lookup)\n * - domain contains a '.' -> Tier 2 (DNS -- stub)\n * - domain has no dots -> Tier 3 (on-chain namespace lookup)\n */\nexport class SmartResolver extends AddressResolver {\n private _relayDomain: string;\n private _tier1: Tier1Resolver;\n private _tier2: Tier2Resolver;\n private _tier3: Tier3Resolver | null;\n\n constructor(relayDomain: string, tier3Config?: Tier3Config) {\n super();\n this._relayDomain = relayDomain;\n this._tier1 = new Tier1Resolver();\n this._tier2 = new Tier2Resolver();\n this._tier3 = tier3Config ? new Tier3Resolver(tier3Config) : null;\n }\n\n async resolvePublicKey(\n address: string,\n token: string,\n relayUrl: string\n ): Promise<string> {\n const parsed = parseAddress(address);\n const domain = parsed.domain;\n\n if (domain === this._relayDomain) {\n return this._tier1.resolvePublicKey(address, token, relayUrl);\n }\n\n if (domain.includes(\".\")) {\n return this._tier2.resolvePublicKey(address, token, relayUrl);\n }\n\n if (!this._tier3) {\n throw new UAMError(\n `Tier 3 resolution requires contract config. ` +\n `Cannot resolve dot-free domain: '${domain}'`\n );\n }\n return this._tier3.resolvePublicKey(address, token, relayUrl);\n }\n}\n\n// Re-export Tier3 types for convenience\nexport { Tier3Resolver, type Tier3Config } from \"./tier3.js\";\n","/**\n * Abstract transport interface for relay communication.\n *\n * Two implementations:\n * - HTTPTransport: stateless polling via REST API\n * - WebSocketTransport: persistent real-time connection\n */\n\nexport abstract class TransportBase {\n /** Establish connection to the relay. */\n abstract connect(): Promise<void>;\n\n /** Close the connection. */\n abstract disconnect(): Promise<void>;\n\n /** Send a message envelope to the relay. */\n abstract send(envelope: Record<string, unknown>): Promise<void>;\n\n /** Retrieve pending messages from the relay. */\n abstract receive(limit?: number): Promise<Record<string, unknown>[]>;\n\n /**\n * Start listening for real-time messages.\n *\n * For WebSocket: registers a callback for push delivery.\n * For HTTP: not supported (throws Error).\n */\n abstract listen(\n callback: (msg: Record<string, unknown>) => Promise<void>\n ): Promise<void>;\n}\n","/**\n * HTTP transport via native fetch (SDK-09).\n *\n * Sends envelopes via POST /api/v1/send and retrieves inbox\n * via GET /api/v1/inbox/{address}.\n *\n * Uses native fetch (Node.js 18+ has global fetch).\n */\n\nimport { TransportBase } from \"./base.js\";\n\nexport class HTTPTransport extends TransportBase {\n private _relayUrl: string;\n private _token: string;\n private _address: string;\n\n constructor(relayUrl: string, token: string, address: string) {\n super();\n this._relayUrl = relayUrl.replace(/\\/+$/, \"\");\n this._token = token;\n this._address = address;\n }\n\n async connect(): Promise<void> {\n // No persistent connection needed for HTTP\n }\n\n async disconnect(): Promise<void> {\n // No-op\n }\n\n async send(envelope: Record<string, unknown>): Promise<void> {\n const resp = await fetch(`${this._relayUrl}/api/v1/send`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this._token}`,\n },\n body: JSON.stringify({ envelope }),\n });\n if (!resp.ok) {\n throw new Error(\n `HTTP send failed: ${resp.status} ${resp.statusText}`\n );\n }\n }\n\n async receive(limit: number = 50): Promise<Record<string, unknown>[]> {\n const url = new URL(\n `${this._relayUrl}/api/v1/inbox/${this._address}`\n );\n url.searchParams.set(\"limit\", String(limit));\n\n const resp = await fetch(url.toString(), {\n headers: {\n Authorization: `Bearer ${this._token}`,\n },\n });\n if (!resp.ok) {\n throw new Error(\n `HTTP receive failed: ${resp.status} ${resp.statusText}`\n );\n }\n const data = (await resp.json()) as Record<string, unknown>;\n return (data[\"messages\"] as Record<string, unknown>[]) ?? [];\n }\n\n async listen(\n _callback: (msg: Record<string, unknown>) => Promise<void>\n ): Promise<void> {\n throw new Error(\n \"HTTP transport does not support real-time listening. \" +\n \"Use receive() for polling or switch to WebSocket transport.\"\n );\n }\n}\n","/**\n * WebSocket transport with exponential backoff and jitter (SDK-05).\n *\n * Maintains a persistent connection to the relay, automatically\n * reconnecting on disconnection with exponential backoff plus\n * random jitter to prevent thundering herd.\n */\n\nimport WebSocket from \"ws\";\nimport { TransportBase } from \"./base.js\";\n\n// Reconnection constants\nconst BASE_DELAY = 1.0; // Initial delay in seconds\nconst MAX_DELAY = 60.0; // Maximum delay cap\nconst JITTER_RANGE = 1.0; // Random jitter 0 to JITTER_RANGE\n\nexport class WebSocketTransport extends TransportBase {\n private _url: string;\n private _onMessage:\n | ((msg: Record<string, unknown>) => Promise<void>)\n | null;\n private _ws: WebSocket | null = null;\n private _pending: Record<string, unknown>[] = [];\n private _connected: boolean = false;\n private _connectResolve: (() => void) | null = null;\n private _connectReject: ((err: Error) => void) | null = null;\n private _running: boolean = false;\n private _reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n wsUrl: string,\n token: string,\n onMessage?: (msg: Record<string, unknown>) => Promise<void>\n ) {\n super();\n this._url = `${wsUrl}?token=${token}`;\n this._onMessage = onMessage ?? null;\n }\n\n async connect(): Promise<void> {\n this._running = true;\n return new Promise<void>((resolve, reject) => {\n this._connectResolve = resolve;\n this._connectReject = reject;\n this._startConnectionLoop();\n\n // 30s timeout for initial connection\n const timeout = setTimeout(() => {\n this._connectReject = null;\n this._connectResolve = null;\n reject(new Error(\"WebSocket connection timeout (30s)\"));\n }, 30000);\n\n // Patch resolve to clear timeout\n const origResolve = this._connectResolve;\n this._connectResolve = () => {\n clearTimeout(timeout);\n origResolve?.();\n };\n });\n }\n\n async disconnect(): Promise<void> {\n this._running = false;\n if (this._reconnectTimeout !== null) {\n clearTimeout(this._reconnectTimeout);\n this._reconnectTimeout = null;\n }\n if (this._ws) {\n this._ws.removeAllListeners();\n this._ws.close();\n this._ws = null;\n }\n this._connected = false;\n }\n\n async send(envelope: Record<string, unknown>): Promise<void> {\n if (!this._ws || this._ws.readyState !== WebSocket.OPEN) {\n throw new Error(\"WebSocket not connected\");\n }\n this._ws.send(JSON.stringify(envelope));\n }\n\n async receive(limit: number = 50): Promise<Record<string, unknown>[]> {\n const result = this._pending.slice(0, limit);\n this._pending = this._pending.slice(limit);\n return result;\n }\n\n async listen(\n callback: (msg: Record<string, unknown>) => Promise<void>\n ): Promise<void> {\n this._onMessage = callback;\n }\n\n private _startConnectionLoop(): void {\n let attempt = 0;\n\n const tryConnect = () => {\n if (!this._running) return;\n\n const ws = new WebSocket(this._url);\n this._ws = ws;\n\n ws.on(\"open\", () => {\n this._connected = true;\n attempt = 0; // Reset on successful connection\n if (this._connectResolve) {\n this._connectResolve();\n this._connectResolve = null;\n this._connectReject = null;\n }\n });\n\n ws.on(\"message\", (data: WebSocket.Data) => {\n try {\n const msg = JSON.parse(data.toString()) as Record<string, unknown>;\n this._handleMessage(msg);\n } catch {\n // Ignore unparseable messages\n }\n });\n\n ws.on(\"close\", () => {\n this._connected = false;\n this._ws = null;\n if (!this._running) return;\n\n attempt += 1;\n const delay = Math.min(BASE_DELAY * Math.pow(2, attempt), MAX_DELAY);\n const jitter = Math.random() * JITTER_RANGE;\n const totalDelay = (delay + jitter) * 1000;\n\n this._reconnectTimeout = setTimeout(tryConnect, totalDelay);\n });\n\n ws.on(\"error\", (err: Error) => {\n // On first connect, reject the promise\n if (this._connectReject && !this._connected) {\n // Don't reject immediately; let 'close' handle retry\n }\n // Error will trigger close event\n });\n };\n\n tryConnect();\n }\n\n private _handleMessage(msg: Record<string, unknown>): void {\n const msgType = msg[\"type\"] as string | undefined;\n\n if (msgType === \"ping\") {\n // Respond to relay heartbeat\n if (this._ws && this._ws.readyState === WebSocket.OPEN) {\n this._ws.send(JSON.stringify({ type: \"pong\" }));\n }\n } else if (msgType === \"ack\") {\n // Acknowledgment -- log silently\n } else if (msgType === \"error\" || \"error\" in msg) {\n // Relay error -- log silently\n } else if (\"uam_version\" in msg) {\n // Inbound envelope\n if (this._onMessage) {\n this._onMessage(msg).catch(() => {\n // Fire-and-forget callback errors\n });\n } else {\n this._pending.push(msg);\n }\n }\n }\n}\n","/**\n * UAM SDK transport layer.\n */\n\nimport type { SDKConfig } from \"../config.js\";\nimport { TransportBase } from \"./base.js\";\nimport { HTTPTransport } from \"./http.js\";\nimport { WebSocketTransport } from \"./websocket.js\";\n\nexport { TransportBase } from \"./base.js\";\nexport { HTTPTransport } from \"./http.js\";\nexport { WebSocketTransport } from \"./websocket.js\";\n\n/**\n * Factory to create the appropriate transport based on config.\n */\nexport function createTransport(\n config: SDKConfig,\n token: string,\n address: string,\n onMessage?: (msg: Record<string, unknown>) => Promise<void>\n): TransportBase {\n if (config.transportType === \"http\") {\n return new HTTPTransport(config.relayUrl, token, address);\n } else {\n return new WebSocketTransport(config.relayWsUrl, token, onMessage);\n }\n}\n","/**\n * Agent class -- the primary SDK interface (SDK-01).\n *\n * Provides send(), inbox(), handshake flow, contact management,\n * trust policies, approve/deny/block/unblock.\n *\n * Matches Python agent.py API surface.\n */\n\nimport {\n MessageType,\n UAMError,\n KeyPinningError,\n SignatureVerificationError,\n DecryptionError,\n sodiumReady,\n createEnvelope,\n verifyEnvelope,\n decryptPayload,\n toWireDict,\n fromWireDict,\n serializeVerifyKey,\n deserializeVerifyKey,\n createContactCard,\n contactCardToDict,\n contactCardFromDict,\n verifyContactCard,\n type MessageEnvelope,\n} from \"../protocol/index.js\";\nimport { SDKConfig } from \"./config.js\";\nimport { KeyManager } from \"./key-manager.js\";\nimport type { ReceivedMessage } from \"./message.js\";\nimport { ContactBook } from \"./contact-book.js\";\nimport { HandshakeManager } from \"./handshake.js\";\nimport { type AddressResolver, SmartResolver } from \"./resolver.js\";\nimport { createTransport, type TransportBase } from \"./transport/index.js\";\n\nexport class Agent {\n /** @internal */\n readonly _config: SDKConfig;\n /** @internal */\n readonly _keyManager: KeyManager;\n /** @internal */\n _transport: TransportBase | null = null;\n\n private _resolver: AddressResolver;\n private _address: string | null = null;\n private _token: string | null = null;\n private _connected: boolean = false;\n private _autoRegister: boolean;\n\n /** @internal */\n readonly _contactBook: ContactBook;\n /** @internal */\n readonly _handshake: HandshakeManager;\n\n /**\n * Create an Agent. No I/O happens here -- call connect() to initialize.\n */\n constructor(\n name: string,\n options?: {\n relay?: string | null;\n domain?: string | null;\n keyDir?: string | null;\n autoRegister?: boolean;\n displayName?: string | null;\n transport?: string;\n trustPolicy?: string;\n }\n ) {\n this._config = new SDKConfig({\n name,\n relayUrl: options?.relay,\n relayDomain: options?.domain ?? undefined,\n keyDir: options?.keyDir,\n displayName: options?.displayName ?? name,\n transportType: options?.transport ?? \"websocket\",\n trustPolicy: options?.trustPolicy ?? \"auto-accept\",\n });\n this._keyManager = new KeyManager(this._config.keyDir);\n this._resolver = new SmartResolver(this._config.relayDomain);\n this._autoRegister = options?.autoRegister ?? true;\n\n // Contact management\n this._contactBook = new ContactBook(this._config.dataDir);\n this._handshake = new HandshakeManager(\n this._contactBook,\n this._config.trustPolicy\n );\n }\n\n // -- Properties ----------------------------------------------------------\n\n /** The agent's full UAM address (e.g., 'myagent::youam.network'). */\n get address(): string {\n if (this._address === null) {\n throw new Error(\n \"Agent not yet connected. Call await agent.connect() first.\"\n );\n }\n return this._address;\n }\n\n /** UAM SDK version. */\n get version(): string {\n return \"0.1.0\";\n }\n\n /** The agent's public key (base64-encoded Ed25519 verify key). */\n get publicKey(): string {\n return serializeVerifyKey(this._keyManager.verifyKey);\n }\n\n /** Whether the agent has completed connection setup. */\n get isConnected(): boolean {\n return this._connected;\n }\n\n /**\n * Generate and return a signed contact card for this agent.\n */\n async contactCard(): Promise<Record<string, unknown>> {\n if (!this._connected) {\n throw new Error(\"Agent not connected. Call connect() first.\");\n }\n const card = await createContactCard(\n this._address!,\n this._config.displayName,\n this._config.relayWsUrl,\n this._keyManager.signingKey\n );\n return contactCardToDict(card);\n }\n\n // -- Lifecycle -----------------------------------------------------------\n\n /**\n * Initialize the agent: load/generate keys, register, connect transport.\n *\n * Idempotent -- calling twice is safe.\n */\n async connect(): Promise<void> {\n if (this._connected) {\n return;\n }\n\n // 0. Ensure sodium is ready\n await sodiumReady;\n\n // 1. Load or generate keypair\n this._keyManager.loadOrGenerate(this._config.name);\n\n // 2. Check for stored token (returning user)\n const storedToken = this._keyManager.loadToken(this._config.name);\n\n if (storedToken) {\n // Returning user: use stored token\n this._token = storedToken;\n this._address = `${this._config.name}::${this._config.relayDomain}`;\n } else if (this._autoRegister) {\n // First-run: register with relay\n await this._registerWithRelay();\n } else {\n throw new UAMError(\n \"No stored token and autoRegister=false. \" +\n \"Register manually or set autoRegister=true.\"\n );\n }\n\n // 3. Create and connect transport\n this._transport = createTransport(\n this._config,\n this._token!,\n this._address!\n );\n await this._transport.connect();\n\n // 4. Open contact book\n this._contactBook.open();\n\n this._connected = true;\n\n // 5. Sweep expired handshakes (HAND-03)\n await this._sweepExpiredHandshakes();\n }\n\n /**\n * Disconnect the transport and clean up resources.\n */\n async close(): Promise<void> {\n // Close contact book first\n this._contactBook.close();\n if (this._transport) {\n await this._transport.disconnect();\n }\n this._connected = false;\n }\n\n // -- Messaging -----------------------------------------------------------\n\n /**\n * Send an encrypted, signed message. Returns the message_id.\n */\n async send(\n toAddress: string,\n message: string,\n options?: {\n threadId?: string;\n attachments?: Array<Record<string, unknown>>;\n }\n ): Promise<string> {\n await this._ensureConnected();\n\n // TOFU-05: require_verify blocks unverified first sends\n if (this._config.trustPolicy === \"require_verify\") {\n const trust = this._contactBook.getTrustState(toAddress);\n if (trust !== \"pinned\" && trust !== \"verified\") {\n throw new UAMError(\n `Trust policy 'require_verify' requires fingerprint ` +\n `verification before sending to ${toAddress}. ` +\n `Run: uam contact verify ${toAddress}`\n );\n }\n }\n\n // Resolve recipient's verify key (Ed25519)\n const recipientVk = await this._resolvePublicKey(toAddress);\n\n // Check if first contact -- send handshake if needed\n if (!this._contactBook.isKnown(toAddress)) {\n await this._initiateHandshake(toAddress, recipientVk);\n }\n\n // Create signed, encrypted envelope\n const envelope = await createEnvelope(\n this._address!,\n toAddress,\n MessageType.MESSAGE,\n new TextEncoder().encode(message),\n this._keyManager.signingKey,\n recipientVk,\n {\n threadId: options?.threadId,\n mediaType: \"text/plain\",\n attachments: options?.attachments,\n }\n );\n\n // Send via transport (with multi-relay failover -- CARD-06)\n const wire = toWireDict(envelope);\n const relayUrls = await this._getRelayUrls(toAddress);\n if (\n relayUrls !== null &&\n relayUrls.length === 1 &&\n relayUrls[0] === this._config.relayUrl\n ) {\n // Same relay -- use existing transport (no failover overhead)\n await this._transport!.send(wire);\n } else if (relayUrls !== null && relayUrls.length > 0) {\n // Multi-relay or cross-relay: try each in order\n await this._trySendWithFailover(wire, relayUrls);\n } else {\n // No relay info -- fall back to own transport\n await this._transport!.send(wire);\n }\n\n return envelope.messageId;\n }\n\n /**\n * Retrieve, decrypt, and verify pending messages.\n *\n * Returns a list of ReceivedMessage data objects.\n * Silently drops messages with invalid signatures or decryption errors.\n */\n async inbox(limit: number = 50): Promise<ReceivedMessage[]> {\n await this._ensureConnected();\n\n // Sweep expired handshakes\n await this._sweepExpiredHandshakes();\n\n const rawMessages = await this._transport!.receive(limit);\n const result: ReceivedMessage[] = [];\n for (const raw of rawMessages) {\n const msg = await this._processInbound(raw);\n if (msg !== null) {\n result.push(msg);\n // Auto-send receipt.read for user messages (RCPT-01)\n await this._sendReadReceipt(msg);\n }\n }\n return result;\n }\n\n // -- Trust management (HAND-02, HAND-04) ---------------------------------\n\n /** List pending handshake requests. */\n async pending(): Promise<Array<{ address: string; contactCard: string; receivedAt: string }>> {\n await this._ensureConnected();\n return this._contactBook.getPending();\n }\n\n /**\n * Approve a pending handshake request.\n *\n * Adds the sender to contacts with trust_source='explicit-approval'\n * and sends handshake.accept back.\n */\n async approve(address: string): Promise<void> {\n await this._ensureConnected();\n\n const pendingList = this._contactBook.getPending();\n const entry = pendingList.find((p) => p.address === address);\n if (!entry) {\n throw new UAMError(`No pending handshake from ${address}`);\n }\n\n // Parse and verify the stored contact card\n const cardDict = JSON.parse(entry.contactCard) as Record<string, unknown>;\n const card = contactCardFromDict(cardDict);\n verifyContactCard(card);\n\n // Add to contacts with trust_source tracking\n this._contactBook.addContact(card.address, card.publicKey, {\n displayName: card.displayName,\n trustState: \"trusted\",\n trustSource: \"explicit-approval\",\n });\n\n // Remove from pending\n this._contactBook.removePending(address);\n\n // Send handshake.accept back\n const senderVk = deserializeVerifyKey(card.publicKey);\n await this._handshake._sendAccept(this, address, senderVk);\n }\n\n /**\n * Deny a pending handshake request.\n *\n * Removes the entry from pending and sends handshake.deny.\n */\n async deny(address: string): Promise<void> {\n await this._ensureConnected();\n\n const pendingList = this._contactBook.getPending();\n const entry = pendingList.find((p) => p.address === address);\n if (!entry) {\n throw new UAMError(`No pending handshake from ${address}`);\n }\n\n // Parse contact card for sender's public key\n const cardDict = JSON.parse(entry.contactCard) as Record<string, unknown>;\n const card = contactCardFromDict(cardDict);\n const senderVk = deserializeVerifyKey(card.publicKey);\n\n // Remove from pending\n this._contactBook.removePending(address);\n\n // Send handshake.deny\n await this._handshake._sendDeny(this, address, senderVk);\n }\n\n /**\n * Block an address or domain pattern (HAND-04).\n */\n async block(pattern: string): Promise<void> {\n await this._ensureConnected();\n this._contactBook.addBlock(pattern);\n }\n\n /**\n * Remove a block pattern (HAND-04).\n */\n async unblock(pattern: string): Promise<void> {\n await this._ensureConnected();\n this._contactBook.removeBlock(pattern);\n }\n\n // -- Domain verification (DNS-02) ----------------------------------------\n\n /**\n * Verify domain ownership via relay endpoint (DNS-02).\n *\n * Polls `POST /api/v1/verify-domain` until the relay confirms\n * DNS TXT (or HTTPS fallback) verification succeeds, or timeout\n * elapses.\n *\n * Returns `true` if verified, `false` on timeout.\n */\n async verifyDomain(\n domain: string,\n options?: { timeout?: number; pollInterval?: number }\n ): Promise<boolean> {\n const { generateTxtRecord } = await import(\"./dns-verifier.js\");\n await this._ensureConnected();\n\n const timeout = options?.timeout ?? 300000; // 5 minutes\n const pollInterval = options?.pollInterval ?? 10000; // 10 seconds\n\n const expectedTxt = generateTxtRecord(\n this.publicKey,\n this._config.relayUrl\n );\n // Log expected TXT for user reference (they need to publish this)\n void expectedTxt;\n\n const start = Date.now();\n while (Date.now() - start < timeout) {\n try {\n const resp = await fetch(\n `${this._config.relayUrl}/api/v1/verify-domain`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this._token}`,\n },\n body: JSON.stringify({ domain }),\n signal: AbortSignal.timeout(30000),\n }\n );\n if (resp.ok) {\n const result = (await resp.json()) as Record<string, unknown>;\n if (result[\"status\"] === \"verified\") {\n return true;\n }\n }\n } catch {\n // Request failed, retry after poll interval\n }\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n return false;\n }\n\n // -- Internal methods ----------------------------------------------------\n\n /** Multi-relay failover (CARD-06). */\n private async _getRelayUrls(toAddress: string): Promise<string[] | null> {\n const urls = this._contactBook.getRelayUrls(toAddress);\n if (urls !== null) {\n return urls;\n }\n return [this._config.relayUrl];\n }\n\n /**\n * Try sending wire envelope to each relay URL in order (CARD-06).\n *\n * Uses transient fetch POST requests so the envelope can be delivered\n * to any relay that hosts the recipient.\n */\n private async _trySendWithFailover(\n wire: Record<string, unknown>,\n relayUrls: string[]\n ): Promise<void> {\n let lastError: Error | null = null;\n\n for (const url of relayUrls) {\n // Normalize: strip trailing '/ws', convert ws:// -> http://\n let base = url.replace(/\\/+$/, \"\");\n if (base.endsWith(\"/ws\")) {\n base = base.slice(0, -3);\n }\n base = base.replace(\"wss://\", \"https://\").replace(\"ws://\", \"http://\");\n const sendUrl = `${base}/api/v1/send`;\n\n try {\n const resp = await fetch(sendUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this._token}`,\n },\n body: JSON.stringify({ envelope: wire }),\n signal: AbortSignal.timeout(10000),\n });\n if (!resp.ok) {\n throw new Error(`HTTP ${resp.status}`);\n }\n return; // Success\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err));\n }\n }\n\n if (lastError !== null) {\n throw lastError;\n }\n throw new UAMError(\"No relay URLs to try\");\n }\n\n private async _ensureConnected(): Promise<void> {\n if (!this._connected) {\n await this.connect();\n }\n }\n\n /**\n * Resolve a recipient's public key, checking contact book first.\n *\n * TOFU-01: Known contacts always use stored key (zero network I/O).\n * TOFU-03: Race-condition double-check after network resolve.\n * Raises KeyPinningError if a pinned contact's key doesn't match.\n */\n private async _resolvePublicKey(toAddress: string): Promise<Uint8Array> {\n // TOFU-01: Check contact book first (local-first, zero network I/O)\n const pkStr = this._contactBook.getPublicKey(toAddress);\n if (pkStr !== null) {\n // Known contact: always use stored key\n return deserializeVerifyKey(pkStr);\n }\n\n // Unknown contact: resolve from network\n const resolvedPkStr = await this._resolver.resolvePublicKey(\n toAddress,\n this._token!,\n this._config.relayUrl\n );\n\n // TOFU-03: Double-check no pinned key exists (race condition guard)\n const storedPk = this._contactBook.getPublicKey(toAddress);\n if (storedPk !== null && storedPk !== resolvedPkStr) {\n const trust = this._contactBook.getTrustState(toAddress);\n if (trust === \"pinned\" || trust === \"trusted\" || trust === \"verified\") {\n throw new KeyPinningError(\n `CRITICAL: Public key mismatch for ${toAddress}! ` +\n `Stored key does not match resolved key. ` +\n `This may indicate a relay MITM attack. ` +\n `To accept the new key: uam contact remove ${toAddress}`\n );\n }\n }\n\n // Store as provisional (TOFU: unverified until handshake completes)\n this._contactBook.addContact(toAddress, resolvedPkStr, {\n trustState: \"provisional\",\n });\n\n return deserializeVerifyKey(resolvedPkStr);\n }\n\n private async _initiateHandshake(\n toAddress: string,\n recipientVk: Uint8Array\n ): Promise<void> {\n const wire = await this._handshake.createHandshakeRequest(\n this,\n toAddress,\n recipientVk\n );\n await this._transport!.send(wire);\n\n // Mark as handshake-sent in contact book\n this._contactBook.addContact(\n toAddress,\n serializeVerifyKey(recipientVk),\n { trustState: \"handshake-sent\" }\n );\n }\n\n /**\n * Process a single inbound envelope: verify, decrypt, handle handshakes.\n *\n * Returns null for invalid messages or handshake protocol messages.\n */\n private async _processInbound(\n raw: Record<string, unknown>\n ): Promise<ReceivedMessage | null> {\n // Parse envelope\n const envelope = fromWireDict(raw);\n\n // Check block list BEFORE expensive crypto (HAND-04)\n if (this._contactBook.isBlocked(envelope.fromAddress)) {\n return null;\n }\n\n // Look up sender's public key for verification\n let senderPkStr = this._contactBook.getPublicKey(envelope.fromAddress);\n if (senderPkStr === null) {\n // Unknown sender -- try resolving from relay\n try {\n senderPkStr = await this._resolver.resolvePublicKey(\n envelope.fromAddress,\n this._token!,\n this._config.relayUrl\n );\n } catch {\n return null;\n }\n }\n\n const senderVk = deserializeVerifyKey(senderPkStr);\n\n // Verify signature (SEC-03: mandatory)\n try {\n verifyEnvelope(envelope, senderVk);\n } catch (err) {\n if (err instanceof SignatureVerificationError) {\n return null; // Silently reject unsigned/invalid messages\n }\n throw err;\n }\n\n // Handle handshake messages (not user-visible)\n if (\n envelope.type === MessageType.HANDSHAKE_REQUEST ||\n envelope.type === MessageType.HANDSHAKE_ACCEPT ||\n envelope.type === MessageType.HANDSHAKE_DENY\n ) {\n return this._handshake.handleInbound(this, envelope, senderVk);\n }\n\n // For non-auto-accept policies, filter messages from unapproved senders\n if (this._handshake._trustPolicy !== \"auto-accept\") {\n if (!this._contactBook.isTrustedOrVerified(envelope.fromAddress)) {\n return null;\n }\n }\n\n // Decrypt payload (SEC-04: mandatory)\n let plaintextBytes: Uint8Array;\n try {\n plaintextBytes = decryptPayload(\n envelope.payload,\n this._keyManager.signingKey,\n senderVk\n );\n } catch (err) {\n if (err instanceof DecryptionError) {\n return null;\n }\n throw err;\n }\n\n // Build ReceivedMessage data object\n return Object.freeze({\n messageId: envelope.messageId,\n fromAddress: envelope.fromAddress,\n toAddress: envelope.toAddress,\n content: new TextDecoder().decode(plaintextBytes),\n timestamp: envelope.timestamp,\n type: envelope.type,\n threadId: envelope.threadId,\n replyTo: envelope.replyTo,\n mediaType: envelope.mediaType,\n verified: true,\n });\n }\n\n /**\n * Sweep expired pending handshakes and send receipt.failed (HAND-03).\n */\n private async _sweepExpiredHandshakes(): Promise<void> {\n const expired = this._contactBook.getExpiredPending(7);\n for (const entry of expired) {\n try {\n const cardDict = JSON.parse(entry.contactCard) as Record<\n string,\n unknown\n >;\n const card = contactCardFromDict(cardDict);\n const recipientVk = deserializeVerifyKey(card.publicKey);\n\n const failPayload = JSON.stringify({\n reason: \"handshake_expired\",\n original_from: entry.address,\n });\n const envelope = await createEnvelope(\n this._address!,\n entry.address,\n MessageType.RECEIPT_FAILED,\n new TextEncoder().encode(failPayload),\n this._keyManager.signingKey,\n recipientVk\n );\n const wire = toWireDict(envelope);\n await this._transport!.send(wire);\n } catch {\n // Failed to send receipt.failed -- ignore\n }\n\n // Remove from pending regardless\n this._contactBook.removePending(entry.address);\n }\n }\n\n /**\n * Send receipt.read back to the sender (RCPT-01).\n *\n * Fire-and-forget: errors are never propagated.\n * Anti-loop guard: receipts, handshakes, and session messages are skipped.\n */\n private async _sendReadReceipt(msg: ReceivedMessage): Promise<void> {\n // Anti-loop: never generate receipts for protocol messages\n if (\n msg.type.startsWith(\"receipt.\") ||\n msg.type.startsWith(\"handshake.\") ||\n msg.type.startsWith(\"session.\")\n ) {\n return;\n }\n\n try {\n const senderPkStr = this._contactBook.getPublicKey(msg.fromAddress);\n if (senderPkStr === null) return;\n\n const senderVk = deserializeVerifyKey(senderPkStr);\n\n const receiptPayload = JSON.stringify({\n message_id: msg.messageId,\n });\n const envelope = await createEnvelope(\n this._address!,\n msg.fromAddress,\n MessageType.RECEIPT_READ,\n new TextEncoder().encode(receiptPayload),\n this._keyManager.signingKey,\n senderVk\n );\n\n const wire = toWireDict(envelope);\n await this._transport!.send(wire);\n } catch {\n // Fire-and-forget\n }\n }\n\n /**\n * Register with the relay server.\n *\n * Calls POST /api/v1/register with agent name and public key.\n * Stores the returned API key on disk.\n */\n private async _registerWithRelay(): Promise<void> {\n const publicKeyStr = serializeVerifyKey(this._keyManager.verifyKey);\n\n const resp = await fetch(\n `${this._config.relayUrl}/api/v1/register`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n agent_name: this._config.name,\n public_key: publicKeyStr,\n }),\n }\n );\n\n if (resp.status === 409) {\n throw new UAMError(\n `Address already registered with a different key: ` +\n `${this._config.name}::${this._config.relayDomain}`\n );\n }\n\n if (!resp.ok) {\n const text = await resp.text();\n throw new UAMError(\n `Registration failed: ${resp.status} ${text}`\n );\n }\n\n const data = (await resp.json()) as Record<string, unknown>;\n this._address = data[\"address\"] as string;\n this._token = data[\"token\"] as string;\n\n // Persist token for returning-user flow\n this._keyManager.saveToken(this._config.name, this._token);\n }\n}\n","/**\n * Receiver-side webhook signature verification (HOOK-03).\n *\n * Small utility for webhook receivers to verify that incoming webhook\n * payloads were signed by the UAM relay. Uses HMAC-SHA256 with the\n * agent's token as the shared secret.\n *\n * Matches Python webhook_verify.py API surface.\n *\n * Usage:\n *\n * import { verifyWebhookSignature } from \"uam\";\n *\n * const payload = Buffer.from(requestBody);\n * const signature = request.headers[\"x-uam-signature\"];\n * const token = \"your-agent-token\";\n *\n * if (verifyWebhookSignature(payload, signature, token)) {\n * // payload is authentic\n * }\n */\n\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\n\n/**\n * Verify an HMAC-SHA256 webhook signature.\n *\n * @param payload - Raw request body bytes\n * @param signatureHeader - \"sha256=<hex>\" format (X-UAM-Signature header)\n * @param token - Shared secret (agent token)\n * @returns `true` if valid, `false` otherwise.\n *\n * Uses `crypto.timingSafeEqual()` for constant-time comparison\n * to prevent timing attacks.\n */\nexport function verifyWebhookSignature(\n payload: Buffer | Uint8Array,\n signatureHeader: string,\n token: string\n): boolean {\n if (!signatureHeader.startsWith(\"sha256=\")) {\n return false;\n }\n\n const expected = createHmac(\"sha256\", token)\n .update(payload)\n .digest(\"hex\");\n const received = signatureHeader.slice(\"sha256=\".length);\n\n // Constant-time comparison requires equal-length buffers\n const expectedBuf = Buffer.from(expected, \"utf-8\");\n const receivedBuf = Buffer.from(received, \"utf-8\");\n\n if (expectedBuf.length !== receivedBuf.length) {\n return false;\n }\n\n return timingSafeEqual(expectedBuf, receivedBuf);\n}\n","/**\n * UAM SDK -- the agent-facing API.\n */\n\nexport { Agent } from \"./agent.js\";\nexport type { ReceivedMessage } from \"./message.js\";\nexport { SDKConfig } from \"./config.js\";\nexport { KeyManager } from \"./key-manager.js\";\nexport { ContactBook } from \"./contact-book.js\";\nexport { HandshakeManager } from \"./handshake.js\";\nexport { AddressResolver, SmartResolver, Tier1Resolver, Tier2Resolver, Tier3Resolver, type Tier3Config } from \"./resolver.js\";\nexport { TransportBase, HTTPTransport, WebSocketTransport, createTransport } from \"./transport/index.js\";\nexport { verifyWebhookSignature } from \"./webhook-verify.js\";\nexport { parseUamTxt, extractPublicKey, queryUamTxt, resolveKeyViaHttps, generateTxtRecord } from \"./dns-verifier.js\";\n"],"mappings":"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","names":["dnsResolveTxt","MessageType","sodium","import_node_crypto","buildSignableDict","import_node_fs","import_node_path","import_node_os","import_node_fs","import_node_path","Database","WebSocket","generateTxtRecord","import_node_crypto"]}
|