# MVNexus - Architecture Documentation

## System Overview

MVNexus is an enterprise-grade internal IT ticketing system built with a Modular Monolith architecture, supporting multi-company and multi-department isolation with advanced SLA tracking, role-based access control, and real-time collaboration.

---

## Core Architectural Principles

### 1. Modular Monolith
- Clear module boundaries with explicit dependencies
- Each module is self-contained with its own domain logic
- Shared kernel for cross-cutting concerns
- Modules communicate through well-defined contracts

### 2. Clean Architecture
- Domain logic independent of frameworks
- Dependency inversion through interfaces
- Use cases encapsulated in Services
- Data access abstracted through Repositories

### 3. SOLID Principles
- **Single Responsibility**: Each class has one reason to change
- **Open/Closed**: Open for extension, closed for modification
- **Liskov Substitution**: Subtypes must be substitutable
- **Interface Segregation**: Many specific interfaces over one general
- **Dependency Inversion**: Depend on abstractions, not concretions

### 4. Design Patterns
- **Repository Pattern**: Data access abstraction
- **Service Layer Pattern**: Business logic orchestration
- **DTO Pattern**: Data transfer objects for API boundaries
- **Action Pattern**: Single-purpose command classes
- **Observer Pattern**: Event-driven architecture
- **Strategy Pattern**: Pluggable behaviors (settings resolvers; future SSO providers)

---

## Multi-Tenancy Architecture

### Tenant Isolation Model
**Shared Database with Tenant Scoping**

```
companies (tenant root)
  └── departments (sub-tenant)
      ├── users (scoped to department)
      ├── tickets (scoped to department)
      ├── categories (scoped to department)
      └── settings (scoped to department)
```

### Isolation Enforcement Layers

1. **Database Level**: Foreign keys ensure referential integrity
2. **Model Level**: Global scopes automatically filter queries
3. **Policy Level**: Authorization checks verify access rights
4. **Middleware Level**: Request validation ensures proper context

---

## Scoped Role & Permission System

### Role Scopes

| Scope | Description | Example Roles |
|-------|-------------|---------------|
| `global` | System-wide access across all companies | Super Admin, Platform Manager |
| `company` | Access to specific company and its departments | Company Admin, Company Viewer |
| `department` | Access to specific department only | Department Manager, Assignable support user |

### Permission Structure

```php
// Global permissions
'companies.manage'
'global.settings.manage'
'global.audit.view'

// Company-scoped permissions
'company.{company_id}.departments.manage'
'company.{company_id}.users.manage'
'company.{company_id}.reports.view'

// Department-scoped permissions
'department.{department_id}.tickets.view'
'department.{department_id}.tickets.assign'
'department.{department_id}.settings.manage'
```

### Permission Inheritance

```
Super Admin (global)
  └── All company permissions
      └── All department permissions

Company Admin (company_id: X)
  └── All department permissions in company X

Department Manager (department_id: Y)
  └── Department Y permissions only
```

---

## Settings Inheritance System

### Hierarchy

```
Global Settings (system defaults)
  ↓ (inherits and can override)
Company Settings (company-specific)
  ↓ (inherits and can override)
Department Settings (department-specific)
```

### SettingsResolver Logic

```php
// Pseudo-code
function resolveSettings($department, $key) {
    // 1. Check department-level override
    if (department.settings.has($key)) {
        return department.settings.get($key);
    }
    
    // 2. Check company-level override
    if (department.company.settings.has($key)) {
        return department.company.settings.get($key);
    }
    
    // 3. Check global default
    if (globalSettings.has($key)) {
        return globalSettings.get($key);
    }
    
    // 4. Return system default
    return systemDefaults[$key];
}
```

### Inheritable Settings

1. **Ticket Statuses**
   - Global: New, In Progress, Resolved, Closed
   - Company: Custom statuses (e.g., "Awaiting Vendor")
   - Department: Specialized statuses (e.g., "Network Review")

2. **Ticket Priorities**
   - Global: Low, Medium, High, Critical
   - Company: Custom priorities
   - Department: Department-specific priorities

3. **SLA Policies**
   - Global: Default response/resolution times
   - Company: Industry-specific SLAs
   - Department: Team-specific SLAs

4. **Assignment Rules**
   - Global: Round-robin by default
   - Company: Skill-based routing
   - Department: Team-specific routing

5. **Notification Templates**
   - Global: Standard templates
   - Company: Branded templates
   - Department: Team-specific messaging

---

## SLA Lifecycle & Traceability

### SLA States

```
Ticket Created
  ↓
SLA Tracking Record Created
  ↓
[ACTIVE] Monitoring Phase
  ↓
├─→ [BREACH] Response SLA Breached → Breach Event Created
│     ↓
│   Escalation Notification Sent
│
├─→ [BREACH] Resolution SLA Breached → Breach Event Created
│     ↓
│   Escalation Notification Sent
│
└─→ [COMPLETED] Ticket Resolved Within SLA
```

### SLA Tracking Data Model

```
ticket_sla_tracking:
  - Full lifecycle timestamps
  - Calculated breach status
  - Duration tracking
  - Links to policy and ticket

sla_breach_events:
  - Links to tracking record (full traceability)
  - Breach type (response/resolution)
  - Breach duration in minutes
  - Escalation metadata
  - Escalation delivery status
```

### SLA Engine Responsibilities

1. **Calculate Due Times**: Business hours aware
2. **Monitor Breaches**: Scheduled job every 5 minutes
3. **Create Breach Events**: With full context and traceability
4. **Trigger Escalations**: Queue escalation notifications
5. **Track Resolution**: Update tracking when ticket resolved
6. **Audit Changes**: Log all SLA state transitions

---

## Authentication Architecture

MVNexus uses **passwordless email authentication** delivered via **Mailgun**, with **Laravel Sanctum SPA (stateful) sessions** — not bearer tokens in browser storage. The React SPA calls `/sanctum/csrf-cookie`, then authenticated API routes with `withCredentials: true` so Laravel issues **httpOnly session cookies** (plus CSRF protection).

### Active sign-in methods

| Method | Purpose | Tables |
|--------|---------|--------|
| **Email OTP** | Primary login for existing users | `login_otps` |
| **Magic link** | One-click sign-in from email | `auth_magic_links` |
| **Admin invite** | Onboarding new users (admin creates invite) | `user_invites` |

All outbound auth email (OTP codes, magic links, invites) is queued and sent through **Mailgun** (`MAILGUN_*`).

### Email OTP flow

1. User submits email on the login page (`POST /api/v1/auth/request-otp`).
2. Backend validates domain (`OTP_ALLOWED_EMAIL_DOMAIN`), rate limits, and that the user exists and is active.
3. A hashed OTP is stored in `login_otps`; `SendOtpEmailJob` delivers the code via Mailgun.
4. User submits OTP (`POST /api/v1/auth/verify-otp`) with optional `remember_device` and `device_fingerprint`.
5. On success, Sanctum establishes a stateful session; an `auth_sessions` row records device/IP/trust.
6. Frontend loads the user via `GET /api/v1/auth/me` (session cookie, no token in `localStorage`).

### Magic link flow

1. `POST /api/v1/auth/request-magic-link` creates a hashed token in `auth_magic_links` and emails a link.
2. User opens `/auth/magic?email=…&token=…`; SPA calls `POST /api/v1/auth/verify-magic-link`.
3. Same session + `auth_sessions` behavior as OTP verify.

### Admin invite flow

1. Authenticated admin creates invite (`POST /api/v1/admin/invites`).
2. Invite stored in `user_invites` (hashed token, company/department/role, expiry).
3. New user accepts via `POST /api/v1/auth/accept-invite` (email, token, name) and can then sign in with OTP or magic link.

### Sessions, trusted devices, and revocation

- **`auth_sessions`**: Per-device session metadata (`device_fingerprint_hash`, `trusted_until`, `revoked_at`, links to Sanctum `token_id` / Laravel `session_id`).
- **Trusted devices**: When `remember_device` is true, `trusted_until` is set from `OTP_TRUSTED_DEVICE_DAYS`; trusted devices may skip full OTP on subsequent logins (see `DeviceTrustService`).
- **Session management**: Authenticated users can list/revoke sessions (`GET/DELETE /api/v1/auth/sessions*`).
- **Logout**: `POST /api/v1/auth/logout` invalidates the current session.

### SPA / CORS / cookies (production)

- **`SANCTUM_STATEFUL_DOMAINS`**: Comma-separated browser hostnames (no scheme) allowed to receive session cookies.
- **`CORS_ALLOWED_ORIGINS`**: Comma-separated full frontend origins (with scheme); must not use `*` when credentials are sent.
- **`SESSION_*`**: `SESSION_DRIVER` (Redis in production), `SESSION_DOMAIN` (e.g. `.mountainview-eg.com`), `SESSION_SECURE_COOKIE=true`, `SESSION_HTTP_ONLY=true`, `SESSION_SAME_SITE=lax` (or `strict`).

### Audit and rate limiting

- Auth events are written to `authentication_logs` (login, logout, failed OTP, etc.).
- Throttles: `otp-request` and `otp-verify` middleware on auth routes; additional limits via `OTP_*` and `RATE_LIMIT_AUTH`.

### Legacy: `sso_identities` (not implemented)

The `sso_identities` table and `SsoIdentity` model exist from an earlier design but **no OAuth/Entra code is wired**. Do **not** configure Microsoft Entra unless building future SSO. Migration history is retained; the table is unused at runtime.

### Future SSO (optional)

A provider interface could be added later (Google, Okta, SAML/OIDC). Until then, all production auth is OTP, magic links, and invites only.

---

## Module Dependency Graph

```
Shared (no dependencies)
  ↓
Identity (depends on: Shared)
  ↓
Settings (depends on: Shared, Identity)
  ↓
├─→ Categories (depends on: Shared, Identity, Settings)
├─→ SLA (depends on: Shared, Identity, Settings)
│
└─→ Ticketing (depends on: Shared, Identity, Settings, Categories, SLA)
      ↓
    ├─→ Replies (depends on: Shared, Identity, Ticketing)
    ├─→ Attachments (depends on: Shared, Identity, Ticketing, Replies)
    ├─→ Search (depends on: Shared, Identity, Ticketing)
    │
    └─→ Cross-Cutting Modules
        ├─→ Notifications (depends on: Shared, Identity, Ticketing)
        ├─→ AuditLogs (depends on: Shared, Identity)
        └─→ Dashboard (depends on: Shared, Identity, Ticketing, SLA)
```

**Dependency Rules:**
- No circular dependencies
- Modules can only depend on lower-layer modules
- Cross-cutting modules access others through events/contracts
- Shared kernel has zero module dependencies

---

## Security Architecture

### Defense in Depth

1. **Authentication Layer**: Email OTP / magic links, Sanctum SPA cookies (httpOnly)
2. **Authorization Layer**: Scoped roles and permissions
3. **Isolation Layer**: Company/Department scoping
4. **Policy Layer**: Fine-grained access control
5. **Middleware Layer**: Request validation
6. **Database Layer**: Foreign keys and constraints
7. **Audit Layer**: Complete activity tracking

### Data Isolation Enforcement

```php
// Every query must be scoped
Ticket::forDepartment($departmentId)->get();

// Policies verify access
$this->authorize('view', $ticket);

// Middleware validates context
Route::middleware(['auth:sanctum', 'department.isolation']);

// Global scopes auto-apply
class Ticket extends Model {
    protected static function booted() {
        static::addGlobalScope(new DepartmentScope);
    }
}
```

---

## Performance Optimization Strategy

### Database Optimization
- UUIDs with proper indexing
- Composite indexes on frequently queried columns
- Eager loading to prevent N+1 queries
- Query result caching with Redis

### Application Caching
- Settings cache (1 hour TTL)
- User permissions cache (30 min TTL)
- Dashboard metrics cache (5 min TTL)
- Category tree cache (until invalidated)

### Queue Processing
- Async email notifications
- SLA breach checks (every 5 min)
- Bulk actions processing
- Report generation

### Frontend Optimization
- Code splitting by route
- Lazy loading modules
- TanStack Query caching
- Optimistic updates with Reverb

---

## Testing Strategy

### Test Pyramid

```
        /\
       /E2E\
      /------\
     /  API   \
    /----------\
   /   Unit     \
  /--------------\
```

**Unit Tests (70%)**
- Services logic
- Repository methods
- Actions
- DTOs
- Policies

**Integration Tests (20%)**
- API endpoints
- Database interactions
- Authentication flows
- Permission checks

**E2E Tests (10%)**
- Critical user journeys
- Ticket lifecycle
- SLA breach scenarios

---

## Deployment Architecture

### Infrastructure Components

```
Load Balancer
  ↓
Application Servers (Laravel)
  ↓
├─→ MySQL Primary
│   └─→ MySQL Replica (read)
├─→ Redis (cache + sessions)
├─→ Redis (queue)
├─→ File Storage
└─→ Laravel Reverb (WebSocket)
```

### Environment Configuration

**Development**: Single server, local MySQL/Redis
**Staging**: Simulated production setup
**Production**: Load-balanced, replicated databases, managed Redis

---

## Monitoring & Observability

### Key Metrics
- Ticket creation rate
- Average response time
- Average resolution time
- SLA breach rate
- User login success/failures
- API response times
- Queue processing times

### Logging Strategy
- Application logs (Laravel Log)
- Audit logs (database)
- API access logs
- Error tracking (Sentry recommended)
- Performance monitoring (APM recommended)

---

## Scalability Considerations

### Horizontal Scaling
- Stateless application servers
- Session storage in Redis
- File storage on shared filesystem or S3
- WebSocket server clustering

### Vertical Scaling
- Database optimization first
- Query performance tuning
- Index optimization
- Connection pooling

### Data Growth Strategy
- Archive closed tickets after 2 years
- Compress attachments
- Partition audit logs by date
- Regular maintenance tasks

---

## Maintenance & Operations

### Scheduled Jobs
- SLA breach checker (every 5 min)
- Notification queue processor (continuous)
- Old log cleanup (daily)
- Cache warmup (hourly)
- Database backups (daily)

### Health Checks
- Database connectivity
- Redis connectivity
- Queue workers status
- Disk space monitoring
- Reverb server status

---

This architecture provides a solid foundation for building a production-ready, scalable, and maintainable enterprise IT ticketing system.
