Skip to content

v1.6.0

Choose a tag to compare

@jiashuoz jiashuoz released this 07 Aug 02:40
5624646

Backward compatible with 1.5.0 on the wire — nothing in this release removes an
operation, field, or enum value, and every addition is opt-in or additive.
Four behavior changes are deliberate and called out under "Behavior changes"
below; read that section before upgrading.
One migration, a metadata-only
ALTER TABLE with a constant default — see "Upgrading".

Behavior changes

Each of these changes an outcome that 1.5.0 produced.

  • Invalid UTF-8 is rejected with 400 invalid_request across the /v1
    surface. Previously malformed byte sequences were accepted in some fields and
    surfaced as a 500 in others — the same class of fix as 1.5.0's NUL-byte
    rejection. If you relay third-party content, validate or re-encode it as UTF-8
    before sending.

  • Re-registering a domain you already own is idempotent and no longer counts
    against the domain cap
    (#819). Previously a repeated POST /v1/domains for
    an already-owned domain could consume quota; it now returns the existing
    registration.

  • agent_count is now populated correctly in domain reads where it was
    previously wrong or empty (#817, #806). Clients that special-cased the empty
    value can drop the workaround.

  • send_at survives a review hold (#838). A scheduled send that a
    protection policy holds for review keeps its schedule when approved: it fires
    at the original send_at (or immediately if that time has passed) instead of
    silently converting to an immediate send. Self-sends with send_at are
    guarded consistently.

API

  • reply_to accepts a list of addresses (#831) — everywhere a single
    reply-to was accepted: send, reply, and forward, across the API (oneOf
    widening, verified backward-compatible), both SDKs, the CLI (--reply-to is
    repeatable), and MCP. Single-address requests are unchanged.

  • Operator-configured outbound footer (#839) — a new optional
    outbound_footer config block appends an operator-supplied footer (text +
    HTML, RFC 3676 signature delimiter) to outbound mail at composition time,
    gated per account via a new account_limits.outbound_footer_enabled column
    plus a row-less default. Fully inert unless configured: self-hosted
    deployments see zero change. Useful for AI-disclosure footers or hosted
    branding. The footer is applied inside the DKIM-signed body, is excluded for
    self-send loopback delivery and non-standard account classes, and resolves at
    approval time for review-held mail (including TTL auto-approval).

  • /mcp serves a landing page and the docs ship llms-full.txt (#807) —
    a browser hitting the MCP endpoint gets oriented instead of a protocol error.

  • 405 responses carry an Allow header listing the methods the resource
    supports.

Dashboard

Message-view and settings fixes (#834, #820, #810, #808) and design-token
cleanup — no functional surface changes.

Observability

  • Queue-dwell metrics exclude scheduled sends waiting for their fire time
    (#818) — backlog alerts no longer count mail that is supposed to be
    waiting.

Publishing

  • The CLI now publishes on its own cli-v* tag (#796), removing the
    npm-ordering race between @e2a/cli and @e2a/sdk on release day.

Upgrading

  • One migration, 095_account_limits_outbound_footer.sql: adds a boolean
    column with a constant default to account_limits — metadata-only, no table
    rewrite, no CONCURRENTLY index builds, safe at any size. Auto-applied on
    startup as usual.
  • The outbound_footer config block is optional and defaults off; no config
    changes are required.
  • SDKs/CLI: new releases of @e2a/sdk, e2a (PyPI), and @e2a/cli accompany
    this release for the reply_to list support; existing versions continue to
    work unchanged.