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:
saqib mir
2026-08-21 16:22:21 +05:30
co-authored by Claude Sonnet 5
parent c61b78fcd1
commit f475a55a53
11 changed files with 1954 additions and 0 deletions
+57
View File
@@ -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.
+145
View File
@@ -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.**
+91
View File
@@ -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.
+237
View File
@@ -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.
```
+165
View File
@@ -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).
+154
View File
@@ -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).
+549
View File
@@ -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.
+229
View File
@@ -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).
+148
View File
@@ -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 |
+97
View File
@@ -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)).
+82
View File
@@ -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 49 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) |