# Changelog

Source: https://wraps.dev/changelog

![Wraps Logo](https://wraps.dev/wraps-light-logo.png)![Wraps Logo](https://wraps.dev/wraps-dark-logo.png)

](https://wraps.dev/)

[](https://github.com/wraps-team/wraps)[Log in](https://app.wraps.dev/auth?mode=signin)[Sign up](https://app.wraps.dev/auth?mode=signup)

Toggle menu

wraps · changelog

# What's new in Wraps.

Stay up to date with the latest features, improvements, and fixes across the Wraps CLI, SDK, and Dashboard.

CLISeptember 2026Latest

### [Teardown That Leaves Your DNS Alone](https://wraps.dev/changelog/teardown-that-leaves-your-dns-alone)

wraps email destroy now touches only the DNS records Wraps created, across Route53, Cloudflare and Vercel.

-   `wraps email destroy`deletes only the records Wraps created. Every deletion matches name, type and exact value, and a Route53 record set holding values Wraps did not write is rewritten without Wraps’ value rather than deleted whole — deletion previously matched name and type alone, so accepting the DNS cleanup prompt on a domain that already had a `_dmarc` policy removed that policy along with the records Wraps wrote. Cloudflare and Vercel domains are cleaned up too, not just Route53, and the record lookup is paginated so zones larger than 500 record sets no longer skip records silently. If you ran `destroy` before this and the domain had a `_dmarc` policy predating Wraps, confirm it is still published
-   `wraps email reply destroy` deletes the MX and SPF records it created at `r.mail.<domain>`instead of printing a reminder to remove them by hand — left in place, the MX still pointed at SES with nothing configured to receive, so signed reply addresses bounced. `wraps email inbound destroy` now warns when reply threading is configured, and still never deletes those records itself: they follow the sending domain, not the inbound receiving domain
-   Fix: a DNS write that correctly did nothing is no longer reported as a failure. Re-running `wraps email inbound init`, `inbound add` or `reply init` against records that were already correct used to print the full manual SPF block, and following it against an existing SPF record produced a second `v=spf1`record — the RFC 7208 PermError the preflight exists to prevent
-   Fix: `wraps email check` recommends `~all` and no longer grades a domain down for it. A `-all` deduction now applies only where the domain authorizes senders and DMARC is absent, invalid, `p=none` or `t=y`— RFC 9989 section 7.1 cautions against `-all`because it rejects mail pre-DATA, before DMARC can pass it on an aligned DKIM signature — and a parked `v=spf1 -all` is never flagged

Also fixed (2)

-   The apex SPF record is still left for you to edit by hand — stripping include:amazonses.com from a record that may carry other providers' includes is a rewrite rather than a deletion, and destroy does not attempt it.
-   wraps support printed a GitHub issues link under the wraps-dev organization, which 404s; it now points at wraps-team, where the repository lives (CLI v3.11.2).

CLI v3.11.1

DashboardSeptember 2026

### [Sending Domains, Suppressions & Stale Roles](https://wraps.dev/changelog/sending-domains-suppressions-and-stale-roles)

Sending domains, suppressions and role health move from CLI-only into the dashboard.

![A Wraps card reading: September 2026 — Add a domain in the dashboard. DKIM records, verification state, and the configuration set behind each identity.](https://wraps.dev/_next/image?url=%2Femail%2F2026-09-dashboard-domains.png&w=3840&q=75&dpl=dpl_AtMuFDHv7YUxevJ6rkd5iV19n1HE)

-   A sending-domains page lists every SES identity with its verification state and the DKIM CNAMEs and MAIL FROM records still to publish, adds a domain with SES-managed Easy DKIM, and opens a per-identity sheet for the configuration set that governs it: tracking domain, TLS policy, suppression reasons and event destinations — the sheet flags an `OPTIONAL` tracking `HttpsPolicy` and an empty event-destination list, the usual reasons click links break and delivery events never arrive. Onboarding had told customers they could manage domains in the dashboard while the only working paths were installing the CLI or rebuilding the CloudFormation stack
-   The SES suppression list is browsable from the dashboard, and an address can be removed. A `COMPLAINT`\-reason removal re-reads the reason from SES rather than trusting the browser, and refuses without an explicit acknowledgement. The underlying `email.suppression.*`grants now ship on every deployment path — CDK, Pulumi and CloudFormation — but an existing deployment needs `wraps platform update-role` (CLI v3.9.0+), a CDK 0.3.0+/Pulumi 0.4.0+ redeploy, or a CloudFormation stack update before those calls stop returning AccessDenied
-   The account page flags when the console role’s policy is behind the version Wraps expects and links to the IAM-console repair route, and reports AWS’s actual SES production-access verdict instead of discarding it. `wraps email status --json`reports sandbox state and quota and recognizes a CloudFormation deployment instead of exiting 1 with “No email infrastructure found”
-   Fix: a broadcast into an SES account AWS has paused is now blocked at the review step instead of running past the point-of-no-return dialog and failing every recipient — a `PROBATION` account only warns rather than blocking, and a check that cannot read account state never refuses a legitimate send. Fix: the sending-domains list pages through every SES identity instead of showing only the first 100

Also fixed (1)

-   The setup dashboard's "Send a test email" step now links to the sending-domains page instead of sending a test email itself.

Platform v0.28.0

APISeptember 2026

### [The API Catches Up With the Dashboard](https://wraps.dev/changelog/the-api-catches-up-with-the-dashboard)

API keys can now manage templates, segments and broadcast batches, and read the account-health data the dashboard shows.

![A Wraps card reading: API v1.2 — Templates and segments by API key. Domain verification, email metrics and SES account health ship alongside them.](https://wraps.dev/_next/image?url=%2Femail%2F2026-09-api-v1-2.png&w=3840&q=75&dpl=dpl_AtMuFDHv7YUxevJ6rkd5iV19n1HE)

-   The template editor is reachable by API key. `/v1/templates` adds a cursor-paginated list, full detail, create, partial update, `/:id/publish` and `/:id/duplicate`— publish running the same sequence the dashboard uses. A `limit` bound on `GET /v1/templates/pull`is opt-in — it used to return every code-pushed template with full TSX source and no pagination, its only ceiling Lambda’s response limit — so the CLI’s push/pull protocol is byte-for-byte unchanged when the bound is omitted. The API does not compile TSX, so `compiledHtml` must come from the caller. There is no DELETE: templates are referenced by send history, and removing one would silently detach it
-   `/v1/segments` adds list, read, create, update, delete and `/preview` for an unsaved condition. The whole group sits behind a Pro plan gate on every verb including reads; `memberCount` is always computed live rather than read from the cached column, and a delete refuses with 409 while a scheduled or processing broadcast still targets the segment
-   `/v1/batch` adds a list, per-recipient outcomes and a click breakdown, so a caller can see who a broadcast reached instead of only creating, promoting, getting, cancelling and resuming it
-   `GET /v1/domains`, `GET /v1/email/metrics` and `GET /v1/account/health`round out what a caller can read about its own connected account: domain verification and DKIM status (an unreachable connected account is marked rather than failing the whole request), aggregate email numbers by dimension and granularity with no plan gate, and the SES verdict — sandbox status, production access, enforcement pauses, 24-hour quota — a hosted provider has no equivalent for, since there is no per-customer SES account to describe. Health thresholds come from the classifier’s exported constants, so a caller computes its own headroom without hardcoding AWS’s numbers; `unknown` never collapses to healthy, and the read costs zero AWS calls

API v1.2

DashboardSeptember 2026

### [Audit Export, SMS Consent & Account Health](https://wraps.dev/changelog/audit-export-sms-consent-and-account-health)

Account health, audit export and SMS consent are now visible and self-service in the dashboard, without waiting on an alert to fire.

-   Audit logs export to CSV on Business. The plan was sold on audit export with no export path behind it. The export is scoped to the caller’s organization, bounded by the plan’s retention window, and self-auditing: exporting the audit trail leaves a row in the audit trail
-   The preference center lets a contact grant and withdraw SMS consent. It already offered SMS as a preferred channel whenever a contact had a phone, but nothing let the contact actually consent, so every write to that status was an operator assertion. Both transitions record the exact consent sentence shown, the IP and the user agent. Granting requires the organization to still be able to send; withdrawal never does
-   A header pill reports SES account health whenever it is not healthy, from a Postgres-only read. The hourly sweep compared `GetAccount`and CloudWatch reputation against AWS’s enforcement lines and threw every number away, so “is my account okay right now?” had no answer anywhere unless an alert happened to fire in the last 24 hours
-   Fix: the stale-feed alert stops firing on foreign SES traffic. The fallback probe reads the account-wide SES send count, which includes mail from applications that have nothing to do with Wraps. One customer sharing SES with their own app was flagged with zero Wraps sends against 15,804 account-wide; the probe now measures that count against a seven-day baseline of recorded sends and stays quiet when the surplus is someone else’s mail

Also fixed (2)

-   An unauthenticated waitlist endpoint on the dashboard and wraps.dev could subscribe the wrong contact to a topic by resolving an existing address with a substring match; both routes had no caller and are removed.
-   A documentation code block that omitted its default tab rendered as an empty box, across 95 call sites in 16 files including the base URL on the API reference; the default now falls back to the first item's language.

Platform v0.27.0

CLISeptember 2026

### [Custom Tracking Domains & Proven-Orphan Cleanup](https://wraps.dev/changelog/custom-tracking-domains-and-proven-orphan-cleanup)

Custom tracking domains resolve over HTTPS by default, and doctor --cleanup no longer guesses at orphaned resources.

![A Wraps card reading: CLI v3.6.0 — Custom tracking domains. Open and click links resolve through a host you own.](https://wraps.dev/_next/image?url=%2Femail%2F2026-09-tracking-domains.png&w=3840&q=75&dpl=dpl_AtMuFDHv7YUxevJ6rkd5iV19n1HE)

-   `wraps email domains add` and `wraps email domains config` accept `--tracking-domain`, so open and click links resolve through a host under your own domain instead of `r.<region>.awstrack.me`. `--tracking-https` requests an ACM certificate and puts a CloudFront distribution in front of that host — two runs, since ACM validation takes 5 to 30 minutes: the first prints the validation record, the second finishes once the certificate is ISSUED
-   `wraps email domains list`and the dashboard report whether tracking links are HTTPS, per configuration set — a multi-domain account no longer reports one set’s state as the whole account’s. The failure hides well, since opens keep working over plain HTTP and only clicks break. Every tracking-domain write now carries an explicit `HttpsPolicy` instead of leaving it `OPTIONAL`, which wrapped click links in the original link’s protocol and produced a certificate warning instead of the destination — three paths could reach that `OPTIONAL` default, including `domains verify` re-issuing a policy-less write that downgraded an already-`REQUIRE` configuration set
-   Fix: `wraps email doctor --cleanup`no longer treats an unreachable Pulumi stack probe or an unchecked CloudFormation stack as a proven orphan — a failed probe used to sweep in the console access role and the configuration sets `domains add` creates, and a CloudFormation quick-create deployment was mistaken for loose resources. A check that cannot confirm an orphan now refuses `--cleanup` instead of assuming, and names the owning stack when it finds one
-   Fix: disabling and re-enabling HTTPS no longer hands back a CloudFront distribution the CLI had already switched off, breaking every click link until it is restored. A failed HTTPS provision during `domains add` now warns and falls back to plain HTTP instead of aborting and orphaning the identity it already created

Also fixed (8)

-   The five tracking-domain error codes are documented at /docs/reference/errors; a subdomain that was never added separately inherits the primary domain's tracking host.
-   If you saw "Cannot find module '@wraps/core'" in index.d.ts when installing @wraps.dev/cdk or @wraps.dev/pulumi, upgrade to CDK v0.3.1 or Pulumi v0.4.1 — the published type declarations no longer reference the unpublished @wraps/core package.
-   domains config --tracking-domain now offers HTTPS at the point it sets the domain, instead of requiring a second trip through the menu.
-   A zone-scoped Cloudflare token (Zone → DNS → Edit) now validates correctly for DNS automation; validation previously required the broader User → API Tokens → Read scope it didn't need.
-   Two DNS paths that used to fail silently now report whether the record was written: the tracking CNAME print, and the ACM validation push that gates certificate issuance.
-   ACM and CloudFront listings are paginated too, so a second page no longer causes a fresh certificate request on every run.
-   wraps --help was hiding thirteen shipped subcommands across five groups, including email reply, email logs and workflow entirely; a parity test now checks the dispatcher against the help output.
-   @wraps.dev/pulumi and @wraps.dev/cdk both accepted tracking.customRedirectDomain and failed differently — Pulumi deployed it with SES's OPTIONAL policy and no CloudFront, CDK ignored it entirely; both now warn at deploy time.

CLI v3.6.0 · CLI v3.7.0

CLIAugust 2026

### [Adopting a Deployment the CLI Did Not Create](https://wraps.dev/changelog/adopting-a-deployment-the-cli-did-not-create)

-   `wraps platform connect` and `wraps platform update-role`adopt an existing deployment. A CloudFormation quick-create customer has no local state file and no S3 state bucket to sync from, so both commands dead-ended — including on the documented repair path for a broken IAM trust policy. Registration is idempotent on the External ID, so adoption registers the account and repairs the trust policy without deploying anything
-   `wraps doctor` reports `wraps-*` resources it finds in AWS with no local connection record, instead of announcing no email deployment. That is what a CloudFormation-first connection looks like, and what a second machine looks like
-   Fix: `wraps update` never resolved a release. It matched tags beginning `cli@`; every release is tagged `cli-v`. Standalone installs only ever saw “Could not determine latest version from GitHub releases”
-   Fix: one telemetry event per invocation. `wraps permissions` emitted three and `wraps email domains add` emitted two names a millisecond apart, which inflated the reported failure rate and split one command across two names
-   Fix: a failure thrown before the handler runs is named by its third positional, so a failing `email domains verify` is distinguishable from a failing `email domains remove` rather than collapsing into `email:domains`

CLI v3.5.3

DashboardAugust 2026

### [Free, Pro & Business](https://wraps.dev/changelog/free-pro-and-business)

-   The starter, growth and scale ladder is replaced by three purchasable plans: Free at $0, Pro at $29 a month, Business at $199 a month. Each is a flat fee with no Wraps-side overage. Live subscriptions on the old names keep their limits, mapped to the successor plan and never displayed again
-   Free includes 5,000 custom events a month, warns as the allowance runs down, and blocks at 110% of it. Sends are unmetered on every plan: SES bills you directly, so metering them would tax the pass-through the product is built on
-   The daily request meter is retired on every plan and removed from the rate-limit reference. The per-minute limiter stays, because that one protects the API from bursts rather than metering the customer
-   Dashboard history is enforced where it is sold: 30 days on Free, 90 on Pro, 365 on Business. The emails list clamps to the plan window on the fresh request and on the cursor, which carries its own bounds and could otherwise widen page 2 after page 1 was cut back
-   Both surfaces now name the window instead of stopping silently, and the upgrade path is resolved server-side: Pro gets a self-serve link, Business is pointed at Enterprise
-   Audit logs move to Business, including the required-plan copy on the gated page and the feature list on the Business card. SES event ingestion now requires a live subscription, keyed on subscription status rather than plan name so free-tier organizations are unaffected, and it fails open — a database blip must not drop a paying customer’s events
-   Fix: the dashboard’s IAM role repair is reachable and works. Assume-role failures are classified by error code rather than by matching message text, and the SMS phone-number query can tell the client the role needs repairing
-   Fix: workflow sends skip contacts SES has already suppressed. The gate asked whether a contact was unsubscribed, bounced or complained and had no opinion about `suppressed`, so those addresses reached SES, were rejected, and returned as bounces charged to the workflow’s own stats

Platform v0.26.0

DashboardAugust 2026

### [Ask Mode & Guided Setup](https://wraps.dev/changelog/ask-mode-and-guided-setup)

-   `⌘K`now answers questions. Type two or more characters and pick “Ask Wraps” to get a setup-status card, an email-metrics card, or a recent-sends list — streamed, and validated against the tool’s output schema before anything renders
-   The assistant reads through a read-only tool layer. Every tool closes over the `organizationId`of the authenticated request (never a model input), projects an explicit field allowlist — no secrets, no PII, no raw metadata — and is filtered by the caller’s role before the model is offered it
-   Setup gained a next-best-action card that names the single blocking step. The choice is deterministic, not generated: a first send comes before requesting SES production access, because a sandboxed account can already send to verified recipients and the mailbox simulator
-   Copy on the top insight and the next step is now phrased from facts the dashboard already established. Detection thresholds are unchanged and a model decides nothing; only numbers and closed enums cross into the prompt, the result is schema-validated, and static copy stands in on any failure
-   The events feed refreshes itself on the unfiltered first page, and pauses when the tab is hidden or you switch it off. Waiting on an event you just fired no longer looks the same as a broken integration
-   Fix: navigating between dashboard routes keeps the shell mounted instead of tearing it down and rebuilding it
-   Fix: the events live-refresh toggle no longer crashes during server render

Platform v0.25.0

APIAugust 2026

### [Machine-Readable Errors & Data Retention](https://wraps.dev/changelog/machine-readable-errors-and-data-retention)

-   Every 4xx and 5xx body now carries a stable, enumerated `code` and a `requestId` alongside `error`. It comes from one response plugin, so all ~40 routes that return their own error object are covered rather than nearly all of them
-   The OpenAPI spec declares that shape as `ApiError` and attaches it to every operation. The `code`enum is derived from the handler’s own table, so the spec cannot drift from what the API emits
-   Rate-limited responses gain `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset` and `RateLimit-Policy` next to the `X-` originals, which are kept. `Reset`is seconds remaining, and the quota headers describe whichever window is closest to exhaustion — the one actually pacing you
-   New `/docs/reference/versioning` states what counts as a breaking change and how a deprecation is announced
-   A nightly retention worker ages out `message_send` and `contact_event`rows against your plan’s visible window, with a 30-day grace period and a one-time owner and admin notification before anything is removed. It ships in dry-run: it reports what it would delete and deletes nothing
-   The unreachable per-org event volume block is retired, and the tracked-events definition is corrected everywhere agents read it: the docs, `llms.txt` and the generated `pricing.md`
-   wraps.dev serves a markdown representation of every page the three ways an agent actually asks for one, and sitemap entries carry a real `lastmod` instead of the current timestamp on every request

API v1.1

DashboardAugust 2026

### [Three Deploy Paths & Feed Health](https://wraps.dev/changelog/three-deploy-paths-and-feed-health)

-   Onboarding offers the CLI, a coding agent, and the AWS console as peer cards. The step used to lead with CloudFormation and bury the other two in collapsibles, so a shift toward the CLI would have read as a funnel drop rather than a preference
-   Self-hosted orgs no longer see the platform CloudFormation path at all: the quick-create URL is not built, the card is not rendered, and the CLI steps and agent prompt name `wraps selfhost login` and `wraps selfhost connect`
-   Launching a stack closes the other two paths, so nobody runs `wraps email init`over resources CloudFormation is still creating. The connection gate has a visible terminal state and no longer unmounts an in-flight Deploy & Connect
-   Retired four onboarding steps that nothing could reach: deploy-infrastructure, deploy, cli-install, and the orphaned AWS connect path
-   Event-feed stall alerts judge staleness per message rather than against a cursor the webhook throttles to one write a minute. That cursor flagged every later message in a burst as unacknowledged: 13 of the 14 alerts this feature had ever sent were false, all against feeds that never missed an event
-   SDK senders get a stall alert at all. Sends through `@wraps.dev/email` go straight from your infrastructure to your SES and never touch the Wraps API, so a broken feed produced no rows and looked healthy. The hourly console-access role now reads the `AWS/SES`Send metric as an independent fallback, and a null probe means no evidence — never zero sends
-   Fix: the org webhook secret is no longer exposed through the Open AWS Console link
-   Fix: AWS connection routes require `awsAccounts:write`, not `awsAccounts:read`

Platform v0.24.0

CLIAugust 2026

### [One Doctor Command & Structured Remediations](https://wraps.dev/changelog/one-doctor-command-and-structured-remediations)

-   New `wraps doctor` merges the AWS and email doctors into one report and one exit code, with `--json` carrying remediations for MCP and agent callers. `wraps email doctor` is unchanged
-   Every finding now carries a structured remediation from one registry — the command that repairs it, rather than a hand-written sentence beside it. A single missing SES configuration set previously took a user five commands and a CLI reinstall, three of them because the CLI misdirected them. Checks with no automatic repair say so instead of guessing
-   Remediation commands carry the region the doctor actually scanned, so a pasted fix cannot fall back to `us-east-1` and report that the connection does not exist. `wraps aws doctor -r/--region` answers for a named region on both the human and `--json` paths
-   An unrecognized command is reported as bad input with the nearest routed command suggested, not as a crash
-   Fix: error telemetry is flushed before the process exits — it was being dropped. Event names no longer carry whatever you typed, error telemetry no longer ships raw error messages, and `wraps push` no longer puts the template slug in the payload
-   Fix: `wraps platform connect` and `wraps email upgrade` no longer print raw API error text
-   Fix: a failed Pulumi deploy exits non-zero instead of reporting success
-   Fix: the standalone binary ships on the Node version it claims to require

CLI v3.4.0

DashboardAugust 2026

### [Audience Counts That Match What Sends](https://wraps.dev/changelog/audience-counts-that-match-what-sends)

-   Segment and topic counts are computed by the send path’s own counting instead of a `memberCount` column written at create and never recomputed. The only segment in production was rendering a six-month-old number, and the details sheet showed a different figure for that same segment on the same page
-   Those counts respect channel eligibility and join contact, so bounced, complained, and globally unsubscribed people stop counting as subscribers — one topic read 5 subscribers and would have sent to 2. Double opt-in pending subscribers get their own count, so turning on a compliance feature no longer shrinks your audience with no number explaining where the people went
-   The segment Status filter resolves to `email_status`, the column every send path already reads, instead of the deprecated `contact.status` that defaults to active. Status equals Active matched every contact in the org, and Unsubscribed, Bounced, and Complained could never match at all
-   The list operators on that field emit arrays. Two of the four failed every time behind a generic “Failed to preview segment” with the previous count left on screen; a failed preview now says why. Event filters were fully implemented and unreachable from any UI
-   Fix: CSV import merges custom properties instead of overwriting them. Every update-strategy import silently deleted whatever properties the file did not mention, including the ones segments filter on, with no undo
-   Fix: the contact timeline distinguishes events aged out past retention from nothing ever having happened, stops swallowing load-more failures, and no longer caps out around 120 events regardless of real volume
-   Fix: a failed audience fetch renders an error with a retry instead of an empty list that reads as an empty org
-   Fix: contacts health buckets are a filter you can see and undo, and CSV export ships the search the list actually applied

Platform v0.23.0

DashboardAugust 2026

### [Test Sends, Recipient Results & Resume](https://wraps.dev/changelog/test-sends-recipient-results-and-resume)

![A broadcast finishing, with the delivery funnel filling in from sent through delivered, opened, and clicked](https://wraps.dev/email/2026-08-broadcast-send.gif?dpl=dpl_AtMuFDHv7YUxevJ6rkd5iV19n1HE)

-   Send a test before committing to the whole list: one rendered copy to one address, using a real contact from the selected audience and the same variable mappings the batch sender resolves, so what arrives is what the broadcast would send. It records nothing — no batch row, no message row, no counters
-   A broadcast that reports 50 failed now shows which 50 and why. Address, status, error, and SES bounce type per recipient, defaulting to the failures, paginated, and exportable to CSV with an explicit notice when the export is capped
-   Broadcast history paginates against the real total. Rows 21 and beyond were unreachable, the footer showed the loaded-row count instead of your broadcast count, and CSV export serialised whatever happened to be loaded and reported it as the total. Server-side search over name and subject, plus a status filter, both live in the URL
-   A stuck or failed send can be resumed from the detail page, gated the same way the API gates itself. The resume endpoint existed and nothing in the dashboard called it, so recovery meant curl and a runbook
-   Rates name their denominator and use a consistent one — unsubscribes were rated against sent while opens and clicks used delivered. 0% opened now distinguishes nobody opening from no SES event ever arriving
-   Fix: any fetch failure on the detail page rendered a 404, telling an operator watching a live send that their broadcast did not exist
-   Fix: auto-refresh latched at mount, so a scheduled broadcast that began sending never started polling
-   Fix: the clicked-URL breakdown had no limit, so per-recipient unsubscribe links returned one row per recipient

Platform v0.22.0

DashboardAugust 2026

### [Message-Level Search & Full Send History](https://wraps.dev/changelog/message-level-search-and-full-send-history)

-   The emails page now pages through your entire send history with cursor pagination - the previous build capped the list at the 100 most recent rows. Search runs server-side across recipient, subject, and sender, and uses the same query as browsing, so a message visible in the list can no longer vanish the moment you search for it
-   Dashboard numbers now come from Wraps’ own record of what it sent rather than from account-wide SES metrics. Two things change as a result, and both are the count becoming correct rather than data loss. Totals no longer include mail your AWS account sent outside Wraps. And open and click counts are now unique per message - a recipient who opens the same email three times counts once, where SES counted three times - so those two numbers in particular will read lower than they did before. Account-level SES reputation is still shown, now labelled as account-wide
-   Every state says what it is: a failed load says so and offers retry instead of rendering "No emails found", sandboxed AWS accounts are told they are in the SES sandbox instead of being asked to send their first email, and orgs whose event pipeline has never delivered an event see a banner explaining why everything reads as Sent
-   The message detail page distinguishes an unreadable event timeline from an empty one, names the AWS account involved, and points at `wraps email doctor` - it previously bounced you back to the list on any failure
-   Filters, search, sort, and time range live in the URL, so a filtered view survives reload and can be handed to a colleague mid-incident. Rows are real links: keyboard, middle-click, and screen readers all reach message detail now
-   CSV export pages through up to 10,000 matching rows and states the cap before writing the file - it previously exported whatever was on screen and reported it as the total
-   Fix: the analytics refresh button now expires the server-side cache instead of refetching the same cached payload for up to five minutes

Platform v0.21.0

CLIAugust 2026

### [Non-Interactive SMS Setup & Corrected Error Codes](https://wraps.dev/changelog/non-interactive-sms-setup-and-corrected-error-codes)

-   `wraps sms init --countries` makes SMS setup fully automatable without a TTY
-   Non-interactive and `--json` runs fail fast naming the flag they need instead of hanging on a prompt, and an already-deployed `init` exits with a proper JSON envelope
-   Fix: the documented CLI error codes were rewritten from CLI source — all 22 of them were fictional — and the reference’s camelCase flags, which the CLI silently ignored, are corrected
-   Fix: SSO login links to unverified local users, and callback errors are mapped instead of surfacing raw
-   Fix: 52 dependency advisories cleared by raising stale CVE-floor overrides that were holding packages below their patched versions

CLI v3.2

CLIAugust 2026

### [BIMI Checks & Configurable Event Types](https://wraps.dev/changelog/bimi-checks-and-configurable-event-types)

-   `wraps email check` now reports BIMI: record status, logo and VMC validation, a generated `default._bimi.<domain>` TXT template, and which inboxes require a VMC or CMC versus which show a self-asserted logo. When DMARC is not yet at enforcement it says so instead of printing setup steps that cannot work yet
-   Fix: `eventTracking.events` was declared, threaded through the stack, and never read. Every deployment sent the same hardcoded ten event types to SES, so dropping `OPEN` and `CLICK` to stop engagement tracking reported success and did nothing. The configured list is now what SES gets
-   `BOUNCE` and `COMPLAINT` can no longer be dropped from an event destination. A suppression-list event arrives as a bounce, so losing either leaves your pipeline blind to both
-   The custom config prompt gained a real event-type multiselect, and the Production preset no longer carries its own stale eight-type list
-   Fix: the deployed IAM policy grants `ses:ListConfigurationSets`, so configuration-set discovery works
-   BIMI asset fetching is opt-in, keeping the public tools API off attacker-supplied URLs

CLI v3.1.0

CDK & PulumiAugust 2026

### [Email Stack Parity Guard](https://wraps.dev/changelog/email-stack-parity-guard)

-   The CLI and `@wraps.dev/pulumi` ship two implementations of the same email stack. A parity test now compares them resource by resource, so a fix landing in one and not the other fails CI instead of drifting quietly
-   Resource names come from shared constants rather than duplicated string literals in each implementation
-   Docs spell out what the library does not provide versus the CLI, and record that Mail Manager ships as a dynamic provider

Pulumi v0.3.0

DashboardAugust 2026

### [Preference Center Theming & Multi-Day Broadcasts](https://wraps.dev/changelog/preference-center-theming-and-multi-day-broadcasts)

![The When to Send step of a broadcast, offering send immediately or schedule for later with a date and time](https://wraps.dev/_next/image?url=%2Femail%2F2026-08-schedule.png&w=3840&q=75&dpl=dpl_AtMuFDHv7YUxevJ6rkd5iV19n1HE)

-   Theme your preference center: an accent-derived color ramp, live inline preview, CSS import, and contrast checking so a brand color cannot quietly ship unreadable text. Subscribers can switch light, dark, or system themselves
-   Organization logo uploads are backed by S3, with a dedicated preference-center logo that falls back to the org logo
-   Broadcasts larger than a single day's SES quota now send across multiple days instead of being blocked. The confirm dialog shows the estimated number of days and folds in other in-flight broadcasts competing for the same quota
-   New per-AWS-account daily quota reserve keeps headroom for transactional sends. Broadcast chunks pause against the reserve and resume as the rolling 24-hour window frees up
-   Fix: broadcasts stalled silently at exactly 800 recipients. Lambda’s recursive-loop detection was terminating the chunk chain at its 16-hop default, with no error, no throttle, and no log line. A reaper cron now revives any batch stuck without progress for 30 minutes
-   A broadcast's audience is frozen at send start, one failing chunk no longer fails the whole audience, and a paused broadcast reads as paused instead of processing
-   Recipient IP addresses from open and click events are no longer stored. The columns are dropped and the field is discarded at the webhook
-   Onboarding leads with Connect AWS, and you can send a real test email from the dashboard while still in the SES sandbox. The deploy step offers a copy-paste prompt for your coding agent
-   The template editor is React Email TSX plus an AI chat panel. The TipTap editor and its serializer are gone
-   Fix: SCIM sync verbs, deactivation, and token hashing, plus SSO IdP trusted origins are now configurable instead of hardcoded

Platform v0.20.0

CLISelf-hostedJuly 2026

### [One Self-Hosted Path](https://wraps.dev/changelog/one-self-hosted-path)

-   Breaking: the Pulumi self-host variant is removed. Self-hosting is the SST full platform via `pnpm selfhost:deploy`. The Pulumi control plane multiplexed HTTP and SQS in one Lambda, threw after every chunk it processed, and left broadcasts stalled at `processing` forever
-   `wraps selfhost` keeps the commands that act on an existing deployment: `login`, `logout`, `status`, `logs`, `env`, `connect`, and `update-role`
-   A pre-deploy check still catches leftovers from a crashed earlier deploy. The account-global scheduler role surviving would otherwise kill the next deploy partway through and lock you out of the deploy path
-   Self-hosted installs gained batch queue alarms, a workflow DLQ alarm, an SES account-health cron, an event-feed staleness cron, and a workflow reaper
-   Fix: migrations run before the code that needs them in both the API deploy and the CI upgrade, and CI upgrades reconstruct env-file-only keys instead of dropping them

CLI v3.0.0

CLISelf-hostedJuly 2026

### [Self-Hosted Logs & Control-Plane Routing](https://wraps.dev/changelog/self-hosted-logs-and-control-plane-routing)

-   New `wraps selfhost logs` streams CloudWatch logs from a self-hosted install without opening the AWS console. Scope to a single source with `api`, `web`, or `workers`, tail with `--follow`, rewind with `--since`, and narrow with `--filter` or `--errors`
-   Fix: API commands now route to the control plane you signed in to. A self-hosted login no longer sends requests at the Wraps cloud API
-   Fix: `wraps status` prints your own dashboard URL on a self-hosted install instead of always printing the Wraps one
-   Fix: a self-hosted web domain can live outside Route 53, and adding a domain after the fact repoints the app URLs that unsubscribe, preference, and verification links are built from
-   Fix: the SST deployment variant normalizes its API URL, so the two deploy paths agree on what the API is called
-   Fix: the database connection pool is capped explicitly rather than inheriting node-postgres’ default of 10
-   Fix: SDK snippets printed by the CLI — deploy output, `sms init`, and the TUI deploy step — referenced a class and an `emails.send` method that never existed. They now show the real `email.send` API with an explicit region
-   Workers report failures to Sentry, and the self-hosted deploy workflow configures the Sentry DSN

CLI v2.30

CLISelf-hostedJuly 2026

### [Self-Hosted URL Fixes](https://wraps.dev/changelog/self-hosted-url-fixes)

-   Fix: `wraps selfhost deploy` no longer defaults the app URL to the Wraps dashboard. Accepting that default deployed a control plane that believed our dashboard was its own, and that URL builds every unsubscribe, preference and verification link the deployment emails to its recipients
-   Fix: `wraps email init`, `connect`, `config`, `upgrade` and `status` now report your own dashboard on a self-hosted install instead of always printing the Wraps one
-   Fix: the support address shown by the CLI and its telemetry footer pointed at a domain we do not own

CLI v2.29.1

CLISelf-hostedJuly 2026

### [Self-Hosted Control Plane Hardening](https://wraps.dev/changelog/self-hosted-control-plane-hardening)

-   Deploy and upgrade now publish the SES templates the dashboard sends by name, so signup verification, invitations and password reset work on a fresh install instead of failing on a missing template
-   `wraps selfhost env` emits `AUTH_EMAIL_FROM`, `AUTH_EMAIL_CONFIGURATION_SET` and `WRAPS_EMAIL_ROLE_ARN` — the API-only variant hosts its own dashboard, and this is where it gets that configuration
-   The auth sender address is derived from the verified SES identity rather than the dashboard domain, which is only sendable when the two happen to match
-   A self-hosted deployment gets its own `wraps-selfhost-console-access-role`, trusting your account rather than Wraps
-   `wraps selfhost connect`adds a dedicated SES event target instead of repointing the platform's, so both control planes receive events
-   Self-hosters can route errors to their own Sentry DSN instead of Wraps'
-   `--selfhosted` is replaced by the `wraps selfhost` subcommand
-   Fix: recover the API URL on SST deployments, whose resource names carry a generated suffix

CLI v2.29.0

CLIJuly 2026

### [SES Pricing Plan Detection](https://wraps.dev/changelog/ses-pricing-plan-detection)

-   `wraps email plan` — reports the SES pricing plan for every tracked Region, the cheaper alternative if there is one, and the annual savings against your real send volume
-   AWS added pricing plans to SES on 2026-07-21 and defaults new accounts to Essentials at $0.16/1K instead of a la carte at $0.10/1K. The plan is set per account, per Region, and no line item on your bill names the difference
-   Read-only by default. `--set` switches plans and always requires a confirmation naming the Region and account, or `--yes` — and never guesses a Region for a multi-Region account
-   Every comparison row carries a per-1K rate, so the gap between plans stays legible even when your monthly cost rounds to $0.00
-   `--volume` models the comparison against a volume you supply; `--json` for scripting
-   Fix: wraps platform connect chose the console role's trust principal from whether self-hosted metadata existed on the local machine rather than from the invoked subcommand. A normal connect run on a machine that had ever run wraps selfhost deploy would silently point the trust policy at the customer's own AWS account and break dashboard access with no error
-   Fix: `selfhost deploy` and `upgrade` now store the API URL normalized, matching `selfhost status`. The raw Lambda Function URL's trailing slash produced a double slash in webhook paths that the API would not route

CLI v2.28.0

DashboardJuly 2026

### [In-App Notifications](https://wraps.dev/changelog/in-app-notifications)

-   Notification bell in the dashboard — account health, billing, team, and send events surface where you already work
-   Hourly SES health checks: sending pauses, bounce/complaint rates entering the AWS review range, and daily quota above 80% all raise an alert
-   Milestone notifications for domain verification, SES production access, broadcast completion (with real failure counts), and contact imports
-   Security notifications: new-device sign-ins, invite acceptances, role changes, and API key creation or revocation
-   Payment failures notify org owners and admins in-app, alongside the existing email
-   Alerts for SES `Reject` and `Rendering Failure` events — sends that previously died silently now ring the bell, deduped to once per day
-   Built on `better-inbox`, an open-source better-auth plugin — notifications are rows in the database, not a third-party service

Platform v0.19.0

DashboardJune 2026

### [Reliability & Security Hardening](https://wraps.dev/changelog/reliability-and-security-hardening)

-   Fix: editing a scheduled workflow's schedule no longer fails with AccessDenied in production
-   Cross-org IDOR prevention on engagement resume — every workflow path scoped by organization
-   Role-based access control enforced on all workflow mutations
-   Stuck-execution recovery — a reaper automatically detects and recovers executions that stall mid-run
-   Atomic execution claims and schedule updates eliminate duplicate runs and lost edits under concurrency
-   Idempotent counters and hardened dead-letter queue transactions prevent double-counting and data loss
-   Cycle detection rejects workflow definitions that would loop indefinitely

Workflow Engine v2

CLIMay 2026

### [Email Logs Inspection](https://wraps.dev/changelog/email-logs-inspection)

-   `wraps email logs list` — paginated table of sent emails with status, recipient, subject, and message ID
-   `wraps email logs get <messageId>` — full delivery detail for a single message including bounce type and timestamps
-   Filter by status: `--status delivered`, `--status bounced`, `--status complained`, and more
-   Cursor-based pagination with `--limit` and `--cursor` flags for large result sets
-   `--json` output for CI/CD pipelines and scripting
-   Logs cover both SDK sends and batch broadcasts — unified view across all sending paths

CLI v2.22.0

DashboardAgentsMay 2026

### [Agent Discovery & WebMCP Tools](https://wraps.dev/changelog/agent-discovery-and-webmcp-tools)

-   WebMCP tools — `get_pricing`, `get_quickstart`, `search_docs` registered via `navigator.modelContext.provideContext()` for in-browser agent interaction
-   Per-page markdown at `/api/md/<path>` — agents requesting any docs URL get page-specific content rather than the generic `llms.txt` summary (11 pages: quickstarts, SDK reference, CLI reference, webhooks, domain verification)
-   OAuth 2.0 discovery at `/.well-known/oauth-authorization-server` (RFC 8414) on both wraps.dev and api.wraps.dev — describes Device Authorization Grant for agent and CLI authentication
-   RFC 9727 API catalog at `/.well-known/api-catalog` — linkset+json pointing to OpenAPI spec, docs, and health endpoint
-   RFC 8288 Link header on the homepage advertises /docs as the service documentation endpoint for agent discovery
-   `robots.txt` AI signals via a single `Content-Signal: ai-train=no, search=yes, ai-input=yes` response header

Platform v0.18.0

CLIMay 2026

### [Per-Domain SES Configuration Sets](https://wraps.dev/changelog/per-domain-ses-configuration-sets)

-   `wraps email domains config` — configure SES options per domain interactively or via flags
-   Migrate via `wraps email upgrade` → "Per-domain configuration sets": creates a dedicated config set for each sending identity, no DNS changes needed
-   7 configuration groups: open/click tracking, TLS delivery, sending toggle, reputation metrics, bounce/complaint suppression, email archiving, and VDM
-   10 boolean flags for scripting: `--opens`, `--clicks`, `--tls-required`, `--suppress-bounce`, `--archive`, `--vdm-engagement`, and more
-   Shared `wraps-email-archive` Mail Manager archive — auto-created on first use, linked to each domain that enables archiving
-   VDM options (engagement metrics, inbox placement) only shown when account has Virtual Deliverability Manager enabled
-   Fix: EventBridge now forwards all SES event types — previously some event subtypes were silently dropped

CLI v2.21.0

DashboardApril 2026

### [Okta SSO, SCIM 2.0 & Role-Based Access Control](https://wraps.dev/changelog/okta-sso-scim-2-0-and-role-based-access-control)

-   Okta SSO with OIDC-based authentication and IdP-initiated sign-in
-   SCIM 2.0 provisioning — automatic user and group sync from your identity provider
-   Domain verification for SSO with DNS TXT record guidance and in-dashboard status
-   Sign-in redirect URI surfaced in setup form for seamless Okta app configuration
-   6-role permission model: Owner, Admin, Member, Developer, Viewer, and Billing
-   RBAC enforced across all dashboard actions and server-side mutations
-   Billing role isolates billing management from content operations

Enterprise v1.0

DashboardApril 2026

### [Broadcast Drafts, Contact externalId & Segment Improvements](https://wraps.dev/changelog/broadcast-drafts-contact-externalid-and-segment-improvements)

-   Broadcast drafts — save work-in-progress broadcasts without sending
-   Duplicate any existing broadcast to create a new one from it
-   Contact `externalId` field for multi-identifier resolution — link contacts by your own system IDs via SDK or API
-   Numeric comparators (>, <, ≥, ≤) in segment builder for custom number properties
-   Refresh buttons on all list and analytics pages for on-demand data updates
-   `@wraps.dev/email-check` published to npm — run `npx @wraps.dev/email-check yourdomain.com` under the Wraps scope
-   Email sends are analytics-only and not plan-gated

Platform v0.17.0

CLIApril 2026

### [Signed Reply-To Threading](https://wraps.dev/changelog/signed-reply-to-threading)

-   `wraps email reply init --domain yourdomain.com` to enable cryptographic reply threading for agent workflows
-   Outbound: SDK accepts a `conversationId` option on `email.send` and returns `{ conversationId, sendId }`
-   Inbound: `email.received` now includes `replyToken: { status, conversationId?, sendId? }` and `autoReply: boolean`
-   HMAC secret stays in your AWS SSM Parameter Store — Wraps platform never sees it
-   Fix: `wraps email inbound init` now respects `--yes` and `--json` on the DNS confirmation prompt for CI scripting
-   See the [reply threading guide](https://wraps.dev/docs/guides/reply-threading)

CLI v2.19.0

DashboardMarch 2026

### [Onboarding Activation](https://wraps.dev/changelog/onboarding-activation)

-   Choose Path step replaces Welcome — start building or connect AWS first
-   Mobile signup rescue gate with device-based continuation flow
-   Go-live banner with AWS action gates across dashboard pages
-   Activation score tracking with API endpoint and contact property sync
-   Invite members onboarding step plus sidebar invite activation loop
-   Template gallery with 6 starters and AI path on empty state
-   Two-path activation drip: start-building vs connect-aws users
-   Power-user activation template for velocity signups

Platform v0.16.0

DashboardMarch 2026

### [AI Conversation Persistence & Brand Kits](https://wraps.dev/changelog/ai-conversation-persistence-and-brand-kits)

-   AI chat history persists across sessions — pick up where you left off
-   Brand kit auto-applied in AI code assistant for on-brand output
-   Version history with restore — every AI apply is recoverable
-   New templates default to react-email with JIT TipTap migration
-   `previewText` column on templates for inbox preheaders
-   Real unsubscribe and preference URLs in test email sends
-   Shared preview panel across code template editor tabs
-   Broadcast stats with Sankey diagram, click URL tracking, engagement funnel

Template Editor v2

AgentsMarch 2026

### [Built for AI Coding Agents](https://wraps.dev/changelog/built-for-ai-coding-agents)

-   `agent.json` at the root for AI agent discovery
-   `llms.txt` expanded with agent guidance, comparisons, and skills
-   `context7.json` for Context7 documentation indexing
-   Full API reference docs with linked OpenAPI spec
-   Rate limits documentation for agent integration
-   Agent-discoverable npm descriptions and keywords across all packages
-   Context7 guide for AI-assisted development with Wraps

Agent-Ready Platform

CLIMarch 2026

### [Standalone Deliverability CLI](https://wraps.dev/changelog/standalone-deliverability-cli)

-   `npx mail-audit yourdomain.com` to grade any sending domain without a Wraps account
-   Auth triad grading across SPF, DKIM, and DMARC with weighted scoring
-   Reliable bar chars and auto-padded borders in terminal score box
-   YC W26 batch audit blog post covering deliverability findings
-   Free tool to capture SES-curious developers before the full Wraps flow

mail-audit v1.1.1

CLIFebruary 2026

### [CLI Polish & Multi-Domain Management](https://wraps.dev/changelog/cli-polish-and-multi-domain-management)

-   `--json` output on all commands for CI/CD integration
-   Guided multi-domain management with subdomain suggestions for reputation isolation
-   Root domain support for inbound email receiving
-   Auto-clear Pulumi stack locks on deploy retry
-   Hosting provider change in the upgrade menu
-   Pulumi detection fix for SDK-installed binaries
-   `wraps email templates preview` with live reload via SSE
-   Terminal dashboard UI (TUI) with email init wizard

CLI v2.14–2.17

DashboardFebruary 2026

### [Dashboard Overhaul](https://wraps.dev/changelog/dashboard-overhaul)

-   Unified overview page with channel-granular health monitoring
-   Universal `Cmd-K` command palette with server-side search
-   Analytics charts on contacts, events, emails, and inbound pages
-   CSV import with column mapping and custom properties
-   CSV export on all dashboard tables
-   Bulk template actions — select multiple to delete, publish, or change type
-   Natural language date input for broadcast scheduling (e.g. `next Tuesday at 9am`)
-   Send volume sparklines on API key cards
-   Undo/redo in the visual workflow builder
-   Pre-enable readiness checks that validate workflows before going live
-   Searchable condition combobox replacing free-text input
-   Unsaved changes guard in the workflow builder
-   SDK quick start snippets in topic subscribers sheet

Platform v0.15.0

SDKFebruary 2026

### [Zero-Config Vercel OIDC & Config Helpers](https://wraps.dev/changelog/zero-config-vercel-oidc-and-config-helpers)

-   Zero-config Vercel OIDC — SDK auto-detects `AWS_ROLE_ARN` from env, no secrets or env vars needed
-   `defineConfig` and `defineBrand` helpers for templates-as-code
-   Workflow definition helpers for workflows-as-code
-   `inbox.forward()` and `inbox.reply()` for inbound email
-   Security patch for fast-xml-parser (CVE override)

SDK v0.10.0

CLIFebruary 2026

### [Multi-Channel SMS Launch](https://wraps.dev/changelog/multi-channel-sms-launch)

-   SMS moved from waitlist to generally available
-   Multi-channel database schema — templates, contacts, and workflows support both email and SMS
-   Cascade nodes in the workflow builder for multi-step, multi-channel sequences
-   SMS dashboard cleanup with correct event status mapping
-   SMS SDK v0.1.2 with proper error type mapping

SMS v0.1.2

DashboardFebruary 2026

### [Workflow Reliability Hardening](https://wraps.dev/changelog/workflow-reliability-hardening)

-   DLQ consumer with CloudWatch alarms for failed workflow and batch messages
-   Fixed dual-resume race condition in the workflow processor
-   Definition snapshots — in-flight executions are immune to live dashboard edits
-   Repaired broken EventBridge schedule chains with reconciliation watchdog
-   Hardened webhook SSRF validation — blocks loopback, link-local, and private networks
-   8 critical and high severity workflow bugs resolved in one pass
-   Atomic idempotency keys on step execution inserts to prevent duplicate sends

Workflow Engine

DashboardFebruary 2026

### [Security Patches & Structured Logging](https://wraps.dev/changelog/security-patches-and-structured-logging)

-   Patched XSS, cross-org IDOR, and RCE vulnerabilities
-   Timing-safe secret comparison across all auth paths
-   Resolved 22 Dependabot alerts via dependency upgrades and pnpm overrides
-   Migrated entire API from console logging to structured JSON logging
-   Canonical log lines per authenticated request for debugging and analytics
-   PostHog error tracking on API and Stripe webhooks
-   Cross-org IDOR prevention: all queries scoped by `organizationId` from auth context
-   Guardrail system with Biome GritQL plugins and architecture tests

Security & Observability

DashboardFebruary 2026

### [14 New Doc Pages & Performance](https://wraps.dev/changelog/14-new-doc-pages-and-performance)

-   14 new documentation pages: inbound email, EventBridge events, Vercel setup, webhooks, and migration guide
-   Redesigned pricing comparison with scroll-driven tabs
-   New about and contact pages with author bylines
-   Inbound email marketing page
-   SEO-optimized SES cost calculator
-   Converted 13 large PNGs to WebP — 95% size reduction (30MB → 1.3MB)
-   Auto-discovering sitemap replacing hardcoded page list
-   Vercel Speed Insights integration
-   SSR static content on tools pages for SEO

Website

CLIFebruary 2026

### [Webhook Events](https://wraps.dev/changelog/webhook-events)

-   Configure an HTTPS webhook endpoint to receive real-time SES email events
-   CLI: `wraps email upgrade` → "Configure webhook endpoint"
-   Events delivered via EventBridge API Destination with secret-based authentication
-   Supports all SES event types: delivery, bounce, complaint, open, click, and more
-   `X-Wraps-Signature` header for request verification
-   Manage, regenerate secrets, or disable from the same upgrade menu

CLI v2.13.0

DashboardFebruary 2026

### [AI Template Editor & Workflows-as-Code](https://wraps.dev/changelog/ai-template-editor-and-workflows-as-code)

-   AI code assistant with live preview pane and resizable split view
-   Brand kit picker and local image uploads in AI assistant
-   Bulk template actions with SES sync on delete
-   Natural language date input for broadcast scheduling (e.g. `next Tuesday at 9am`)
-   Workflows-as-code: define and push automations from the CLI
-   CloudFormation template brought to full CLI parity
-   Activation email series and product update templates
-   Auto-create contacts for `SUBSCRIPTION` events

Platform v0.14.0

CLIFebruary 2026

### [Reliability & Security](https://wraps.dev/changelog/reliability-and-security)

-   Batch send security, correctness, and maintainability fixes
-   Device auth flow fixes for telemetry, errors, and config
-   Delete S3 metadata on destroy to prevent stuck state after partial failure
-   Graceful Pulumi destroy failure handling instead of leaving stale metadata
-   Domain verification check before test email send
-   Prevent Pulumi import collision when stack already has resources
-   Fix CI detection silently disabling telemetry for Vercel and Netlify users
-   `wraps email templates preview` command

CLI v2.12

CLIFebruary 2026

### [Inbound Email](https://wraps.dev/changelog/inbound-email)

-   Receive emails in your AWS account with SES receipt rules
-   Parse incoming emails with headers, body, and attachments
-   Spam and virus scanning via SES verdicts
-   CLI: `wraps email inbound init`, `status`, `test`, and `destroy` commands
-   SDK: `inbox.list()`, `get()`, `reply()`, `forward()` methods
-   EventBridge `email.received` events for real-time webhooks
-   Dashboard: Receiving tab with inbound email viewer

CLI v2.7.0 + SDK v0.6.0

CLIFebruary 2026

### [S3 Remote State](https://wraps.dev/changelog/s3-remote-state)

-   Pulumi state automatically stored in S3 for multi-machine deploys
-   Auto-creates encrypted, versioned state bucket on first deploy
-   Seamless migration of existing local state to S3
-   Connection metadata synced across machines with timestamp-based merging
-   Set `WRAPS_LOCAL_ONLY=1` to opt out and keep local-only state
-   Graceful fallback to local state if S3 is unreachable

CLI v2.6.1

DashboardJanuary 2026

### [Free Plan](https://wraps.dev/changelog/free-plan)

-   Free tier with contacts, topics, broadcasts, and workflows
-   Getting Started dashboard with guided activation checklist
-   Google and GitHub OAuth sign-in
-   Events log with search, filtering, and usage tracking
-   Monthly and annual billing toggle with promo code support
-   CLI: `wraps permissions` command for IAM troubleshooting

Platform v0.13.0

CLIJanuary 2026

### [Infrastructure as Code](https://wraps.dev/changelog/infrastructure-as-code)

-   Published `@wraps.dev/cdk` and `@wraps.dev/pulumi` npm packages
-   One-click CloudFormation deployment from the dashboard
-   Multi-provider DNS support (Route53, Cloudflare, Vercel)
-   CLI: `wraps platform connect` to link CLI deployments to the dashboard
-   CloudWatch reputation alerting for SES metrics
-   DKIM, SPF, and DMARC DNS record outputs for all IaC providers

CLI v2.4.0

CLIJanuary 2026

### [CDN Infrastructure](https://wraps.dev/changelog/cdn-infrastructure)

-   S3 bucket + CloudFront CDN deployment
-   Custom domain support with ACM SSL certificates
-   Browser-based image optimization
-   Origin Access Control for secure S3 access
-   CLI: `wraps cdn init`, `verify`, `upgrade`, and `destroy` commands
-   Pay AWS directly (~$5-7/mo for typical usage)

CLI v2.1.0

DashboardJanuary 2026

### [Workflow Automations](https://wraps.dev/changelog/workflow-automations)

-   Visual workflow builder with React Flow canvas
-   AI-powered Flow Designer for natural language automation
-   Conditional branching and wait-for-event patterns
-   CLI: `wraps doctor` and `wraps setup` with SSO support
-   SDK: `@wraps.dev/client` events and workflow trigger endpoints

Platform v0.10.0

DashboardJanuary 2026

### [Broadcasts](https://wraps.dev/changelog/broadcasts)

-   Scheduled broadcasts with bulk SES sending
-   Brand kits for consistent email styling
-   Broadcast analytics and delivery tracking

Platform v0.9.0

DashboardJanuary 2026

### [Topics & Double Opt-In](https://wraps.dev/changelog/topics-and-double-opt-in)

-   Topics for subscription management
-   Double opt-in confirmation emails
-   Preference center for subscription management
-   SDK: `@wraps.dev/client` topicSlugs support

Platform v0.8.0

CLIDecember 2025

### [SMS Infrastructure](https://wraps.dev/changelog/sms-infrastructure)

-   SMS support via AWS End User Messaging
-   Toll-free number provisioning
-   SMS analytics and delivery tracking
-   CLI: `wraps sms init`, `status`, and `destroy` commands
-   SDK: `@wraps.dev/sms` v0.1.0 for sending SMS via AWS

CLI v1.5.0

CLIDecember 2025

### [Deliverability Check](https://wraps.dev/changelog/deliverability-check)

-   CLI: `wraps email check` command
-   DNS record validation (SPF, DKIM, DMARC)
-   Email authentication analysis
-   Blocklist monitoring across major providers
-   Actionable remediation suggestions

CLI v1.4.0

SDKDecember 2025

### [Platform SDK](https://wraps.dev/changelog/platform-sdk)

-   New `@wraps.dev/client` SDK for Platform API
-   Type-safe contacts, topics, and segments management
-   Batch email sending via Platform
-   API key authentication

SDK v0.1.0

DashboardDecember 2025

### [Contacts Management](https://wraps.dev/changelog/contacts-management)

-   Contact creation, editing, and deletion
-   Activity timeline showing email events per contact
-   Custom properties with flexible schema
-   Contact import/export (CSV)
-   Search and filtering by properties
-   SDK: `@wraps.dev/client` contacts API

Platform v0.4.0

DashboardDecember 2025

### [Template Editor](https://wraps.dev/changelog/template-editor)

-   Visual drag-and-drop template editor
-   Keyboard shortcuts and command menu
-   Template showcase section

Platform v0.3.0

CLINovember 2025

### [Dashboard & Multi-Service CLI](https://wraps.dev/changelog/dashboard-and-multi-service-cli)

-   Wraps Platform at app.wraps.dev
-   Email analytics and event tracking
-   Contact management with activity timeline
-   CLI: Multi-service architecture (`wraps email`, `wraps sms`)
-   CLI: `wraps email domains` and custom tracking domains
-   SDK: `@wraps.dev/email` v0.3-0.4 with OIDC federation and attachments
-   Documentation site with SDK reference

CLI v1.0.0

CLINovember 2025

### [Initial Release](https://wraps.dev/changelog/initial-release)

-   One-command AWS SES deployment
-   Preset configurations (Starter, Production, Enterprise)
-   Domain verification, DKIM, and MAIL FROM setup
-   Local console for development
-   Vercel OIDC authentication
-   `@wraps.dev/cli` for infrastructure deployment
-   `@wraps.dev/email` v0.1-0.2 TypeScript SDK for sending emails

CLI v0.1.0

October 30th, 2025

### The Idea

What if deploying email infrastructure to AWS was as simple as one command? No vendor lock-in, no markup on AWS pricing, just great developer experience.
