@atlashub/smartstack-cli 1.4.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.documentation/agents.html +916 -916
  2. package/.documentation/apex.html +1018 -1018
  3. package/.documentation/business-analyse.html +1501 -1501
  4. package/.documentation/commands.html +680 -680
  5. package/.documentation/css/styles.css +2168 -2168
  6. package/.documentation/efcore.html +2505 -2505
  7. package/.documentation/gitflow.html +2618 -2618
  8. package/.documentation/hooks.html +413 -413
  9. package/.documentation/index.html +323 -323
  10. package/.documentation/installation.html +462 -462
  11. package/.documentation/js/app.js +794 -794
  12. package/.documentation/test-web.html +513 -513
  13. package/dist/index.js +807 -277
  14. package/dist/index.js.map +1 -1
  15. package/package.json +1 -1
  16. package/templates/agents/efcore/conflicts.md +44 -17
  17. package/templates/agents/efcore/db-status.md +27 -6
  18. package/templates/agents/efcore/scan.md +43 -13
  19. package/templates/commands/ai-prompt.md +315 -315
  20. package/templates/commands/application/create.md +362 -362
  21. package/templates/commands/controller/create.md +216 -216
  22. package/templates/commands/controller.md +59 -0
  23. package/templates/commands/documentation/module.md +202 -202
  24. package/templates/commands/efcore/_env-check.md +153 -153
  25. package/templates/commands/efcore/conflicts.md +109 -192
  26. package/templates/commands/efcore/db-status.md +101 -89
  27. package/templates/commands/efcore/migration.md +23 -11
  28. package/templates/commands/efcore/scan.md +115 -119
  29. package/templates/commands/efcore.md +54 -6
  30. package/templates/commands/feature-full.md +267 -267
  31. package/templates/commands/gitflow/11-finish.md +145 -11
  32. package/templates/commands/gitflow/13-sync.md +216 -216
  33. package/templates/commands/gitflow/14-rebase.md +251 -251
  34. package/templates/commands/gitflow/2-status.md +120 -10
  35. package/templates/commands/gitflow/3-commit.md +150 -0
  36. package/templates/commands/gitflow/7-pull-request.md +134 -5
  37. package/templates/commands/gitflow/9-merge.md +142 -1
  38. package/templates/commands/implement.md +663 -663
  39. package/templates/commands/init.md +562 -0
  40. package/templates/commands/mcp-integration.md +330 -0
  41. package/templates/commands/notification.md +129 -129
  42. package/templates/commands/validate.md +233 -0
  43. package/templates/commands/workflow.md +193 -193
  44. package/templates/skills/ai-prompt/SKILL.md +778 -778
  45. package/templates/skills/application/SKILL.md +563 -563
  46. package/templates/skills/application/templates-backend.md +450 -450
  47. package/templates/skills/application/templates-frontend.md +531 -531
  48. package/templates/skills/application/templates-i18n.md +520 -520
  49. package/templates/skills/application/templates-seed.md +647 -647
  50. package/templates/skills/controller/SKILL.md +240 -240
  51. package/templates/skills/controller/postman-templates.md +614 -614
  52. package/templates/skills/controller/templates.md +1468 -1468
  53. package/templates/skills/documentation/SKILL.md +133 -133
  54. package/templates/skills/documentation/templates.md +476 -476
  55. package/templates/skills/feature-full/SKILL.md +838 -838
  56. package/templates/skills/notification/SKILL.md +555 -555
  57. package/templates/skills/ui-components/SKILL.md +870 -870
  58. package/templates/skills/workflow/SKILL.md +582 -582
@@ -1,582 +1,582 @@
1
- ---
2
- name: workflow
3
- description: |
4
- Cree et configure des workflows automatises SmartStack.
5
- Utiliser ce skill quand:
6
- - L'utilisateur veut automatiser des actions (emails, webhooks)
7
- - L'utilisateur mentionne "workflow", "automatisation", "trigger"
8
- - Creation d'un processus metier avec etapes
9
- - Integration d'emails transactionnels
10
- Types: SendEmail, Wait, Condition, Webhook
11
- ---
12
-
13
- # Skill Workflow SmartStack
14
-
15
- > **Architecture:** Workflow = Trigger → Steps → Actions (Email/Wait/Condition/Webhook)
16
- > Les workflows sont executes automatiquement lors d'evenements applicatifs.
17
-
18
- ## QUAND CE SKILL S'ACTIVE
19
-
20
- Claude invoque automatiquement ce skill quand il detecte :
21
-
22
- | Declencheur | Exemple |
23
- |-------------|---------|
24
- | Demande explicite | "Cree un workflow pour l'inscription" |
25
- | Email automatique | "Envoie un email quand un ticket est cree" |
26
- | Automatisation | "Automatise le processus d'onboarding" |
27
- | Enchainement | "Apres 24h sans reponse, envoyer un rappel" |
28
- | Mots-cles | "workflow", "trigger", "automatisation", "email template" |
29
-
30
- ---
31
-
32
- ## ARCHITECTURE WORKFLOW
33
-
34
- ```
35
- ┌─────────────────────────────────────────────────────────────────────────────┐
36
- │ WORKFLOW ENGINE │
37
- ├─────────────────────────────────────────────────────────────────────────────┤
38
- │ │
39
- │ [EVENT] ─────────────────────────────────────────────────────────────────┐ │
40
- │ │ │ │
41
- │ ▼ │ │
42
- │ ┌─────────────────────────────┐ │ │
43
- │ │ WorkflowTrigger │ │ │
44
- │ │ ex: "user.registered" │ │ │
45
- │ │ "ticket.created" │ │ │
46
- │ └─────────────┬───────────────┘ │ │
47
- │ │ │ │
48
- │ ▼ │ │
49
- │ ┌─────────────────────────────┐ │ │
50
- │ │ IWorkflowService │ │ │
51
- │ │ TriggerAsync(code, vars) │ │ │
52
- │ └─────────────┬───────────────┘ │ │
53
- │ │ │ │
54
- │ ┌────────┴────────┐ │ │
55
- │ ▼ ▼ │ │
56
- │ ┌─────────┐ ┌─────────────┐ │ │
57
- │ │Workflow │ │ Workflow │ (plusieurs workflows par trigger) │ │
58
- │ │ "A" │ │ "B" │ │ │
59
- │ └────┬────┘ └──────┬──────┘ │ │
60
- │ │ │ │ │
61
- │ ▼ ▼ │ │
62
- │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
63
- │ │ WORKFLOW STEPS │ │ │
64
- │ │ │ │ │
65
- │ │ Step 1: SendEmail Step 2: Wait Step 3: Condition │ │ │
66
- │ │ ┌───────────────┐ ┌─────────────┐ ┌────────────────┐ │ │ │
67
- │ │ │ EmailTemplate │ → │ Delay 24h │ → │ IF condition │ │ │ │
68
- │ │ │ + Variables │ │ │ │ THEN Step 4 │ │ │ │
69
- │ │ └───────────────┘ └─────────────┘ │ ELSE Step 5 │ │ │ │
70
- │ │ └────────────────┘ │ │ │
71
- │ │ │ │ │
72
- │ │ Step 4: Webhook Step 5: SendEmail │ │ │
73
- │ │ ┌───────────────┐ ┌───────────────┐ │ │ │
74
- │ │ │ POST /api/... │ │ ReminderEmail │ │ │ │
75
- │ │ │ + Payload │ │ + Variables │ │ │ │
76
- │ │ └───────────────┘ └───────────────┘ │ │ │
77
- │ │ │ │ │
78
- │ └─────────────────────────────────────────────────────────────────────┘ │ │
79
- │ │ │
80
- └─────────────────────────────────────────────────────────────────────────────┘
81
- ```
82
-
83
- ---
84
-
85
- ## TRIGGERS DISPONIBLES
86
-
87
- ### User Events
88
-
89
- | Trigger Code | Declencheur | Variables Disponibles |
90
- |--------------|-------------|----------------------|
91
- | `user.registered` | Inscription | userId, email, displayName, confirmUrl |
92
- | `user.email-confirmed` | Email confirme | userId, email, displayName |
93
- | `user.password-reset-requested` | Reset demande | userId, email, resetUrl |
94
- | `user.password-changed` | Password change | userId, email |
95
- | `user.account-locked` | Compte bloque | userId, email, lockReason |
96
- | `user.account-unlocked` | Compte debloque | userId, email |
97
- | `user.onboarding-completed` | Onboarding termine | userId, email, displayName |
98
- | `user.admin-password-reset` | Admin reset via lien | userId, email, resetUrl |
99
- | `user.admin-password-reset-direct` | Admin reset direct | userId, email, tempPassword |
100
-
101
- ### Ticket Events (Support)
102
-
103
- | Trigger Code | Declencheur | Variables Disponibles |
104
- |--------------|-------------|----------------------|
105
- | `ticket.created` | Ticket cree | ticketId, ticketNumber, title, creatorEmail, creatorName |
106
- | `ticket.resolved` | Ticket resolu | ticketId, ticketNumber, title, resolverName |
107
- | `ticket.assigned` | Ticket assigne | ticketId, ticketNumber, assigneeName, assigneeEmail |
108
- | `ticket.commented` | Commentaire ajoute | ticketId, ticketNumber, commenterName, commentPreview |
109
- | `ticket.sla-warning` | SLA proche expiration | ticketId, ticketNumber, deadline, remainingMinutes |
110
- | `ticket.sla-breached` | SLA depasse | ticketId, ticketNumber, breachedAt |
111
-
112
- ### Ajouter un Nouveau Trigger
113
-
114
- ```csharp
115
- // 1. Infrastructure/Persistence/Configurations/Communications/WorkflowTriggerConfiguration.cs
116
- // Dans la methode GetSeedData(), ajouter:
117
-
118
- new
119
- {
120
- Id = Guid.Parse("NEW-GUID-HERE"),
121
- Code = "entity.event",
122
- Name = "Entity Event",
123
- Description = "Triggered when entity event occurs",
124
- TriggerType = "EntityEvent",
125
- AvailableVariablesJson = JsonSerializer.Serialize(new[]
126
- {
127
- new { Name = "entityId", Type = "Guid", Description = "Entity ID" },
128
- new { Name = "entityName", Type = "string", Description = "Entity name" },
129
- new { Name = "userEmail", Type = "string", Description = "User email" },
130
- }),
131
- IsActive = true,
132
- CreatedAt = seedDate
133
- },
134
-
135
- // 2. Declencher dans le service/controller
136
- await _workflowService.TriggerAsync(
137
- "entity.event",
138
- new Dictionary<string, object>
139
- {
140
- ["entityId"] = entity.Id,
141
- ["entityName"] = entity.Name,
142
- ["userEmail"] = user.Email,
143
- },
144
- language: "fr");
145
- ```
146
-
147
- ---
148
-
149
- ## TYPES DE STEPS
150
-
151
- ### 1. SendEmail
152
-
153
- Envoie un email en utilisant un template.
154
-
155
- ```csharp
156
- // Creation via Factory Method
157
- var step = WorkflowStep.CreateEmailStep(
158
- name: "Welcome Email",
159
- emailTemplateId: welcomeTemplateId,
160
- order: 1);
161
-
162
- // Configuration JSON (si specifique)
163
- {
164
- "templateId": "guid-template",
165
- "recipientVariable": "userEmail", // Variable contenant l'email
166
- "ccEmails": ["admin@company.com"], // CC optionnels
167
- "bccEmails": []
168
- }
169
- ```
170
-
171
- **Variables automatiques:**
172
- - Toutes les variables du trigger sont injectees dans le template
173
- - `{{userName}}`, `{{userEmail}}`, `{{ticketNumber}}`, etc.
174
-
175
- ### 2. Wait
176
-
177
- Ajoute un delai avant le step suivant.
178
-
179
- ```csharp
180
- // Creation
181
- var step = WorkflowStep.CreateWaitStep(
182
- name: "Wait 24 hours",
183
- delayMinutes: 24 * 60, // 1440 minutes
184
- order: 2);
185
- ```
186
-
187
- **Cas d'usage:**
188
- - Rappel apres X heures sans reponse
189
- - Sequence d'onboarding espacee
190
- - Delai avant escalade
191
-
192
- ### 3. Condition
193
-
194
- Branche conditionnelle basee sur les variables.
195
-
196
- ```csharp
197
- // Creation
198
- var step = WorkflowStep.CreateConditionStep(
199
- name: "Check if premium user",
200
- configurationJson: JsonSerializer.Serialize(new
201
- {
202
- condition = "{{userType}} == 'Premium'",
203
- trueStepOrder = 3, // Si vrai, aller au step 3
204
- falseStepOrder = 4 // Si faux, aller au step 4
205
- }),
206
- order: 2);
207
- ```
208
-
209
- **Operateurs supportes:**
210
- - `==`, `!=` (egalite)
211
- - `>`, `<`, `>=`, `<=` (comparaison)
212
- - `contains`, `startsWith`, `endsWith` (strings)
213
- - `&&`, `||` (logique)
214
-
215
- ### 4. Webhook
216
-
217
- Appelle une API externe.
218
-
219
- ```csharp
220
- // Creation
221
- var step = WorkflowStep.CreateWebhookStep(
222
- name: "Notify CRM",
223
- configurationJson: JsonSerializer.Serialize(new
224
- {
225
- url = "https://crm.example.com/api/events",
226
- method = "POST",
227
- headers = new Dictionary<string, string>
228
- {
229
- ["Authorization"] = "Bearer {{crmApiKey}}",
230
- ["Content-Type"] = "application/json"
231
- },
232
- body = new
233
- {
234
- eventType = "user.registered",
235
- userId = "{{userId}}",
236
- email = "{{userEmail}}"
237
- },
238
- retryCount = 3,
239
- timeoutSeconds = 30
240
- }),
241
- order: 3);
242
- ```
243
-
244
- ---
245
-
246
- ## WORKFLOW CREATION
247
-
248
- ### ETAPE 1: Definir le Trigger
249
-
250
- ```csharp
251
- // Choisir un trigger existant ou en creer un nouveau
252
- var triggerId = existingTriggerId; // ex: user.registered trigger ID
253
- ```
254
-
255
- ### ETAPE 2: Creer le Workflow
256
-
257
- ```csharp
258
- // Domain/Communications/Workflow.cs via Factory Method
259
- var workflow = Workflow.Create(
260
- code: "welcome-sequence",
261
- name: "Welcome Email Sequence",
262
- description: "Sends welcome emails after registration",
263
- triggerId: triggerId,
264
- applicationId: null, // null = global
265
- isSystem: false,
266
- priority: 10); // Plus haut = execute en premier
267
- ```
268
-
269
- ### ETAPE 3: Ajouter les Steps
270
-
271
- ```csharp
272
- // Step 1: Email de bienvenue immediat
273
- workflow.AddStep(WorkflowStep.CreateEmailStep(
274
- name: "Welcome Email",
275
- emailTemplateId: welcomeTemplateId,
276
- order: 1));
277
-
278
- // Step 2: Attendre 24h
279
- workflow.AddStep(WorkflowStep.CreateWaitStep(
280
- name: "Wait 24h",
281
- delayMinutes: 1440,
282
- order: 2));
283
-
284
- // Step 3: Email de suivi
285
- workflow.AddStep(WorkflowStep.CreateEmailStep(
286
- name: "Follow-up Email",
287
- emailTemplateId: followUpTemplateId,
288
- order: 3));
289
- ```
290
-
291
- ### ETAPE 4: Seed Data (Infrastructure)
292
-
293
- ```csharp
294
- // Infrastructure/Persistence/Configurations/Communications/WorkflowConfiguration.cs
295
-
296
- public void Configure(EntityTypeBuilder<Workflow> builder)
297
- {
298
- // ... configuration ...
299
-
300
- builder.HasData(GetSeedData());
301
- }
302
-
303
- private static object[] GetSeedData()
304
- {
305
- var seedDate = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
306
-
307
- return new object[]
308
- {
309
- new
310
- {
311
- Id = Guid.Parse("WORKFLOW-GUID"),
312
- Code = "welcome-sequence",
313
- Name = "Welcome Email Sequence",
314
- Description = "Sends welcome emails after registration",
315
- TriggerId = Guid.Parse("TRIGGER-GUID"),
316
- ApplicationId = (Guid?)null,
317
- IsActive = true,
318
- IsSystem = true,
319
- Priority = 10,
320
- CreatedAt = seedDate
321
- }
322
- };
323
- }
324
- ```
325
-
326
- ---
327
-
328
- ## DECLENCHEMENT WORKFLOW
329
-
330
- ### Dans un Service
331
-
332
- ```csharp
333
- public class UserService : IUserService
334
- {
335
- private readonly IWorkflowService _workflowService;
336
-
337
- public async Task<Result> RegisterAsync(RegisterCommand command, CancellationToken ct)
338
- {
339
- // ... creation utilisateur ...
340
-
341
- // Declencher le workflow
342
- await _workflowService.TriggerAsync(
343
- "user.registered",
344
- new Dictionary<string, object>
345
- {
346
- ["userId"] = user.Id,
347
- ["email"] = user.Email,
348
- ["displayName"] = user.DisplayName,
349
- ["confirmUrl"] = GenerateConfirmUrl(user.Id)
350
- },
351
- language: "fr",
352
- cancellationToken: ct);
353
-
354
- return Result.Success();
355
- }
356
- }
357
- ```
358
-
359
- ### Dans un Controller
360
-
361
- ```csharp
362
- [HttpPost("tickets")]
363
- public async Task<ActionResult> CreateTicket(CreateTicketRequest request, CancellationToken ct)
364
- {
365
- var ticket = await _ticketService.CreateAsync(request, ct);
366
-
367
- // Declencher workflow
368
- await _workflowService.TriggerAsync(
369
- "ticket.created",
370
- new Dictionary<string, object>
371
- {
372
- ["ticketId"] = ticket.Id,
373
- ["ticketNumber"] = ticket.Number,
374
- ["title"] = ticket.Title,
375
- ["creatorEmail"] = _currentUser.Email,
376
- ["creatorName"] = _currentUser.DisplayName
377
- });
378
-
379
- return CreatedAtAction(nameof(GetById), new { id = ticket.Id }, ticket);
380
- }
381
- ```
382
-
383
- ---
384
-
385
- ## EMAIL TEMPLATES
386
-
387
- ### Structure Template
388
-
389
- ```csharp
390
- // Domain/Communications/EmailTemplate.cs
391
- public class EmailTemplate : BaseEntity
392
- {
393
- public string Code { get; private set; } // "welcome-email"
394
- public string Name { get; private set; } // "Welcome Email"
395
- public string Category { get; private set; } // "Transactional"
396
- public bool IsActive { get; private set; }
397
- public bool IsSystem { get; private set; }
398
-
399
- // Translations (multi-langue)
400
- public ICollection<EmailTemplateTranslation> Translations { get; }
401
- }
402
-
403
- public class EmailTemplateTranslation
404
- {
405
- public string LanguageCode { get; set; } // "fr", "en"
406
- public string Subject { get; set; } // "Bienvenue {{userName}}"
407
- public string HtmlBody { get; set; } // HTML avec variables
408
- public string TextBody { get; set; } // Version texte
409
- }
410
- ```
411
-
412
- ### Variables dans Templates
413
-
414
- ```html
415
- <!-- HtmlBody avec Handlebars-like syntax -->
416
- <h1>Bienvenue {{userName}}!</h1>
417
- <p>Votre compte a ete cree avec succes.</p>
418
- <p>Email: {{userEmail}}</p>
419
- <a href="{{confirmUrl}}">Confirmer votre email</a>
420
-
421
- <!-- Conditions -->
422
- {{#if isPremium}}
423
- <p>Merci pour votre abonnement Premium!</p>
424
- {{else}}
425
- <p>Decouvrez nos offres Premium.</p>
426
- {{/if}}
427
-
428
- <!-- Boucles -->
429
- {{#each items}}
430
- <li>{{this.name}} - {{this.price}}</li>
431
- {{/each}}
432
- ```
433
-
434
- ---
435
-
436
- ## FRONTEND WORKFLOW EDITOR
437
-
438
- ### API Workflows
439
-
440
- ```typescript
441
- // services/api/workflowsApi.ts
442
- export const workflowsApi = {
443
- // CRUD Workflows
444
- getAll: () => apiClient.get<WorkflowDto[]>('/admin/workflows'),
445
- getById: (id: string) => apiClient.get<WorkflowDto>(`/admin/workflows/${id}`),
446
- create: (data: CreateWorkflowRequest) => apiClient.post('/admin/workflows', data),
447
- update: (id: string, data: UpdateWorkflowRequest) => apiClient.put(`/admin/workflows/${id}`, data),
448
- delete: (id: string) => apiClient.delete(`/admin/workflows/${id}`),
449
-
450
- // Triggers
451
- getTriggers: () => apiClient.get<WorkflowTriggerDto[]>('/admin/workflows/triggers'),
452
-
453
- // Steps
454
- addStep: (workflowId: string, step: CreateStepRequest) =>
455
- apiClient.post(`/admin/workflows/${workflowId}/steps`, step),
456
- updateStep: (workflowId: string, stepId: string, step: UpdateStepRequest) =>
457
- apiClient.put(`/admin/workflows/${workflowId}/steps/${stepId}`, step),
458
- deleteStep: (workflowId: string, stepId: string) =>
459
- apiClient.delete(`/admin/workflows/${workflowId}/steps/${stepId}`),
460
- reorderSteps: (workflowId: string, stepIds: string[]) =>
461
- apiClient.post(`/admin/workflows/${workflowId}/steps/reorder`, { stepIds }),
462
-
463
- // Execution
464
- execute: (workflowId: string, variables: Record<string, unknown>) =>
465
- apiClient.post(`/admin/workflows/${workflowId}/execute`, { variables }),
466
- };
467
- ```
468
-
469
- ### Composant WorkflowStepsEditor
470
-
471
- ```tsx
472
- // components/admin/workflows/WorkflowStepsEditor.tsx
473
- import { Mail, Clock, GitBranch, Webhook, Plus, GripVertical, Trash2 } from 'lucide-react';
474
-
475
- const stepTypeConfig = {
476
- SendEmail: { icon: Mail, color: 'blue', label: 'Email' },
477
- Wait: { icon: Clock, color: 'amber', label: 'Delai' },
478
- Condition: { icon: GitBranch, color: 'purple', label: 'Condition' },
479
- Webhook: { icon: Webhook, color: 'green', label: 'Webhook' },
480
- };
481
-
482
- export function WorkflowStepsEditor({ workflowId, steps, onUpdate }) {
483
- // Drag and drop pour reordonner
484
- // Modal pour editer chaque step
485
- // Bouton pour ajouter un step
486
-
487
- return (
488
- <div className="space-y-4">
489
- {steps.map((step, index) => (
490
- <WorkflowStepCard
491
- key={step.id}
492
- step={step}
493
- index={index}
494
- onEdit={() => openEditModal(step)}
495
- onDelete={() => handleDelete(step.id)}
496
- />
497
- ))}
498
-
499
- <button
500
- onClick={() => openAddModal()}
501
- className="w-full p-4 border-2 border-dashed rounded-lg"
502
- >
503
- <Plus className="w-5 h-5 mr-2" />
504
- Ajouter une etape
505
- </button>
506
- </div>
507
- );
508
- }
509
- ```
510
-
511
- ---
512
-
513
- ## WORKFLOWS SYSTEME (SEED)
514
-
515
- | Code | Trigger | Description |
516
- |------|---------|-------------|
517
- | `email-confirmation` | `user.registered` | Email de confirmation apres inscription |
518
- | `welcome-email` | `user.email-confirmed` | Email de bienvenue apres confirmation |
519
- | `password-reset` | `user.password-reset-requested` | Email avec lien de reset |
520
- | `account-unlocked-notification` | `user.account-unlocked` | Notification compte debloque |
521
- | `user-onboarding` | `user.onboarding-completed` | Email fin d'onboarding |
522
- | `admin-password-reset` | `user.admin-password-reset` | Reset admin via lien |
523
- | `admin-password-reset-direct` | `user.admin-password-reset-direct` | Reset admin direct |
524
-
525
- ---
526
-
527
- ## CHECKLIST CREATION WORKFLOW
528
-
529
- ```
530
- □ Trigger identifie (existant ou nouveau)
531
- □ Si nouveau trigger:
532
- □ Ajoute dans WorkflowTriggerConfiguration.cs seed
533
- □ Variables definies (AvailableVariablesJson)
534
- □ Migration EF Core creee
535
- □ Workflow cree avec:
536
- □ Code unique (kebab-case)
537
- □ Nom descriptif
538
- □ Trigger lie
539
- □ Priority definie
540
- □ Steps configures:
541
- □ SendEmail avec templateId valide
542
- □ Wait avec delayMinutes
543
- □ Condition avec expression valide
544
- □ Webhook avec URL et payload
545
- □ Email templates crees (si SendEmail steps)
546
- □ Declenchement ajoute dans le code source
547
- □ Tests:
548
- □ Trigger declenche le workflow
549
- □ Emails envoyes correctement
550
- □ Variables substituees
551
- □ Migration EF Core si seed data modifie
552
- ```
553
-
554
- ---
555
-
556
- ## REGLES ABSOLUES
557
-
558
- 1. **TOUJOURS** utiliser IWorkflowService.TriggerAsync (jamais execution directe)
559
- 2. **TOUJOURS** fournir toutes les variables attendues par le trigger
560
- 3. **TOUJOURS** specifier la langue pour les emails
561
- 4. **TOUJOURS** utiliser des codes kebab-case uniques
562
- 5. **TOUJOURS** definir une priority (10 = standard, 20+ = prioritaire)
563
- 6. **TOUJOURS** logger les executions de workflow
564
- 7. **JAMAIS** hardcoder les URLs dans les templates
565
- 8. **JAMAIS** exposer des secrets dans les variables
566
- 9. **JAMAIS** creer des boucles infinies (workflow A → trigger B → workflow A)
567
- 10. **JAMAIS** oublier les email templates pour les steps SendEmail
568
-
569
- ---
570
-
571
- ## FICHIERS CLES
572
-
573
- | Fichier | Role |
574
- |---------|------|
575
- | `Domain/Communications/Workflow.cs` | Entite workflow |
576
- | `Domain/Communications/WorkflowStep.cs` | Entite step |
577
- | `Domain/Communications/WorkflowTrigger.cs` | Entite trigger |
578
- | `Domain/Communications/Enums/WorkflowStepType.cs` | Types de steps |
579
- | `Application/Common/Interfaces/IWorkflowService.cs` | Interface service |
580
- | `Infrastructure/Services/Workflow/WorkflowExecutionService.cs` | Implementation |
581
- | `Infrastructure/Persistence/Configurations/Communications/WorkflowConfiguration.cs` | EF Config + Seed |
582
- | `web/src/components/admin/workflows/WorkflowStepsEditor.tsx` | UI Editor |
1
+ ---
2
+ name: workflow
3
+ description: |
4
+ Cree et configure des workflows automatises SmartStack.
5
+ Utiliser ce skill quand:
6
+ - L'utilisateur veut automatiser des actions (emails, webhooks)
7
+ - L'utilisateur mentionne "workflow", "automatisation", "trigger"
8
+ - Creation d'un processus metier avec etapes
9
+ - Integration d'emails transactionnels
10
+ Types: SendEmail, Wait, Condition, Webhook
11
+ ---
12
+
13
+ # Skill Workflow SmartStack
14
+
15
+ > **Architecture:** Workflow = Trigger → Steps → Actions (Email/Wait/Condition/Webhook)
16
+ > Les workflows sont executes automatiquement lors d'evenements applicatifs.
17
+
18
+ ## QUAND CE SKILL S'ACTIVE
19
+
20
+ Claude invoque automatiquement ce skill quand il detecte :
21
+
22
+ | Declencheur | Exemple |
23
+ |-------------|---------|
24
+ | Demande explicite | "Cree un workflow pour l'inscription" |
25
+ | Email automatique | "Envoie un email quand un ticket est cree" |
26
+ | Automatisation | "Automatise le processus d'onboarding" |
27
+ | Enchainement | "Apres 24h sans reponse, envoyer un rappel" |
28
+ | Mots-cles | "workflow", "trigger", "automatisation", "email template" |
29
+
30
+ ---
31
+
32
+ ## ARCHITECTURE WORKFLOW
33
+
34
+ ```
35
+ ┌─────────────────────────────────────────────────────────────────────────────┐
36
+ │ WORKFLOW ENGINE │
37
+ ├─────────────────────────────────────────────────────────────────────────────┤
38
+ │ │
39
+ │ [EVENT] ─────────────────────────────────────────────────────────────────┐ │
40
+ │ │ │ │
41
+ │ ▼ │ │
42
+ │ ┌─────────────────────────────┐ │ │
43
+ │ │ WorkflowTrigger │ │ │
44
+ │ │ ex: "user.registered" │ │ │
45
+ │ │ "ticket.created" │ │ │
46
+ │ └─────────────┬───────────────┘ │ │
47
+ │ │ │ │
48
+ │ ▼ │ │
49
+ │ ┌─────────────────────────────┐ │ │
50
+ │ │ IWorkflowService │ │ │
51
+ │ │ TriggerAsync(code, vars) │ │ │
52
+ │ └─────────────┬───────────────┘ │ │
53
+ │ │ │ │
54
+ │ ┌────────┴────────┐ │ │
55
+ │ ▼ ▼ │ │
56
+ │ ┌─────────┐ ┌─────────────┐ │ │
57
+ │ │Workflow │ │ Workflow │ (plusieurs workflows par trigger) │ │
58
+ │ │ "A" │ │ "B" │ │ │
59
+ │ └────┬────┘ └──────┬──────┘ │ │
60
+ │ │ │ │ │
61
+ │ ▼ ▼ │ │
62
+ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │
63
+ │ │ WORKFLOW STEPS │ │ │
64
+ │ │ │ │ │
65
+ │ │ Step 1: SendEmail Step 2: Wait Step 3: Condition │ │ │
66
+ │ │ ┌───────────────┐ ┌─────────────┐ ┌────────────────┐ │ │ │
67
+ │ │ │ EmailTemplate │ → │ Delay 24h │ → │ IF condition │ │ │ │
68
+ │ │ │ + Variables │ │ │ │ THEN Step 4 │ │ │ │
69
+ │ │ └───────────────┘ └─────────────┘ │ ELSE Step 5 │ │ │ │
70
+ │ │ └────────────────┘ │ │ │
71
+ │ │ │ │ │
72
+ │ │ Step 4: Webhook Step 5: SendEmail │ │ │
73
+ │ │ ┌───────────────┐ ┌───────────────┐ │ │ │
74
+ │ │ │ POST /api/... │ │ ReminderEmail │ │ │ │
75
+ │ │ │ + Payload │ │ + Variables │ │ │ │
76
+ │ │ └───────────────┘ └───────────────┘ │ │ │
77
+ │ │ │ │ │
78
+ │ └─────────────────────────────────────────────────────────────────────┘ │ │
79
+ │ │ │
80
+ └─────────────────────────────────────────────────────────────────────────────┘
81
+ ```
82
+
83
+ ---
84
+
85
+ ## TRIGGERS DISPONIBLES
86
+
87
+ ### User Events
88
+
89
+ | Trigger Code | Declencheur | Variables Disponibles |
90
+ |--------------|-------------|----------------------|
91
+ | `user.registered` | Inscription | userId, email, displayName, confirmUrl |
92
+ | `user.email-confirmed` | Email confirme | userId, email, displayName |
93
+ | `user.password-reset-requested` | Reset demande | userId, email, resetUrl |
94
+ | `user.password-changed` | Password change | userId, email |
95
+ | `user.account-locked` | Compte bloque | userId, email, lockReason |
96
+ | `user.account-unlocked` | Compte debloque | userId, email |
97
+ | `user.onboarding-completed` | Onboarding termine | userId, email, displayName |
98
+ | `user.admin-password-reset` | Admin reset via lien | userId, email, resetUrl |
99
+ | `user.admin-password-reset-direct` | Admin reset direct | userId, email, tempPassword |
100
+
101
+ ### Ticket Events (Support)
102
+
103
+ | Trigger Code | Declencheur | Variables Disponibles |
104
+ |--------------|-------------|----------------------|
105
+ | `ticket.created` | Ticket cree | ticketId, ticketNumber, title, creatorEmail, creatorName |
106
+ | `ticket.resolved` | Ticket resolu | ticketId, ticketNumber, title, resolverName |
107
+ | `ticket.assigned` | Ticket assigne | ticketId, ticketNumber, assigneeName, assigneeEmail |
108
+ | `ticket.commented` | Commentaire ajoute | ticketId, ticketNumber, commenterName, commentPreview |
109
+ | `ticket.sla-warning` | SLA proche expiration | ticketId, ticketNumber, deadline, remainingMinutes |
110
+ | `ticket.sla-breached` | SLA depasse | ticketId, ticketNumber, breachedAt |
111
+
112
+ ### Ajouter un Nouveau Trigger
113
+
114
+ ```csharp
115
+ // 1. Infrastructure/Persistence/Configurations/Communications/WorkflowTriggerConfiguration.cs
116
+ // Dans la methode GetSeedData(), ajouter:
117
+
118
+ new
119
+ {
120
+ Id = Guid.Parse("NEW-GUID-HERE"),
121
+ Code = "entity.event",
122
+ Name = "Entity Event",
123
+ Description = "Triggered when entity event occurs",
124
+ TriggerType = "EntityEvent",
125
+ AvailableVariablesJson = JsonSerializer.Serialize(new[]
126
+ {
127
+ new { Name = "entityId", Type = "Guid", Description = "Entity ID" },
128
+ new { Name = "entityName", Type = "string", Description = "Entity name" },
129
+ new { Name = "userEmail", Type = "string", Description = "User email" },
130
+ }),
131
+ IsActive = true,
132
+ CreatedAt = seedDate
133
+ },
134
+
135
+ // 2. Declencher dans le service/controller
136
+ await _workflowService.TriggerAsync(
137
+ "entity.event",
138
+ new Dictionary<string, object>
139
+ {
140
+ ["entityId"] = entity.Id,
141
+ ["entityName"] = entity.Name,
142
+ ["userEmail"] = user.Email,
143
+ },
144
+ language: "fr");
145
+ ```
146
+
147
+ ---
148
+
149
+ ## TYPES DE STEPS
150
+
151
+ ### 1. SendEmail
152
+
153
+ Envoie un email en utilisant un template.
154
+
155
+ ```csharp
156
+ // Creation via Factory Method
157
+ var step = WorkflowStep.CreateEmailStep(
158
+ name: "Welcome Email",
159
+ emailTemplateId: welcomeTemplateId,
160
+ order: 1);
161
+
162
+ // Configuration JSON (si specifique)
163
+ {
164
+ "templateId": "guid-template",
165
+ "recipientVariable": "userEmail", // Variable contenant l'email
166
+ "ccEmails": ["admin@company.com"], // CC optionnels
167
+ "bccEmails": []
168
+ }
169
+ ```
170
+
171
+ **Variables automatiques:**
172
+ - Toutes les variables du trigger sont injectees dans le template
173
+ - `{{userName}}`, `{{userEmail}}`, `{{ticketNumber}}`, etc.
174
+
175
+ ### 2. Wait
176
+
177
+ Ajoute un delai avant le step suivant.
178
+
179
+ ```csharp
180
+ // Creation
181
+ var step = WorkflowStep.CreateWaitStep(
182
+ name: "Wait 24 hours",
183
+ delayMinutes: 24 * 60, // 1440 minutes
184
+ order: 2);
185
+ ```
186
+
187
+ **Cas d'usage:**
188
+ - Rappel apres X heures sans reponse
189
+ - Sequence d'onboarding espacee
190
+ - Delai avant escalade
191
+
192
+ ### 3. Condition
193
+
194
+ Branche conditionnelle basee sur les variables.
195
+
196
+ ```csharp
197
+ // Creation
198
+ var step = WorkflowStep.CreateConditionStep(
199
+ name: "Check if premium user",
200
+ configurationJson: JsonSerializer.Serialize(new
201
+ {
202
+ condition = "{{userType}} == 'Premium'",
203
+ trueStepOrder = 3, // Si vrai, aller au step 3
204
+ falseStepOrder = 4 // Si faux, aller au step 4
205
+ }),
206
+ order: 2);
207
+ ```
208
+
209
+ **Operateurs supportes:**
210
+ - `==`, `!=` (egalite)
211
+ - `>`, `<`, `>=`, `<=` (comparaison)
212
+ - `contains`, `startsWith`, `endsWith` (strings)
213
+ - `&&`, `||` (logique)
214
+
215
+ ### 4. Webhook
216
+
217
+ Appelle une API externe.
218
+
219
+ ```csharp
220
+ // Creation
221
+ var step = WorkflowStep.CreateWebhookStep(
222
+ name: "Notify CRM",
223
+ configurationJson: JsonSerializer.Serialize(new
224
+ {
225
+ url = "https://crm.example.com/api/events",
226
+ method = "POST",
227
+ headers = new Dictionary<string, string>
228
+ {
229
+ ["Authorization"] = "Bearer {{crmApiKey}}",
230
+ ["Content-Type"] = "application/json"
231
+ },
232
+ body = new
233
+ {
234
+ eventType = "user.registered",
235
+ userId = "{{userId}}",
236
+ email = "{{userEmail}}"
237
+ },
238
+ retryCount = 3,
239
+ timeoutSeconds = 30
240
+ }),
241
+ order: 3);
242
+ ```
243
+
244
+ ---
245
+
246
+ ## WORKFLOW CREATION
247
+
248
+ ### ETAPE 1: Definir le Trigger
249
+
250
+ ```csharp
251
+ // Choisir un trigger existant ou en creer un nouveau
252
+ var triggerId = existingTriggerId; // ex: user.registered trigger ID
253
+ ```
254
+
255
+ ### ETAPE 2: Creer le Workflow
256
+
257
+ ```csharp
258
+ // Domain/Communications/Workflow.cs via Factory Method
259
+ var workflow = Workflow.Create(
260
+ code: "welcome-sequence",
261
+ name: "Welcome Email Sequence",
262
+ description: "Sends welcome emails after registration",
263
+ triggerId: triggerId,
264
+ applicationId: null, // null = global
265
+ isSystem: false,
266
+ priority: 10); // Plus haut = execute en premier
267
+ ```
268
+
269
+ ### ETAPE 3: Ajouter les Steps
270
+
271
+ ```csharp
272
+ // Step 1: Email de bienvenue immediat
273
+ workflow.AddStep(WorkflowStep.CreateEmailStep(
274
+ name: "Welcome Email",
275
+ emailTemplateId: welcomeTemplateId,
276
+ order: 1));
277
+
278
+ // Step 2: Attendre 24h
279
+ workflow.AddStep(WorkflowStep.CreateWaitStep(
280
+ name: "Wait 24h",
281
+ delayMinutes: 1440,
282
+ order: 2));
283
+
284
+ // Step 3: Email de suivi
285
+ workflow.AddStep(WorkflowStep.CreateEmailStep(
286
+ name: "Follow-up Email",
287
+ emailTemplateId: followUpTemplateId,
288
+ order: 3));
289
+ ```
290
+
291
+ ### ETAPE 4: Seed Data (Infrastructure)
292
+
293
+ ```csharp
294
+ // Infrastructure/Persistence/Configurations/Communications/WorkflowConfiguration.cs
295
+
296
+ public void Configure(EntityTypeBuilder<Workflow> builder)
297
+ {
298
+ // ... configuration ...
299
+
300
+ builder.HasData(GetSeedData());
301
+ }
302
+
303
+ private static object[] GetSeedData()
304
+ {
305
+ var seedDate = new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc);
306
+
307
+ return new object[]
308
+ {
309
+ new
310
+ {
311
+ Id = Guid.Parse("WORKFLOW-GUID"),
312
+ Code = "welcome-sequence",
313
+ Name = "Welcome Email Sequence",
314
+ Description = "Sends welcome emails after registration",
315
+ TriggerId = Guid.Parse("TRIGGER-GUID"),
316
+ ApplicationId = (Guid?)null,
317
+ IsActive = true,
318
+ IsSystem = true,
319
+ Priority = 10,
320
+ CreatedAt = seedDate
321
+ }
322
+ };
323
+ }
324
+ ```
325
+
326
+ ---
327
+
328
+ ## DECLENCHEMENT WORKFLOW
329
+
330
+ ### Dans un Service
331
+
332
+ ```csharp
333
+ public class UserService : IUserService
334
+ {
335
+ private readonly IWorkflowService _workflowService;
336
+
337
+ public async Task<Result> RegisterAsync(RegisterCommand command, CancellationToken ct)
338
+ {
339
+ // ... creation utilisateur ...
340
+
341
+ // Declencher le workflow
342
+ await _workflowService.TriggerAsync(
343
+ "user.registered",
344
+ new Dictionary<string, object>
345
+ {
346
+ ["userId"] = user.Id,
347
+ ["email"] = user.Email,
348
+ ["displayName"] = user.DisplayName,
349
+ ["confirmUrl"] = GenerateConfirmUrl(user.Id)
350
+ },
351
+ language: "fr",
352
+ cancellationToken: ct);
353
+
354
+ return Result.Success();
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### Dans un Controller
360
+
361
+ ```csharp
362
+ [HttpPost("tickets")]
363
+ public async Task<ActionResult> CreateTicket(CreateTicketRequest request, CancellationToken ct)
364
+ {
365
+ var ticket = await _ticketService.CreateAsync(request, ct);
366
+
367
+ // Declencher workflow
368
+ await _workflowService.TriggerAsync(
369
+ "ticket.created",
370
+ new Dictionary<string, object>
371
+ {
372
+ ["ticketId"] = ticket.Id,
373
+ ["ticketNumber"] = ticket.Number,
374
+ ["title"] = ticket.Title,
375
+ ["creatorEmail"] = _currentUser.Email,
376
+ ["creatorName"] = _currentUser.DisplayName
377
+ });
378
+
379
+ return CreatedAtAction(nameof(GetById), new { id = ticket.Id }, ticket);
380
+ }
381
+ ```
382
+
383
+ ---
384
+
385
+ ## EMAIL TEMPLATES
386
+
387
+ ### Structure Template
388
+
389
+ ```csharp
390
+ // Domain/Communications/EmailTemplate.cs
391
+ public class EmailTemplate : BaseEntity
392
+ {
393
+ public string Code { get; private set; } // "welcome-email"
394
+ public string Name { get; private set; } // "Welcome Email"
395
+ public string Category { get; private set; } // "Transactional"
396
+ public bool IsActive { get; private set; }
397
+ public bool IsSystem { get; private set; }
398
+
399
+ // Translations (multi-langue)
400
+ public ICollection<EmailTemplateTranslation> Translations { get; }
401
+ }
402
+
403
+ public class EmailTemplateTranslation
404
+ {
405
+ public string LanguageCode { get; set; } // "fr", "en"
406
+ public string Subject { get; set; } // "Bienvenue {{userName}}"
407
+ public string HtmlBody { get; set; } // HTML avec variables
408
+ public string TextBody { get; set; } // Version texte
409
+ }
410
+ ```
411
+
412
+ ### Variables dans Templates
413
+
414
+ ```html
415
+ <!-- HtmlBody avec Handlebars-like syntax -->
416
+ <h1>Bienvenue {{userName}}!</h1>
417
+ <p>Votre compte a ete cree avec succes.</p>
418
+ <p>Email: {{userEmail}}</p>
419
+ <a href="{{confirmUrl}}">Confirmer votre email</a>
420
+
421
+ <!-- Conditions -->
422
+ {{#if isPremium}}
423
+ <p>Merci pour votre abonnement Premium!</p>
424
+ {{else}}
425
+ <p>Decouvrez nos offres Premium.</p>
426
+ {{/if}}
427
+
428
+ <!-- Boucles -->
429
+ {{#each items}}
430
+ <li>{{this.name}} - {{this.price}}</li>
431
+ {{/each}}
432
+ ```
433
+
434
+ ---
435
+
436
+ ## FRONTEND WORKFLOW EDITOR
437
+
438
+ ### API Workflows
439
+
440
+ ```typescript
441
+ // services/api/workflowsApi.ts
442
+ export const workflowsApi = {
443
+ // CRUD Workflows
444
+ getAll: () => apiClient.get<WorkflowDto[]>('/admin/workflows'),
445
+ getById: (id: string) => apiClient.get<WorkflowDto>(`/admin/workflows/${id}`),
446
+ create: (data: CreateWorkflowRequest) => apiClient.post('/admin/workflows', data),
447
+ update: (id: string, data: UpdateWorkflowRequest) => apiClient.put(`/admin/workflows/${id}`, data),
448
+ delete: (id: string) => apiClient.delete(`/admin/workflows/${id}`),
449
+
450
+ // Triggers
451
+ getTriggers: () => apiClient.get<WorkflowTriggerDto[]>('/admin/workflows/triggers'),
452
+
453
+ // Steps
454
+ addStep: (workflowId: string, step: CreateStepRequest) =>
455
+ apiClient.post(`/admin/workflows/${workflowId}/steps`, step),
456
+ updateStep: (workflowId: string, stepId: string, step: UpdateStepRequest) =>
457
+ apiClient.put(`/admin/workflows/${workflowId}/steps/${stepId}`, step),
458
+ deleteStep: (workflowId: string, stepId: string) =>
459
+ apiClient.delete(`/admin/workflows/${workflowId}/steps/${stepId}`),
460
+ reorderSteps: (workflowId: string, stepIds: string[]) =>
461
+ apiClient.post(`/admin/workflows/${workflowId}/steps/reorder`, { stepIds }),
462
+
463
+ // Execution
464
+ execute: (workflowId: string, variables: Record<string, unknown>) =>
465
+ apiClient.post(`/admin/workflows/${workflowId}/execute`, { variables }),
466
+ };
467
+ ```
468
+
469
+ ### Composant WorkflowStepsEditor
470
+
471
+ ```tsx
472
+ // components/admin/workflows/WorkflowStepsEditor.tsx
473
+ import { Mail, Clock, GitBranch, Webhook, Plus, GripVertical, Trash2 } from 'lucide-react';
474
+
475
+ const stepTypeConfig = {
476
+ SendEmail: { icon: Mail, color: 'blue', label: 'Email' },
477
+ Wait: { icon: Clock, color: 'amber', label: 'Delai' },
478
+ Condition: { icon: GitBranch, color: 'purple', label: 'Condition' },
479
+ Webhook: { icon: Webhook, color: 'green', label: 'Webhook' },
480
+ };
481
+
482
+ export function WorkflowStepsEditor({ workflowId, steps, onUpdate }) {
483
+ // Drag and drop pour reordonner
484
+ // Modal pour editer chaque step
485
+ // Bouton pour ajouter un step
486
+
487
+ return (
488
+ <div className="space-y-4">
489
+ {steps.map((step, index) => (
490
+ <WorkflowStepCard
491
+ key={step.id}
492
+ step={step}
493
+ index={index}
494
+ onEdit={() => openEditModal(step)}
495
+ onDelete={() => handleDelete(step.id)}
496
+ />
497
+ ))}
498
+
499
+ <button
500
+ onClick={() => openAddModal()}
501
+ className="w-full p-4 border-2 border-dashed rounded-lg"
502
+ >
503
+ <Plus className="w-5 h-5 mr-2" />
504
+ Ajouter une etape
505
+ </button>
506
+ </div>
507
+ );
508
+ }
509
+ ```
510
+
511
+ ---
512
+
513
+ ## WORKFLOWS SYSTEME (SEED)
514
+
515
+ | Code | Trigger | Description |
516
+ |------|---------|-------------|
517
+ | `email-confirmation` | `user.registered` | Email de confirmation apres inscription |
518
+ | `welcome-email` | `user.email-confirmed` | Email de bienvenue apres confirmation |
519
+ | `password-reset` | `user.password-reset-requested` | Email avec lien de reset |
520
+ | `account-unlocked-notification` | `user.account-unlocked` | Notification compte debloque |
521
+ | `user-onboarding` | `user.onboarding-completed` | Email fin d'onboarding |
522
+ | `admin-password-reset` | `user.admin-password-reset` | Reset admin via lien |
523
+ | `admin-password-reset-direct` | `user.admin-password-reset-direct` | Reset admin direct |
524
+
525
+ ---
526
+
527
+ ## CHECKLIST CREATION WORKFLOW
528
+
529
+ ```
530
+ □ Trigger identifie (existant ou nouveau)
531
+ □ Si nouveau trigger:
532
+ □ Ajoute dans WorkflowTriggerConfiguration.cs seed
533
+ □ Variables definies (AvailableVariablesJson)
534
+ □ Migration EF Core creee
535
+ □ Workflow cree avec:
536
+ □ Code unique (kebab-case)
537
+ □ Nom descriptif
538
+ □ Trigger lie
539
+ □ Priority definie
540
+ □ Steps configures:
541
+ □ SendEmail avec templateId valide
542
+ □ Wait avec delayMinutes
543
+ □ Condition avec expression valide
544
+ □ Webhook avec URL et payload
545
+ □ Email templates crees (si SendEmail steps)
546
+ □ Declenchement ajoute dans le code source
547
+ □ Tests:
548
+ □ Trigger declenche le workflow
549
+ □ Emails envoyes correctement
550
+ □ Variables substituees
551
+ □ Migration EF Core si seed data modifie
552
+ ```
553
+
554
+ ---
555
+
556
+ ## REGLES ABSOLUES
557
+
558
+ 1. **TOUJOURS** utiliser IWorkflowService.TriggerAsync (jamais execution directe)
559
+ 2. **TOUJOURS** fournir toutes les variables attendues par le trigger
560
+ 3. **TOUJOURS** specifier la langue pour les emails
561
+ 4. **TOUJOURS** utiliser des codes kebab-case uniques
562
+ 5. **TOUJOURS** definir une priority (10 = standard, 20+ = prioritaire)
563
+ 6. **TOUJOURS** logger les executions de workflow
564
+ 7. **JAMAIS** hardcoder les URLs dans les templates
565
+ 8. **JAMAIS** exposer des secrets dans les variables
566
+ 9. **JAMAIS** creer des boucles infinies (workflow A → trigger B → workflow A)
567
+ 10. **JAMAIS** oublier les email templates pour les steps SendEmail
568
+
569
+ ---
570
+
571
+ ## FICHIERS CLES
572
+
573
+ | Fichier | Role |
574
+ |---------|------|
575
+ | `Domain/Communications/Workflow.cs` | Entite workflow |
576
+ | `Domain/Communications/WorkflowStep.cs` | Entite step |
577
+ | `Domain/Communications/WorkflowTrigger.cs` | Entite trigger |
578
+ | `Domain/Communications/Enums/WorkflowStepType.cs` | Types de steps |
579
+ | `Application/Common/Interfaces/IWorkflowService.cs` | Interface service |
580
+ | `Infrastructure/Services/Workflow/WorkflowExecutionService.cs` | Implementation |
581
+ | `Infrastructure/Persistence/Configurations/Communications/WorkflowConfiguration.cs` | EF Config + Seed |
582
+ | `web/src/components/admin/workflows/WorkflowStepsEditor.tsx` | UI Editor |