Ship one complete browser artifact
npm run build produces the entry bundle and stylesheet, content-hashed copies, lazy chunks,
licenses, vendored React files, embed.js and asset-manifest.json. Keep the chunks next to
the bundle and preserve vendor/. The built loader contains that build’s filenames and SRI
values; data-rw-asset-base changes their base URL, not which build they reference.
Upload immutable assets before switching the loader/manifest, and retain previous hashed
assets for rollback. Cross-origin SRI requires CORS-readable asset responses. Byte-rewriting
CDN optimizations break integrity checks; normal gzip/brotli encoding is compatible.
The static
Dockerfile/Nginx image serves browser assets; Dockerfile.server packages the API.
Reset the source loader with npm run embed:reset after a local build, while retaining the
complete built artifact for publication.
Configure the API
For normal production startup set the selected provider key,ALLOWED_ORIGINS, and
STATESET_WIDGET_AUTH_SECRET. AI_PROVIDER accepts openai, anthropic or gemini.
An explicit STATESET_WIDGET_AUTH_REQUIRED=false permits a tokenless compatibility deployment;
it does not establish verified conversation ownership for the native inbox or analytics.
Use verified tokens and enforce them after qualifying existing storefronts.
Without Redis, stores are process-local and disappear on restart. Run one replica for that
mode. Production multi-replica operation needs shared Redis plus a persistence policy suitable
for the conversations you retain.
Use
GET /api/health for liveness and /api/ready for readiness. Readiness stays 503 until
thread, rate-limit, response-outbox and execution stores initialize. Thread reads are
rate-limited too: allow for visitor polling when sizing budgets rather than bypassing access
checks or the limiter.
Response reporting
When Hasura response reporting is configured, the server queues stable response IDs and retries background delivery. By default enqueue failure logs/counts the loss and allows chat to continue.RESPONSE_OUTBOX_STRICT=true makes enqueue success a reply precondition and
requires a durable Redis outbox in production when reporting is configured. Queue failure can
then return 503 or an SSE error without [DONE].
Monitor pending records, enqueue failures and confirmed deliveries separately from HTTP
success. The strict queue acknowledgement is not a transaction spanning provider actions,
commerce mutations, helpdesk writes and reporting.
Enable sessions and native support in stages
Prepare the admin database and credentials, then bind the public session issuer to exact website origins, org/agent and optional site. Store secrets in the deployment’s secret manager. MatchWIDGET_SESSION_ALLOWED_ORIGINS with
CORS ALLOWED_ORIGINS and keep session TTL between 60 and 900 seconds.
The repository’s
scripts/prepare-live-chat-rollout.js produces a strategic merge patch for
known deployment bindings and an immutable GHCR digest. It does not apply it. Review the
selected deployment’s origins and bindings before using the generated patch. Do not infer
legacy conversation ownership from visitor metadata.
Inside each candidate API pod, with its runtime environment and operator credential:
pilot or enforced phase later. Preflight checks liveness/readiness,
authenticated inbox access, a ready Redis thread store, issuer bindings and Hasura schema.
Exit 0 means ready, 1 failed and 2 incomplete; omitting --runtime leaves checks pending.
An unauthenticated 401 by itself does not prove readiness.
Qualify a signed visitor turn and operator reply across different replicas. Check wrong-tenant
denial, notes absent from visitor/model transcripts, stable-ID duplicate protection, and token
renewal without a remount or lost draft. An old replica can still generate AI replies during
takeover, so every replica needs the native handler before enabling support.
Release evidence
The current CI/release workflow records asset SHA-256 values inrelease-evidence.json,
serves that artifact for browser checks, verifies both images against it, and uses the same
bytes for tag publication. Source mismatches, uncommitted source and stale extra chunks fail
the artifact gate. WIDGET_ASSET_DIR selects an isolated artifact directory for checks.
Tag publication also requires a configured WIDGET_CANARY_URL. JSON and real SSE replay
must both pass; a JSON fallback does not pass the streaming gate. Canary reports record
attempt/check counts without transcript text or capabilities and reference the verified
asset-evidence digest. These gates establish the cases exercised. Physical iPhone use,
screen-reader review and real-provider answer quality still need separate evidence.
If a rollout fails qualification, restore the prior image/loader and feature flags, preserving
additive tables and credentials. Release controlled operator claims before disabling live chat.
See native live chat for the operator flow.