Runbooks

Runbooks

Operational procedures for common situations.

Deploy the web app

cd apps/web && npx vercel --prod

GitHub auto-deploy is unreliable — always deploy via CLI. Verify with the health check:

curl -s https://app.tryvio.ai/api/health   # expect 200 {"status":"ok"}

Releasing the storefront widget + API (backward-compat is law)

The storefront widget is a theme app extension: its JS/CSS are hosted on Shopify’s CDN, versioned per app version (shopify app deploy), and propagate to storefronts with a Shopify-side lag we do not control. The API (Vercel) deploys instantly. So at any time — for weeks, across merchants — old, cached widgets call the new API.

Rules:

  • API changes are additive-only / backward-compatible. Add fields, endpoints, or optional params (safe defaults). Never remove/rename a field an old widget reads, change a response shape, or break an endpoint contract. A breaking change ships as a new versioned endpoint; retire the old only once no storefront runs the old widget.
  • Deploy order: API first → then the widget (shopify app deploy --force). Never widget-first.
  • Never rename widget asset files to bust cache. Shopify versions assets automatically; renaming breaks the scripts’ self-location and can pin a storefront to a broken version.
  • Test the widget on a dev store / preview theme before deploying. A broken widget version can get pinned on a storefront.

Verify what a storefront actually serves (the version is in the asset URL):

# public CDN asset for a version:
curl -sI "https://cdn.shopify.com/extensions/<extension-uuid>/<versionTag>/assets/tryvio-theme.js"
# read a password-protected dev store's real page:
curl -s -c cj -L "https://<shop>.myshopify.com/password" -o pw.html   # grab authenticity_token
curl -s -b cj -c cj -L -X POST "https://<shop>.myshopify.com/password" \
  --data-urlencode form_type=storefront_password --data-urlencode password=<pw>
curl -s -b cj "https://<shop>.myshopify.com/products/<handle>" | grep -oE 'extensions/[^/]+/tryvio-ai-[0-9]+'

If a storefront is stuck on an old version: toggle / remove+re-add the app embed, or duplicate+publish the theme, to force re-resolution.

A merchant’s billing UI looks wrong

The /billing page self-reconciles against Shopify on every load. If a merchant reports a stuck state, have them reload /billing. To inspect: check app_logs (billing.reconciled_from_shopify, billing.no_active_subscription).

Debugging billing (trace events)

Set app_config.log_level to debug for a full step trace (default info only logs anomalies). Pull app_logs filtered by requestId or clientTraceId to read one merchant action front-to-back. Key events: billing.reconcile.*, billing.subscribe.*, billing.callback.*, webhook.{received,reconcile_by_domain,processed,cancelled_others}, shopify.token.{refreshed,recovered_after_race,needs_reconnect}, shopify.graphql.auth_retry, and the browser-side client.billing.subscribe.* / client.dashboard.metrics.* events. See Billing Pipeline → Observability for the full event list.

Reset a store’s usage / grant relief

Admin → Merchants → expand the store:

  • Reset usage — zeroes try_ons_used + overage_pending.
  • Grant credit — issues a Shopify app credit.
  • ★ Custom plan — create a tailored subscription (sends a confirmation URL).

Debug a stuck generation

  1. Find the session in tryon_sessions / the job in tryon_provider_jobs (external task id).
  2. Check the provider snapshot via getTaskSnapshot(taskId).
  3. KIE results land on tempfile.aiquickdraw.com; the callback persists to Supabase Storage. If the callback never fired, the client keeps polling try-on-status.

The landing live demo is failing

  • Confirm the demo garment images resolve: https://app.tryvio.ai/landing/demo/<id>.jpg.
  • /api/demo/try-on has an in-memory per-IP cap (12/hr per warm instance) — not the issue for normal traffic.
  • It does not touch the demo store; check app_logs demo.tryon.*.

Read demo leads / contact inquiries

Admin → Demo Leads (CSV export) and Inquiries tabs. Both are rows in captured_emails filtered by source.

Rotate a key

Update the value in Vercel env (tryvio-shopify project) → redeploy (vercel --prod). For TOKEN_ENCRYPTION_KEY, rotating invalidates stored tokens — avoid unless necessary.

Deploy docs

cd apps/docs && npx vercel --prod --scope mihogv-1894s-projects           # public
cd apps/docs-internal && npx vercel --prod --scope mihogv-1894s-projects  # internal