Skip to main content

System Architecture

Overview

Checkmate is a full-stack test case management system built with modern web technologies. It provides a robust platform for organizing test cases, executing test runs, tracking progress, and generating reports.

Architectural Principles

  • Monolithic Full-Stack - Single deployable unit with clear separation of concerns
  • Type-Safe Throughout - End-to-end TypeScript for reliability
  • API-First Design - RESTful APIs for external integrations
  • Security-First - Role-based access control with Casbin
  • Data-Centric - MySQL as single source of truth
  • Modern Stack - Latest stable versions of proven technologies

Technology Stack

Why These Technologies?

Each technology was chosen to address specific requirements while maintaining consistency and developer experience.

Frontend

TechnologyPurposeWhy We Chose It
RemixFull-stack React frameworkServer-side rendering, fast page loads, nested routing, excellent DX
React 18UI libraryComponent-based architecture, large ecosystem, team familiarity
TypeScript 5Type safetyCatch errors early, better IDE support, improved maintainability
shadcn/uiComponent libraryModern, accessible, customizable, built on Radix UI primitives
TailwindCSS 3StylingUtility-first, rapid development, consistent design system
TanStack Table v8Data tablesAdvanced features (sorting, filtering, pagination), type-safe
ZodValidationSchema validation, type inference, excellent error messages

Backend

TechnologyPurposeWhy We Chose It
Node.js 18+JavaScript runtimeFast, scalable, JavaScript everywhere
RemixServer frameworkUnified frontend/backend, loader pattern, form handling
Drizzle ORMDatabase ORMType-safe, SQL-like syntax, minimal overhead, migration support
MySQL 8DatabaseProven reliability, ACID compliance, excellent performance
CasbinAuthorizationFlexible RBAC, policy-based, supports complex permissions
Remix-AuthAuthenticationGoogle OAuth integration, session management

Infrastructure & Tools

TechnologyPurpose
Docker & Docker ComposeContainerization and orchestration
ViteBuild tool and dev server
JestUnit and integration testing
GitHub ActionsCI/CD pipeline (future)

System Architecture

The system follows a layered architecture with clear separation between presentation, business logic, and data access.

graph TB
subgraph Client["Client Layer"]
Browser["🌐 Browser<br/>(React UI)"]
API["📮 API Clients<br/>(Postman, cURL)"]
External["🔌 Integrations<br/>(CI/CD, Scripts)"]
end

subgraph AppServer["Application Server (Remix + Node.js)"]
subgraph Presentation["Presentation Layer"]
React["React Components"]
Routes["Remix Routes (SSR)"]
State["Client State"]
end

subgraph BusinessLogic["Business Logic Layer"]
Controllers["Data Controllers"]
Services["Services<br/>(Auth, RBAC, Config)"]
Validation["Validation<br/>(Zod Schemas)"]
end

subgraph DataAccess["Data Access Layer"]
ORM["Drizzle ORM"]
DAO["Data Access Objects"]
DBClient["Database Client"]
end
end

subgraph Database["Database Layer"]
MySQL["🗄️ MySQL<br/>Tests, Projects, Runs<br/>Users, Organizations<br/>Labels, Sections, Squads"]
end

subgraph ExternalServices["External Services"]
OAuth["🔐 Google OAuth 2.0"]
Casbin["🛡️ Casbin RBAC"]
end

Browser -->|HTTPS| Presentation
API -->|HTTPS| Presentation
External -->|HTTPS| Presentation

Presentation --> BusinessLogic
BusinessLogic --> DataAccess
DataAccess --> MySQL

BusinessLogic -.->|Auth| OAuth
BusinessLogic -.->|RBAC| Casbin

style Client fill:#e1f5ff
style AppServer fill:#fff4e6
style Database fill:#f3e5f5
style ExternalServices fill:#e8f5e9

Application Architecture

Layer Breakdown

1. Presentation Layer (app/)

Responsibilities:

  • Render UI components
  • Handle user interactions
  • Client-side routing
  • Form management
  • State management

Key Directories:

app/
├── components/ # Reusable UI components
├── screens/ # Page-level components
├── ui/ # shadcn/ui primitives
├── routes/ # Remix route handlers
└── styles/ # Global styles

Component Hierarchy:

Root Layout (app/root.tsx)
├── Header Component
│ ├── App Logo & Navigation
│ ├── User Profile Dropdown
│ └── Logout Button
├── Main Content Area
│ ├── Projects Page
│ ├── Tests Page
│ │ ├── Test List
│ │ ├── Test Filters
│ │ ├── Section Tree
│ │ └── Test Detail Panel
│ ├── Runs Page
│ │ ├── Run List
│ │ ├── Run Filters
│ │ └── Run Detail View
│ └── Admin Panel
└── Footer

2. Business Logic Layer (app/dataController/)

Responsibilities:

  • Implement business rules
  • Validate data
  • Orchestrate operations
  • Transform data

Controllers:

app/dataController/
├── projects.controller.ts # Project CRUD
├── tests.controller.ts # Test management
├── runs.controller.ts # Run management
├── users.controller.ts # User operations
├── labels.controller.ts # Label operations
├── sections.controller.ts # Section hierarchy
├── squads.controller.ts # Squad management
├── priority.controller.ts # Priority types
├── platform.controller.ts # Platform types
└── automationStatus.controller.ts

3. Data Access Layer (app/db/)

Responsibilities:

  • Database connection management
  • Execute queries
  • Transaction handling
  • Schema definitions

Structure:

app/db/
├── client.ts # DB connection
├── schema/ # Drizzle schemas
│ ├── users.ts
│ ├── projects.ts
│ ├── tests.ts
│ ├── runs.ts
│ └── ...
├── dao/ # Data access objects
│ ├── users.dao.ts
│ ├── projects.dao.ts
│ ├── tests.dao.ts
│ └── ...
└── seed/ # Seed data

4. Service Layer (app/services/)

Responsibilities:

  • Authentication logic
  • Authorization policies
  • Configuration management
  • Cross-cutting concerns

Services:

app/services/
├── auth/ # Authentication
│ ├── Auth.server.ts
│ ├── GoogleStrategy.ts
│ └── session.server.ts
├── rbac/ # Authorization
│ ├── enforcer.ts
│ ├── policies.ts
│ └── roles.ts
└── config.ts # App configuration

Data Model

Checkmate follows a project-centric approach where everything is organized hierarchically under projects.

Conceptual Model

Organization
└── Projects
├── Test Cases
│ ├── Sections (hierarchical)
│ ├── Labels (flexible tagging)
│ ├── Squads (team ownership)
│ └── Attributes (priority, platform, etc.)
└── Test Runs
├── Selected Tests
├── Test Results
└── Execution History

Projects

Projects represent a collection of tests for a specific application, feature, or service.

Key Features:

  • Organize tests by application or feature
  • Team collaboration and ownership
  • Independent test and run management
  • Role-based access control per project

Test Cases

Test cases are the core entities containing test specifications and metadata.

Required Attributes:

  • Title - Test case name
  • Section - Hierarchical organization (required)

Classification Attributes:

  • Squad - Team or group ownership
  • Labels - Flexible tagging (e.g., "release-blocker", "regression")
  • Priority - Critical, High, Medium, Low
  • Platform - All Platforms, Android Only, iOS Only, Web Only
  • Automation Status - Not Automatable, Automated, Automatable
  • Test Covered By - Manual, E2E, Integration, Unit, Contract

Detailed Attributes:

  • Preconditions
  • Steps
  • Expected Results
  • Additional Groups
  • Jira Ticket Reference
  • Automation ID
  • Related Defects

Benefits:

  • Efficient Filtering - Find tests quickly by any attribute
  • Clear Ownership - Squads and sections define responsibility
  • Flexible Grouping - Labels adapt to evolving needs
  • Streamlined Execution - Create targeted test runs based on filters

Test Runs

Runs are collections of test cases organized for execution, enabling progress tracking and reporting.

Key Features:

  • Flexible Creation - Filter tests by squad, label, section, or any attribute
  • Real-Time Tracking - Monitor progress with live status updates
  • Dynamic Modifications - Edit run details or remove tests
  • Status Management - Update individual or bulk test results
  • Locking Mechanism - Prevent changes to completed runs
  • Comprehensive Reports - Download CSV reports with full results

Test Statuses:

  • Passed
  • Failed
  • Blocked
  • Retest
  • Skipped
  • Untested (default)

Benefits:

  • Enhanced Focus - Group related tests for specific objectives
  • Informed Decisions - Real-time insights guide testing efforts
  • Efficient Management - Adapt runs as requirements evolve

Sections (Hierarchical)

Sections provide hierarchical organization of test cases within a project.

Structure:

Login & Authentication
├── Login Flow
│ ├── Email Login
│ └── Social Login
└── Password Management
├── Forgot Password
└── Reset Password

Features:

  • Unlimited nesting depth
  • Filter tests by section
  • Bulk select by section
  • Auto-creation during bulk import

Labels (Flexible Tagging)

Labels provide dynamic classification beyond hierarchical sections.

Use Cases:

  • Release readiness (release-blocker, post-release)
  • Feature association (checkout, payments, search)
  • Testing scope (smoke-test, regression, exploratory)
  • Business priority (business-critical, nice-to-have)

Features:

  • Multiple labels per test
  • Filter and search by labels
  • Create runs filtered by labels
  • Bulk apply labels

Squads (Team Ownership)

Squads represent teams or groups responsible for test cases.

Benefits:

  • Clear ownership and accountability
  • Team-based filtering and reporting
  • Workload distribution visibility
  • Cross-team collaboration

Request Flow

User Request Flow (Web Interface)

sequenceDiagram
participant User
participant Browser
participant RemixSSR as Remix SSR
participant Controller
participant DAO
participant DB as MySQL

User->>Browser: Navigate to /projects
Browser->>RemixSSR: HTTP GET /projects
RemixSSR->>RemixSSR: Check authentication
RemixSSR->>Controller: loader({ request })
Controller->>DAO: getProjects(orgId)
DAO->>DB: SELECT * FROM projects
DB-->>DAO: Project rows
DAO-->>Controller: Project objects
Controller-->>RemixSSR: { data: projects }
RemixSSR->>RemixSSR: Render React components
RemixSSR-->>Browser: HTML + hydration data
Browser-->>User: Rendered page

API Request Flow

sequenceDiagram
participant Client
participant API as Remix API Route
participant RBAC as Casbin
participant Controller
participant DAO
participant DB as MySQL

Client->>API: POST /api/v1/test/create
API->>API: Validate session/token
API->>RBAC: enforce(user, resource, action)
RBAC-->>API: Authorization result
alt Authorized
API->>API: Validate request body (Zod)
API->>Controller: createTest(data)
Controller->>DAO: insertTest(data)
DAO->>DB: INSERT INTO tests
DB-->>DAO: Insert result
DAO-->>Controller: Created test
Controller-->>API: { data: test, error: null }
API-->>Client: 200 OK + test data
else Not Authorized
API-->>Client: 403 Forbidden
end

Authentication & Authorization

Authentication Flow

sequenceDiagram
participant User
participant App
participant Google
participant Session

User->>App: Click "Sign in with Google"
App->>Google: Redirect to OAuth
Google->>Google: User authenticates
Google-->>App: Authorization code
App->>Google: Exchange code for tokens
Google-->>App: Access token + user info
App->>Session: Create session
App->>App: Check/create user in DB
App-->>User: Redirect to dashboard

Authorization (RBAC)

Three Roles:

  1. Admin - Full access (projects, runs, users)
  2. User - Create/modify tests and runs
  3. Reader - View-only access

Policy Model:

  • Subject (user) → Resource (API endpoint) → Action (GET/POST/PUT/DELETE)
  • Hierarchical permissions (Admin inherits User, User inherits Reader)
  • Configured via Casbin policies

Example Policies:

# Admin can do everything
admin, /api/v1/project/create, POST
admin, /api/v1/run/delete, DELETE

# User can manage tests and runs
user, /api/v1/test/create, POST
user, /api/v1/run/edit, PUT

# Reader can only view
reader, /api/v1/projects, GET
reader, /api/v1/tests, GET

API Architecture

RESTful Design

All APIs follow REST principles with consistent patterns.

Base URL: http://localhost:3000/api/v1

Endpoint Structure:

/api/v1/{resource}/{action}

Example Endpoints:

POST   /api/v1/project/create
GET /api/v1/projects
PUT /api/v1/test/update
DELETE /api/v1/test/delete
GET /api/v1/run/detail
POST /api/v1/run/create

Standard Response Format

All API responses follow a consistent structure:

{
data: T | null, // Response data
error: string | null // Error message
}

Success Response:

{
"data": { "testId": 123, "title": "Login Test" },
"error": null
}

Error Response:

{
"data": null,
"error": "Unauthorized access"
}

Authentication Methods

  1. Session Cookies - Web application (automatic)
  2. API Tokens - External integrations (Bearer token)

See API Documentation for detailed endpoint reference.


Deployment Architecture

Docker Compose Setup

Checkmate uses Docker Compose for local development and deployment.

services:
checkmate-db:
- MySQL 8.0
- Port 3306
- Persistent volume

db_seeder:
- Seeds initial data
- Runs once on startup

checkmate-app:
- Remix application
- Port 3000
- Depends on DB

Development Workflow

# Start all services
docker-compose up

# Access application
http://localhost:3000

# Database accessible at
localhost:3306

Environment Variables

Required configuration:

DATABASE_URL=mysql://user:pass@host:3306/db
GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
SESSION_SECRET=xxx

Security Architecture

Multi-Layer Security

  1. Authentication Layer

    • Google OAuth 2.0
    • Secure session management
    • Token-based API access
  2. Authorization Layer

    • Casbin RBAC
    • Role-based policies
    • Resource-level permissions
  3. Data Layer

    • SQL injection prevention (ORM)
    • Prepared statements
    • Input validation (Zod)
  4. Transport Layer

    • HTTPS in production
    • Secure cookies (httpOnly, secure)
    • CORS configuration

Best Practices

  • Principle of Least Privilege - Users get minimum required permissions
  • Token Security - API tokens treated as passwords
  • Session Management - Secure session cookies with expiration
  • Input Validation - All inputs validated with Zod schemas
  • SQL Safety - Drizzle ORM prevents SQL injection

Performance Optimization

Frontend Optimization

  • Server-Side Rendering - Fast initial page loads
  • Code Splitting - Lazy load components
  • Asset Optimization - Minification, compression
  • Caching Strategy - Browser caching for static assets

Backend Optimization

  • Database Indexes - Optimized queries
  • Connection Pooling - Efficient DB connections
  • Query Optimization - Minimal data fetching
  • Pagination - Limited result sets

Measured Performance

MetricTargetCurrent
Time to Interactive< 3.5s~3.0s
API Response Time< 200ms~150ms
Database Query Time< 100ms~80ms
Page Load Time< 2s~1.8s

Scalability Considerations

Current Architecture

  • Vertical Scaling - Increase container resources
  • Database - MySQL handles millions of rows
  • Session Storage - In-memory (can move to Redis)

Future Enhancements

  • Horizontal scaling with load balancer
  • Database read replicas
  • Redis for session storage
  • CDN for static assets
  • Message queue for async operations

Testing Strategy

Test Pyramid

        /\
/E2E\ ← Few (Critical paths)
/------\
/Integr-\ ← Some (API, DB)
/----------\
/---Unit-----\ ← Many (Business logic)
/--------------\

Testing Layers

  1. Unit Tests - Business logic, utilities (Jest)
  2. Integration Tests - API endpoints, database operations
  3. E2E Tests - Critical user flows (future: Playwright)

Current Coverage

  • Unit tests for data controllers
  • Integration tests for critical APIs
  • Manual E2E testing

Development Workflow

Git Workflow

main (production)
└── feature branches
└── fix branches

Development Process

  1. Clone repository
  2. yarn install - Install dependencies
  3. docker-compose up - Start services
  4. yarn dev - Start dev server
  5. Make changes
  6. yarn test - Run tests
  7. Commit and push
  8. Create pull request

Code Standards

  • TypeScript - Strict mode enabled
  • ESLint - Code quality
  • Prettier - Code formatting
  • Commit Messages - Conventional commits

Additional Resources


Next Steps for Developers