Files
hub-insurance/wp-content/plugins/esp-instanda-integration
zbatteandClaude Fable 5 5d2e9cb7e5 fix(instanda): hygiene pass + v1.1.0 (uninstall, notices, cron, resubmit, theme)
- F-15: uninstall now removes ALL espinstanda_* options and transients (incl. the
  encrypted password and its self-provisioned key).
- F-16: register the "Gravity Forms required" admin notice unconditionally so it is
  reachable when GF is inactive (gform_loaded never fires then).
- F-22: self-heal the daily retention cron on admin_init (matches the schema self-heal).
- F-19: re-validate the stored payload via Field_Mapper::validate_payload() before a
  resubmit (DB-tamper trust boundary).
- F-20: increment the retry count on resubmit and dispatch the previously-dead
  espinstanda_resubmit_success notification event.
- F-23: emit the theme's Form-5 date-range JS only on pages that embed a Gravity Form
  and disconnect the MutationObserver (was observing the DOM subtree forever).
- F-24: bump plugin to 1.1.0; add readme.txt changelog documenting the audit fixes and
  the required ops actions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 16:20:10 -06:00
..
2026-07-02 15:54:39 -06:00

=== ESP INSTANDA Start Quote Integration ===
Contributors: getfused
Requires at least: 7.0
Requires PHP: 8.5
Stable tag: 1.1.0

Pushes Gravity Forms "Start a Quote" submissions into INSTANDA's Package API with
write-ahead transaction logging, native entry recording, admin resubmit, and a test-mode lock.

== Changelog ==

= 1.1.0 =
Remediation of the 2026-07 security/reliability/PII audit (see docs/audit-esp-instanda-2026-07.md).

No duplicate policies / no lost quotes:
* Dedupe key is now content-addressed (form id + mapped field values) instead of a
  per-request token, so an identical re-POST or a retry-after-error reuses the existing
  quote instead of creating a second one at INSTANDA (F-01). Adds a 30-minute
  short-circuit window and a content-key race lock.
* Refuse to resubmit an already-delivered transaction (F-12); scope the resubmit
  self-recovery guard to the content dedupe key so a customer's *different* event is not
  skipped (F-18).
* A 2xx response with a missing/empty quoteRef is now recorded as ambiguous
  (possible_duplicate = 1), not a hard failure (F-10, F-17).
* Aborts the StartQuote when the write-ahead insert fails, so no unaudited call is made (F-14).

Go-live safety:
* switch_to_live() now also sets the environment to Live; previously the go-live button
  left real quotes hitting the Test endpoint (F-03).
* Go-live advisory flags when more than one active INSTANDA feed exists (F-02).

Security & PII:
* Corrected the at-rest-secret docblock: the "DB dump never exposes a secret" guarantee
  only holds when SPG_INSTANDA_KEY is set as a constant (F-04).
* Retention now scrubs PII from stale failed/pending rows (previously kept forever) and
  exempts stranded delivered leads from the purge (F-05, F-13); wired WordPress's Erase
  Personal Data tool to delete a customer's transactions (F-05).
* Uninstall now removes ALL plugin options and transients, including the encrypted
  password and its key (F-15).
* Added per-IP (20/h) and per-email (5/h) rate limiting on the public create (F-06).

Reliability & correctness:
* Timestamps are written in UTC to match the retention/dedupe cutoffs and displayed in
  site-local time (F-07). NOTE: rows created before 1.1.0 were stored in site-local time;
  clear the transaction table (test data) at deploy to avoid a mixed-timezone history.
* Fail closed on an unexpected error in the create path (no quote-less entry) and alert
  admins, instead of silently passing (F-11); log when async recording cannot resolve a
  transaction (F-09).
* The "Gravity Forms required" admin notice is now shown even when Gravity Forms is
  inactive (F-16); the daily retention cron self-heals on admin_init (F-22).
* Resubmit re-validates the stored payload before re-sending (F-19); the Retries count is
  now incremented and the resubmit-success notification event is dispatched (F-20).

Theme:
* The Form-5 date-range inline JS is emitted only on pages that embed a Gravity Form and
  its MutationObserver now disconnects instead of watching the DOM forever (F-23).

Operations required alongside this release (see the audit report, Ops checklist):
* Set SPG_INSTANDA_KEY + SPG_INSTANDA_USERNAME_LIVE/_PASSWORD_LIVE + SPG_INSTANDA_ENV in
  production wp-config.php (blocking) - OPS-1 / F-04.
* Deactivate the INSTANDA feed on the test Form 6 in production (blocking) - OPS-3 / F-02.
* Configure espinstanda_alert_emails and the quote-success notification (blocking) - OPS-4.
* Rotate the SendGrid API key out of committed wp-config.php - OPS-2 / F-08.
* Add reCAPTCHA/Akismet to the canonical quote form - OPS-5 / F-06.

= 1.0.7 =
* Initial audited release.