JUNOHUB-test/docs/usecases-gmail-storefront.md
2026-04-12 00:40:25 +05:00

452 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gmail vs storefront widget — use-case guide
This document maps **every customer-facing module** from [`docs/req-AI.md`](req-AI.md) §3 to **how it behaves on email (Gmail integration)** vs **the storefront chat widget**. It is a companion to the spec, not a replacement: **identifiers** (`module codes`, API paths) may differ in code; **behavior** should match the pillars below.
**Legend (pillars)**
| Code | Pillar |
|------|--------|
| **K** | Knowledge (FAQ / KB / RAG; no order mutation) |
| **T** | Transactional L1 (verified identity + DB read / limited write) |
| **X** | Ticket-led (human resolves; L1 may intake + acknowledge + ticket) |
| **Cat** | Catalog metadata (DB-backed category metadetails via tools when enabled) |
---
## 1. Identity and verification (both channels)
### 1.1 Gmail (email)
| Rule | Behavior |
|------|----------|
| Identity | Customer email = **`From:`** on the message. |
| Transactional / ticket “fiber” | Only trust lookups when **`From`** matches the **customer/order email** in your DB. No servicing “someone else’s” order from the wrong inbox. |
| OTP | **Not** in v1 of the spec for email — trust is **email alignment** only. |
| Unknown email | **Generic** safe reply: do not confirm whether an order exists for another address; ask them to contact support from the **email used at checkout**. |
| Multi-order | If `From` matches **multiple** recent/open orders, **list candidates** and ask **which order** before full detail or action. |
### 1.2 Storefront widget
| Rule | Behavior |
|------|----------|
| Pure **K** (e.g. FAQ) | May answer **without** email if the module allows — no session required. |
| **T** / **X** / identity-dependent flows | **Email asserted → OTP → verified session (TTL, e.g. 1h)**. No Shopify login, no magic links. |
| After TTL | **Re-OTP** for new transactional work. |
| Session | Server-side: asserted email, verified time, expiry, optional bound order after disambiguation. |
---
## 2. Module-by-module: Gmail vs storefront
For each row: **what the customer is trying to do**, then **Gmail** vs **Widget** specifics. Modules follow [`docs/req-AI.md`](req-AI.md) §3.
---
### `ALL` — Global store context
| | Gmail | Storefront |
|---|--------|------------|
| **Role** | Informs tone, links, support channels, SLA copy in all replies. | Same: baseline context for every reply. |
| **Verification** | N/A (not a standalone intent). | N/A |
| **Notes** | Uses shared fields (brand name, support channels, tone, policy links, etc.). | Same. |
---
### `FAQ` — General policies & “how we work”
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **K** | **K** |
| **Typical asks** | Return window explanation, “how long do refunds take?” (policy), shipping regions. | Same; widget can be used without OTP for pure policy if FAQ module enabled. |
| **Verification** | None required for pure policy. | None for pure FAQ path per §1.2. |
| **Human** | If out of scope → suggest email or ticket. | Same. |
**Important:** Refund **policy** = **K**. Refund **status for my order** = **T** (`REFUND_STATUS`), not FAQ.
---
### `CATEGORY_METADETAILS` — Category-level details from DB sync
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **Cat** | **Cat** |
| **Typical asks** | “What’s the care instruction for [category]?” after product/category resolution. | Same; often needs product/SKU → category resolution. |
| **Verification** | Needed when combined with order-specific **T** flows; for pure catalog facts, product resolution may suffice. | Gated by store **`categoryMetadetailsEnabled`** (or equivalent). If **off**, fall back to KB / PDP / ticket — **do not** call category-metadetails tools. |
| **Human** | If disabled, no row, or ambiguous → KB link / ticket. | Same. |
---
### `PRODUCT_FIT` — Fit, sizing, compatibility
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **K** (+ optional light **T** to resolve product) | **K** (+ product resolve) |
| **Typical asks** | Sizing, voltage, device compatibility. | Same. |
| **Sources** | KB + **category metadetails** (if enabled) + product metafields/chunks. | Same. |
| **Verification** | Usually not for generic fit; if tied to “my order,” need email alignment or OTP session. | OTP if transactional coupling. |
| **Human** | Edge cases → ticket. | Same. |
---
### `STORE_LOCAL` — Hours, pickup, local
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **K** | **K** |
| **Typical asks** | Store hours, pickup location, BOPIS rules. | Same. |
| **Verification** | None. | None. |
---
### `FEEDBACK` — After-resolution feedback
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **K** | **K** |
| **Typical asks** | CSAT link, one-off survey. | Same. |
| **Verification** | Optional ticket id in context. | Same. |
| **Human** | Negative follow-up → human. | Same. |
---
### `HUMAN_ESCALATION` — “I want a person”
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **K** / routing | **K** / routing |
| **Typical asks** | Escalation to agent. | Same. |
| **Verification** | Context-dependent; may create ticket per policy. | May create ticket; **post-ticket** human dialogue often continues **email** per spec §0.3. |
| **Human** | Queue / human ownership. | Same. |
---
### `ORDER_STATUS` — Where is my order
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | **`From`** matches DB + **order id** (or disambiguation list). | **OTP-verified session** + order id / disambiguation. |
| **L1** | Read order state from DB; status summary. | Same. |
| **Human** | Anomaly outside playbook → ticket. | Same. |
---
### `ORDER_SUMMARY` — Receipt / recap
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | Same as order status: aligned email + order resolution. | OTP session + order resolution. |
| **L1** | Line items / totals from DB. | Same. |
| **Human** | Tax invoice edge cases → ticket if policy says. | Same. |
---
### `SHIPPING_TRACKING` — Carrier, tracking, ETA
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | Email alignment + order. | OTP + order. |
| **L1** | Tracking fields from DB for that order. | Same. |
| **Human** | Carrier claim / dispute → **X**. | Same. |
---
### `ORDER_CANCEL` — Cancel order
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | Verified identity + order + business rules. | OTP + order + rules. |
| **L1** | Eligibility + cancel **if allowed** by implementation; else KB explanation. | Same. *(JUNOHUB MVP may be read-only — see [`docs/req-AI.md`](req-AI.md) §10.)* |
| **Human** | Ambiguous / edge → **X**. | Same. |
---
### `REFUND_STATUS` — Status of *my* refund / payout
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | Verified identity + order/return reference. | OTP + references. |
| **L1** | Read refund/return state from DB **if modeled**; else templated + ticket. | Same. |
| **Human** | When data missing or dispute. | Same. |
---
### `INVENTORY_STOCK` — Is this in stock?
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **T** | **T** |
| **Prerequisites** | Product name / SKU; email alignment **if** tied to “my” purchase (product decision). | Session optional for anonymous stock checks per product policy; cart-specific may need OTP. |
| **L1** | Read inventory from DB. | Same. |
| **Human** | SKU disambiguation across many variants. | Same. |
---
### `NOT_RECEIVED_MARKED_DELIVERED` — Tracking says delivered, I don’t have it
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + order. | OTP + order. |
| **L1** | Tracking snapshot + policy snippet + **open ticket**. | Same. |
| **Human** | Carrier / claim investigation. | Same. |
---
### `SHIPMENT_STUCK_OR_DELAYED` — Not moving / very late
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + order. | OTP + order. |
| **L1** | Last known scan + policy + **ticket**. | Same. |
| **Human** | Carrier / ops follow-up. | Same. |
---
### `PAYMENT_PROBLEM` — Double charge, wrong amount, promo failed, etc.
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Order-scoped: verified identity + **order reference**; some sub-intents need extra slots (last4, date). | Same where applicable. |
| **L1** | Structured intake + **ticket**; **no** automated money movement. | Same. |
| **Human** | Finance / support. | Same. |
---
### `ORDER_CHANGE` — Change address / items / qty
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + order + requested change. | OTP + order + change description. |
| **L1** | **Open ticket** + acknowledgement (v1: no auto-change). | Same. |
| **Human** | Feasibility decision. | Same. |
---
### `RETURN_EXCHANGE` — Start return or exchange
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + order (+ reason). | OTP + order (+ reason). |
| **L1** | KB policy + **ticket** (or portal link if product adds it). | Same; spec notes post-ticket dialogue often **email**. |
| **Human** | RMA / ops. | Same. |
---
### `WARRANTY` — Warranty claim
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + proof-of-purchase / order. | OTP + order. |
| **L1** | Intake + **ticket**. | Same. |
| **Human** | Adjudication. | Same. |
---
### `WRONG_ITEM` — Wrong / damaged / missing item
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | Verified identity + order + issue type; **email** may include **photos**. | OTP + order + issue type. |
| **L1** | Ack + policy + **ticket** with structured fields. | Same. |
| **Human** | Reship / refund / return handling. | Same. |
---
### `COMPLAINT` — Strong dissatisfaction
| | Gmail | Storefront |
|---|--------|------------|
| **Pillar** | **X** | **X** |
| **Prerequisites** | **Strict** verification same as other fiber flows. | OTP + full context. |
| **L1** | Empathetic ack + **ticket** + severity. | Same. |
| **Human** | Resolution owner. | Same. |
---
## 3. Excluded use-cases (spec § opening)
Not in scope for this framework: subscriptions/repeat orders, wholesale/B2B, account & security beyond email+OTP, VIP/loyalty, **Shopify customer login**, **magic-link** verification.
---
## 4. Quick reference — channel vs pillar
| Pillar | Gmail summary | Storefront summary |
|--------|----------------|-------------------|
| **K** | Answer from KB/RAG; `From` not required for pure policy. | FAQ may work **without** OTP; enable FAQ module. |
| **T** | **`From` = identity**; multi-order → disambiguate. | **Email + OTP + session TTL**; disambiguate orders when needed. |
| **X** | Intake + ticket; thread stays on **email**. | Intake + ticket; **ongoing human↔customer** often **email** per spec. |
| **Cat** | Category metadetails tools only if **store toggle on** + product/category resolution. | Same + OTP when combined with **T**/**X**. |
---
## 5. Testing and operations (JUNOHUB)
- **Prisma / DB:** After schema changes: `npx prisma generate`, migrate or `db push` — see [`docs/req-AI.md`](req-AI.md) §10.1.
- **Env:** `DATABASE_URL`, `GROQ_API_KEY`, embeddings/OpenAI keys as needed, `STOREFRONT_OTP_SECRET`, SMTP for real OTP mail — §10.3.
- **Store toggles:** `categoryMetadetailsEnabled`, `aiModules` JSON — §10.2.
- **Illustrative tests:** [`tests/l1/`](tests/l1/), [`tests/gmail-auto-reply/`](tests/gmail-auto-reply/).
---
## 6. Copy-paste test examples (Gmail + storefront widget)
Use these **verbatim** (or with your real order numbers / SKUs) to exercise each pillar. Replace placeholders:
| Placeholder | Meaning |
|-------------|---------|
| `YOUR_APP` | Base URL, e.g. `http://localhost:3000` |
| `YOUR_SHOP` | Store `shopifyDomain` in DB, e.g. `your-brand.myshopify.com` |
| `YOUR_ORDER` | A real order id / name that exists in **your** `CachedOrder` rows for the tester email |
| `TEST_EMAIL` | For widget OTP: an inbox you can read (or watch server logs if SMTP is dev-only) |
**Gmail:** In production, inbound mail is processed by your Gmail/Pub/Sub pipeline; the **`From:`** address must match a customer with orders when you expect **T**/**X** behavior. For **offline** checks of reply generation, see [`tests/gmail-auto-reply/scenarios.ts`](../tests/gmail-auto-reply/scenarios.ts) and `generateAutoReplyPreview` in [`src/lib/gmail/autoReplyPreview.ts`](../src/lib/gmail/autoReplyPreview.ts).
**Widget:** Open the embedded page (shop is required):
`YOUR_APP/storefront-chat/widget?shop=YOUR_SHOP`
---
### 6.1 Knowledge (**K**) — no OTP required on widget
| Use case | Gmail (`Subject` / `Body`) | Storefront (type in widget) |
|----------|----------------------------|------------------------------|
| **FAQ** — policy | **Subject:** `Return policy`<br>**Body:** `How many days do I have to return an item if I change my mind?` | Same question in one message. |
| **STORE_LOCAL** | **Subject:** `Pickup`<br>**Body:** `What are your store hours and do you offer local pickup?` | Same. |
| **PRODUCT_FIT** (KB) | **Subject:** `Sizing`<br>**Body:** `Does the medium hoodie run true to size?` | Same. |
| **HUMAN_ESCALATION** | **Subject:** `Human`<br>**Body:** `I want to speak to a real person, please.` | Same. |
| **FEEDBACK** | **Subject:** `Thanks`<br>**Body:** `Thank you for the fast delivery — great experience!` | Same (short thank-you). |
---
### 6.2 Catalog metadata (**Cat**) — `CATEGORY_METADETAILS` (toggle must be **on**)
| Use case | Gmail | Storefront |
|----------|-------|------------|
| Category-level facts | **Subject:** `Materials`<br>**Body:** `What materials are used for products in your [Category Name] line?` | Same; include a **specific product or category name** your sync has metadetails for. |
If the toggle is **off**, expect fallback to KB / generic copy, not DB category tools.
---
### 6.3 Transactional (**T**) — Gmail: `From` = order email; Widget: **OTP first**
**Gmail examples** (send from the **same email** as the order in DB):
| Use case | **Subject** | **Body** |
|----------|-------------|----------|
| **ORDER_STATUS** (needs order #) | `Order status` | `Hi, can you confirm status for order #YOUR_ORDER? Thanks.` |
| **ORDER_STATUS** (no order # → disambiguation) | `Where is my package?` | `Hi, I still haven't received anything. Can you check the status for me? Thanks.` |
| **ORDER_SUMMARY** | `Receipt` | `Please send a line-item recap for order #YOUR_ORDER.` |
| **SHIPPING_TRACKING** | `Tracking` | `What carrier and tracking number do you have for order #YOUR_ORDER?` |
| **ORDER_CANCEL** | `Cancel` | `Please cancel order #YOUR_ORDER if it has not shipped yet.` |
| **REFUND_STATUS** | `Refund status` | `Has my refund for order #YOUR_ORDER been issued yet?` |
| **INVENTORY_STOCK** | `Stock check` | `Do you have SKU YOUR-SKU in stock right now?` |
**Hint mismatch (expect “not on file” behavior):**
| **Subject** | **Body** |
|-------------|----------|
| `Order 9999` | `I need help with order #9999.` |
**Storefront — transactional flow**
1. Open `YOUR_APP/storefront-chat/widget?shop=YOUR_SHOP`.
2. **Verify email:** enter `TEST_EMAIL` → **Send code** → enter the **6-digit OTP** from email/logs → **Verify**.
3. Send a **T** message, e.g.:
`Where is order #YOUR_ORDER?`
or
`Is SKU YOUR-SKU in stock?`
Without a verified session, the app may only treat you as anonymous; OTP unlocks identity-bound tools per spec.
---
### 6.4 Ticket-led (**X**) — intake + human; same identity rules
**Gmail** (from purchaser email):
| Use case | **Subject** | **Body** |
|----------|-------------|----------|
| **NOT_RECEIVED_MARKED_DELIVERED** | `Delivered not received` | `Tracking shows delivered for order #YOUR_ORDER but I never got the package.` |
| **SHIPMENT_STUCK_OR_DELAYED** | `Shipment stuck` | `Order #YOUR_ORDER — the tracking has not updated in 10 days.` |
| **PAYMENT_PROBLEM** | `Double charge` | `I see a duplicate charge on my card for order #YOUR_ORDER. Please investigate.` |
| **ORDER_CHANGE** | `Change address` | `Can I change the shipping address on order #YOUR_ORDER?` |
| **RETURN_EXCHANGE** | `Return` | `I want to start a return for order #YOUR_ORDER — wrong size.` |
| **WARRANTY** | `Warranty` | `I need a warranty claim for the item from order #YOUR_ORDER.` |
| **WRONG_ITEM** | `Wrong item` | `Order #YOUR_ORDER arrived with the wrong color — see photos attached.` |
| **COMPLAINT** | `Complaint` | `I am very unhappy with order #YOUR_ORDER and want this escalated.` |
**Storefront:** complete **OTP** (§6.3), then paste the **same body** lines as in the table.
---
### 6.5 Storefront API (`curl`) — same payloads the widget uses
After `next dev` (or your deployed URL):
**1) Post a chat message (anonymous FAQ path)**
```bash
curl -sS -X POST "YOUR_APP/api/storefront-chat/messages" \
-H "Content-Type: application/json" \
-d '{"shop":"YOUR_SHOP","visitorId":"test-visitor-1","content":"What is your return policy?"}'
```
**2) Request OTP**
```bash
curl -sS -X POST "YOUR_APP/api/storefront-chat/otp/request" \
-H "Content-Type: application/json" \
-d '{"shop":"YOUR_SHOP","visitorId":"test-visitor-1","email":"TEST_EMAIL"}'
```
**3) Verify OTP** (replace `123456`)
```bash
curl -sS -X POST "YOUR_APP/api/storefront-chat/otp/verify" \
-H "Content-Type: application/json" \
-d '{"shop":"YOUR_SHOP","visitorId":"test-visitor-1","email":"TEST_EMAIL","code":"123456"}'
```
**4) Transactional message** (same `visitorId` as steps 2–3)
```bash
curl -sS -X POST "YOUR_APP/api/storefront-chat/messages" \
-H "Content-Type: application/json" \
-d '{"shop":"YOUR_SHOP","visitorId":"test-visitor-1","content":"Where is order #YOUR_ORDER?","customerEmail":"TEST_EMAIL"}'
```
**5) Load history**
```bash
curl -sS "YOUR_APP/api/storefront-chat/messages?shop=YOUR_SHOP&visitorId=test-visitor-1"
```
---
### 6.6 Repo-automated Gmail-style scenarios
The strings in [`tests/gmail-auto-reply/scenarios.ts`](../tests/gmail-auto-reply/scenarios.ts) are curated for **`generateAutoReplyPreview`** (e.g. counter-question when no order #, order #1002 happy path, hint mismatch #9999, off-topic weather). Run:
`npm run test` (or `npx vitest run tests/gmail-auto-reply/run.test.ts` when your DB test stack is up — see `package.json` `test:gmail-auto-reply` for the full Docker pipeline).
---
*Aligned with [`docs/req-AI.md`](req-AI.md) §0–§3, §6–§7 (module questions), and §10 (implementation).*