== Changelog ==

= 1.8.0 =
Release date: TBC

**Hosted services**
* Mailchimp: add somebody to an audience, or update them if they are already in
  it. The datacentre is read off the end of the API key, so it is one field
  rather than two, with an explicit override for the rare key that carries
  none.
* ActiveCampaign: add or update a contact against your account's own API URL.
* ConvertKit: subscribe somebody to a form. Tags are ConvertKit's numeric IDs,
  and a name typed where an ID belongs is dropped rather than sent as a 0 that
  would tag somebody else's list.
* ClickUp: create a task in a list, with a description and a priority.
* Each refuses before it calls out when the connection, a required field or the
  email address is missing, so a misconfigured step reads as a misconfigured
  step rather than as the service saying no. A 4xx is not retried; a 429 is.

**Connections**
* The panel fills the screen. Services run down the left with their logos and a
  count of what each holds; the chosen one's settings sit on the right. The
  "Services" label that used to name the list sitting beside it is gone.

**Tools**
* One card per tool, each saying what it does and when to reach for it. The
  danger zone is bordered and set apart from the tools that are safe to press.

**System status**
* Reports the server's limits (memory, execution time, upload size, cURL,
  OpenSSL), the WordPress install (multisite, HTTPS, language, permalinks,
  outbound HTTP, the debug constants), the active theme and its parent, and
  Zapify's own figures including the table prefix and whether `KC_ZF_DEV_MODE`
  is set.
* Every installed plugin is listed with its version, whether it is active, and
  which Zapify integration wraps it.
* One button copies the whole report as plain text, for pasting into a support
  thread.

**More from KaizenCoders**
* A new tab listing our other plugins, each with what it is for and whether
  this site already has it.

**The screens themselves**
* Other plugins' admin notices are cleared from Zapify's screens. The WordPress
  admin has no notice area -- every plugin prints into the same strip -- and on
  a busy site Zapify's own warning that cron is off sat under four upgrade
  offers for something else. Kept: Zapify's own, the bundled wpforge's,
  Freemius's licensing notices, and Action Scheduler's past-due warning, which
  is about Zapify's delayed actions. `zapify_notice_owners` adjusts the list and
  `zapify_clear_foreign_notices` switches the whole thing off.
* A Zapify footer at the bottom of Zapify's screens: the plugin, its version --
  the first thing any support thread asks for -- links to the documentation,
  support and the paid plans on a free build, a review ask, and "Made with love
  by KaizenCoders". WordPress's own two footer lines are emptied there to make
  room: the "Thank you for creating with WordPress" credit and the "Get Version"
  nag were saying the same things in smaller type. Everywhere else in wp-admin
  they are untouched.

**Fixed**
* A premium template imported past the guard that normally refuses it built an
  automation with no trigger at all. Both callers already checked; the check is
  now what the tests exercise too.

= 1.7.0 =
Release date: TBC

**Pro integrations**
* LifterLMS: course completed, lesson completed, enrolled in a course, and
  membership purchased, with actions to enrol somebody or remove them.
* Tutor LMS: course completed, lesson completed and enrolled.
* Easy Digital Downloads: a purchase completes.
* Ninja Forms and Formidable Forms: a form is submitted.

**Everywhere**
* Every integration shows its own logo. The lettered tiles are gone.

= 1.6.0 =
Release date: TBC

**The builder**
* Rebuilt on the shape a builder should have: triggers and actions each sit in
  their own panel rather than floating on the page, every card carries the
  integration's mark and its `#id`, and the sentence is the thing you read
  first.
* One footer row instead of three stacked buttons. Adding a filter, a delay, a
  branch or a loop is behind a single menu on the thing it applies to.
* A card says nothing about a filter or a delay until one exists. Every action
  used to carry two lines announcing features it was not using.
* Conditions read as part of the flow. The automation's gate sits between the
  two panels; an action's filter sits on the action, above its sentence and
  visible without opening anything.
* AND/OR is switchable between rules, nested groups render inside their parent,
  and a group is named by what it means -- "any of these" or "all of these" --
  rather than by the word "group".

**Switches**
* An automation can be set live or paused from the list, in one click on its
  status.
* Every trigger and every action carries its own switch: live, off, or draft.
  Off is a decision about something that works; draft is unfinished. Neither
  runs, and the two are told apart.
* The automation's switch no longer overwrites its triggers' and actions' own.
  Turning an automation off and on again leaves every step exactly as it was,
  which is the reason to have a switch rather than delete the step.

**Delays**
* An action can wait minutes, hours or days before it runs. The engine has
  supported this since the first release; there was no way to ask for it.
* The queue runs about once a minute, so the delay is a floor rather than an
  exact moment, and the editor says so.

**Buttons**
* A new trigger: somebody clicks a button. Put `[zapify_button key="..."]` or
  `[zapify_link key="..."]` on any page and clicking it starts the automation.
* The button is a form rather than a link, so prefetchers, scanners and cache
  warmers cannot press it on a visitor's behalf.
* For logged-in visitors, so the run is attributed and per-user limits still
  mean something. A logged-out visitor sees the button say what it needs.

**Templates**
* Thirty-two templates, up from sixteen: buttons, LearnDash lessons, quizzes
  and groups, comment approval, role changes, post terms, Gravity Forms
  payments and refunds, and three more collectors.
* Every integration a template needs now shows its mark, including the ones
  this site has not got -- which are exactly the ones worth recognising.

**The free build**
* Premium integrations appear on a free install, greyed with a lock badge, and
  can be opened to see what they offer. They used to be absent entirely,
  because their code is not in the free build at all.
* `KC_ZF_DEV_MODE` now decides both ways. Set it to `false` in `wp-config.php`
  to see exactly what a free install sees without removing anything.

**Fixes**
* An unfinished condition -- a row added and never filled in -- silently
  stopped an automation for ever. It fails closed by design, but at the trigger
  filter that happens without a log entry, so a live automation could sit there
  doing nothing with no stated reason. Going live now refuses and names the
  place.
* Editing an action's filter threw away its delay. A registered argument's
  default was being written on every request that did not mention it.
* Removing a delay often did not, because the amount field committed on blur
  and the button's click raced it.
* A live action rendered as a black button rather than a green pill.
* The status menu's descriptions overlapped the labels beneath them.
* The integration picker sat flush against its search box, and the caption for
  an integration that is not installed ran out of its tile and across the next
  one.

= 1.5.0 =
Release date: TBC

**Conditions**
* One condition engine for every place a condition can appear: the trigger
  filter, the automation, an action, and a loop item. Rules compare token
  expressions rather than belonging to a type, so anything the token system can
  reach can be compared.
* Filtering the trigger is free on every plan. Conditions on an automation, an
  action or a loop item are Pro.
* A skipped run records why it was skipped, at the moment it was skipped — both
  resolved sides and their types. "The webhook sent the number 6054 and your
  rule compared it against the text 6055" is the answer, and it cannot be
  reconstructed afterwards.
* Comparisons fail closed. An unresolvable scope, a malformed rule or an
  operator this build does not have all mean "did not pass", and all of them
  say so.

**Webhooks**
* Webhook sources are first-class: one URL can feed any number of automations,
  each selecting itself on the payload.
* Eight authentication methods, including signatures. Every provider preset now
  declares the scheme read from that provider's own documentation, with the URL
  and the date it was checked recorded beside it.
* Stripe and Paddle sign a timestamp joined to the body rather than the body
  alone, and are supported as such. Deliveries outside a five-minute window are
  refused even when the signature verifies, so a captured delivery cannot be
  replayed indefinitely.
* Listen mode captures a real delivery and infers the payload shape from it, so
  tokens can be picked from a tree rather than typed from memory.
* Delivery log with replay, dry-run replay that predicts which automations would
  match, retries with backoff, and a circuit breaker.

**Routes**
* One automation can branch instead of being copied per case. Each branch has
  its own condition and its own actions, in one ordered list with the ungrouped
  ones.
* First-match or every-match, and an "otherwise" branch that always sorts last.
* A branch that did not match records why, per branch. "No branch matched" is
  almost always a configuration mistake and is invisible without the reasons.
* Zapify notices when several automations on one webhook source differ by a
  single value and offers to combine them into one with a branch each. The
  originals become drafts. Nothing is deleted.

**Loops**
* Run a set of actions once for every item in a list — every line item on an
  order, every row in a payload.
* An item filter decides which items are processed, and each rejected item says
  why.
* Each pass writes its own log entry carrying the values that pass was about to
  use, so a failure on item seven shows item seven.
* Bounded at 500 items. A longer list is cut short and the run says so.

**Scheduled and bulk automations**
* Scheduled automations run on a clock with no trigger at all: every so often,
  on a cron expression, or once at a moment you pick. The screen shows the
  moment the schedule resolves to rather than repeating what was typed.
* An expression that would never come round is refused when you save it, not
  discovered when it never fires.
* Bulk automations run once for each member of a set — every subscriber, every
  draft post. Each subject gets its own run, so run limits and user tokens
  behave exactly as they do everywhere else.

**Database**
* Schema revisions 1.0.1 through 1.4.1 all shipped inside this release rather
  than separately: a date index for the tables retention deletes from (1.0.1),
  a unique webhook key per trigger (1.0.2), the settings option moving into
  WPSF's namespace (1.1.0), existing `WP_USER_META_UPDATED` triggers
  re-pointing at the bridged hook (1.1.1), stored explanations on runs and
  action logs (1.2.0), webhook sources and deliveries (1.3.0), a race-safe
  deduplication key (1.3.1), captured requests for listen mode (1.3.2), routes
  (1.3.3), loops (1.4.0), and schedules with the bulk query (1.4.1).

**Fixes**
* Deleting an automation left its routes, loops and schedule behind.
* A corrupt conditions column read as "no conditions", which meant a guard that
  silently stopped guarding. It now fails closed.
* Automation and action conditions could not read `{{variable:…}}` tokens.

= 1.0.0 =
Release date: TBC

First public release.

**The engine**
* Multi-trigger automations with ALL/ANY logic, free.
* Compiled hook map — a request matching no automation costs no extra queries.
* Recursion and loop protection: depth limit, per-request repeat guard, and a
  circuit breaker that deactivates a runaway automation rather than letting it
  take the site down.
* Action Scheduler for queued and delayed work, with inline fallback when it is
  unavailable.

**Logging**
* Every run records each action's configuration after placeholders were
  resolved, written before the action executes.
* Filterable by automation, status and date; bulk delete; configurable
  verbosity.
* Fields marked sensitive are masked in the log.
* Daily batched retention cleaner.

**Integrations**
* WordPress core — 12 triggers and 12 actions.
* Utilities — notes, variables, and a custom hook trigger with listen mode.
* Webhooks — inbound with HMAC verification, replay protection and rate
  limiting; outbound with an SSRF guard that re-checks every redirect.
* WooCommerce — order status changes and product purchases; status updates and
  order notes.
* Contact Form 7, WPForms, Gravity Forms, Fluent Forms — one placeholder per
  form field.

**Security**
* Custom capability on every route and admin page.
* Credentials encrypted at rest with authenticated encryption.
* "Call a PHP function" and "Run a WP hook" are absent unless
  `ZAPIFY_ENABLE_ADVANCED_ACTIONS` is defined in `wp-config.php`.

**Pro**
* Conditions at automation, trigger and action level.
* Delays, run retry, import and export, configurable retention.
* Stored connections with OAuth.
* Slack, OpenAI and Anthropic, Google Sheets, FluentCRM, LearnDash.
