/**
 * T0 — typed error classes for relay-e2e (PLAN_RELAY_E2E §3 T0).
 *
 * Every error subclasses {@link E2EError} and carries a stable, greppable `code`. Per INV9,
 * a thrown message MUST NEVER embed key/nonce/plaintext material — callers surface the code,
 * not secret bytes. No `console` here; the caller decides how to handle.
 */

/** Base class for all relay-e2e crypto errors. */
export class E2EError extends Error {
  readonly code: string
  constructor(code: string, message: string) {
    super(message)
    this.name = new.target.name
    this.code = code
  }
}

/** Pinned enroll_fpr / registry pubkey disagreement ⇒ MITM abort (§4d). */
export class FingerprintMismatchError extends E2EError {
  constructor(message = 'host fingerprint mismatch') {
    super('E2E_FINGERPRINT_MISMATCH', message)
  }
}

/** AEAD tag verification failed ⇒ drop the frame and tear the session down. */
export class AeadOpenError extends E2EError {
  constructor(message = 'AEAD authentication failed') {
    super('E2E_AEAD_OPEN', message)
  }
}

/** Sequence number non-monotonic / duplicate / reordered / gapped (INV13). */
export class ReplayError extends E2EError {
  constructor(message = 'sequence replay/reorder rejected') {
    super('E2E_REPLAY', message)
  }
}

/** Illegal handshake transition, wrong phase, or unusable negotiation. */
export class HandshakeStateError extends E2EError {
  constructor(message = 'illegal handshake state transition') {
    super('E2E_HANDSHAKE_STATE', message)
  }
}

/** Malformed wire bytes / unsupported version / bad AEAD id. */
export class EnvelopeFormatError extends E2EError {
  constructor(message = 'malformed envelope') {
    super('E2E_ENVELOPE_FORMAT', message)
  }
}

/** No WebCrypto / CSPRNG available in the host environment (fail-fast boundary). */
export class CryptoUnavailableError extends E2EError {
  constructor(message = 'WebCrypto is unavailable in this environment') {
    super('E2E_CRYPTO_UNAVAILABLE', message)
  }
}
