@atlashub/smartstack-cli 1.5.1 → 1.5.2

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 (147) hide show
  1. package/.documentation/css/styles.css +2168 -2168
  2. package/.documentation/js/app.js +794 -794
  3. package/config/default-config.json +86 -86
  4. package/config/settings.json +53 -53
  5. package/config/settings.local.example.json +16 -16
  6. package/dist/index.js +0 -0
  7. package/dist/index.js.map +1 -1
  8. package/package.json +88 -88
  9. package/templates/agents/action.md +36 -36
  10. package/templates/agents/efcore/conflicts.md +84 -84
  11. package/templates/agents/efcore/db-deploy.md +51 -51
  12. package/templates/agents/efcore/db-reset.md +59 -59
  13. package/templates/agents/efcore/db-seed.md +56 -56
  14. package/templates/agents/efcore/db-status.md +64 -64
  15. package/templates/agents/efcore/migration.md +85 -85
  16. package/templates/agents/efcore/rebase-snapshot.md +62 -62
  17. package/templates/agents/efcore/scan.md +90 -90
  18. package/templates/agents/efcore/squash.md +67 -67
  19. package/templates/agents/explore-codebase.md +65 -65
  20. package/templates/agents/explore-docs.md +97 -97
  21. package/templates/agents/fix-grammar.md +49 -49
  22. package/templates/agents/gitflow/abort.md +45 -45
  23. package/templates/agents/gitflow/cleanup.md +85 -85
  24. package/templates/agents/gitflow/commit.md +40 -40
  25. package/templates/agents/gitflow/exec.md +48 -48
  26. package/templates/agents/gitflow/finish.md +92 -92
  27. package/templates/agents/gitflow/init.md +139 -139
  28. package/templates/agents/gitflow/merge.md +62 -62
  29. package/templates/agents/gitflow/plan.md +42 -42
  30. package/templates/agents/gitflow/pr.md +78 -78
  31. package/templates/agents/gitflow/review.md +49 -49
  32. package/templates/agents/gitflow/start.md +61 -61
  33. package/templates/agents/gitflow/status.md +32 -32
  34. package/templates/agents/snipper.md +36 -36
  35. package/templates/agents/websearch.md +46 -46
  36. package/templates/commands/_resources/formatting-guide.md +124 -124
  37. package/templates/commands/ai-prompt.md +315 -315
  38. package/templates/commands/apex/1-analyze.md +100 -100
  39. package/templates/commands/apex/2-plan.md +145 -145
  40. package/templates/commands/apex/3-execute.md +171 -171
  41. package/templates/commands/apex/4-examine.md +116 -116
  42. package/templates/commands/apex/5-tasks.md +209 -209
  43. package/templates/commands/apex.md +76 -76
  44. package/templates/commands/application/create.md +362 -362
  45. package/templates/commands/application/templates-backend.md +463 -463
  46. package/templates/commands/application/templates-frontend.md +517 -517
  47. package/templates/commands/application/templates-i18n.md +478 -478
  48. package/templates/commands/application/templates-seed.md +362 -362
  49. package/templates/commands/application.md +303 -303
  50. package/templates/commands/business-analyse/0-orchestrate.md +640 -640
  51. package/templates/commands/business-analyse/1-init.md +269 -269
  52. package/templates/commands/business-analyse/2-discover.md +520 -520
  53. package/templates/commands/business-analyse/3-analyse.md +408 -408
  54. package/templates/commands/business-analyse/4-specify.md +598 -598
  55. package/templates/commands/business-analyse/5-validate.md +326 -326
  56. package/templates/commands/business-analyse/6-handoff.md +746 -746
  57. package/templates/commands/business-analyse/7-doc-html.md +602 -602
  58. package/templates/commands/business-analyse/bug.md +325 -325
  59. package/templates/commands/business-analyse/change-request.md +368 -368
  60. package/templates/commands/business-analyse/hotfix.md +200 -200
  61. package/templates/commands/business-analyse.md +640 -640
  62. package/templates/commands/controller/create.md +216 -216
  63. package/templates/commands/controller/postman-templates.md +528 -528
  64. package/templates/commands/controller/templates.md +600 -600
  65. package/templates/commands/controller.md +337 -337
  66. package/templates/commands/create/agent.md +138 -138
  67. package/templates/commands/create/command.md +166 -166
  68. package/templates/commands/create/hook.md +234 -234
  69. package/templates/commands/create/plugin.md +329 -329
  70. package/templates/commands/create/project.md +507 -507
  71. package/templates/commands/create/skill.md +199 -199
  72. package/templates/commands/create.md +220 -220
  73. package/templates/commands/debug.md +95 -95
  74. package/templates/commands/documentation/module.md +202 -202
  75. package/templates/commands/documentation/templates.md +432 -432
  76. package/templates/commands/documentation.md +190 -190
  77. package/templates/commands/efcore/_env-check.md +153 -153
  78. package/templates/commands/efcore/conflicts.md +186 -186
  79. package/templates/commands/efcore/db-deploy.md +193 -193
  80. package/templates/commands/efcore/db-reset.md +426 -426
  81. package/templates/commands/efcore/db-seed.md +326 -326
  82. package/templates/commands/efcore/db-status.md +226 -226
  83. package/templates/commands/efcore/migration.md +400 -400
  84. package/templates/commands/efcore/rebase-snapshot.md +264 -264
  85. package/templates/commands/efcore/scan.md +198 -198
  86. package/templates/commands/efcore/squash.md +298 -298
  87. package/templates/commands/efcore.md +224 -224
  88. package/templates/commands/epct.md +69 -69
  89. package/templates/commands/explain.md +186 -186
  90. package/templates/commands/explore.md +45 -45
  91. package/templates/commands/feature-full.md +267 -267
  92. package/templates/commands/gitflow/1-init.md +1038 -1038
  93. package/templates/commands/gitflow/10-start.md +768 -768
  94. package/templates/commands/gitflow/11-finish.md +457 -457
  95. package/templates/commands/gitflow/12-cleanup.md +276 -276
  96. package/templates/commands/gitflow/13-sync.md +216 -216
  97. package/templates/commands/gitflow/14-rebase.md +251 -251
  98. package/templates/commands/gitflow/2-status.md +277 -277
  99. package/templates/commands/gitflow/3-commit.md +344 -344
  100. package/templates/commands/gitflow/4-plan.md +145 -145
  101. package/templates/commands/gitflow/5-exec.md +147 -147
  102. package/templates/commands/gitflow/6-abort.md +344 -344
  103. package/templates/commands/gitflow/7-pull-request.md +453 -355
  104. package/templates/commands/gitflow/8-review.md +240 -176
  105. package/templates/commands/gitflow/9-merge.md +451 -365
  106. package/templates/commands/gitflow.md +128 -128
  107. package/templates/commands/implement.md +663 -663
  108. package/templates/commands/init.md +567 -567
  109. package/templates/commands/mcp-integration.md +330 -330
  110. package/templates/commands/notification.md +129 -129
  111. package/templates/commands/oneshot.md +57 -57
  112. package/templates/commands/quick-search.md +72 -72
  113. package/templates/commands/ralph-loop/cancel-ralph.md +18 -18
  114. package/templates/commands/ralph-loop/help.md +126 -126
  115. package/templates/commands/ralph-loop/ralph-loop.md +18 -18
  116. package/templates/commands/review.md +106 -106
  117. package/templates/commands/utils/test-web-config.md +160 -160
  118. package/templates/commands/utils/test-web.md +151 -151
  119. package/templates/commands/validate.md +233 -233
  120. package/templates/commands/workflow.md +193 -193
  121. package/templates/gitflow/config.json +138 -138
  122. package/templates/hooks/ef-migration-check.md +139 -139
  123. package/templates/hooks/hooks.json +25 -25
  124. package/templates/hooks/stop-hook.sh +177 -177
  125. package/templates/skills/ai-prompt/SKILL.md +778 -778
  126. package/templates/skills/application/SKILL.md +563 -563
  127. package/templates/skills/application/templates-backend.md +450 -450
  128. package/templates/skills/application/templates-frontend.md +531 -531
  129. package/templates/skills/application/templates-i18n.md +520 -520
  130. package/templates/skills/application/templates-seed.md +647 -647
  131. package/templates/skills/business-analyse/SKILL.md +191 -191
  132. package/templates/skills/business-analyse/questionnaire.md +283 -283
  133. package/templates/skills/business-analyse/templates-frd.md +477 -477
  134. package/templates/skills/business-analyse/templates-react.md +580 -580
  135. package/templates/skills/controller/SKILL.md +240 -240
  136. package/templates/skills/controller/postman-templates.md +614 -614
  137. package/templates/skills/controller/templates.md +1468 -1468
  138. package/templates/skills/documentation/SKILL.md +133 -133
  139. package/templates/skills/documentation/templates.md +476 -476
  140. package/templates/skills/feature-full/SKILL.md +838 -838
  141. package/templates/skills/notification/SKILL.md +555 -555
  142. package/templates/skills/ui-components/SKILL.md +870 -870
  143. package/templates/skills/workflow/SKILL.md +582 -582
  144. package/templates/test-web/api-health.json +38 -38
  145. package/templates/test-web/minimal.json +19 -19
  146. package/templates/test-web/npm-package.json +46 -46
  147. package/templates/test-web/seo-check.json +54 -54
@@ -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 |