Diagnostics bundle

Download diagnostics on the Integration Health card (Stores › Configuration › Conviro › AI Chat) downloads one JSON file, conviro-diagnostics-<UTC time>.json, to attach to a Conviro support ticket. It answers "why does the integration misbehave?" without SSH access and without handing over anything sensitive. Plan §14. Code: AiChat/Service/Diagnostics/DiagnosticsBundle.php, Redactor.php, AiChat/Controller/Adminhtml/Diagnostics/Download.php.

Access: admin session with Conviro_AiChat::config; served as an attachment with no-store caching (measured: not served without an admin session).

What is in it

bundleVersion: 1, generatedAt, then:

KeyContents
moduleModule name, installed / setup / schema / data versions, enabled, version status and latest version from Conviro.
platformMagento version and edition, deploy mode, PHP version and SAPI, cURL version.
healthThe Integration Health verdict and every row (state, summary, remediation).
connectionAPI URL, whether an API key / webhook secret is configured (booleans), signature enforcement, tenant id, chatbot id, auth mode, OAuth error text, store URL.
conviroConviro's last answer to tenant-info: measured / ok, HTTP status, error, when, latency, and an allow-listed copy of the answer.
integrationThe "Conviro AI Chat" integration: exists, active, granted ACL resources, missing resources, the permissions in plain words.
cronRecent runs of every Conviro cron job in etc/crontab.xml — nine in 1.5.0: conviro_deliver_events, conviro_catalog_resync, conviro_sync_jobs, conviro_connection_maintenance, conviro_purge_outbox, conviro_purge_webhook_log, conviro_purge_sync_jobs, conviro_purge_inbound_events, conviro_purge_identity_bindings (1.5.0). (Corrected 2026-09-27: this row said "six" and listed six; a unit test keeps the bundle's list equal to crontab.xml.)
outboxQueue health (pending, retrying, blocked, dead, sent in 24 h, last delivery, last error), counts per event type and status, per last HTTP status, and 2xx / 4xx / 5xx / no-response categories.
inboundWebhooksCounts of webhooks Conviro sent the store, by HTTP status.
syncLast delivery per kind (product, order, …), the catalog re-sync job, every sync job (counts, times, last error — no item data).
storeViews / websitesId, code, name, active, default, website, locale, base and display currency, base URLs, whether the widget is enabled; sync toggles per website.
capabilitiesThe AI capability toggles and trust policy as sent to Conviro.
setupWizard facts: app URL, store-view selection (mode, ids, saved at), initial sync plan, cart / payment confirmation state, connection state, a queued disconnect (since, attempts, last error — not its key), OAuth migration status.
identity1.5.0 (unreleased) — signed customer identity, states and counts only: per website whether identity, My orders and guest verification are on and the order scope; signing — switched on anywhere, the key registration state (registered, not_registered, refused, …), the first 8 characters of the key id (public), the previous key id's first 8, registered / rotated / created times, age in days, rotation due, a closed-set class of the last registration error (auth, server, network, …), whether an installation id exists (not the id); clock — this server's clock against Conviro's in seconds and when it was read (from the Date header of Conviro's answers; null without a reading in 24 hours); the order-listing permission state (myOrdersAcl); verified-identity bindings created in the last 24 hours, revoked in the last 24 hours per reason (customer_logout, customer_deleted, account_switched, password_changed, other), live and stored rows; the last successful run of the binding purge.

What is never in it

Collected from allow-listed aggregates only. Not collected: the Conviro API key, the webhook secret, OAuth consumer or token values, customer names, e-mails or phones, order or cart contents, event payloads, event subjects (order numbers, customer ids), cron messages. 1.5.0: not the identity signing key in any form (no class that builds the bundle reads its configuration path — a unit test fails if one does), not the full key id, the public key, the installation or integration id, a binding id, a session hash or a customer id; the binding figures are COUNT(*) queries, so no row is ever read.

Redaction

After the bundle is built, Redactor walks it:

The bundle reports redactions, the number of values masked — 0 on a correct build; anything higher means something slipped into a free-text field (for example an error message quoting an e-mail) and was caught.

Measured (diagnostics.sh 19/19, local stack): with an API key, webhook secret, OAuth credentials, a customer, a guest order and a PII-carrying event in the database, none of 6 secret values and none of 30 PII values appeared in the served bundle or before redaction, no e-mail at all, redactions 0; a planted error text containing an e-mail and the API key was masked (redactions 4).

1.5.0 (2026-09-27, threat T19): unit-tested only — with the Phase 1 test vector's key seeded, none of its 8 spellings, the full key id, the public key, the installation / integration id, a binding id, a session hash or a customer id is in the identity section; the section passes the redactor unchanged (redactions 0); every spelling planted in a field is masked (Test/Unit/Service/Diagnostics/DiagnosticsIdentityTest). diagnostics.sh now switches identity on, creates the key and repeats every leak check with its spellings plus a planted error text holding the key's hex — passed on Magento 2.4.7-p4 (2026-09-27, 32 checks, 0 failures).