Ticket Masala - Architecture Documentation¶
Version: 2.1 (Actual State) Date: December 2025 Status: Living Document
1. Executive Summary¶
Ticket Masala is a configuration-driven work management engine built as a Modular Monolith with AI Augmentation. It embraces an "In-Process" Architecture to simplify operations while enabling extensibility through YAML configuration.
Core Philosophy: "Everything is Configurable"¶
| Concern | Old Approach (v1) | Current Approach (v2) |
|---|---|---|
| Domain Logic | Hardcoded C# classes | masala_domains.yaml configuration |
| Data Schema | Fixed SQL columns | Hybrid (SQL + JSON) Entity Model |
| Business Rules | if/else statements |
Compiled Expression Trees |
| AI Strategy | Hardcoded logic | Feature Extraction Pipeline + Strategy Factory |
| Infrastructure | Docker Composition | In-Process (.NET Channels, SQLite WAL) |
2. The "In-Process" Infrastructure (KISS)¶
The system relies on Logical Separation rather than Physical Separation to reduce DevOps complexity.
| "Enterprise" Component | Replacement (C#) | Why it works |
|---|---|---|
| RabbitMQ | IHostedService + in-memory queues |
Background processing within the same OS process. |
| Redis | IMemoryCache |
Zero-latency in-memory caching. |
| PostgreSQL | SQLite (WAL Mode) / SQL Server |
Concurrent reads/writes; swappable via EF Core. |
| Elasticsearch | SQLite FTS |
Native full-text search capability. |
Exit Strategy: The domain core is agnostic to the persistence layer. The EF Core provider can be swapped for SQL Server/Postgres when scaling beyond single-node capacity (already supported via appsettings.json).
3. Repository Structure (Actual State)¶
ticket-masala/
├── src/
│ ├── TicketMasala.Web/ # Main ASP.NET Core MVC Application
│ │ ├── Areas/Identity/ # ASP.NET Core Identity scaffolded pages
│ │ ├── Controllers/ # MVC Controllers + API Controllers
│ │ │ ├── Api/ # REST API endpoints
│ │ │ ├── TicketController.cs # Core ticket management
│ │ │ ├── ProjectsController.cs # Project management
│ │ │ └── ManagerController.cs # Admin/management views
│ │ ├── Data/
│ │ │ ├── MasalaDbContext.cs # EF Core DbContext
│ │ │ └── DbSeeder.cs # Database seeding logic
│ │ ├── Engine/ # Core business logic engines
│ │ │ ├── Compiler/ # Rule compilation (Expression Trees)
│ │ │ ├── GERDA/ # AI subsystem
│ │ │ └── Ingestion/ # Ticket ingestion (CSV, Email, API)
│ │ ├── Models/ # Domain entities
│ │ ├── Observers/ # Observer pattern implementations
│ │ ├── Repositories/ # Repository pattern + Specifications
│ │ ├── Services/ # Business services
│ │ │ └── Projects/ # Project management service
│ │ ├── ViewModels/ # MVC View Models
│ │ ├── Views/ # Razor views
│ │ ├── masala_domains.yaml # Domain configuration
│ │ └── masala_config.json # GERDA AI configuration
│ └── TicketMasala.Tests/ # Unit & Integration tests
├── config/
│ └── masala_domains.yaml # Shared domain configuration
├── samples/
│ └── landscaping-client/ # Demo integration client
├── how-to-deploy/ # Deployment documentation
├── Dockerfile # Container build
└── docker-compose.yml # Local development orchestration
4. Layered Architecture¶
┌─────────────────────────────────────────────────────────────┐
│ Presentation Layer │
│ Controllers / Views / ViewModels / Areas/Identity │
│ (Domain-Agnostic UI Components) │
├─────────────────────────────────────────────────────────────┤
│ Application Layer │
│ Services: │
│ - TicketService (ITicketService, ITicketQueryService, │
│ ITicketCommandService) │
│ - ProjectService (IProjectService) │
│ - RuleEngineService (IRuleEngineService) │
├─────────────────────────────────────────────────────────────┤
│ Domain Layer │
│ Models: Ticket, Project, ApplicationUser, ProjectTemplate, │
│ Document, Notification, KnowledgeBaseArticle │
├─────────────────────────────────────────────────────────────┤
│ Infrastructure Layer │
│ EfCoreRepositories │ DynamicFeatureExtractor │ GERDA AI │
└─────────────────────────────────────────────────────────────┘
5. Configuration Extensibility¶
5.1 Domain Configuration (masala_domains.yaml)¶
The system supports multiple domains (IT, Gardening) with domain-specific:
- Entity Labels: Customize terminology (Ticket → "Service Visit", Agent → "Horticulturist")
- Work Item Types: Domain-specific ticket types with SLAs, icons, colors
- Custom Fields: Dynamic fields stored as JSON
- Workflows: State machines with transition rules
- AI Strategies: Domain-specific ranking, dispatching, estimating algorithms
- Integrations: Ingestion sources and outbound webhooks
domains:
IT:
display_name: "IT Support"
work_item_types:
- code: INCIDENT
name: "Incident"
default_sla_days: 1
custom_fields:
- name: urgency
type: select
options: ["Low", "Medium", "High", "Critical"]
ai_strategies:
ranking: WSJF
dispatching: MatrixFactorization
Gardening:
display_name: "Landscaping Services"
ai_strategies:
ranking: SeasonalPriority
dispatching: ZoneBased
5.2 Hybrid Data Model¶
Entities use a mix of structured relational columns and flexible JSON storage:
public class Ticket : BaseModel
{
// ═══ RIGID COLUMNS (Indexed, Relational) ═══
public required string DomainId { get; set; } // "IT", "Gardening"
public required string Status { get; set; } // "New", "Triaged", "Done"
public required string Title { get; set; }
public string? ConfigVersionId { get; set; } // Links to active config
public string? ContentHash { get; set; } // Duplicate detection
// ═══ FLEXIBLE STORAGE (The "Masala" Model) ═══
[Column(TypeName = "TEXT")]
public required string CustomFieldsJson { get; set; } = "{}";
// ═══ GERDA AI FIELDS ═══
public int EstimatedEffortPoints { get; set; }
public double PriorityScore { get; set; }
public string? GerdaTags { get; set; } // "AI-Dispatched,Spam-Cluster"
public string? RecommendedProjectName { get; set; }
// ═══ RELATIONSHIPS ═══
public ApplicationUser? Customer { get; set; }
public ApplicationUser? Responsible { get; set; }
public Project? Project { get; set; }
public List<TicketComment> Comments { get; set; }
public List<Document> Attachments { get; set; }
}
6. GERDA AI Subsystem¶
GERDA (GovTech Extended Resource Dispatch & Anticipation) is a pluggable AI pipeline orchestrated by GerdaService.
6.1 GERDA Modules¶
| Letter | Module | Location | Technique |
|---|---|---|---|
| G | Grouping | Engine/GERDA/Grouping/ |
K-Means clustering (spam/duplicate detection) |
| E | Estimating | Engine/GERDA/Estimating/ |
Classification (effort points) |
| R | Ranking | Engine/GERDA/Ranking/ |
WSJF, SeasonalPriority strategies |
| D | Dispatching | Engine/GERDA/Dispatching/ |
MatrixFactorization, ZoneBased strategies |
| A | Anticipation | Engine/GERDA/Anticipation/ |
Time Series (capacity forecasting) |
6.2 Strategy Factory Pattern¶
AI behaviors are injected dynamically based on domain configuration:
// Strategies are resolved by name from DI container
public interface IStrategyFactory
{
T? GetStrategy<T>(string strategyName) where T : class, IStrategy;
}
6.3 Feature Extraction Pipeline¶
graph LR
T[Ticket] --> E[DynamicFeatureExtractor]
C[YAML Config] --> E
E --> F[float[] Vector]
F --> M[ML Model / Strategy]
M --> P[Prediction/Score]
The DynamicFeatureExtractor supports transformations:
- min_max: Normalize numeric values to [0,1]
- one_hot: Categorical encoding
- bool: Boolean to float conversion
6.4 Background Processing¶
GerdaBackgroundService (IHostedService) runs periodic maintenance:
- Batch processing of open tickets
- Capacity risk analysis
- Re-ranking priority scores
7. Rule Engine (Expression Trees)¶
The RuleCompilerService compiles workflow transition rules into executable delegates:
// Config: conditions: [{field: "urgency", operator: "==", value: "Critical"}]
Func<Ticket, ClaimsPrincipal, bool> compiledRule = _ruleCompiler.Compile(conditions);
// Runtime evaluation - no string parsing
bool canTransition = compiledRule(ticket, currentUser);
Supported operations:
- Role checks:
user.IsInRole("Manager") - Field comparisons:
>,>=,<,<=,==,!= - String matching: Case-insensitive equality
- Empty checks:
is_empty,is_not_empty
8. Service Architecture & Patterns¶
| Pattern | Implementation | Location |
|---|---|---|
| Observer | Ticket/Project lifecycle hooks | Observers/ |
| Strategy | Pluggable AI algorithms | Engine/GERDA/Strategies/ |
| Factory | Strategy resolution by config name | StrategyFactory |
| Specification | Encapsulated query logic | Repositories/Specifications/ |
| Repository + UoW | Data access abstraction | Repositories/ |
| CQRS-lite | Separate query/command interfaces | ITicketQueryService, ITicketCommandService |
Key Service Interfaces¶
public interface ITicketService : ITicketQueryService, ITicketCommandService, ITicketFactory
{
// Unified interface for backward compatibility
}
public interface IProjectService
{
Task<Project> CreateProjectAsync(Project project);
Task<Project> CreateProjectFromTemplateAsync(Guid templateId, string name, string? managerId);
Task<Project?> GetProjectByIdAsync(Guid id);
}
9. Ingestion Pipeline¶
9.1 Ingestion Sources¶
| Source | Implementation | Status |
|---|---|---|
| CSV Import | CsvImportService |
Active |
EmailIngestionService |
Active | |
| External API | Api/TicketsController |
Active |
| Background Generator | TicketGeneratorService |
Active (demo/testing) |
9.2 Validation Pipeline¶
10. Security & Identity¶
- Authentication: ASP.NET Core Identity with scaffold UI
- Authorization: Role-based policies (Admin, Manager, Employee, Customer)
- Tenancy: Single-tenant, Multi-domain architecture
- Data Privacy: All ML processing is local (no external API calls)
11. Observers (Event-Driven)¶
Observers react to entity lifecycle events without coupling to UI:
| Observer | Trigger | Action |
|---|---|---|
GerdaTicketObserver |
Ticket created | Process through GERDA pipeline |
LoggingTicketObserver |
Ticket changes | Audit logging |
NotificationTicketObserver |
Status changes | Send notifications |
NotificationProjectObserver |
Project updates | Notify stakeholders |
12. Development Status¶
Completed (v2 Baseline)¶
- Configuration Engine (YAML → Objects)
- Hybrid Data Model (JSON Custom Fields)
- Rule Compiler (Expression Trees)
- Feature Extraction Pipeline
- GERDA Core Services (G+E+R+D+A)
- Observer Pattern for lifecycle hooks
- Repository + Unit of Work pattern
- Project Templates system
- Multi-domain support (IT, Gardening)
- External API ingestion
- Background job processing
🔄 In Progress¶
- Strategy registration for all domain-referenced strategies
- Complete integration test coverage
- UI localization (Domain-aware labels)
13. Suggested Improvements for v3¶
13.1 Configuration & Extensibility¶
| Improvement | Description | Priority |
|---|---|---|
| Scriban Templates | Use Scriban templating for ingestion field mapping | High |
| Config Versioning UI | Admin interface to view/rollback config versions | Medium |
| Hot Reload | Reload YAML config without app restart | Medium |
| Schema Validation | JSON Schema validation for CustomFieldsJson |
Medium |
13.2 AI/ML Enhancements¶
| Improvement | Description | Priority |
|---|---|---|
| ML.NET Model Persistence | Save trained models to disk for faster startup | High |
| Explainability API | Expose why GERDA made specific recommendations | High |
| Feedback Loop | Learn from user acceptance/rejection of recommendations | Medium |
| NLP Summarization | Auto-summarize ticket descriptions using local LLM | Low |
13.3 Architecture Improvements¶
| Improvement | Description | Priority |
|---|---|---|
| Event Sourcing (Optional) | Track all state changes for audit/replay | Medium |
| CQRS Full Implementation | Separate read/write models for complex queries | Low |
| Plugin Architecture | Allow external assemblies to register strategies | Medium |
| API Gateway Pattern | Centralized API versioning and rate limiting | Low |
13.4 Developer Experience¶
| Improvement | Description | Priority |
|---|---|---|
| OpenAPI/Swagger | Full API documentation with examples | High |
| Integration Test Fixtures | Reusable test data builders | High |
| Dev Container | Pre-configured VS Code devcontainer | Medium |
| Performance Dashboard | Real-time metrics for GERDA processing | Low |
13.5 Operations & Monitoring¶
| Improvement | Description | Priority |
|---|---|---|
| Structured Logging | Serilog with correlation IDs | High |
| Health Check Dashboard | Visual health status page | Medium |
| Prometheus Metrics | Export metrics for Grafana dashboards | Medium |
| Alerting Webhooks | Notify on GERDA capacity risks | Medium |
14. Quick Start for Developers¶
Program.cs→ DI setup, service registrationmasala_domains.yaml→ Domain configurationmasala_config.json→ GERDA AI settingsDbSeeder.cs→ Sample data initializationTicketService.cs→ Core business logicGerdaService.cs→ AI orchestration hub
15. Key Design Decisions¶
| Decision | Rationale |
|---|---|
| Local ML.NET | GDPR privacy, no API costs, offline capability |
| Modular Monolith | Simpler ops than microservices, easy to split later |
| Observer Pattern | AI processing doesn't block UI thread |
| Repository Pattern | Testable, database-agnostic |
| Expression Trees | High-performance rule evaluation |
| Hybrid JSON Model | Schema flexibility without migrations |
For detailed documentation on specific subsystems, see the /docs subdirectories.