---
name: workflow
description: |
  Creates and configures automated SmartStack workflows.
  Use this skill when:
  - User wants to automate actions (emails, webhooks)
  - User mentions "workflow", "automation", "trigger"
  - Creating a business process with steps
  - Integrating transactional emails
  Types: SendEmail, Wait, Condition, Webhook
---

# Skill Workflow SmartStack

> **Architecture:** Trigger → Steps → Actions (Email/Wait/Condition/Webhook)

**Reference:** [_shared.md](../_shared.md) for common services

## WHEN THIS SKILL ACTIVATES

| Trigger | Example |
|---------|---------|
| Explicit request | "Create a workflow for registration" |
| Automatic email | "Send an email when a ticket is created" |
| Chaining | "After 24h without response, send a reminder" |
| Keywords | "workflow", "trigger", "automation", "email template" |

## FLOW

```
EVENT → WorkflowTrigger("user.registered")
    ↓
IWorkflowService.TriggerAsync(code, variables)
    ↓
Workflow Steps: SendEmail → Wait → Condition → Webhook
```

## AVAILABLE TRIGGERS

### User Events
| Trigger | Variables |
|---------|-----------|
| `user.registered` | userId, email, displayName, confirmUrl |
| `user.email-confirmed` | userId, email, displayName |
| `user.password-reset-requested` | userId, email, resetUrl |
| `user.account-locked/unlocked` | userId, email, lockReason |

### Ticket Events
| Trigger | Variables |
|---------|-----------|
| `ticket.created` | ticketId, ticketNumber, title, creatorEmail |
| `ticket.resolved/assigned` | ticketId, ticketNumber, assigneeName |
| `ticket.sla-warning/breached` | ticketId, deadline, remainingMinutes |

### Add a Trigger
```csharp
// WorkflowTriggerConfiguration.cs - GetSeedData()
new { Id = Guid.Parse("..."), Code = "entity.event", Name = "Entity Event",
    AvailableVariablesJson = JsonSerializer.Serialize(new[]{ ... }), ... }

// Trigger
await _workflowService.TriggerAsync("entity.event", new Dictionary<string, object>{...}, language: "en");
```

## STEP TYPES

### 1. SendEmail
```csharp
WorkflowStep.CreateEmailStep("Welcome Email", emailTemplateId, order: 1);
// Config: templateId, recipientVariable, ccEmails
```

### 2. Wait
```csharp
WorkflowStep.CreateWaitStep("Wait 24h", delayMinutes: 1440, order: 2);
```

### 3. Condition
```csharp
WorkflowStep.CreateConditionStep("Check premium", JsonSerializer.Serialize(new {
    condition = "{{userType}} == 'Premium'",
    trueStepOrder = 3, falseStepOrder = 4
}), order: 2);
// Operators: ==, !=, >, <, contains, &&, ||
```

### 4. Webhook
```csharp
WorkflowStep.CreateWebhookStep("Notify CRM", JsonSerializer.Serialize(new {
    url = "https://...", method = "POST",
    headers = new { Authorization = "Bearer {{apiKey}}" },
    body = new { eventType = "...", userId = "{{userId}}" },
    retryCount = 3
}), order: 3);
```

## WORKFLOW CREATION

```csharp
// 1. Create workflow
var workflow = Workflow.Create("welcome-sequence", "Welcome Sequence", description, triggerId, null, false, 10);

// 2. Add steps
workflow.AddStep(WorkflowStep.CreateEmailStep("Welcome", templateId, 1));
workflow.AddStep(WorkflowStep.CreateWaitStep("Wait 24h", 1440, 2));
workflow.AddStep(WorkflowStep.CreateEmailStep("Follow-up", followUpTemplateId, 3));

// 3. Seed data (WorkflowConfiguration.cs)
builder.HasData(new { Id = ..., Code = "welcome-sequence", TriggerId = ..., IsActive = true, ... });
```

## TRIGGERING

```csharp
// In Service or Controller
await _workflowService.TriggerAsync("user.registered", new Dictionary<string, object>
{
    ["userId"] = user.Id,
    ["email"] = user.Email,
    ["confirmUrl"] = GenerateConfirmUrl(user.Id)
}, language: "en", ct);
```

## EMAIL TEMPLATES

### Structure
```csharp
EmailTemplate: Code, Name, Category, IsActive, Translations[]
EmailTemplateTranslation: LanguageCode, Subject, HtmlBody, TextBody
```

### Syntax (Handlebars)
```html
<h1>Welcome {{userName}}!</h1>
{{#if isPremium}}<p>Thank you Premium member!</p>{{else}}<p>Premium offers...</p>{{/if}}
{{#each items}}<li>{{this.name}}</li>{{/each}}
```

## FRONTEND API

```typescript
workflowsApi.getAll() / getById(id) / create(data) / update(id, data)
workflowsApi.getTriggers()
workflowsApi.addStep(workflowId, step) / updateStep / deleteStep / reorderSteps
workflowsApi.execute(workflowId, variables)
```

## CHECKLIST

```
□ Trigger identified (existing or new in WorkflowTriggerConfiguration.cs)
□ Workflow created: Unique code, Linked trigger, Priority (10=standard, 20+=priority)
□ Steps: SendEmail+templateId, Wait+delayMinutes, Condition+expression, Webhook+url
□ Email templates created (if SendEmail)
□ Trigger added to source code
□ Tests: trigger, emails, variables
```

## RELATION WITH DOMAIN EVENTS

Workflow triggers (`TriggerAsync`) are the **primary mechanism** for cross-process automation (emails, webhooks, multi-step flows).

**Domain Events** (MediatR `INotificationHandler<T>`) are a complementary pattern for **in-process** side effects (audit logging, cache invalidation, read-model updates).

**Recommended pattern:** Domain Event handler bridges to Workflow triggers:
```csharp
// OrderCreatedEventHandler calls TriggerAsync for cross-process actions
public async Task Handle(OrderCreatedEvent notification, CancellationToken ct)
{
    await _workflowService.TriggerAsync("order.created",
        new Dictionary<string, object>{ ["orderId"] = notification.OrderId }, ct: ct);
}
```

**When to use which:**
| Scenario | Mechanism |
|----------|-----------|
| Send email after entity creation | Workflow Trigger |
| Invalidate cache after entity update | Domain Event |
| Log audit trail | Domain Event |
| Multi-step business process with delays | Workflow Trigger |
| Notify multiple services of same change | Domain Event → Workflow Trigger |

See `review-code/references/smartstack-conventions.md` (Domain Events section) for the full implementation pattern.

## ABSOLUTE RULES

| DO | DON'T |
|----|-------|
| IWorkflowService.TriggerAsync | Direct execution |
| All trigger variables | Hardcoded URLs in templates |
| Specify language for emails | Secrets in variables |
| Unique kebab-case codes | Infinite loops (A→B→A) |
| Log executions | Forget email templates |

## KEY FILES

| File | Role |
|------|------|
| `Domain/Communications/Workflow.cs` | Workflow entity |
| `Domain/Communications/WorkflowStep.cs` | Step entity |
| `Domain/Communications/WorkflowTrigger.cs` | Trigger entity |
| `Application/Common/Interfaces/IWorkflowService.cs` | Interface |
| `Infrastructure/Services/Workflow/WorkflowExecutionService.cs` | Implementation |
| `Infrastructure/.../WorkflowConfiguration.cs` | EF Config + Seed |
