/** * Assistant attestation utilities. * * Implements the cryptographic verification scheme for Convos assistants * as described in the assistant-attestation design doc. * * Attestation scheme: * message = sha256(inboxId || timestamp) * signature = Ed25519.sign(message, privateKey) * * The signature, timestamp, and key ID are stored in ProfileUpdate metadata: * attestation = base64url(signature) * attestation_ts = ISO 8601 UTC timestamp * attestation_kid = key ID from JWKS endpoint */ export interface Attestation { /** Base64url-encoded Ed25519 signature (64 bytes) */ signature: string; /** ISO 8601 UTC timestamp used in the signed message */ timestamp: string; /** Key ID from the JWKS endpoint */ kid: string; } export interface JwksKey { /** Key ID */ kid: string; /** Key type — must be "OKP" for Ed25519 */ kty: string; /** Curve — must be "Ed25519" */ crv: string; /** Base64url-encoded 32-byte public key */ x: string; /** Key use — "sig" for signing */ use?: string; /** Optional expiry — ISO 8601 */ exp?: string; /** Issuer identifier (e.g. "convos") — used by iOS to resolve trust level */ issuer?: string; } export interface Jwks { keys: JwksKey[]; } export interface Ed25519KeyPair { /** Base64url-encoded 32-byte public key */ publicKey: string; /** Base64url-encoded 64-byte private key (seed + public) or PEM */ privateKeyPem: string; /** Key ID */ kid: string; } /** * Sign an attestation for an agent's inbox ID. * * @param inboxId - The agent's XMTP inbox ID (hex string) * @param privateKeyPem - Ed25519 private key in PEM format * @param kid - Key ID to include in the attestation * @param timestamp - Optional timestamp (defaults to now) */ export declare function signAttestation(inboxId: string, privateKeyPem: string, kid: string, timestamp?: string): Attestation; /** * Verify an attestation against a public key. * * @param inboxId - The agent's XMTP inbox ID * @param attestation - The attestation to verify * @param publicKeyBase64url - Base64url-encoded 32-byte Ed25519 public key * @param maxAgeMs - Maximum age of the attestation in milliseconds (default: 24 hours) * @param referenceDate - Reference date for age check (default: now) */ export declare function verifyAttestation(inboxId: string, attestation: Attestation, publicKeyBase64url: string, maxAgeMs?: number, referenceDate?: Date): { valid: boolean; reason?: string; }; /** * Verify an attestation against a JWKS keyset. * * Looks up the key by `kid`, checks expiry, then verifies the signature. */ export declare function verifyAttestationWithJwks(inboxId: string, attestation: Attestation, jwks: Jwks, maxAgeMs?: number, referenceDate?: Date): { valid: boolean; reason?: string; }; /** * Generate an Ed25519 key pair for testing attestations. * * @param kid - Key ID to assign */ export declare function generateAttestationKeyPair(kid: string): Ed25519KeyPair; /** * Build a JWKS from key pairs (for testing). */ export declare function buildJwks(keys: Array<{ publicKey: string; kid: string; exp?: string; issuer?: string; }>): Jwks; /** * Fetch a JWKS from a URL. */ export declare function fetchJwks(url: string): Promise; /** * Common attestation-flag shape consumed by `agent serve` and * `conversations join`. Either: * * - all three of `attestation` / `attestation-ts` / `attestation-kid` * are pre-computed (the agent signed elsewhere, e.g. backend), OR * - `attestation-private-key` (path) + `attestation-kid` are given * and the CLI signs at runtime against the resolved inbox id. * * The signing path eliminates the chicken-and-egg between * `identity create` (which doesn't materialize an inbox id) and * `signAttestation` (which needs the inbox id). The CLI defers signing * until after the XMTP client is initialized, so the inbox id is known * exactly when we mint the attestation. */ export interface AttestationFlagSet { attestation?: string; "attestation-ts"?: string; "attestation-kid"?: string; "attestation-private-key"?: string; } /** * Resolve attestation metadata from CLI flags. Returns the * `{attestation, attestation_ts, attestation_kid}` triple ready to * embed in ProfileUpdate metadata, or `undefined` if no attestation * was requested. Throws on partial / inconsistent flag combinations * so misuse fails loudly rather than silently producing an empty * profile. * * @param flags - Parsed flag object (oclif-style) * @param inboxId - Resolved XMTP inbox id of the signer (required for * the sign-on-the-fly path; ignored on the pre-computed path) */ export declare function resolveAttestationFromFlags(flags: AttestationFlagSet, inboxId: string): Promise; /** * Convert an `Attestation` triple into the snake_case keys expected on * the ProfileUpdate metadata wire (matches the iOS reader). */ export declare function attestationToProfileMetadata(attestation: Attestation): Record;