diff --git a/docs/00-INDEX.md b/docs/00-INDEX.md new file mode 100644 index 0000000..77c452c --- /dev/null +++ b/docs/00-INDEX.md @@ -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. diff --git a/docs/01-product-vision-and-principles.md b/docs/01-product-vision-and-principles.md new file mode 100644 index 0000000..9d15510 --- /dev/null +++ b/docs/01-product-vision-and-principles.md @@ -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.** diff --git a/docs/02-integration-and-security.md b/docs/02-integration-and-security.md new file mode 100644 index 0000000..fdce23a --- /dev/null +++ b/docs/02-integration-and-security.md @@ -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; +} +``` + +## 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. diff --git a/docs/03-ai-support-architecture.md b/docs/03-ai-support-architecture.md new file mode 100644 index 0000000..a8604f2 --- /dev/null +++ b/docs/03-ai-support-architecture.md @@ -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. +``` diff --git a/docs/04-ticketing-and-problem-management.md b/docs/04-ticketing-and-problem-management.md new file mode 100644 index 0000000..5da0d83 --- /dev/null +++ b/docs/04-ticketing-and-problem-management.md @@ -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). diff --git a/docs/05-orchestration-sla-escalation.md b/docs/05-orchestration-sla-escalation.md new file mode 100644 index 0000000..fbad35f --- /dev/null +++ b/docs/05-orchestration-sla-escalation.md @@ -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). diff --git a/docs/06-database-schema.md b/docs/06-database-schema.md new file mode 100644 index 0000000..f1bffb5 --- /dev/null +++ b/docs/06-database-schema.md @@ -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. diff --git a/docs/07-backend-architecture.md b/docs/07-backend-architecture.md new file mode 100644 index 0000000..5804159 --- /dev/null +++ b/docs/07-backend-architecture.md @@ -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; +} +``` + +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). diff --git a/docs/08-frontend-architecture.md b/docs/08-frontend-architecture.md new file mode 100644 index 0000000..d6227b6 --- /dev/null +++ b/docs/08-frontend-architecture.md @@ -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 | diff --git a/docs/09-testing-observability-cicd.md b/docs/09-testing-observability-cicd.md new file mode 100644 index 0000000..38e5ad1 --- /dev/null +++ b/docs/09-testing-observability-cicd.md @@ -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)). diff --git a/docs/10-implementation-roadmap.md b/docs/10-implementation-roadmap.md new file mode 100644 index 0000000..459b3fe --- /dev/null +++ b/docs/10-implementation-roadmap.md @@ -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) |