Integration Health card

At the top of Stores › Configuration › Conviro › AI Chat. One row per part of the integration, each Pass, Warning or Action required with the sentence that fixes it, then one verdict. Nothing is shown as healthy without a measurement. Plan §13, §23. Code: AiChat/Block/Adminhtml/IntegrationHealth.php, AiChat/Service/Health/{HealthCheck,HealthFacts,ConviroStatus}.php. Every message quoted below is from HealthCheck.php (2026-09-24; the Store-wide bearer tokens row 2026-09-26).

Verdict

Where the facts come from

Magento-side facts (queue, cron, settings, the integration's ACL) are read on every page load. Conviro's view comes from one call to GET /api/magento/tenant-info (3 s connect / 4 s total), cached 60 seconds per API URL and key; the card says how old it is. Save Config drops that cache; Test connection bypasses it. When Conviro cannot be asked, rows that depend on it say so ("as of the last Save Config") and show a Warning, not a Pass.

Rows

Every row that is not a Pass links here ("What this means and how to fix it"), to <Documentation URL>/integration-health#row-<row> — the base is Documentation URL (conviro_aichat/general/docs_url, default https://repo.conviro.io/docs/magento2, where Conviro serves these pages).

Connection

StateMeaningFix
Pass"Connected to Conviro workspace "…" (answered in N ms, checked …)".—
ActionNot connected: no API key saved.Setup wizard › Connect to Conviro (or paste a key and Save Config).
WarningDisconnected on … (and whether Conviro confirmed, is still being told by cron, or could not be told).Setup wizard › Reconnect. If Conviro could not be told, also disconnect in the Conviro dashboard.
WarningNot checked yet.Test connection.
ActionThe API key belongs to another workspace than the one this store was connected to.Save Config (connects to the key's workspace) or paste the other workspace's key.
WarningConnected, but the module is disabled (Enable = No): no widget, no events.General Settings › Enable = Yes, Save Config.
ActionMagento cannot reach Conviro (no HTTP answer).Allow outbound connections to api.conviro.io:443, then Test connection.
Action"Conviro's network protection blocked this server — contact Conviro support" (1.4.1): the answer was a challenge / block page of the network protection in front of the Conviro API (cf-mitigated: challenge, or an HTML "Just a moment…" page), not the API.Contact Conviro support with this server's public IP address; nothing to change in Magento (Troubleshooting).
ActionHTTP 401 / 403 that is not an answer of the Conviro API (no JSON body; 1.4.1): a proxy or firewall on this side, or Conviro's network protection.Check outbound proxies / firewalls; otherwise contact Conviro support.
ActionHTTP 401 from the Conviro API: key wrong, revoked or expired.Paste an active key, Save Config.
ActionHTTP 403 from the Conviro API: key lacks kb:write (or magento:module).Use Connect to Conviro in the setup wizard, or create a key with kb:write and Save Config.
WarningHTTP 429 or 5xx — temporary; queued events are kept and retried.Test connection again in a few minutes.
ActionAny other answer.Test connection; if it persists, download diagnostics for Conviro support.

Authentication

StateMeaningFix
PassMagento OAuth 1.0a: every Conviro request is signed; the granted permissions; when Conviro last verified.—
WarningSame, but Conviro could not be asked now.Test connection once Conviro is reachable.
WarningLegacy bearer token: Magento rejected the OAuth signature.A proxy / CDN terminates HTTPS: make it pass the header in web/secure/offloader_header (default X-Forwarded-Proto: https), then Save Config.
WarningLegacy bearer token, other reason.Save Config to switch to OAuth 1.0a.
ActionWaiting for the connection (no key).Connect first.
ActionThe "Conviro AI Chat" integration does not exist / is inactive.Save Config.
ActionThe integration is missing N permission(s).Save Config (grants them again).
ActionConviro has this store as disconnected (since …).Setup wizard › Reconnect, or Save Config.
ActionConviro holds no Magento credentials for this store yet.Save Config.
ActionConviro's last call to this store failed: …Fix the cause shown, Save Config.
ActionNot registered with Conviro yet.Save Config.

Webhooks

StateMeaningFix
PassSigning secret set; when Conviro last accepted a signed event and when the last signed webhook from Conviro was verified. Adds a note when Conviro still accepts unsigned legacy requests (Require Signed Webhooks = No).Consider Require Signed Webhooks = Yes.
ActionNo signing secret yet: events cannot be signed and Conviro's webhooks are refused.Save Config (Conviro issues the secret).
WarningN webhooks to /conviro/webhook/receive were rejected in the last 24 h after the last verified one.Save Config to re-sync the secret. Rejections that continue are requests not sent by Conviro.
WarningSecret set but no signed event exchanged yet.Send test event.

Catalog sync

StateMeaningFix
PassHow many products Conviro knows, last product update delivered, last full re-sync.—
WarningSync Products to KB is off.Switch it on, Save Config, Re-sync catalog.
ActionThe last catalog re-sync failed: …Fix the cause, Re-sync catalog.
ActionThe re-sync has not moved for over 15 minutes: cron is not running it.bin/magento cron:install; it resumes where it stopped.
WarningRe-sync in progress (progress text).Nothing.
ActionConviro has no products from this store yet.Re-sync catalog.
WarningNo products at Conviro yet, but N events are waiting.Wait for delivery (see Cron / queue).
WarningNot verified with Conviro.Re-sync catalog once, then Test connection.

Orders / events

StateMeaningFix
PassLast event delivered (and how long after it happened), last order event, what Conviro last received and how many today.—
ActionThe event queue table is missing.bin/magento setup:upgrade.
ActionN events held: Conviro refused the store's credentials (401/403).Check the API key, Save Config — held events are re-queued automatically.
ActionN events failed permanently (last error …).Fix the cause, Retry failed (or Repair failed items).
WarningN events being retried (7 attempts over about 10 h 43 min — the text is built from the retry schedule, RetryPolicy::describe()).Test connection to see why.
WarningSend Order Events is off (chat order lookups still work).Switch it on, Save Config.
WarningNo event delivered yet.Send test event.

Cron / queue

StateMeaningFix
PassDelivery job ran … (last success …); connection maintenance ran …; N events waiting.—
ActionCron has never run the Conviro delivery job.bin/magento cron:install; check crontab -l.
ActionCron runs, but not the Conviro jobs.bin/magento cache:flush so cron picks them up.
ActionThe last delivery run failed (with the error's class and message, e-mail addresses masked).See var/log/cron.log and var/log/exception.log.
ActionCron has stopped (delivery job last ran more than 10 minutes ago).Check the crontab and that cron:run completes.
WarningThe last run was missed.Check that cron runs every minute.
WarningN events waiting, the oldest queued more than 15 minutes ago (with the reason, e.g. Conviro's network protection).Delivery is behind: Test connection, check each cron run finishes.

Since 1.4.1 the two jobs that run every minute — conviro_deliver_events (the outbox worker) and conviro_connection_maintenance (OAuth migration, disconnect retry, the health report to Conviro) — record their own last run, last success and last failure (Magento's flag table, rows conviro_cron_<job>); Details shows them as Delivery heartbeat and Maintenance heartbeat. The row judges from these, and uses cron_schedule only until the first heartbeat exists — Magento deletes successful cron_schedule rows after an hour, so "when did it last succeed" was not answerable from it.

A store with nothing to send is never flagged: the heartbeat runs every minute whether or not there are events, and "events waiting" counts only events that exist. Both problems — cron silent for 10 minutes, or an event waiting for 15 minutes while cron runs — are also shown as an admin system message on every admin page of a connected store (1.4.1), and the store reports them to the Conviro dashboard (Delivery health on the Magento store card) every 15 minutes; a report that stops arriving is shown there as "no report since …".

Extension version

StateMeaningFix
PassInstalled version is the latest.—
WarningUpdate recommended.Run the shown command from the Magento root.
ActionSECURITY UPDATE REQUIRED: the installed version is below Conviro's security minimum.Run the shown command.
WarningLatest version could not be checked.Test connection.

The command shown is built by the module from the published version number (since 1.4.0 — any command text Conviro's answer carries is ignored, and a version that is not a plain 1.2.3 / 1.2.3-rc1 is neither shown nor compared). Since 1.4.1 it is built for this store — its Magento mode and the locales a static deploy must build (active store views, active admin users, en_US) — for example, production mode, a tr_TR store: bin/magento maintenance:enable && composer require 'conviro/module-aichat:^<version>' && bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento setup:static-content:deploy -f en_US tr_TR && bin/magento cache:flush && bin/magento maintenance:disable (composer update conviro/module-aichat in place of the composer require when no valid version is known; developer mode: composer, setup:upgrade, cache:flush). The row says which mode it was built for. Run it as the owner of the Magento files, never as root. Each step, and the release-directory method: Installation › Upgrading. The latest-version answer is cached 12 hours (15 minutes after a failed check).

Environment

Pass: Magento version (and deploy mode), PHP, Conviro API latency, HTTPS storefront. Action when any of: Magento older than 2.4.4; PHP older than 7.4; the default store view's base URL is not https ("order and customer data would travel unencrypted"); the API URL is not https; no outbound connection to Conviro.

Cart & payment events (shown only when relevant)

Warning when Abandoned Cart Recovery or Payment Failure Assistance is on (at any scope) but not confirmed — cart.updated / checkout.started / payment.failed are not sent (with "held since the upgrade to 1.4, <date>" when the upgrade held it). Fix: open the admin message's link (Confirm cart and payment data sharing — confirms only, starts no sync), or set Confirm cart / payment data sharing = Yes and Save Config; or switch the toggle off.

Since 1.4.1 the same sentence is also an admin system message (severity major, on every admin page of a connected store) with a link to the confirmation page, until the feature is confirmed or switched off — a merchant who upgraded from the command line sees it without opening this card.

Storefront widget (shown only when relevant)

Since 1.4.1 the card looks at the theme of every active store view — and its parent themes, in Magento's fallback order — for Conviro overrides: Conviro_AiChat/templates/widget.phtml, lead-form.phtml, Conviro_AiChat/web/js/widget-loader.js, any Conviro_AiChat/layout/**, and any theme layout file that names the conviro.aichat.widget block or a Conviro_AiChat:: template (removing or re-adding the widget). The file scan is cached for an hour (cache:flush clears it).

StateMeaningFix
ActionThe override bypasses the module's loader: its own inline cw('init' snippet (the 1.3.x way), a CSP nonce in cacheable HTML, no module configuration block, no module loader, or a loader file of its own. The 1.4 fixes — no shopper data in cached pages, no nonce frozen into cached HTML — and every later loader change do not reach the store.Remove the theme's Conviro_AiChat overrides (Details lists the files). Load the Chat Widget and Lead Form Placement (Widget Settings) now do what such overrides were for. Deploy static content, flush the caches, click Check storefront.
WarningThe override still renders the module's configuration and loader. It works, but template changes in module updates will not reach the store.Remove it if it only defers the widget or hides the lead form.
Action / WarningThe last Check storefront found a problem (below).Fix it, click Check storefront again.

Check storefront (button on the card) makes one read-only GET of the default store view's home page — the public URL, as a visitor gets it, from Magento's full-page cache or Varnish if they answer — and of the widget loader file that page references. It checks: exactly one widget configuration block, carrying this store's widget key (otherwise the page is cached from before a change); exactly one module loader script, and that the file served is this release's loader (otherwise static content was not redeployed after the upgrade); nothing else starting the widget (an inline cw('init' or a direct widget.iife.js tag, e.g. a theme override or a pasted snippet — two widgets); at most one lead-form script. Nothing is sent to Conviro. If the server cannot reach its own public URL (some firewalls), the check says so.

Skipped events (shown only when relevant)

Warning when an observer skipped an event in the last 24 hours because preparing or queuing it failed (1.4.1). Every Conviro observer wraps its whole body: the order, checkout, cart or save it runs in always continues — a Conviro problem never becomes a checkout or payment error — and Conviro misses that one event. The row says how many, the last observer, exception class and time; the details are in var/log/system.log ("[Conviro] … event skipped", no personal data). Counted per hour in the flag table (conviro_observer_failures) and reported to the Conviro dashboard.

Store-wide bearer tokens (shown only when relevant)

Warning when Magento's own Allow OAuth Access Tokens to be used as standalone Bearer tokens (Stores › Configuration › Services › OAuth › Consumer Settings, oauth/consumer/enable_integration_as_bearer) is Yes while Conviro signs with OAuth 1.0a (Conviro's answer; the last Save Config when Conviro cannot be asked). 1.3.x switched it on for the whole store on every Save Config; 1.4.0 never changes it by itself, because another integration of yours may send its access token as a bare bearer token. While it is on, anyone who obtains the access token of any integration on the store can call the REST API with it, without an OAuth signature. Conviro does not need it.

Fix: the row's Turn off store-wide bearer tokens button (needs Conviro_AiChat::setup; asks for confirmation first; a POST with the admin form key) sets it to No at the default scope, the only scope Magento reads — or set it yourself on the page above. Check first that no other integration of yours authenticates with a bearer token; if one stops working, switch it back on there. The button changes nothing while Conviro still uses the legacy bearer connection (the Authentication row says so), and says so when a value in app/etc/env.php or config.php overrides the database. Not shown on the legacy bearer connection or without an API key.

Customer Experience & Identity (1.5.0, unreleased)

1.5.0 (unreleased), read 2026-09-27 on feat/magento-1.5.0-p34-module (Block/Adminhtml/Setup/IdentityCard.php, Service/Identity/IdentityCardView.php; not merged yet). What the feature does: Signed customer identity and My orders.

On this card — below the sync jobs, one line: Customer identity: off., Customer identity: on. or Customer identity: needs attention (…) with a link to the card and — Phase 5, branch feat/magento-1.5.0-p5-module — a link Why doesn't it work? (30-second runbook) that opens the runbook at this store's first failing gate. The reasons it can name: not connected, key not registered, Conviro backend without identity, key refused, key registration failed, PHP sodium missing, key rotation due, order listing permission missing. It reads only this store's facts (no call to Conviro).

The card is on Stores › Settings › Conviro Setup and at the top of Stores › Configuration › Conviro › AI Chat › Signed Customer Identity (beta). It renders even when Conviro cannot be reached; it never shows a secret, a customer or an order.

SectionShowsSource
First blocker (Phase 5)the first line under the title: the first failing gate of the runbook's ordered list — connection, this store's switch, key, announcement, Conviro's switch, integration at Conviro, store view mapping, clock, then (while My orders is on) the My orders switch, OAuth, order permission, Conviro's My orders switch — with the fix and a runbook link; Nothing blocks… when all passthis store at once; both sides once Conviro answered (Conviro's own firstBlocker, when its backend sends one, counts too)
ConnectionConnected: Conviro signs its calls with Magento OAuth 1.0a / Degraded / Disconnectedthe Integration Health facts above
Signed identitythe key state (below), the key id (public), when it was registered or replaced, Rotate identity key and — Phase 5 — Reset identity (the emergency rotation, after a confirmation; runbook) (both with Conviro_AiChat::setup), the key age and the rotation advicethis store
Permissionsonly when there is something to fix: Order listing permission missingthis store (the integration's grant)
FeaturesSigned customer identity, Personalized greeting (display only), My orders, Order tracking (part of My orders), Guest verification, Return assistance (= Order-action assistance) — each off on every website or on for …this store's switches
Store viewseach store view, its website, signed identity and My orders on / off, and which orders a verified shopper sees therethis store
At Conviroloaded after the page (admin AJAX, 3 s, cached a minute): whether Conviro switched the feature on for your workspace, whether it received the store's announcement, whether it holds this store's key (and whether it is the same key), the last successful verification and the last 24 hours (succeeded / failed, with the most frequent failure reason explained), My orders at Conviro, the server clock against Conviro's, and Conviro's store-view mapping next to this store'sGET /api/magento/identity-status; Phase 5: the clock also from the Date header of the module's other Conviro calls (clock)
DiagnosticsTest identity bridge for a chosen store view, with its step listbelow

Key state (the Signed identity line)

StateMeaningFix
OffSigned identity is off on every website.Switch it on per website (how).
On, but no key is registered with Conviro yetThe switch is on; the key was not registered yet.Save Config or Reconnect.
On. This store's public key is registered with ConviroGood.—
The Conviro backend does not support it yetThe key registration route answered 404: an older Conviro backend. Everything else works as before.Wait for Conviro; nothing to change in Magento.
Conviro refused this store's keyThe reason is shown (e.g. store URL in another workspace, store disconnected, a key of another installation).Troubleshooting.
The key could not be registeredNetwork or server error; retried on the next save or Reconnect.Save Config later; check the Connection row.
The PHP sodium extension is not loadedThis store cannot sign.Install / enable ext-sodium for the PHP that runs Magento.

Key age: "Key age: N days (since …)". From 180 days the card warns Keys older than 180 days should be rotated (policy set 2026-09-28); a key created before the module recorded its age shows unknown.

Order listing permission missing

Turkish admin: Sipariş listeleme izni eksik. Show verified shoppers their own orders is on, but the Conviro AI Chat integration does not hold the read permission A verified shopper's own orders (read) (Conviro_AiChat::api_customer_orders), so Conviro cannot list a signed-in shopper's orders — the shopper sees "Order details aren't available in the chat for this store" and the account-page link.

Fix: Repair access on the card (needs Conviro_AiChat::setup; an admin without it is told who can). It registers the store with Conviro again, which grants exactly the permissions the switches call for, then reads the grant back; if the permission is still missing it says so — then check the Conviro AI Chat integration under System › Extensions › Integrations and run bin/magento setup:upgrade if the Conviro_AiChat::api_customer_orders resource is unknown (it comes with 1.5.0). The same warning appears in the Conviro dashboard (Order listing permission missing in Magento), also when Magento refused one of Conviro's order reads with "not authorized".

When the integration cannot be read at all the card says Order listing permission: could not be read (reload; see the Authentication row).

Test identity bridge

Signs a synthetic assertion with this store's real key — audience conviro-widget-identity-test, subject synthetic-test, no customer, no binding row — and asks Conviro to verify it without creating anything (Conviro refuses such a token anywhere else, and a real assertion here). Needs Conviro_AiChat::config; Conviro allows 10 tests an hour per store. Steps:

StepFails whenFix
Store view found in this Magentothe chosen store view is gonechoose another
Signed customer identity is on for this store view's websiteswitched off thereswitch it on for that website
This store signed a synthetic test assertion with its identity keyno usable keyswitch it on and Save Config
Conviro answeredtimeout, no connection, server error, API key refused, rate limit, the network protection in front of Conviro answered, an older backendsee the Connection row; try later
Conviro knows this store's key · The signature verifies · The issuer is this installationa key Conviro does not hold, or another installation'sSave Config (registers again), or Rotate identity key
The test audience is accepted— (Conviro-side check)—
The store view is mapped at Convirothe store view is not in Conviro's store mappingselect it in the setup wizard (step 4) and save
The server clock is in step with Conviro'smore than 30 s apart — every real assertion is then refusedsynchronise the clock (NTP: timedatectl set-ntp true, chrony or ntpd)
Signed customer identity is switched on at Convirothe platform flag is offask Conviro
The integration is active at Convirodisconnected / inactiveReconnect
My orders is openMy orders is off here or at Conviroswitch it on, or ask Conviro
Dry run: nothing was created at ConviroConviro reported that the test created something — it must never do thattell Conviro support

A green test proves the store's key, the mapping, the clock and Conviro's switches — not a real shopper's browser (the same-origin bootstrap). For that, sign in as a test customer and open the chat.

Sync jobs panel

Below the rows: each job type with its progress, counts, times, last error and stall / pause notes, and the buttons Re-sync inventory, Re-sync recent orders, Import customers (only if chosen), Repair failed items (Data sync).

Actions

ButtonDoes
Setup wizardOpens Stores › Settings › Conviro Setup (needs Conviro_AiChat::setup).
Test connectionRuns every check now, re-reads the latest version, and reports each row as an admin message.
Send test eventQueues and delivers a signed test.ping through the real path.
Retry failedRe-queues dead and blocked events.
Re-sync catalogStarts the catalog job (a second click while it runs does nothing).
Download diagnosticsDiagnostics bundle.
Turn off store-wide bearer tokensOnly in the Store-wide bearer tokens row: sets oauth/consumer/enable_integration_as_bearer to No after a confirmation (needs Conviro_AiChat::setup).

Measured: admin-health.sh 32/32 on the local stack (3bb49b22); 42/42 with the Store-wide bearer tokens row and its button (2.4.7-p4 dev stack, 2026-09-26); page timings in Performance.