Pre-Launch Checklist
Pre-Launch Production Checklist
Run these 8 tests before pointing real users at your integration. Most take seconds; a few involve waiting for a JWT to expire. Run this checklist after your LyticaLabs operator completes their onboarding steps.
Prerequisites
- Partner has received the welcome packet (slug, embed URL, API key, allowed domains, branding display name).
- Partner has registered their public JWK with LyticaLabs.
- At least one customer org provisioned via
POST /api/v1/cp/orgs. - Partner has wired
<MarliWidget>and/api/marli-tokenmint endpoint. - Partner is testing from one of the registered
allowedDomains.
1Iframe Loads
Open your product page that mounts <MarliWidget> in a real browser (Chrome / Firefox / Safari). Open DevTools → Network panel. Reload.
Pass criteria
- Iframe network entry for
https://alpha.lyticalabs.ai/embed/cp/{slug}returns 200. - No CSP error in the console ("Refused to display in a frame…").
- Iframe paints — you see "Connecting to {displayName}…" then the chat shell.
| Symptom | Likely Cause | Fix |
|---|---|---|
| "Refused to frame…" in console | Current origin not in allowedDomains | Operator: add the origin in admin UI |
| "Marli is unavailable" inert page | Partner row missing or suspended | Operator: check admin UI |
| Stalls at "Connecting…" | postMessage allow-list rejecting | Check allowedDomains are full origins (https://app.foo.com) |
2JWT Mint Endpoint Works
From your backend (curl or test runner) hit POST /api/marli-token with a logged-in user session.
Pass criteria
- Response is
200 application/jsonwith{"jwt": "eyJ..."}. - JWT decodes to
{alg, kid}header +{iss, iat, exp, partnerOrgId, userId}payload. -
issmatches your registered slug. -
exp - iatis between 300 and 900 seconds (5–15 min TTL).
Fail:any 4xx/5xx response. Common causes: missing env vars, private JWK isn't valid JSON, or kid doesn't match registration.
3Chat Round-Trip
Sign into the partner product as a real user belonging to a provisioned customer org. Open the Marli panel. Send: "ping".
Pass criteria
- Marli's response streams in within ~2 seconds.
- Conversation persists through page refresh (subject to chat history persistence).
| Symptom | Likely Cause | Fix |
|---|---|---|
| "Account not found…" | partnerOrgId not provisioned | Run the provisioning curl for that org id |
| "Configuration error…" | PARTNER_JWT_MISSING_CLAIMS | Check your mint endpoint payload |
| "Reconnecting…" never resolves | JWT signature failing verification | Verify private JWK matches the public JWK uploaded |
| 5xx on /api/v1/cp/marli/agent | Server-side bug | File with LyticaLabs technical contact |
4JWT Expiry → Automatic Refresh
Without closing the iframe, leave the page idle for slightly longer than your JWT's TTL (e.g. 6 minutes for 5-minute tokens). Send another message.
Pass criteria
- First request fails 401
PARTNER_JWT_EXPIRED. - You see "Reconnecting to {displayName}…" briefly.
- SDK automatically calls your mint endpoint once.
- Fresh JWT is delivered and the message goes through.
Fail:if the iframe locks into "Service is degraded" — your mint endpoint may be returning errors and the iframe burned through its retry budget.
5CSP Frame-Ancestors Enforcement
Try mounting the iframe from a domain not in your registered allowedDomains (e.g. localhost:9999).
Pass criteria
- Browser refuses to display the iframe — console shows "Refused to display in a frame because an ancestor violates…".
- No content paints.
6Suspended Partner Produces Inert UXOptional
Have your LyticaLabs operator flip your partner status from active to suspended in the admin UI. Open the iframe.
Pass criteria
- Iframe shows "Marli is unavailable for {displayName}…"
- No chat input visible.
- Operator flips back to active → iframe recovers on next load.
7Customer Org IsolationOptional
Provision two customer orgs: customer-A and customer-B. Have a user from customer-A chat, then mint a JWT for the same user with partnerOrgId: customer-B.
Pass criteria
- No data from customer-A's chat history appears in customer-B's session.
- Usage for customer-B's message attributes to customer-B, not customer-A.
If you only have one customer org during pilot, skip — but run before scaling to multiple customers.
When All Tests Pass
You are ready for production traffic. Optional final steps:
- Add Marli iframe success/failure metrics to your product's observability dashboard.
- Brief your customer-success team on what end users will see for
PARTNER_SUSPENDED/ "Account not found" / "Reconnecting…" / "Service is degraded" so they can field tickets without escalating to engineering. - Schedule a Day-7 review with LyticaLabs to look at usage patterns, error rates, and rough edges.
When Something Fails
| Failure | Who to Contact |
|---|---|
| Test 1 (iframe blocked, partner-row issue) | LyticaLabs operator |
| Test 2 (mint endpoint) | Partner engineering |
| Test 3 (chat round-trip — gateway error) | LyticaLabs technical contact |
| Test 3 (chat round-trip — partner claim error) | Partner engineering |
| Test 4 (refresh loop) | Partner engineering or LyticaLabs |
| Test 5 (CSP not enforced) | LyticaLabs — immediately (security issue) |
| Test 6 (inert-state UX) | LyticaLabs |
| Test 7 (multi-tenant isolation broken) | LyticaLabs — immediately (security issue) |