docs: add product and engineering specification
Full system blueprint (docs 01-10): product vision, integration & security, AI support architecture, ticketing & problem management, orchestration/SLA/escalation, database schema, backend/frontend architecture, testing/observability/CI-CD, and the implementation roadmap. This is the pre-implementation design reference the codebase is being built against. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c61b78fcd1
commit
f475a55a53
@@ -0,0 +1,57 @@
|
||||
# SupportHub — Master Architecture & Implementation Guide
|
||||
|
||||
**System:** AI-First Customer Support + Ticket Management + Problem Resolution + Support Orchestration Platform
|
||||
**Status:** Blueprint / pre-implementation
|
||||
**Scope:** This guide consolidates the full product and engineering specification into a build-ready reference.
|
||||
|
||||
---
|
||||
|
||||
## How this guide is organized
|
||||
|
||||
| # | Document | Covers |
|
||||
|---|----------|--------|
|
||||
| 01 | [Product Vision & Principles](./01-product-vision-and-principles.md) | Core idea, example flow, system ownership boundaries, business model, UX principles, engineering rules, landing page |
|
||||
| 02 | [Integration & Security](./02-integration-and-security.md) | Product integration model, credentials, service-to-service auth, request contracts, RBAC boundary, secrets |
|
||||
| 03 | [AI Support Architecture](./03-ai-support-architecture.md) | AI-first flow, knowledge system, RAG, diagnosis, tools, runbooks, guided UX, verification, AI safety |
|
||||
| 04 | [Ticketing & Problem Management](./04-ticketing-and-problem-management.md) | Ticket lifecycle, problem entity, investigation, root cause, solution, verification, resolution, messages, attachments |
|
||||
| 05 | [Orchestration, SLA & Escalation](./05-orchestration-sla-escalation.md) | Orchestration engine, dynamic hierarchy, capability matching, assignment, SLA, escalation |
|
||||
| 06 | [Database Schema](./06-database-schema.md) | Full entity catalog, field-level detail, relationships |
|
||||
| 07 | [Backend Architecture](./07-backend-architecture.md) | Tech stack, module structure, request flow, events, jobs, audit |
|
||||
| 08 | [Frontend Architecture](./08-frontend-architecture.md) | Customer, agent, admin frontends; real-time UX |
|
||||
| 09 | [Testing, Observability & CI/CD](./09-testing-observability-cicd.md) | Test strategy, critical E2E flows, logging/metrics, Jenkins pipeline |
|
||||
| 10 | [Implementation Roadmap](./10-implementation-roadmap.md) | 11-phase delivery plan, success criteria, open business decisions |
|
||||
|
||||
---
|
||||
|
||||
## One-paragraph summary
|
||||
|
||||
SupportHub sits behind any number of existing SaaS products and never owns identity, tenancy, product access, subscriptions, or RBAC — that authority stays with the existing SaaS. When a customer reports a problem from inside a product, SupportHub creates a durable ticket immediately, then routes the problem to a **product-aware AI Support Agent** that classifies it, retrieves scoped knowledge (RAG), diagnoses a likely cause with a confidence score, and either executes approved tools or guides the customer through a controlled runbook. Resolution is only recorded after **actual verification**, not a customer's say-so. When AI can't safely or confidently resolve the problem, it escalates — with full context — into a **configuration-driven orchestration engine** that picks the right dynamic support hierarchy node, matches capability before availability, assigns an agent through a pluggable concurrency-safe strategy, and enforces SLA policies that respect business calendars and pause/resume correctly. Everything (assignment, escalation, SLA, knowledge, resolution) is audit-logged and reportable.
|
||||
|
||||
## Core end-to-end flow
|
||||
|
||||
```
|
||||
Customer → Product App → Support Center → SupportHub API
|
||||
→ Ticket/Case created (status: NEW)
|
||||
→ AI understands problem → classifies → retrieves knowledge
|
||||
→ Diagnosis (with confidence) → Direct solution OR guided runbook
|
||||
→ Customer action → System verification
|
||||
├─ Verified solved → AI_RESOLVED → (confirm) → RESOLVED → CLOSED
|
||||
└─ Not solved/low confidence → HUMAN_ESCALATION
|
||||
→ Orchestration Engine (capability → hierarchy → team)
|
||||
→ Assignment (strategy-based, concurrency-safe)
|
||||
→ SLA applied (business-calendar aware)
|
||||
→ Investigation → Root Cause → Solution → Verification
|
||||
→ Resolution → Customer confirmation → CLOSED
|
||||
```
|
||||
|
||||
## Non-negotiable boundaries (repeated throughout this guide because they matter most)
|
||||
|
||||
- **SaaS is the only source of truth** for users, tenants, products, product access, subscriptions, permissions, RBAC, and authentication. SupportHub stores only external references (`externalUserId`, `externalTenantId`, `externalProductId`).
|
||||
- **SupportHub is the only source of truth** for tickets, problems, support org structure, routing/assignment, SLA, escalation, investigation/root cause/solution/verification/resolution, knowledge, and support audit trail.
|
||||
- **AI recommends; deterministic policy decides.** The LLM never gets unrestricted backend access, never invents troubleshooting steps or product behavior, and never executes a high-risk action without a permission and policy check.
|
||||
- **Nothing is hardcoded** that the spec calls out as configurable: support hierarchy, SLA values, escalation paths, assignment strategy, routing rules. All of it is admin-configurable data, not code.
|
||||
- **Verification is evidence-based**, not customer-confirmation-based, wherever a system signal is available.
|
||||
|
||||
## Reading order recommendation
|
||||
|
||||
If you're briefing an engineering team from scratch, read in document order (01 → 10). If you're validating a specific subsystem, jump directly to the relevant document — each is self-contained with cross-references back to this index.
|
||||
@@ -0,0 +1,145 @@
|
||||
# 01 — Product Vision & Principles
|
||||
|
||||
## 1. What SupportHub is (and isn't)
|
||||
|
||||
SupportHub is an **AI-First Customer Support + Ticket Management + Problem Resolution + Support Orchestration Platform**. It is not a basic helpdesk, not a generic chatbot wrapper, and not a second identity/RBAC system.
|
||||
|
||||
It integrates with one or more existing SaaS platforms that already own:
|
||||
|
||||
- Users, tenants/organizations
|
||||
- Products, product registration, product access
|
||||
- Subscriptions/purchases, permissions, RBAC
|
||||
- Authentication
|
||||
- User↔tenant and user↔product relationships
|
||||
|
||||
SupportHub never rebuilds any of the above. It integrates with the SaaS through secure APIs and per-product integration credentials.
|
||||
|
||||
## 2. Core business idea
|
||||
|
||||
A customer using any registered SaaS product reports a problem. SupportHub attempts to resolve it with a **product-aware AI Support Agent** before any human is involved. The agent:
|
||||
|
||||
1. Understands the customer's problem
|
||||
2. Identifies the affected product
|
||||
3. Identifies the feature/module
|
||||
4. Classifies the problem
|
||||
5. Searches relevant product knowledge
|
||||
6. Searches known issues and failure cases
|
||||
7. Diagnoses the likely cause
|
||||
8. Provides product-specific guidance
|
||||
9. Executes approved tools/actions when appropriate
|
||||
10. Asks the customer to follow instructions when required
|
||||
11. Verifies whether the problem was actually solved
|
||||
12. Marks the case AI-resolved on success
|
||||
13. Escalates to human support when it cannot safely or confidently solve it
|
||||
|
||||
**The customer never needs to understand the internal support hierarchy** — they just report a problem and see progress toward a resolution.
|
||||
|
||||
## 3. Reference example: DocuQube
|
||||
|
||||
Used throughout this guide as the canonical example product.
|
||||
|
||||
**Scenario:** Customer uploads a PDF to DocuQube. PDF upload succeeds, OCR succeeds, HTML conversion fails. Customer clicks Help/Support inside DocuQube.
|
||||
|
||||
```
|
||||
Ticket: DQB-2026-00567
|
||||
Product: DocuQube
|
||||
Customer: Tenant/User from SaaS (via external reference)
|
||||
Problem: PDF to HTML conversion failed
|
||||
Status: AI_ANALYZING
|
||||
```
|
||||
|
||||
This ticket is created **immediately**, at the start of the journey — not after AI gives up. See [04 — Ticketing & Problem Management](./04-ticketing-and-problem-management.md).
|
||||
|
||||
## 4. System ownership boundary
|
||||
|
||||
| Owned by existing SaaS (authoritative) | Owned by SupportHub (authoritative) |
|
||||
|---|---|
|
||||
| User identity | Support sessions |
|
||||
| Tenant identity | Tickets |
|
||||
| Product identity | Problems |
|
||||
| Product access / subscription | Support teams, agents, skills/capabilities |
|
||||
| Product permissions / RBAC | Support hierarchy |
|
||||
| Authentication | Routing, assignment |
|
||||
| | SLA, escalation |
|
||||
| | Investigation, root cause, solution, verification, resolution |
|
||||
| | Support messages, attachments |
|
||||
| | Knowledge, runbooks |
|
||||
| | Support audit, support analytics |
|
||||
|
||||
SupportHub stores `externalUserId`, `externalTenantId`, `externalProductId` as **references only** — it never becomes a second SaaS-style identity/tenant/RBAC platform.
|
||||
|
||||
## 5. Business model
|
||||
|
||||
| SaaS decides | SupportHub decides |
|
||||
|---|---|
|
||||
| Who owns the product | How support is delivered |
|
||||
| Which tenant has access | How problems are classified |
|
||||
| Which features are purchased | How AI handles them |
|
||||
| Which permissions exist | Which support team handles them |
|
||||
| | How tickets are assigned |
|
||||
| | How SLA is enforced |
|
||||
| | When escalation happens |
|
||||
| | How resolution is recorded |
|
||||
|
||||
Support is **enabled by default** for any product registered in the SaaS — treated as a platform capability of the product, not an opt-in the customer must separately configure, unless/until premium support tiers are introduced as a business rule. The customer never creates a separate SupportHub account.
|
||||
|
||||
## 6. UX principle by persona
|
||||
|
||||
| Persona | Experience should be |
|
||||
|---|---|
|
||||
| **Customer** | Simple, guided, trustworthy, product-aware. Never sees internal hierarchy, assignment algorithms, agent workload, escalation rules, internal notes, or routing logic. |
|
||||
| **Agent** | Information-dense, fast, operational, context-rich. Continues from AI context — never restarts diagnosis from zero. |
|
||||
| **Admin** | Configurable, visual, rule-driven, auditable. |
|
||||
|
||||
### Customer journey (happy path)
|
||||
```
|
||||
Problem → AI help → Guided solution → Verification → Resolved
|
||||
```
|
||||
|
||||
### Customer journey (escalation path)
|
||||
```
|
||||
Problem → AI attempts → Escalation → Human Support → Resolution
|
||||
```
|
||||
|
||||
### Critical UI rule
|
||||
The customer should **not** land on a generic "ticket system." The first thing they see is a **Support Center** with "How can we help you?" — they describe a problem, and the system absorbs all the complexity behind that single interaction.
|
||||
|
||||
## 7. Landing page positioning (if a public SupportHub site is needed)
|
||||
|
||||
- Positioning: *"AI-first support and intelligent resolution platform."*
|
||||
- Hero: *"Resolve customer problems before they become support tickets."*
|
||||
- Explain: product-aware AI, guided troubleshooting, human support orchestration, capability-based assignment, SLA, escalation, SaaS integration.
|
||||
- **Do not** position this as a basic helpdesk.
|
||||
|
||||
## 8. Engineering rules (non-negotiable)
|
||||
|
||||
**Never:**
|
||||
- Hardcode support hierarchy, SLA values, escalation paths, or assignment decisions
|
||||
- Duplicate SaaS RBAC inside SupportHub
|
||||
- Put Prisma queries in controllers, or business logic in routes
|
||||
- Allow the AI unrestricted backend access
|
||||
- Store large files in PostgreSQL
|
||||
- Use in-memory SLA timers (e.g., `setTimeout`) for production enforcement
|
||||
- Create giant global services, circular module dependencies, or deep cross-module imports
|
||||
|
||||
**Always:**
|
||||
- Use configuration-driven logic for anything the business can change without a deploy
|
||||
- Keep module boundaries clear, exposed only via each module's public `index.ts`
|
||||
- Validate all input; audit all important operations
|
||||
- Test concurrent operations (assignment races, idempotent job handlers)
|
||||
- Preserve full AI history and full resolution history
|
||||
- Keep problem and ticket as separate, related entities
|
||||
- Verify actual resolution with evidence, not customer assertion, wherever possible
|
||||
- Keep the SaaS as the sole identity/access authority
|
||||
|
||||
## 9. Final architectural principle
|
||||
|
||||
```
|
||||
PROBLEM → UNDERSTAND → KNOWLEDGE → DIAGNOSE → GUIDE → VERIFY → RESOLVE
|
||||
|
||||
If AI cannot resolve:
|
||||
PROBLEM → HUMAN SUPPORT → ORCHESTRATE → ASSIGN → SLA
|
||||
→ INVESTIGATE → ROOT CAUSE → SOLUTION → VERIFY → RESOLVE → CLOSE
|
||||
```
|
||||
|
||||
SupportHub is: **AI-first, problem-centric, configuration-driven, product-aware, human-assisted, SLA-aware, escalation-aware, multi-product, API-integrated, enterprise-ready.**
|
||||
@@ -0,0 +1,91 @@
|
||||
# 02 — Integration & Security
|
||||
|
||||
## 1. Product integration model
|
||||
|
||||
Every SaaS product that wants support must be **registered as an integration client** in SupportHub, with its own credential. Credentials are never shared globally across products.
|
||||
|
||||
```
|
||||
Product: DocuQube
|
||||
Product ID: PROD_DQ_001
|
||||
Support Integration: Enabled
|
||||
Integration Credential: PRODUCT_DQ_CREDENTIAL
|
||||
```
|
||||
|
||||
A second product gets an entirely separate `Product ID` and credential — never reuse one credential across products.
|
||||
|
||||
## 2. What SupportHub must validate on every inbound request
|
||||
|
||||
- The calling product's identity
|
||||
- The integration credential presented
|
||||
- Product status (active/suspended/deprecated)
|
||||
- User/tenant context accompanying the request
|
||||
- The allowed integration scope for that credential
|
||||
|
||||
**Never trust a raw `userId` or `productId` blindly** — every value must be validated against the registered integration and its scope before use.
|
||||
|
||||
## 3. Inbound request contract (conceptual)
|
||||
|
||||
```ts
|
||||
interface ProductToSupportHubRequest {
|
||||
productId: string;
|
||||
tenantId: string;
|
||||
userId: string;
|
||||
source: string; // e.g. "docuqube-web", "docuqube-mobile"
|
||||
problem: string; // free-text customer description
|
||||
feature?: string; // e.g. "pdf_to_html"
|
||||
referenceIds?: string[]; // e.g. documentId, jobId — product-specific evidence handles
|
||||
context?: Record<string, unknown>;
|
||||
}
|
||||
```
|
||||
|
||||
## 4. Service-to-service authentication
|
||||
|
||||
Use production-appropriate mechanisms, chosen per integration risk profile:
|
||||
|
||||
- **Signed service tokens** (short-lived, scoped to a product)
|
||||
- **OAuth2 client credentials** grant where suitable
|
||||
- **mTLS** for high-trust server-to-server channels
|
||||
- **Credential rotation** — must be supported without downtime
|
||||
- **Credential revocation** — immediate effect, audited
|
||||
- **Audit logging** of every integration authentication event (success and failure)
|
||||
|
||||
## 5. RBAC boundary
|
||||
|
||||
SupportHub **integrates with** the SaaS's existing RBAC — it does not reimplement it.
|
||||
|
||||
- Support-domain authorization (who can see which ticket, which admin config, which agent queue) is SupportHub's own concern and lives entirely within SupportHub's data model (teams, agents, hierarchy scope).
|
||||
- Customer-facing authorization (does this user have access to this product at all) is always deferred to the SaaS via the validated integration context — SupportHub does not maintain a parallel "does this user own this product" table.
|
||||
- **A customer must never be able to access another customer's tickets.** Every ticket query must be scoped by the validated `externalTenantId`/`externalUserId` from the authenticated session, never by client-supplied values alone.
|
||||
|
||||
## 6. Security requirements checklist
|
||||
|
||||
- [ ] Secure product integration (per-product credentials, scoped)
|
||||
- [ ] Authentication context validated on every request
|
||||
- [ ] RBAC integration with SaaS (never duplicated)
|
||||
- [ ] Support-domain authorization (teams/hierarchy/product scope)
|
||||
- [ ] Customer isolation (tenant/user scoping on every query)
|
||||
- [ ] Rate limiting per integration and per user
|
||||
- [ ] Input validation (schema-first, reject unknown/extra fields)
|
||||
- [ ] Secure file handling (validation, size limits, malware scanning — see [04](./04-ticketing-and-problem-management.md#attachments))
|
||||
- [ ] Encrypted transport (TLS everywhere, mTLS where appropriate)
|
||||
- [ ] Encrypted sensitive storage at rest
|
||||
- [ ] Secret management (never in source, never in `NEXT_PUBLIC_*`)
|
||||
- [ ] Audit logging for all security-relevant actions (append-only from the application's perspective)
|
||||
|
||||
## 7. Environment & secrets handling
|
||||
|
||||
```
|
||||
.env.example
|
||||
.env.development.example
|
||||
.env.test.example
|
||||
.env.production.example
|
||||
```
|
||||
|
||||
- Real environment values are **never committed**.
|
||||
- Production secrets are injected via CI/CD infrastructure (Jenkins credentials store), not checked into any env file.
|
||||
- Use environment validation at boot (fail fast if a required var is missing/malformed).
|
||||
- Only browser-safe variables use the `NEXT_PUBLIC_` prefix — secrets must never be exposed this way.
|
||||
|
||||
## 8. AI-specific safety boundary (summary — full detail in [03](./03-ai-support-architecture.md#ai-safety-and-control))
|
||||
|
||||
The AI must never: invent product behavior or configuration, invent troubleshooting steps, execute unauthorized actions, access arbitrary customer data, expose internal notes or private knowledge, or modify support configuration/SLA/hierarchy. Deterministic application policy is always the actual decision-maker for anything with real-world effect.
|
||||
@@ -0,0 +1,237 @@
|
||||
# 03 — AI Support Architecture
|
||||
|
||||
The AI Support Agent is the **first support layer**, not a generic chatbot. It must be product-aware, evidence-driven, and tightly bounded by deterministic policy.
|
||||
|
||||
## 1. High-level flow
|
||||
|
||||
```
|
||||
Customer Problem
|
||||
→ Problem Classification
|
||||
→ Knowledge Retrieval (RAG)
|
||||
→ Relevant Context
|
||||
→ AI Reasoning
|
||||
→ Next Action (direct solution / guided runbook / tool call / escalate)
|
||||
```
|
||||
|
||||
## 2. Product knowledge system
|
||||
|
||||
Knowledge is **retrieved, not stuffed into one giant system prompt.** Use a RAG architecture scoped per product.
|
||||
|
||||
Conceptual structure per product:
|
||||
|
||||
```
|
||||
Product
|
||||
├── Overview
|
||||
├── Features
|
||||
├── Troubleshooting
|
||||
├── Known Issues
|
||||
├── Error Catalog
|
||||
├── Runbooks
|
||||
├── FAQs
|
||||
├── Resolution Procedures
|
||||
└── Product Operations
|
||||
```
|
||||
|
||||
Example knowledge entry:
|
||||
|
||||
```
|
||||
Knowledge ID: KB-DQ-102
|
||||
Product: DocuQube
|
||||
Feature: PDF → HTML
|
||||
Type: Known Issue
|
||||
Problem: Conversion fails for complex layouts.
|
||||
Symptoms: Layout parser failure.
|
||||
Error: LAYOUT_PARSE_042
|
||||
Cause: Specific PDF layouts fail through the primary parser.
|
||||
Recommended: Use fallback parser.
|
||||
Verification: Retry conversion and confirm output.
|
||||
Escalation: Escalate if fallback parser fails.
|
||||
```
|
||||
|
||||
Knowledge must be:
|
||||
- Versioned, searchable, auditable
|
||||
- Product-scoped, and category-scoped where necessary
|
||||
- Permission-aware (never expose raw internal knowledge to customers — the AI converts retrieved knowledge into simple, product-specific guidance)
|
||||
- Maintainable by administrators, with quality metadata:
|
||||
|
||||
| Field | Purpose |
|
||||
|---|---|
|
||||
| `version` | Change tracking |
|
||||
| `status` | draft / published / unpublished |
|
||||
| `effectiveDate` | When it becomes eligible for retrieval |
|
||||
| `productScope`, `featureScope`, `categoryScope` | Retrieval filters |
|
||||
| `validationStatus` | Has this been verified to actually work? |
|
||||
| `owner`, `lastReview` | Accountability / staleness detection |
|
||||
| `source` | Where it originated (runbook author, resolved ticket, docs) |
|
||||
|
||||
**The AI should prefer validated knowledge** over unvalidated entries when both are retrieved.
|
||||
|
||||
## 3. Knowledge retrieval example
|
||||
|
||||
Customer says: *"My PDF is not converting to HTML."*
|
||||
|
||||
The system resolves:
|
||||
|
||||
```
|
||||
Product: DocuQube
|
||||
Feature: PDF → HTML
|
||||
Problem type: Conversion Failure
|
||||
```
|
||||
|
||||
Then searches: feature documentation → error catalog → known issues → troubleshooting → runbooks → previously validated solutions. Only relevant, filtered knowledge is returned to the AI's context — never a bulk dump.
|
||||
|
||||
## 4. AI diagnosis
|
||||
|
||||
The AI produces a **structured** diagnosis, not prose alone:
|
||||
|
||||
```json
|
||||
{
|
||||
"product": "docuqube",
|
||||
"feature": "pdf_to_html",
|
||||
"problemType": "conversion_failure",
|
||||
"severity": "medium",
|
||||
"confidence": 0.91,
|
||||
"possibleCauses": ["unsupported_layout", "parser_failure", "processing_timeout"]
|
||||
}
|
||||
```
|
||||
|
||||
### Confidence policy (configurable)
|
||||
|
||||
| Confidence band | Behavior |
|
||||
|---|---|
|
||||
| High | AI may proceed automatically |
|
||||
| Medium | AI may ask additional diagnostic questions |
|
||||
| Low | Escalate to human support |
|
||||
|
||||
Thresholds are stored in configuration, never hardcoded, and must be tunable per product/category without a deploy.
|
||||
|
||||
## 5. AI tool system
|
||||
|
||||
The AI **requests** tools; the **application decides** whether execution is allowed. The LLM never gets unrestricted database/application access.
|
||||
|
||||
Example tools (DocuQube):
|
||||
|
||||
| Tool | Purpose |
|
||||
|---|---|
|
||||
| `getDocumentStatus()` | Read current processing state |
|
||||
| `getDocumentMetadata()` | Read document metadata |
|
||||
| `getProcessingStatus()` | Read pipeline stage status |
|
||||
| `getErrorDetails()` | Read structured error info |
|
||||
| `retryConversion()` | Re-trigger conversion job |
|
||||
| `retryOCR()` | Re-trigger OCR job |
|
||||
| `enableFallbackParser()` | Toggle fallback parser for this document |
|
||||
| `checkServiceStatus()` | Read upstream service health |
|
||||
| `getSupportedFileTypes()` | Read static capability info |
|
||||
| `escalateToSupport()` | Trigger human escalation |
|
||||
|
||||
Each tool definition must include:
|
||||
|
||||
```ts
|
||||
interface AITool {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: ZodSchema;
|
||||
outputSchema: ZodSchema;
|
||||
permission: string; // permission required to invoke
|
||||
riskLevel: "low" | "medium" | "high";
|
||||
supportedProducts: string[];
|
||||
auditRequired: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
**High-risk operations require deterministic policy checks and/or human approval** before execution — the AI's request is a proposal, not an authorization.
|
||||
|
||||
## 6. Troubleshooting runbook engine
|
||||
|
||||
Runbooks are **configurable step sequences**, not something the LLM improvises. The AI communicates the runbook naturally in conversation; the workflow engine controls which steps are actually permitted next.
|
||||
|
||||
Example — `PDF_HTML_CONVERSION_FAILURE`:
|
||||
|
||||
```
|
||||
Step 1: Check file size → if over limit, guide customer to reduce size
|
||||
Step 2: Check file type
|
||||
Step 3: Check document structure
|
||||
Step 4: Try fallback parser
|
||||
Step 5: Verify conversion → if still failing, escalate via configured path
|
||||
```
|
||||
|
||||
**Do not allow the LLM to invent arbitrary troubleshooting steps.** The runbook engine is the source of the permitted sequence; the AI's job is presentation and interpretation of results, not authorship of new steps.
|
||||
|
||||
## 7. Guided customer experience
|
||||
|
||||
When the AI identifies a known solution, it presents:
|
||||
|
||||
```
|
||||
Problem → Likely cause → Recommended action → Customer instruction → Verification
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
> "Your document failed during layout processing." → "Enable fallback parser."
|
||||
>
|
||||
> 1. Open Conversion Settings
|
||||
> 2. Open Advanced
|
||||
> 3. Enable *Use Fallback Parser*
|
||||
> 4. Save
|
||||
> 5. Retry conversion
|
||||
|
||||
The system then **waits** for the customer/product action rather than assuming completion.
|
||||
|
||||
## 8. Verification (first-class, evidence-based)
|
||||
|
||||
**Never assume** "customer says done" equals "problem resolved." Prefer actual system evidence.
|
||||
|
||||
```
|
||||
Conversion started → processing completed → HTML generated → output validated
|
||||
→ Verification = SUCCESS → only then can AI mark "Resolved by AI"
|
||||
```
|
||||
|
||||
Supported verification modes:
|
||||
- Product signal verification (webhook/event from the product confirming success)
|
||||
- Automated verification (poll a status endpoint via an approved tool)
|
||||
- Customer confirmation (used as a secondary/confirming signal, not primary evidence)
|
||||
- Agent verification (for human-handled cases)
|
||||
|
||||
## 9. AI safety and control
|
||||
|
||||
**AI must never:**
|
||||
- Invent product behavior, configuration settings, or troubleshooting steps
|
||||
- Execute unauthorized actions
|
||||
- Access arbitrary customer data
|
||||
- Expose internal notes or private knowledge
|
||||
- Modify support configuration, SLA policies, or hierarchy
|
||||
- Escalate arbitrarily without going through policy evaluation
|
||||
|
||||
**AI can recommend. Deterministic application policies decide.** Tool execution is always permission-aware, and high-risk actions require stronger controls (policy check and/or human approval) regardless of AI confidence.
|
||||
|
||||
## 10. Escalation trigger conditions (AI → Human)
|
||||
|
||||
Escalate when any of the following hold:
|
||||
|
||||
- AI cannot identify the issue
|
||||
- Confidence is below the configured threshold
|
||||
- No matching knowledge exists
|
||||
- The runbook is exhausted without success
|
||||
- A required tool execution fails
|
||||
- The problem requires human judgment/intervention
|
||||
- The problem looks like a product defect
|
||||
- It's flagged as a critical incident
|
||||
- The customer explicitly asks for a human
|
||||
- Policy requires a human for this case type
|
||||
- The AI cannot safely execute a required action
|
||||
|
||||
When this happens, the **AI session hands off to a human support ticket with full context** — see [04](./04-ticketing-and-problem-management.md) and [05](./05-orchestration-sla-escalation.md).
|
||||
|
||||
Example AI hand-off summary:
|
||||
|
||||
```
|
||||
Problem: PDF → HTML conversion failure.
|
||||
Diagnosis: Layout parser issue.
|
||||
Steps attempted:
|
||||
✓ File validation
|
||||
✓ Processing status check
|
||||
✓ Fallback parser
|
||||
✗ Still failed
|
||||
AI confidence: 62%
|
||||
Recommendation: Investigate conversion service.
|
||||
```
|
||||
@@ -0,0 +1,165 @@
|
||||
# 04 — Ticketing & Problem Management
|
||||
|
||||
## 1. Ticket creation timing
|
||||
|
||||
The operational ticket/case is created **at the very start** of the support journey — not after AI fails. This preserves the complete interaction from the first moment: problem, diagnosis, knowledge used, AI messages, tool calls, failed attempts, customer actions, timestamps, evidence, and escalation history.
|
||||
|
||||
### Example lifecycle
|
||||
|
||||
```
|
||||
NEW → AI_ANALYZING → AI_TROUBLESHOOTING → AI_VERIFYING
|
||||
→ AI_RESOLVED
|
||||
or
|
||||
→ HUMAN_ESCALATION
|
||||
```
|
||||
|
||||
## 2. Problem is first-class — separate from ticket
|
||||
|
||||
**Ticket** = the operational container tracking the interaction.
|
||||
**Problem** = the actual thing being solved, which can outlive and span multiple tickets.
|
||||
|
||||
Problem contains:
|
||||
- Problem statement, symptoms, impact
|
||||
- Product, feature, category, problem type
|
||||
- Severity, customer impact, business impact
|
||||
- Environment, evidence, related tickets
|
||||
|
||||
Recurring-problem support:
|
||||
|
||||
```
|
||||
Problem → Ticket A
|
||||
→ Ticket B
|
||||
→ Ticket C
|
||||
```
|
||||
|
||||
This lets SupportHub recognize "this is the same underlying problem occurring again" rather than treating every occurrence as unrelated.
|
||||
|
||||
## 3. Human support flow (post-escalation)
|
||||
|
||||
```
|
||||
Ticket → Orchestration → Capability → Support Hierarchy → Team
|
||||
→ Eligible Agents → Assignment → SLA
|
||||
→ Investigation → Root Cause → Solution → Verification
|
||||
→ Resolution → Closure
|
||||
```
|
||||
|
||||
If an agent cannot solve the issue:
|
||||
|
||||
```
|
||||
Current Support Node → Evaluate escalation rules → Target Support Node
|
||||
→ Target Team → Availability → Assignment → Continue SLA
|
||||
```
|
||||
|
||||
## 4. Investigation (structured, not free-text notes)
|
||||
|
||||
Store:
|
||||
- Investigator, timestamp
|
||||
- Findings, evidence, internal notes, references
|
||||
- Investigation status
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
Investigation: Payment service logs checked.
|
||||
Finding: Webhook was received.
|
||||
Finding: Payment processing failed.
|
||||
```
|
||||
|
||||
## 5. Root cause — separate from investigation
|
||||
|
||||
Investigation is *what was found*. Root cause is *why it happened*, and is its own record.
|
||||
|
||||
```
|
||||
Problem: PDF conversion fails.
|
||||
Investigation: Layout parser returns error.
|
||||
Root Cause: Parser cannot handle a specific table structure.
|
||||
```
|
||||
|
||||
Root cause types to support: technical cause, configuration cause, external dependency cause, business cause, contributing factor.
|
||||
|
||||
## 6. Solution — proposed vs. implemented
|
||||
|
||||
Keep these distinct fields/states, not one blob:
|
||||
- Proposed solution
|
||||
- Approved solution
|
||||
- Implemented solution
|
||||
- Implementation notes
|
||||
- Implemented by / implementation timestamp
|
||||
|
||||
```
|
||||
Proposed: Enable fallback parser.
|
||||
Implemented: Fallback parser enabled and conversion retried.
|
||||
```
|
||||
|
||||
## 7. Verification — after implementation
|
||||
|
||||
```
|
||||
Solution → Verification
|
||||
```
|
||||
|
||||
Verification types: automated, technical test, customer confirmation, agent confirmation.
|
||||
|
||||
If verification fails:
|
||||
|
||||
```
|
||||
Verification → Investigation (re-open investigation)
|
||||
or
|
||||
Verification → Escalation (escalate further)
|
||||
```
|
||||
|
||||
## 8. Resolution — separate from solution
|
||||
|
||||
**Solution** = what was done. **Resolution** = the final outcome.
|
||||
|
||||
```
|
||||
Solution: Fallback parser enabled.
|
||||
Verification: HTML generated successfully.
|
||||
Resolution: Customer document successfully converted.
|
||||
```
|
||||
|
||||
## 9. Customer confirmation & reopen
|
||||
|
||||
Configurable confirmation flow:
|
||||
|
||||
```
|
||||
RESOLUTION_PENDING_CUSTOMER → Customer confirms → RESOLVED → CLOSED
|
||||
```
|
||||
or
|
||||
```
|
||||
RESOLVED → configured waiting period (auto-close) → CLOSED
|
||||
```
|
||||
|
||||
**Reopen must be supported** — a customer or agent can reopen a closed ticket, which should re-enter the appropriate lifecycle stage (and, per [05](./05-orchestration-sla-escalation.md), repeated reopens are themselves an escalation trigger).
|
||||
|
||||
## 10. Messages
|
||||
|
||||
Message types:
|
||||
|
||||
| Type | Visible to customer? |
|
||||
|---|---|
|
||||
| `CUSTOMER_MESSAGE` | Yes |
|
||||
| `AI_MESSAGE` | Yes |
|
||||
| `AGENT_MESSAGE` | Yes |
|
||||
| `INTERNAL_NOTE` | **No — never** |
|
||||
| `SYSTEM_EVENT` | Depends on event (status changes typically yes) |
|
||||
| `INVESTIGATION_NOTE` | No |
|
||||
| `SOLUTION_NOTE` | No |
|
||||
|
||||
**Internal notes must never be shown to customers** — enforce this at the API/serialization layer, not just in the UI.
|
||||
|
||||
## 11. Attachments
|
||||
|
||||
Supported types: screenshots, PDFs, logs, videos, documents.
|
||||
|
||||
**Storage:** object storage (S3-compatible in production, MinIO for local dev). **Never store large binary files in PostgreSQL** — store metadata + object storage reference only.
|
||||
|
||||
Required capabilities:
|
||||
- File validation (type/size)
|
||||
- Size limits (configurable, per product/tenant if needed)
|
||||
- Malware scanning before the file is considered available
|
||||
- Secure download via expiring, authorization-checked URLs
|
||||
- Authorization scoped to the ticket's tenant/user context
|
||||
|
||||
## 12. Domain events emitted by this subsystem
|
||||
|
||||
`TicketCreated`, `ProblemCreated`, `TicketClassified`, `InvestigationStarted`, `RootCauseIdentified`, `SolutionProposed`, `SolutionImplemented`, `VerificationCompleted`, `TicketResolved`, `TicketClosed`, `TicketReopened`. Full event catalog and consumers are in [07 — Backend Architecture](./07-backend-architecture.md#domain-events).
|
||||
@@ -0,0 +1,154 @@
|
||||
# 05 — Orchestration, SLA & Escalation
|
||||
|
||||
This is the central decision-making subsystem for human support. It is entirely **configuration-driven** — no hardcoded `L1 → L2 → L3 → L4` levels anywhere.
|
||||
|
||||
## 1. Orchestration engine
|
||||
|
||||
Determines, for every escalated ticket: what problem is this, what capability is needed, which support path, which team, which agents, which assignment strategy, which SLA, which escalation policy.
|
||||
|
||||
```
|
||||
Product → Problem Type → Category → Priority → Severity
|
||||
→ Required Capability → Business Rules
|
||||
→ Dynamic Support Hierarchy → Team → Eligible Agents
|
||||
→ Assignment Strategy → SLA → Escalation Policy
|
||||
```
|
||||
|
||||
## 2. Dynamic support hierarchy
|
||||
|
||||
Administrators configure arbitrary support nodes — different products can have completely different hierarchies, and changing one must never require a code change.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
DocuQube Support
|
||||
├── General Support
|
||||
├── Document Processing
|
||||
│ ├── OCR Specialist
|
||||
│ └── Conversion Specialist
|
||||
└── Engineering
|
||||
├── Backend
|
||||
└── Infrastructure
|
||||
```
|
||||
|
||||
A hierarchy node's fields:
|
||||
|
||||
```ts
|
||||
interface HierarchyNode {
|
||||
id: string;
|
||||
name: string;
|
||||
parentId?: string;
|
||||
order: number;
|
||||
team: string;
|
||||
skills: string[]; // capability tags this node covers
|
||||
productScope: string[];
|
||||
categoryScope: string[];
|
||||
priorityScope: string[];
|
||||
assignmentStrategy: AssignmentStrategy;
|
||||
slaPolicyId: string;
|
||||
escalationPolicyId: string;
|
||||
entryConditions: RuleExpression;
|
||||
exitConditions: RuleExpression;
|
||||
active: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## 3. Capability and skill matching
|
||||
|
||||
**Capability is evaluated before availability.** Example:
|
||||
|
||||
```
|
||||
Rahul: DocuQube, PDF, Conversion
|
||||
Aamir: Billing, Payments
|
||||
Sahil: Infrastructure, DevOps
|
||||
|
||||
Problem: DocuQube PDF conversion failure → Eligible: Rahul
|
||||
```
|
||||
|
||||
Only after the eligible set is computed does the system consider: active state, availability, working hours, current workload, team, hierarchy node.
|
||||
|
||||
## 4. Assignment engine
|
||||
|
||||
Must be **pluggable**. Supported strategies:
|
||||
|
||||
| Strategy | Behavior |
|
||||
|---|---|
|
||||
| `ROUND_ROBIN` | Cycles through eligible agents only; must be concurrency-safe |
|
||||
| `LEAST_LOADED` | Picks the eligible agent with lowest current workload |
|
||||
| `SKILL_BASED` | Weighted match on skill depth, not just presence |
|
||||
| `MANUAL` | Human picks the assignee |
|
||||
| `DIRECT` | Explicit target (e.g. reassign to a named agent) |
|
||||
| `PRIORITY_BASED` | Priority ticket preempts queue position |
|
||||
|
||||
**Round robin only operates over the eligible-agent set** (post capability-match), and **must be concurrency-safe** — two tickets arriving simultaneously must never corrupt the round-robin cursor or double-assign. Use a database-level lock/transaction or an atomic Redis operation, not an in-memory counter.
|
||||
|
||||
**Assignment history must be recorded** for every assignment and reassignment (who, when, why, strategy used).
|
||||
|
||||
## 5. SLA engine
|
||||
|
||||
SLA policies are **configuration**, never a hardcoded number. Policies may depend on: product, category, problem type, priority, severity, support node, customer type, business calendar.
|
||||
|
||||
### SLA types to support
|
||||
- First response SLA
|
||||
- Investigation SLA
|
||||
- Resolution SLA
|
||||
- Customer response SLA
|
||||
- States: warning, pause, resume, breach, completion
|
||||
|
||||
### Business-calendar awareness
|
||||
|
||||
Support business hours, weekends, holidays, time zones, and per-team schedules. **Do not compute enterprise SLA as `createdAt + N hours`** — that ignores calendars entirely and will silently violate real commitments.
|
||||
|
||||
### SLA pause/resume
|
||||
|
||||
```
|
||||
IN_PROGRESS → WAITING_FOR_CUSTOMER → SLA PAUSED
|
||||
WAITING_FOR_CUSTOMER → IN_PROGRESS → SLA RESUMES
|
||||
```
|
||||
|
||||
SLA calculations must be **durable** — never dependent on an in-memory timer that resets on a process restart. Use durable jobs (BullMQ) with persisted due-times recomputed against the business calendar, not `setTimeout`.
|
||||
|
||||
## 6. Escalation engine
|
||||
|
||||
Escalation is **rule-driven**, not `if L1 then L2`.
|
||||
|
||||
Example rule:
|
||||
|
||||
```
|
||||
IF resolution SLA breached AND priority = critical
|
||||
THEN move to configured escalation node, notify manager, create escalation event
|
||||
```
|
||||
|
||||
### Escalation triggers
|
||||
- First response breach
|
||||
- Resolution breach
|
||||
- Investigation breach
|
||||
- Inactivity
|
||||
- Priority increase
|
||||
- Customer escalation request
|
||||
- Repeated reopen
|
||||
- Manual escalation
|
||||
- Product defect identified
|
||||
- External dependency timeout
|
||||
- Critical incident
|
||||
|
||||
**All escalation events must be auditable.**
|
||||
|
||||
## 7. End-to-end human support flow
|
||||
|
||||
```
|
||||
Ticket → Orchestration → Capability → Support Hierarchy → Team
|
||||
→ Eligible Agents → Assignment → SLA
|
||||
→ Investigation → Root Cause → Solution → Verification
|
||||
→ Resolution → Closure
|
||||
```
|
||||
|
||||
Re-escalation when an agent can't solve it:
|
||||
|
||||
```
|
||||
Current Support Node → Evaluate escalation rules → Target Support Node
|
||||
→ Target Team → Availability → Assignment → Continue SLA
|
||||
```
|
||||
|
||||
## 8. Module implication
|
||||
|
||||
Because this subsystem contains genuine decision logic (not just CRUD), the `orchestration` module needs the extended internal structure — `engine/`, `rules/`, `strategies/`, `calculators/` — in addition to the standard controller/service/repository layers. See [07 — Backend Architecture](./07-backend-architecture.md#module-internal-structure).
|
||||
@@ -0,0 +1,549 @@
|
||||
# 06 — Database Schema
|
||||
|
||||
**Primary database:** PostgreSQL. **ORM:** Prisma. All schema below is conceptual/pseudo-Prisma — refine field types and add indexes during Phase 1 modeling (see [10 — Implementation Roadmap](./10-implementation-roadmap.md)).
|
||||
|
||||
Cross-cutting requirements for every table below:
|
||||
- Migrations tracked in version control
|
||||
- Indexes on every foreign key and every field used in ticket/queue filtering
|
||||
- Unique constraints where the spec implies natural keys (e.g. `productId` + credential)
|
||||
- Optimistic or transactional concurrency control wherever two actors could race (assignment, SLA state, hierarchy edits)
|
||||
- `createdAt`/`updatedAt` on every table; soft-delete or status field where records must never disappear (audit, escalation events)
|
||||
|
||||
---
|
||||
|
||||
## Domain: Integration / Catalog
|
||||
|
||||
```prisma
|
||||
model Product {
|
||||
id String @id @default(cuid())
|
||||
externalProductId String @unique // reference into SaaS, not authoritative
|
||||
name String
|
||||
supportEnabled Boolean @default(true)
|
||||
status String // active | suspended | deprecated
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
integration ProductIntegration?
|
||||
knowledgeEntries KnowledgeEntry[]
|
||||
runbooks Runbook[]
|
||||
tickets Ticket[]
|
||||
}
|
||||
|
||||
model ProductIntegration {
|
||||
id String @id @default(cuid())
|
||||
productId String @unique
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
credentialRef String // pointer into secret manager, never the raw secret
|
||||
authMechanism String // signed_token | oauth2_client_credentials | mtls
|
||||
allowedScope Json // structured scope definition
|
||||
rotatedAt DateTime?
|
||||
revokedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model CustomerReference {
|
||||
id String @id @default(cuid())
|
||||
externalUserId String
|
||||
externalTenantId String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
@@unique([externalUserId, externalTenantId])
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Ticketing
|
||||
|
||||
```prisma
|
||||
model Ticket {
|
||||
id String @id @default(cuid())
|
||||
code String @unique // e.g. DQB-2026-00567
|
||||
productId String
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
problemId String
|
||||
problem Problem @relation(fields: [problemId], references: [id])
|
||||
externalUserId String
|
||||
externalTenantId String
|
||||
status String // NEW, AI_ANALYZING, AI_TROUBLESHOOTING, AI_VERIFYING,
|
||||
// AI_RESOLVED, HUMAN_ESCALATION, IN_PROGRESS,
|
||||
// WAITING_FOR_CUSTOMER, RESOLUTION_PENDING_CUSTOMER,
|
||||
// RESOLVED, CLOSED, REOPENED
|
||||
priority String
|
||||
severity String
|
||||
categoryId String?
|
||||
problemTypeId String?
|
||||
assignmentId String?
|
||||
slaRunId String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
messages TicketMessage[]
|
||||
attachments TicketAttachment[]
|
||||
aiSessions AISupportSession[]
|
||||
assignments Assignment[]
|
||||
escalationEvents EscalationEvent[]
|
||||
}
|
||||
|
||||
model Problem {
|
||||
id String @id @default(cuid())
|
||||
statement String
|
||||
symptoms String
|
||||
impact String?
|
||||
productId String
|
||||
featureId String?
|
||||
categoryId String?
|
||||
problemTypeId String?
|
||||
severity String
|
||||
customerImpact String?
|
||||
businessImpact String?
|
||||
environment String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
tickets Ticket[]
|
||||
investigations Investigation[]
|
||||
rootCauses RootCause[]
|
||||
solutions Solution[]
|
||||
}
|
||||
|
||||
model TicketMessage {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id])
|
||||
type String // CUSTOMER_MESSAGE, AI_MESSAGE, AGENT_MESSAGE, INTERNAL_NOTE,
|
||||
// SYSTEM_EVENT, INVESTIGATION_NOTE, SOLUTION_NOTE
|
||||
authorRef String // agentId, "ai", or externalUserId
|
||||
body String
|
||||
visibleToCustomer Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model TicketAttachment {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id])
|
||||
storageKey String // S3/MinIO object key, not the file itself
|
||||
fileName String
|
||||
mimeType String
|
||||
sizeBytes Int
|
||||
scanStatus String // pending | clean | infected | rejected
|
||||
uploadedBy String
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Category / Problem Type / Priority
|
||||
|
||||
```prisma
|
||||
model Category { id String @id @default(cuid()) name String productId String? active Boolean @default(true) }
|
||||
model ProblemType { id String @id @default(cuid()) name String categoryId String? active Boolean @default(true) }
|
||||
model PriorityPolicy {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
productId String?
|
||||
categoryId String?
|
||||
rules Json // structured priority derivation rules
|
||||
active Boolean @default(true)
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Support Hierarchy / Teams / Agents
|
||||
|
||||
```prisma
|
||||
model HierarchyNode {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
parentId String?
|
||||
parent HierarchyNode? @relation("HierarchyTree", fields: [parentId], references: [id])
|
||||
children HierarchyNode[] @relation("HierarchyTree")
|
||||
order Int
|
||||
teamId String?
|
||||
skills String[]
|
||||
productScope String[]
|
||||
categoryScope String[]
|
||||
priorityScope String[]
|
||||
assignmentStrategy String
|
||||
slaPolicyId String?
|
||||
escalationPolicyId String?
|
||||
entryConditions Json?
|
||||
exitConditions Json?
|
||||
active Boolean @default(true)
|
||||
}
|
||||
|
||||
model Team {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
active Boolean @default(true)
|
||||
agents Agent[]
|
||||
}
|
||||
|
||||
model Agent {
|
||||
id String @id @default(cuid())
|
||||
teamId String
|
||||
team Team @relation(fields: [teamId], references: [id])
|
||||
name String
|
||||
active Boolean @default(true)
|
||||
skills AgentSkill[]
|
||||
availability AgentAvailability?
|
||||
}
|
||||
|
||||
model AgentSkill {
|
||||
id String @id @default(cuid())
|
||||
agentId String
|
||||
agent Agent @relation(fields: [agentId], references: [id])
|
||||
skillTag String
|
||||
level Int // proficiency, used by SKILL_BASED strategy
|
||||
}
|
||||
|
||||
model AgentAvailability {
|
||||
id String @id @default(cuid())
|
||||
agentId String @unique
|
||||
agent Agent @relation(fields: [agentId], references: [id])
|
||||
status String // available | busy | away | offline
|
||||
workingHours Json // per business calendar
|
||||
currentLoad Int @default(0)
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Assignment
|
||||
|
||||
```prisma
|
||||
model Assignment {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id])
|
||||
agentId String
|
||||
strategy String
|
||||
assignedAt DateTime @default(now())
|
||||
unassignedAt DateTime?
|
||||
reason String?
|
||||
}
|
||||
|
||||
model AssignmentHistory {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
agentId String?
|
||||
action String // assigned | reassigned | unassigned
|
||||
strategy String
|
||||
reason String?
|
||||
actor String // system | agentId | adminId
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: SLA
|
||||
|
||||
```prisma
|
||||
model SLAPolicy {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
productId String?
|
||||
categoryId String?
|
||||
problemTypeId String?
|
||||
priority String?
|
||||
firstResponseMinutes Int
|
||||
investigationMinutes Int?
|
||||
resolutionMinutes Int
|
||||
customerResponseMinutes Int?
|
||||
businessCalendarId String?
|
||||
active Boolean @default(true)
|
||||
}
|
||||
|
||||
model SLARun {
|
||||
id String @id @default(cuid())
|
||||
ticketId String @unique
|
||||
policyId String
|
||||
firstResponseDueAt DateTime?
|
||||
resolutionDueAt DateTime?
|
||||
status String // running | paused | warning | breached | completed
|
||||
pausedAt DateTime?
|
||||
resumedAt DateTime?
|
||||
breachedAt DateTime?
|
||||
completedAt DateTime?
|
||||
}
|
||||
|
||||
model BusinessCalendar {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
timezone String
|
||||
workingHours Json
|
||||
holidays Holiday[]
|
||||
}
|
||||
|
||||
model Holiday {
|
||||
id String @id @default(cuid())
|
||||
calendarId String
|
||||
calendar BusinessCalendar @relation(fields: [calendarId], references: [id])
|
||||
date DateTime
|
||||
description String?
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Escalation
|
||||
|
||||
```prisma
|
||||
model EscalationPolicy {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
productId String?
|
||||
active Boolean @default(true)
|
||||
rules EscalationRule[]
|
||||
}
|
||||
|
||||
model EscalationRule {
|
||||
id String @id @default(cuid())
|
||||
policyId String
|
||||
policy EscalationPolicy @relation(fields: [policyId], references: [id])
|
||||
triggerType String // first_response_breach | resolution_breach | inactivity |
|
||||
// priority_increase | customer_escalation | repeated_reopen |
|
||||
// manual | product_defect | dependency_timeout | critical_incident
|
||||
condition Json
|
||||
targetNodeId String
|
||||
notify Json // who/how to notify
|
||||
active Boolean @default(true)
|
||||
}
|
||||
|
||||
model EscalationEvent {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id])
|
||||
ruleId String?
|
||||
fromNodeId String?
|
||||
toNodeId String?
|
||||
reason String
|
||||
triggeredBy String // system | agentId | customer
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Problem Resolution
|
||||
|
||||
```prisma
|
||||
model Investigation {
|
||||
id String @id @default(cuid())
|
||||
problemId String
|
||||
problem Problem @relation(fields: [problemId], references: [id])
|
||||
investigator String
|
||||
findings Json
|
||||
evidence Json?
|
||||
internalNotes String?
|
||||
status String // open | complete
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model RootCause {
|
||||
id String @id @default(cuid())
|
||||
problemId String
|
||||
problem Problem @relation(fields: [problemId], references: [id])
|
||||
type String // technical | configuration | external_dependency | business | contributing_factor
|
||||
description String
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Solution {
|
||||
id String @id @default(cuid())
|
||||
problemId String
|
||||
problem Problem @relation(fields: [problemId], references: [id])
|
||||
proposed String
|
||||
approved Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
implementation SolutionImplementation?
|
||||
verification SolutionVerification?
|
||||
}
|
||||
|
||||
model SolutionImplementation {
|
||||
id String @id @default(cuid())
|
||||
solutionId String @unique
|
||||
solution Solution @relation(fields: [solutionId], references: [id])
|
||||
notes String?
|
||||
implementedBy String
|
||||
implementedAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model SolutionVerification {
|
||||
id String @id @default(cuid())
|
||||
solutionId String @unique
|
||||
solution Solution @relation(fields: [solutionId], references: [id])
|
||||
method String // automated | technical_test | customer_confirmation | agent_confirmation
|
||||
result String // success | failed
|
||||
evidence Json?
|
||||
verifiedAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Resolution {
|
||||
id String @id @default(cuid())
|
||||
ticketId String @unique
|
||||
outcome String
|
||||
resolvedBy String // "ai" | agentId
|
||||
resolvedAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: AI Support
|
||||
|
||||
```prisma
|
||||
model AISupportSession {
|
||||
id String @id @default(cuid())
|
||||
ticketId String
|
||||
ticket Ticket @relation(fields: [ticketId], references: [id])
|
||||
status String // analyzing | troubleshooting | verifying | resolved | escalated
|
||||
startedAt DateTime @default(now())
|
||||
endedAt DateTime?
|
||||
|
||||
diagnoses AIDiagnosis[]
|
||||
interactions AIInteraction[]
|
||||
actions AIAction[]
|
||||
knowledgeRefs AIKnowledgeReference[]
|
||||
}
|
||||
|
||||
model AIDiagnosis {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session AISupportSession @relation(fields: [sessionId], references: [id])
|
||||
product String
|
||||
feature String?
|
||||
problemType String
|
||||
severity String
|
||||
confidence Float
|
||||
possibleCauses String[]
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model AIInteraction {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session AISupportSession @relation(fields: [sessionId], references: [id])
|
||||
role String // customer | ai
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model AIRunbook {
|
||||
id String @id @default(cuid())
|
||||
key String // e.g. PDF_HTML_CONVERSION_FAILURE
|
||||
productId String
|
||||
steps Json // ordered, versioned step definitions
|
||||
active Boolean @default(true)
|
||||
}
|
||||
|
||||
model AIAction {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session AISupportSession @relation(fields: [sessionId], references: [id])
|
||||
toolName String
|
||||
input Json
|
||||
riskLevel String
|
||||
approvedBy String? // system-policy | agentId, when human approval required
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
result AIActionResult?
|
||||
}
|
||||
|
||||
model AIActionResult {
|
||||
id String @id @default(cuid())
|
||||
actionId String @unique
|
||||
action AIAction @relation(fields: [actionId], references: [id])
|
||||
output Json
|
||||
status String // success | failed
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model AIKnowledgeReference {
|
||||
id String @id @default(cuid())
|
||||
sessionId String
|
||||
session AISupportSession @relation(fields: [sessionId], references: [id])
|
||||
knowledgeId String
|
||||
relevanceScore Float?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Knowledge
|
||||
|
||||
```prisma
|
||||
model KnowledgeEntry {
|
||||
id String @id @default(cuid())
|
||||
code String @unique // e.g. KB-DQ-102
|
||||
productId String
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
feature String?
|
||||
type String // known_issue | faq | resolution_procedure | operations
|
||||
problem String?
|
||||
symptoms String?
|
||||
errorCode String?
|
||||
cause String?
|
||||
recommendedSolution String?
|
||||
verificationSteps String?
|
||||
escalationGuidance String?
|
||||
version Int @default(1)
|
||||
status String // draft | published | unpublished
|
||||
effectiveDate DateTime?
|
||||
categoryScope String[]
|
||||
validationStatus String // unvalidated | validated
|
||||
owner String?
|
||||
lastReview DateTime?
|
||||
source String?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model KnownIssue {
|
||||
id String @id @default(cuid())
|
||||
productId String
|
||||
errorCodeId String?
|
||||
description String
|
||||
status String
|
||||
}
|
||||
|
||||
model ErrorCode {
|
||||
id String @id @default(cuid())
|
||||
code String @unique // e.g. LAYOUT_PARSE_042
|
||||
productId String
|
||||
description String
|
||||
}
|
||||
|
||||
model Runbook {
|
||||
id String @id @default(cuid())
|
||||
key String
|
||||
productId String
|
||||
product Product @relation(fields: [productId], references: [id])
|
||||
steps Json
|
||||
version Int @default(1)
|
||||
active Boolean @default(true)
|
||||
}
|
||||
```
|
||||
|
||||
## Domain: Platform
|
||||
|
||||
```prisma
|
||||
model Notification {
|
||||
id String @id @default(cuid())
|
||||
recipientRef String
|
||||
channel String // in_app | email | push
|
||||
event String
|
||||
payload Json
|
||||
status String // queued | sent | failed
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model AuditLog {
|
||||
id String @id @default(cuid())
|
||||
actor String
|
||||
actorType String // customer | agent | admin | system | ai
|
||||
action String
|
||||
entityType String
|
||||
entityId String
|
||||
oldValue Json?
|
||||
newValue Json?
|
||||
reason String?
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now())
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes on modeling decisions
|
||||
|
||||
- **`Ticket` vs `Problem` are always separate tables** with a many-tickets-to-one-problem relationship, per [04](./04-ticketing-and-problem-management.md#2-problem-is-first-class--separate-from-ticket).
|
||||
- **`Investigation`, `RootCause`, `Solution`, `SolutionVerification`, `Resolution` are five distinct models**, not one "resolution notes" text field — this is intentional per the spec and enables reporting on each stage independently.
|
||||
- **`AuditLog` should be append-only** at the application layer: no update/delete code paths against this table, ever.
|
||||
- **SLA timing must never be computed from `SLARun.createdAt` alone** — always resolve through the linked `BusinessCalendar`/`Holiday` records at read time or via a durable recompute job.
|
||||
@@ -0,0 +1,229 @@
|
||||
# 07 — Backend Architecture
|
||||
|
||||
## 1. Technology stack
|
||||
|
||||
- Node.js + TypeScript
|
||||
- Fastify
|
||||
- PostgreSQL + Prisma
|
||||
- Redis + BullMQ
|
||||
- Pino (structured logging)
|
||||
- OpenAPI
|
||||
- Zod (validation)
|
||||
- Vitest
|
||||
- Docker
|
||||
|
||||
**Architecture style:** modular monolith. Do not start with microservices — the module boundaries below make a future split possible, but premature service decomposition adds operational cost this system doesn't need yet.
|
||||
|
||||
## 2. Top-level source layout
|
||||
|
||||
```
|
||||
src/
|
||||
├── config
|
||||
├── bootstrap
|
||||
├── plugins
|
||||
├── common
|
||||
├── infrastructure
|
||||
├── modules
|
||||
├── events
|
||||
├── jobs
|
||||
└── api
|
||||
```
|
||||
|
||||
## 3. Domain module groups
|
||||
|
||||
```
|
||||
modules/
|
||||
├── identity
|
||||
│ ├── auth
|
||||
│ ├── customers
|
||||
│ ├── agents
|
||||
│ └── teams
|
||||
│
|
||||
├── catalog
|
||||
│ ├── products
|
||||
│ ├── categories
|
||||
│ ├── problem-types
|
||||
│ └── priorities
|
||||
│
|
||||
├── ticketing
|
||||
│ ├── tickets
|
||||
│ ├── messages
|
||||
│ └── attachments
|
||||
│
|
||||
├── problem-management
|
||||
│ ├── problems
|
||||
│ ├── investigation
|
||||
│ ├── root-causes
|
||||
│ ├── solutions
|
||||
│ ├── verification
|
||||
│ └── resolutions
|
||||
│
|
||||
├── ai-support
|
||||
│ ├── agents
|
||||
│ ├── sessions
|
||||
│ ├── diagnosis
|
||||
│ ├── knowledge
|
||||
│ ├── troubleshooting
|
||||
│ ├── tools
|
||||
│ ├── tool-execution
|
||||
│ ├── verification
|
||||
│ └── escalation
|
||||
│
|
||||
├── orchestration
|
||||
│ ├── hierarchy
|
||||
│ ├── routing
|
||||
│ ├── orchestration
|
||||
│ ├── assignments
|
||||
│ ├── sla
|
||||
│ └── escalation
|
||||
│
|
||||
└── platform
|
||||
├── notifications
|
||||
├── audit
|
||||
├── business-calendars
|
||||
├── integrations
|
||||
├── reports
|
||||
└── admin
|
||||
```
|
||||
|
||||
> Note: `identity` here means SupportHub's own agent/team/support-domain identity — **not** a re-implementation of SaaS user/tenant identity. See [01](./01-product-vision-and-principles.md#4-system-ownership-boundary) and [02](./02-integration-and-security.md#5-rbac-boundary).
|
||||
|
||||
## 4. Module internal structure
|
||||
|
||||
Standard module:
|
||||
|
||||
```
|
||||
module/
|
||||
├── controller/
|
||||
├── routes/
|
||||
├── schema/
|
||||
├── repository/
|
||||
├── service/
|
||||
├── types/
|
||||
├── mapper/
|
||||
├── constants/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Complex modules (real decision logic, not just CRUD) add:
|
||||
|
||||
```
|
||||
├── engine/
|
||||
├── rules/
|
||||
├── strategies/
|
||||
└── calculators/
|
||||
```
|
||||
|
||||
Example — `orchestration`:
|
||||
|
||||
```
|
||||
orchestration/
|
||||
├── controller
|
||||
├── routes
|
||||
├── schema
|
||||
├── repository
|
||||
├── service
|
||||
├── engine
|
||||
├── rules
|
||||
├── types
|
||||
├── mapper
|
||||
├── constants
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
`ai-support` and `orchestration` are the two module groups most likely to need the extended structure across nearly all their submodules — see [03](./03-ai-support-architecture.md) and [05](./05-orchestration-sla-escalation.md).
|
||||
|
||||
## 5. Request flow
|
||||
|
||||
```
|
||||
HTTP → Route → Schema validation → Controller → Service
|
||||
→ Engine/Rules (if required) → Repository → Prisma → PostgreSQL
|
||||
```
|
||||
|
||||
Rules:
|
||||
- **Controller never touches Prisma directly.**
|
||||
- **Repository** is the only layer that talks to Prisma.
|
||||
- **Service** coordinates business workflows and calls repositories/engines.
|
||||
- **Engine** implements complex decision logic (assignment strategy selection, SLA calculation, escalation rule evaluation, AI tool-execution policy).
|
||||
|
||||
## 6. Module boundaries
|
||||
|
||||
Modules must not reach into another module's internals. Only import through the target module's public `index.ts`.
|
||||
|
||||
```ts
|
||||
// Allowed
|
||||
import { TicketService } from "@/modules/ticketing/tickets";
|
||||
|
||||
// Not allowed — reaches past the module boundary
|
||||
import { TicketRepository } from "@/modules/ticketing/tickets/repository/ticket.repository";
|
||||
```
|
||||
|
||||
## 7. Redis / BullMQ usage
|
||||
|
||||
Redis is **not** a source of truth — it's for queues, caching, and coordination. Use BullMQ jobs for:
|
||||
|
||||
- SLA monitoring (warning, breach detection)
|
||||
- Escalation triggering
|
||||
- Notifications
|
||||
- AI background work where appropriate (long-running tool calls, batch re-diagnosis)
|
||||
- Analytics rollups
|
||||
- Attachment processing (malware scan, thumbnailing)
|
||||
- Cleanup jobs
|
||||
|
||||
**Jobs must be durable and idempotent.** Never use `setTimeout` or any in-memory timer for production SLA enforcement — a process restart must not lose or double-fire SLA state transitions.
|
||||
|
||||
## 8. Domain events
|
||||
|
||||
Emit and consume these as first-class domain events (not just side effects buried in service code), so audit, notifications, analytics, and SLA/escalation subsystems can all react independently:
|
||||
|
||||
```
|
||||
TicketCreated, ProblemCreated, TicketClassified
|
||||
AIAnalysisStarted, KnowledgeRetrieved, AIDiagnosisCompleted
|
||||
AIActionRequested, AIActionCompleted, AITroubleshootingStarted
|
||||
AIResolutionVerified, TicketEscalatedToHuman
|
||||
TicketAssigned, TicketReassigned, PriorityChanged
|
||||
SLANearingBreach, SLABreached
|
||||
InvestigationStarted, RootCauseIdentified
|
||||
SolutionProposed, SolutionImplemented, VerificationCompleted
|
||||
TicketResolved, TicketClosed, TicketReopened
|
||||
```
|
||||
|
||||
Events must be traceable (correlation ID) and auditable.
|
||||
|
||||
## 9. Notifications
|
||||
|
||||
Channels: in-app, email, push (where appropriate). Triggered asynchronously (via job queue, never inline in the request path) on: ticket created, AI solved, human escalation, assignment, agent reply, SLA warning, SLA breach, escalation, resolution, closure, reopen.
|
||||
|
||||
## 10. Audit
|
||||
|
||||
Audit every important action: ticket creation, AI escalation, assignment/reassignment, priority changes, hierarchy changes, SLA changes, escalation, investigation, root cause, solution, verification, resolution, closure.
|
||||
|
||||
Audit record shape:
|
||||
|
||||
```ts
|
||||
interface AuditRecord {
|
||||
actor: string;
|
||||
actorType: "customer" | "agent" | "admin" | "system" | "ai";
|
||||
action: string;
|
||||
entity: string;
|
||||
entityId: string;
|
||||
oldValue?: unknown;
|
||||
newValue?: unknown;
|
||||
timestamp: Date;
|
||||
reason?: string;
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
```
|
||||
|
||||
Security-relevant audit records should be **append-only** from the application's perspective — no service-layer update/delete path against `AuditLog`.
|
||||
|
||||
## 11. Observability endpoints
|
||||
|
||||
```
|
||||
GET /health
|
||||
GET /health/live
|
||||
GET /health/ready
|
||||
GET /metrics
|
||||
```
|
||||
|
||||
Structured logging via Pino, with request ID and correlation ID on every log line; metrics and tracing wired through from day one, not bolted on later. Full metric list is in [09](./09-testing-observability-cicd.md#observability).
|
||||
@@ -0,0 +1,148 @@
|
||||
# 08 — Frontend Architecture
|
||||
|
||||
## 1. Technology stack
|
||||
|
||||
Next.js (App Router) · TypeScript · Tailwind CSS · shadcn/ui-style components · Lucide icons · TanStack Query · Zustand (where needed) · React Hook Form · Zod · Playwright · Vitest
|
||||
|
||||
## 2. Frontend source structure
|
||||
|
||||
```
|
||||
src/app
|
||||
src/features
|
||||
src/components
|
||||
src/lib
|
||||
src/hooks
|
||||
src/stores
|
||||
src/providers
|
||||
src/types
|
||||
src/constants
|
||||
src/theme
|
||||
src/styles
|
||||
```
|
||||
|
||||
Route groups:
|
||||
|
||||
```
|
||||
(customer)
|
||||
(support)
|
||||
(admin)
|
||||
(public)
|
||||
```
|
||||
|
||||
Feature modules are self-contained:
|
||||
|
||||
```
|
||||
features/tickets/
|
||||
├── api
|
||||
├── components
|
||||
├── hooks
|
||||
├── schemas
|
||||
├── types
|
||||
├── constants
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
**Do not create giant global business components** — logic and UI for a feature live inside that feature's folder.
|
||||
|
||||
## 3. Customer frontend
|
||||
|
||||
Lives inside the SaaS/product context — the customer never leaves their product to get support.
|
||||
|
||||
**Support Center** is the main surface, with areas:
|
||||
- AI Support
|
||||
- My Cases / Tickets
|
||||
- Support History
|
||||
- Optional resources
|
||||
|
||||
Primary journey:
|
||||
|
||||
```
|
||||
Problem → AI analysis → Knowledge found → Guided steps → Customer action
|
||||
→ Verification → Resolved
|
||||
(if unresolved) → Human Support
|
||||
```
|
||||
|
||||
### Support Center home
|
||||
|
||||
Communicates: *"How can we help you?"* The customer can describe a problem, start AI support, view existing cases, or see an active case. A case/ticket card shows: case ID, problem, product, current stage, progress, AI status, and human-support status when applicable.
|
||||
|
||||
### AI Support UI — not a ChatGPT clone
|
||||
|
||||
The interface must visibly communicate each stage, using clear cards/progress indicators, not just a scrolling chat log:
|
||||
|
||||
1. Problem understanding
|
||||
2. Product analysis
|
||||
3. Knowledge search
|
||||
4. Diagnosis
|
||||
5. Recommended solution
|
||||
6. Guided steps
|
||||
7. Customer action
|
||||
8. Verification
|
||||
9. Resolve or escalate
|
||||
|
||||
Example card content:
|
||||
|
||||
```
|
||||
AI analyzed: PDF conversion failure
|
||||
Problem detected: LAYOUT_PARSE_042
|
||||
Likely cause: Layout parser failure
|
||||
Recommended: Enable fallback parser
|
||||
|
||||
Guided steps:
|
||||
1. Open Conversion Settings
|
||||
2. Open Advanced
|
||||
3. Enable fallback parser
|
||||
4. Retry conversion
|
||||
5. Verify output
|
||||
|
||||
[ I completed this step ] [ I need help ] [ Problem solved ] [ Not solved ]
|
||||
```
|
||||
|
||||
### What the customer never sees
|
||||
|
||||
Internal support hierarchy, internal assignment algorithms, agent workload, internal escalation rules, internal notes, internal routing logic.
|
||||
|
||||
## 4. Support agent frontend (internal)
|
||||
|
||||
A distinct experience from the customer app. Main areas:
|
||||
|
||||
- Dashboard
|
||||
- My Queue
|
||||
- All Tickets
|
||||
- Problems
|
||||
- SLA Monitoring
|
||||
- Escalations
|
||||
- Knowledge
|
||||
- Reports
|
||||
|
||||
**Agent ticket workspace** shows: customer, tenant, product, problem, AI summary, diagnosis, troubleshooting history, conversation, investigation, root cause, solution, verification, resolution, SLA, assignment, escalation history.
|
||||
|
||||
**Critical UX requirement:** the agent continues from the AI's context — they never restart diagnosis from zero. The AI hand-off summary (see [03](./03-ai-support-architecture.md#10-escalation-trigger-conditions-ai--human)) should be the first thing the agent reads.
|
||||
|
||||
## 5. Admin frontend
|
||||
|
||||
Configuration surface. Areas: Products, Categories, Problem Types, Priorities, Support Hierarchy, Teams, Agents, Skills, Routing Rules, Assignment Rules, SLA Policies, Escalation Policies, Knowledge, Runbooks, Reports, Audit, Settings.
|
||||
|
||||
**None of these configuration values may be hardcoded** in frontend or backend source — the admin UI is how the business actually changes behavior.
|
||||
|
||||
## 6. Real-time updates
|
||||
|
||||
Use WebSocket or SSE so the customer/agent sees updates without refreshing:
|
||||
|
||||
- AI analyzing
|
||||
- AI found knowledge
|
||||
- AI generated solution
|
||||
- AI waiting for customer
|
||||
- Ticket assigned
|
||||
- Agent replied
|
||||
- SLA warning / SLA breached
|
||||
- Escalation
|
||||
- Ticket resolved
|
||||
|
||||
## 7. UX principle recap by persona
|
||||
|
||||
| Persona | Principle |
|
||||
|---|---|
|
||||
| Customer | Simple, guided, trustworthy, product-aware |
|
||||
| Agent | Information-dense, fast, operational, context-rich |
|
||||
| Admin | Configurable, visual, rule-driven, auditable |
|
||||
@@ -0,0 +1,97 @@
|
||||
# 09 — Testing, Observability & CI/CD
|
||||
|
||||
## 1. Testing strategy
|
||||
|
||||
### Backend
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
- E2E tests
|
||||
- Concurrency tests (assignment race conditions — two tickets assigned simultaneously must never corrupt round-robin state or double-assign)
|
||||
- SLA tests (pause/resume correctness, business-calendar math, durability across a simulated process restart)
|
||||
- Escalation idempotency tests (a rule firing twice must not create duplicate escalation events)
|
||||
- Orchestration tests (capability matching, hierarchy traversal, strategy selection)
|
||||
- AI tool permission tests (the AI must never be able to invoke a tool it isn't scoped for; high-risk tools must require policy/approval regardless of AI confidence)
|
||||
|
||||
### Frontend
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
- Playwright E2E, covering:
|
||||
- AI support flow
|
||||
- Customer escalation flow
|
||||
- Agent flow
|
||||
- Admin configuration flow
|
||||
|
||||
### Critical end-to-end scenarios (must both exist as automated tests)
|
||||
|
||||
**Scenario A — AI resolves directly:**
|
||||
```
|
||||
Customer → Product → Support → Problem → AI → Knowledge
|
||||
→ Guided troubleshooting → Verification → AI resolved
|
||||
```
|
||||
|
||||
**Scenario B — AI escalates to human:**
|
||||
```
|
||||
Customer → Problem → AI → troubleshooting failed → human escalation
|
||||
→ orchestration → assignment → SLA → investigation → solution
|
||||
→ verification → resolution → closure
|
||||
```
|
||||
|
||||
## 2. Observability
|
||||
|
||||
### Logging
|
||||
Pino structured logging across the backend, with a request ID and correlation ID attached to every log line so a single ticket's full journey (AI session → tool calls → escalation → assignment → SLA events) can be traced end to end.
|
||||
|
||||
### Metrics & tracing
|
||||
Wire metrics and tracing in from the start, not retrofitted. Expose:
|
||||
|
||||
```
|
||||
GET /health
|
||||
GET /health/live
|
||||
GET /health/ready
|
||||
GET /metrics
|
||||
```
|
||||
|
||||
### Key metrics to track
|
||||
|
||||
- AI resolution rate
|
||||
- AI escalation rate
|
||||
- Human resolution rate
|
||||
- Average resolution time
|
||||
- First response time
|
||||
- SLA compliance
|
||||
- Escalation rate
|
||||
- Recurring problems
|
||||
- Most common errors
|
||||
- Knowledge effectiveness
|
||||
- Tool failure rate
|
||||
|
||||
### Reporting dashboards
|
||||
|
||||
| Dashboard | Contents |
|
||||
|---|---|
|
||||
| **Management** | Total cases, AI resolved, human escalated, resolved, open, SLA compliance, SLA breaches, escalation count, average response, average resolution |
|
||||
| **Product** | Support volume by product, problem types, recurring problems, AI resolution rate, human escalation rate, top errors |
|
||||
| **Support** | Workload, agent assignments, SLA risk, escalations, response performance, resolution performance |
|
||||
| **AI** | AI resolution rate, failed troubleshooting, knowledge match rate, confidence distribution, tool success/failure, human handoff rate |
|
||||
|
||||
## 3. CI/CD (Jenkins)
|
||||
|
||||
Repository includes a `Jenkinsfile` implementing:
|
||||
|
||||
```
|
||||
Checkout
|
||||
→ Install
|
||||
→ Environment validation
|
||||
→ Typecheck
|
||||
→ Lint
|
||||
→ Format check
|
||||
→ Unit test
|
||||
→ Integration test
|
||||
→ E2E test
|
||||
→ Build
|
||||
→ Docker build
|
||||
→ Publish
|
||||
→ Deploy
|
||||
```
|
||||
|
||||
Production deployments use **protected Jenkins credentials/environment variables** — real secrets are never committed to the repository (see [02](./02-integration-and-security.md#7-environment--secrets-handling)).
|
||||
@@ -0,0 +1,82 @@
|
||||
# 10 — Implementation Roadmap
|
||||
|
||||
Implement incrementally. **Do not implement all business logic in one step.** Each phase below must be typed, tested, documented, integrated, observable, and production-safe before moving on — a feature isn't "done" until it clears all seven of those, not just "coded."
|
||||
|
||||
## Phased plan
|
||||
|
||||
| Phase | Focus | Primary deliverables |
|
||||
|---|---|---|
|
||||
| **1** | Engineering foundation | Repo scaffolding, Fastify modular-monolith skeleton, Next.js app skeleton, Prisma schema baseline, CI pipeline skeleton, env validation, health endpoints |
|
||||
| **2** | SaaS integration | Product/ProductIntegration models, credential validation, service-to-service auth (signed tokens/OAuth2/mTLS), inbound request contract, rate limiting |
|
||||
| **3** | Product knowledge | Knowledge/KnownIssue/ErrorCode/Runbook models, admin CRUD, versioning + publish state, retrieval (RAG) layer |
|
||||
| **4** | AI support | AI session/diagnosis/interaction models, classification, RAG-backed reasoning, confidence thresholds (configurable), tool system with permission/risk gating, runbook engine, verification logic |
|
||||
| **5** | Ticketing | Ticket + Problem models (kept separate), message types, attachment pipeline (object storage, scanning, expiring URLs), ticket lifecycle state machine |
|
||||
| **6** | Support organization | Team/Agent/AgentSkill/AgentAvailability models, dynamic HierarchyNode configuration, admin hierarchy editor |
|
||||
| **7** | Orchestration and assignment | Orchestration engine, capability matching, pluggable assignment strategies, concurrency-safe round robin, assignment history |
|
||||
| **8** | SLA and escalation | SLA policy engine, business calendar/holiday support, durable pause/resume via BullMQ, rule-driven escalation engine, escalation event audit |
|
||||
| **9** | Problem resolution | Investigation/RootCause/Solution/SolutionImplementation/SolutionVerification/Resolution models and workflows, customer confirmation + reopen flow |
|
||||
| **10** | Agent/Admin UI | Agent workspace (continues from AI context), admin configuration surfaces for every configurable subsystem above |
|
||||
| **11** | Analytics, hardening, security, production deployment | Reporting dashboards, full observability, security hardening pass, load/concurrency testing, production deployment pipeline |
|
||||
|
||||
> Note the dependency direction: Phase 4 (AI) and Phase 9 (resolution stages) both plug into Phase 5's ticket, so ticketing's core data model should be stable before AI or resolution logic is built against it — even though ticketing is listed after AI support here, expect to iterate the `Ticket`/`Problem` shape lightly across phases 4–9 rather than treating phase 5 as strictly sequential.
|
||||
|
||||
## Success criteria checklist
|
||||
|
||||
Use this as the actual go/no-go list, not phase names — a phase can be "complete" on paper while missing several of these.
|
||||
|
||||
- [ ] A SaaS product can securely integrate with SupportHub
|
||||
- [ ] The SaaS user can enter support from within the product
|
||||
- [ ] SupportHub receives trusted product/tenant/user context
|
||||
- [ ] A problem creates a durable support case immediately
|
||||
- [ ] AI understands the problem
|
||||
- [ ] AI retrieves correct product knowledge
|
||||
- [ ] AI can diagnose known issues
|
||||
- [ ] AI can guide the customer through supported troubleshooting
|
||||
- [ ] The system verifies successful resolution with evidence
|
||||
- [ ] AI can resolve supported issues automatically
|
||||
- [ ] Unresolved issues are escalated automatically
|
||||
- [ ] AI context is preserved in the ticket for the human agent
|
||||
- [ ] Orchestration chooses the correct support path
|
||||
- [ ] Capability/skill matching works correctly
|
||||
- [ ] Assignment respects availability/workload
|
||||
- [ ] SLA is applied correctly (calendar-aware, durable)
|
||||
- [ ] Escalation occurs according to configured policy
|
||||
- [ ] Human agents receive full context, don't restart diagnosis
|
||||
- [ ] Agents can investigate and resolve the problem
|
||||
- [ ] Resolution is verified and recorded
|
||||
- [ ] Customer sees the final result
|
||||
- [ ] Complete audit history exists
|
||||
- [ ] All critical operations are observable
|
||||
- [ ] CI/CD can validate and deploy the system safely
|
||||
|
||||
## Open business decisions (do not invent final values)
|
||||
|
||||
Anything the business hasn't finalized yet must be explicitly marked in code, config schema, and documentation as one of:
|
||||
|
||||
```
|
||||
CONFIGURABLE
|
||||
OPEN BUSINESS DECISION
|
||||
REQUIRES BUSINESS CONFIRMATION
|
||||
```
|
||||
|
||||
Known candidates for this list at spec time:
|
||||
- Actual SLA minute values per product/priority/category
|
||||
- Actual escalation rule conditions and target nodes per product
|
||||
- Whether/when premium support tiers override "support enabled by default"
|
||||
- Confidence-threshold cut points for high/medium/low AI bands, per product
|
||||
- Assignment strategy choice per hierarchy node
|
||||
- Business calendar definitions (hours, holidays, timezones) per team
|
||||
|
||||
Never hardcode a placeholder value for any of the above and ship it as if it were final — mark it and surface it for confirmation instead.
|
||||
|
||||
## Cross-reference map
|
||||
|
||||
| If you're building... | Read |
|
||||
|---|---|
|
||||
| The overall model and boundaries | [01](./01-product-vision-and-principles.md), [02](./02-integration-and-security.md) |
|
||||
| The AI agent | [03](./03-ai-support-architecture.md) |
|
||||
| The ticket/problem data model | [04](./04-ticketing-and-problem-management.md), [06](./06-database-schema.md) |
|
||||
| Orchestration/SLA/escalation | [05](./05-orchestration-sla-escalation.md) |
|
||||
| Backend module layout | [07](./07-backend-architecture.md) |
|
||||
| Any UI surface | [08](./08-frontend-architecture.md) |
|
||||
| Tests, CI, dashboards | [09](./09-testing-observability-cicd.md) |
|
||||
Reference in New Issue
Block a user