tickethub/docs/ARCHITECTURE.md

18 KiB

TicketHub - Architecture Document

System Overview

TicketHub is a lightweight issue tracking system designed for simplicity and extensibility. It follows a traditional client-server architecture with a React SPA frontend and FastAPI backend.

High-Level Architecture

┌─────────────────────────────────────────────────────────────────────────────────┐
│                                   Client                                         │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                  │
│  ┌─────────────────────────────────────────────────────────────────────────┐    │
│  │                         React Application                                │    │
│  │                                                                          │    │
│  │   ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐              │    │
│  │   │Dashboard │  │ Tickets  │  │  Board   │  │ Projects │  ...         │    │
│  │   └──────────┘  └──────────┘  └──────────┘  └──────────┘              │    │
│  │                                                                          │    │
│  │   ┌──────────────────────────────────────────────────────────────────┐  │    │
│  │   │                    React Query (Cache)                            │  │    │
│  │   └──────────────────────────────────────────────────────────────────┘  │    │
│  │                                                                          │    │
│  │   ┌──────────────────────────────────────────────────────────────────┐  │    │
│  │   │                    Axios HTTP Client                              │  │    │
│  │   └──────────────────────────────────────────────────────────────────┘  │    │
│  │                                                                          │    │
│  └─────────────────────────────────────────────────────────────────────────┘    │
│                                                                                  │
└────────────────────────────────────────┬────────────────────────────────────────┘
                                         │
                                    HTTPS/REST
                                         │
┌────────────────────────────────────────┼────────────────────────────────────────┐
│                                        ▼                                         │
│  ┌─────────────────────────────────────────────────────────────────────────┐    │
│  │                         FastAPI Application                              │    │
│  │                                                                          │    │
│  │   ┌─────────────────────────────────────────────────────────────────┐   │    │
│  │   │                     API Router Layer                             │   │    │
│  │   │  /api/projects  /api/tickets  /api/comments  /api/webhooks      │   │    │
│  │   └────────────────────────────┬────────────────────────────────────┘   │    │
│  │                                │                                         │    │
│  │   ┌────────────────────────────▼────────────────────────────────────┐   │    │
│  │   │                    Business Logic Layer                          │   │    │
│  │   │  ProjectService  TicketService  CommentService  WebhookService  │   │    │
│  │   └────────────────────────────┬────────────────────────────────────┘   │    │
│  │                                │                                         │    │
│  │   ┌────────────────────────────▼────────────────────────────────────┐   │    │
│  │   │                    Data Access Layer                             │   │    │
│  │   │             SQLite (dev) / PostgreSQL (prod)                     │   │    │
│  │   └─────────────────────────────────────────────────────────────────┘   │    │
│  │                                                                          │    │
│  └─────────────────────────────────────────────────────────────────────────┘    │
│                                                                                  │
│                              TicketHub Server                                    │
└─────────────────────────────────────────────────────────────────────────────────┘

Component Details

Frontend Components

src/
├── components/
│   ├── ui/                 # Reusable UI primitives
│   │   ├── Button.tsx      # Button variants
│   │   ├── Card.tsx        # Card container
│   │   ├── Input.tsx       # Form inputs
│   │   ├── Select.tsx      # Dropdowns
│   │   ├── Badge.tsx       # Status/priority badges
│   │   ├── Modal.tsx       # Dialog modals
│   │   ├── Table.tsx       # Data tables
│   │   ├── Tabs.tsx        # Tab navigation
│   │   └── Avatar.tsx      # User avatars
│   └── Layout.tsx          # Shell with sidebar
├── pages/
│   ├── Dashboard.tsx       # Overview page
│   ├── Tickets.tsx         # Ticket list
│   ├── TicketDetail.tsx    # Single ticket view
│   ├── Board.tsx           # Kanban board
│   ├── Projects.tsx        # Project management
│   ├── Team.tsx            # Team management
│   ├── Reports.tsx         # Analytics
│   ├── Integrations.tsx    # External integrations
│   ├── Automation.tsx      # Workflow rules
│   └── Settings.tsx        # Configuration
└── services/
    └── api.ts              # API client

Backend Structure

# Main Application (main.py)

# Models
class Project:
    id: int
    name: str
    key: str (unique, uppercase)
    description: str
    webhook_url: str
    created_at: datetime

class Ticket:
    id: int
    key: str (auto-generated: PROJECT_KEY-N)
    project_id: int (FK)
    title: str
    description: str
    status: enum('open', 'in_progress', 'resolved', 'closed')
    priority: enum('low', 'medium', 'high', 'critical')
    assignee: str
    reporter: str
    created_at: datetime
    updated_at: datetime

class Comment:
    id: int
    ticket_id: int (FK)
    author: str
    content: str
    created_at: datetime

Database Schema

CREATE TABLE projects (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    key TEXT UNIQUE NOT NULL,
    description TEXT,
    webhook_url TEXT,
    ticket_count INTEGER DEFAULT 0,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE tickets (
    id INTEGER PRIMARY KEY,
    key TEXT UNIQUE NOT NULL,
    project_id INTEGER REFERENCES projects(id),
    title TEXT NOT NULL,
    description TEXT,
    status TEXT DEFAULT 'open',
    priority TEXT DEFAULT 'medium',
    assignee TEXT,
    reporter TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE comments (
    id INTEGER PRIMARY KEY,
    ticket_id INTEGER REFERENCES tickets(id),
    author TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Indexes
CREATE INDEX idx_tickets_project ON tickets(project_id);
CREATE INDEX idx_tickets_status ON tickets(status);
CREATE INDEX idx_comments_ticket ON comments(ticket_id);

API Design

RESTful Endpoints

Method Endpoint Description
GET /api/projects List all projects
POST /api/projects Create project
GET /api/projects/{id} Get project
PATCH /api/projects/{id} Update project
DELETE /api/projects/{id} Delete project
GET /api/tickets List tickets (with filters)
POST /api/tickets Create ticket
GET /api/tickets/{id} Get ticket
PATCH /api/tickets/{id} Update ticket
DELETE /api/tickets/{id} Delete ticket
GET /api/tickets/{id}/comments List comments
POST /api/tickets/{id}/comments Add comment

Webhook System

┌─────────────┐     Event      ┌─────────────┐     HTTP POST     ┌──────────────┐
│   Ticket    │ ──────────────►│  Webhook    │ ─────────────────►│   External   │
│   Created   │                │   Handler   │                   │    System    │
└─────────────┘                └─────────────┘                   └──────────────┘

Events: ticket.created, ticket.updated, ticket.resolved, comment.added

Deployment Architecture

Development

┌───────────────┐         ┌───────────────┐
│   Frontend    │ ──────► │   Backend     │
│   Vite Dev    │  proxy  │   Uvicorn     │
│   :5173       │  /api   │   :8001       │
└───────────────┘         └───────────────┘
                                 │
                                 ▼
                          ┌───────────────┐
                          │    SQLite     │
                          │   (file)      │
                          └───────────────┘

Production

┌─────────────────────────────────────────────────────────────┐
│                     Docker Swarm                             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────────┐                                        │
│  │  Traefik Proxy  │ ◄── tickethub.startdata.com.br        │
│  └────────┬────────┘                                        │
│           │                                                  │
│           ├────────► /api/* ────► ┌─────────────────┐       │
│           │                       │   API Service   │       │
│           │                       │   FastAPI       │       │
│           │                       └────────┬────────┘       │
│           │                                │                 │
│           │                                ▼                 │
│           │                       ┌─────────────────┐       │
│           │                       │   PostgreSQL    │       │
│           │                       └─────────────────┘       │
│           │                                                  │
│           └────────► /* ──────► ┌─────────────────┐         │
│                                 │  NGINX Static   │         │
│                                 │  (React Build)  │         │
│                                 └─────────────────┘         │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Data Flow

Creating a Ticket

1. User fills form
   └─► React state

2. Submit
   └─► POST /api/tickets
       └─► Validate
           └─► Generate key (PROJECT-N)
               └─► Insert to DB
                   └─► Return ticket

3. Webhook (async)
   └─► If project.webhook_url
       └─► POST to external URL
           └─► Payload: {event, timestamp, data}

4. Update UI
   └─► React Query invalidate
       └─► Refetch tickets
           └─► Display new ticket

Kanban Drag & Drop

1. User drags ticket
   └─► onDragStart(ticketId)

2. Drop on column
   └─► onDrop(status)
       └─► PATCH /api/tickets/{id}
           └─► {status: newStatus}

3. Optimistic update
   └─► React Query mutation
       └─► Update local cache
           └─► Rerender board

4. Server confirms
   └─► Persist change
       └─► Trigger webhook

Security

Current Implementation

  • No authentication (open access)
  • Input validation via Pydantic
  • SQL injection prevention via parameterized queries
  1. JWT authentication
  2. Role-based access control
  3. API rate limiting
  4. Audit logging
  5. CSRF protection

Performance

Frontend

  • React Query caching (5 min stale time)
  • Lazy loading for routes
  • Optimistic updates for mutations
  • Virtualized lists for large datasets

Backend

  • Async endpoints (non-blocking I/O)
  • Database connection pooling
  • Pagination for list endpoints
  • Indexed queries

Extensibility

Adding New Features

  1. New ticket fields: Add to model, migration, API, and UI
  2. New integrations: Add to Integrations page and webhook handler
  3. New automation: Add to rules engine and trigger points

Plugin System (Future)

┌─────────────────┐
│   TicketHub     │
│   Core          │
├─────────────────┤
│  Plugin API     │
├─────────────────┤
│ ┌─────┐ ┌─────┐ │
│ │Slack│ │Email│ │
│ └─────┘ └─────┘ │
│ ┌─────┐ ┌─────┐ │
│ │Jira │ │Git  │ │
│ └─────┘ └─────┘ │
└─────────────────┘

Monitoring

Health Check

GET /api/health
→ {"status": "healthy", "version": "1.0.0"}

Metrics (Future)

  • Request count
  • Response times
  • Error rates
  • Active users

Document Version: 1.0 Last Updated: February 2026 StartData Engineering