@atlashub/smartstack-cli 2.7.0 → 2.7.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.
- package/dist/index.js +70 -13
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +12 -10
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +2 -2
- package/templates/agents/ba-writer.md +180 -11
- package/templates/skills/business-analyse/_shared.md +19 -5
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +43 -1
- package/templates/skills/business-analyse/schemas/shared/common-defs.json +96 -3
- package/templates/skills/business-analyse/steps/step-00-init.md +48 -0
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +75 -7
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +21 -10
- package/templates/skills/business-analyse/steps/step-03-specify.md +702 -93
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +169 -4
- package/templates/skills/business-analyse/steps/step-05-handoff.md +24 -0
|
@@ -79,6 +79,44 @@ ba-reader.readApplicationContext({feature_id})
|
|
|
79
79
|
|
|
80
80
|
Update module status in master: "pending" → "in-progress"
|
|
81
81
|
|
|
82
|
+
### 2-ter. Derive Module Discovery Section (MANDATORY)
|
|
83
|
+
|
|
84
|
+
> **The module feature.json MUST have a `discovery` section.** In multi-module mode, derive it from the parent application's `cadrage`. In single-module mode, it should already exist from step-01.
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
ba-reader.readApplicationContext({feature_id})
|
|
88
|
+
→ Read cadrage: problem, asIs, toBe, trigger, stakeholders, risks, acceptanceCriteria
|
|
89
|
+
|
|
90
|
+
// Filter to this module's scope
|
|
91
|
+
moduleScope = cadrage.coverageMatrix.filter(cm => cm.module === currentModule.code)
|
|
92
|
+
moduleStakeholders = cadrage.stakeholders.filter(s => s.tasks relevant to this module)
|
|
93
|
+
moduleRisks = cadrage.risks.filter(r => r related to this module)
|
|
94
|
+
|
|
95
|
+
ba-writer.enrichSection({
|
|
96
|
+
featureId: {module_feature_id},
|
|
97
|
+
section: "discovery",
|
|
98
|
+
data: {
|
|
99
|
+
problem: cadrage.problem,
|
|
100
|
+
asIs: cadrage.asIs,
|
|
101
|
+
toBe: cadrage.toBe,
|
|
102
|
+
trigger: cadrage.trigger,
|
|
103
|
+
stakeholders: moduleStakeholders,
|
|
104
|
+
scope: {
|
|
105
|
+
mustHave: moduleScope.filter(s => s.category === "mustHave").map(s => s.item),
|
|
106
|
+
shouldHave: moduleScope.filter(s => s.category === "shouldHave").map(s => s.item),
|
|
107
|
+
couldHave: moduleScope.filter(s => s.category === "couldHave").map(s => s.item),
|
|
108
|
+
outOfScope: []
|
|
109
|
+
},
|
|
110
|
+
risks: moduleRisks,
|
|
111
|
+
acceptanceCriteria: cadrage.acceptanceCriteria.filter(ac => relevant to module),
|
|
112
|
+
codebaseContext: cadrage.codebaseContext
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
> **STRUCTURE CARD: discovery** — Same format as cadrage but module-scoped.
|
|
118
|
+
> Fields: `problem`, `asIs`, `toBe`, `trigger`, `stakeholders[]`, `scope{}`, `risks[]`, `acceptanceCriteria[]`, `codebaseContext`, `openQuestions[]`
|
|
119
|
+
|
|
82
120
|
### 2-bis. Coverage Verification (MANDATORY)
|
|
83
121
|
|
|
84
122
|
> **Before specifying any module, verify that the coverageMatrix from cadrage covers this module.**
|
|
@@ -149,8 +187,173 @@ options:
|
|
|
149
187
|
description: "Tableau de bord avec KPIs, graphiques (Recharts) et métriques clés"
|
|
150
188
|
```
|
|
151
189
|
|
|
190
|
+
#### 3a-depth. Determine Specification Depth
|
|
191
|
+
|
|
192
|
+
> **Based on module complexity and type, determine how deeply to specify sections and resources.**
|
|
193
|
+
> **This avoids over-specifying simple modules and under-specifying complex ones.**
|
|
194
|
+
|
|
195
|
+
Read from application master:
|
|
196
|
+
```
|
|
197
|
+
ba-reader.readApplicationContext({feature_id})
|
|
198
|
+
→ module = modules.find(m => m.code === currentModule)
|
|
199
|
+
→ complexity = module.estimatedComplexity // simple | medium | complex
|
|
200
|
+
→ featureType = module.featureType // data-centric | workflow | integration | reporting | full-module
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Depth decision matrix:**
|
|
204
|
+
|
|
205
|
+
| Complexity | featureType | Depth | Behavior |
|
|
206
|
+
|---|---|---|---|
|
|
207
|
+
| simple | data-centric | **convention** | Auto-generate sections + resources from entities. Quick client validation. |
|
|
208
|
+
| simple | reporting | **convention** | Standard dashboard template. Quick validation. |
|
|
209
|
+
| simple | * | **convention** | Standard sections for featureType. Quick validation. |
|
|
210
|
+
| medium | data-centric | **override** | Auto-generate then ask client which sections to customize. |
|
|
211
|
+
| medium | workflow | **full** | State machine required → always full. |
|
|
212
|
+
| medium | * | **override** | Auto-generate then ask client to customize. |
|
|
213
|
+
| complex | * | **full** | Full specification: state machine, typed columns, conditional actions. |
|
|
214
|
+
| * | workflow | **full** | Always full for workflow modules (state machine is mandatory). |
|
|
215
|
+
|
|
216
|
+
Display to client:
|
|
217
|
+
```
|
|
218
|
+
"Module {currentModule}: complexité {complexity}, type {featureType} → profondeur: {depth}"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**IF depth = convention:**
|
|
222
|
+
- Execute 3a-infer (auto-inference) → generates sections + resources
|
|
223
|
+
- Execute 3b (wireframes) for each section
|
|
224
|
+
- Skip 3a-bis detailed walkthrough → present auto-generated spec for quick validation
|
|
225
|
+
- Ask client: "La spécification auto-générée convient-elle, ou souhaitez-vous personnaliser certaines sections ?"
|
|
226
|
+
- If client says OK → proceed to step 4 (questionnaires)
|
|
227
|
+
- If client wants changes → switch to **override** for specified sections
|
|
228
|
+
|
|
229
|
+
**IF depth = override:**
|
|
230
|
+
- Execute 3a-infer (auto-inference) → generates base sections + resources
|
|
231
|
+
- Ask client: "Quelles sections souhaitez-vous personnaliser ?"
|
|
232
|
+
- For selected sections → execute full 3a-bis + 3b + 3b-ter
|
|
233
|
+
- For other sections → keep auto-generated spec
|
|
234
|
+
|
|
235
|
+
**IF depth = full:**
|
|
236
|
+
- Execute standard flow: 3a-bis → 3b → 3b-bis → 3b-ter → 3c → 3d (as currently defined below)
|
|
237
|
+
- PLUS: 3a-state (state machine definition) for entities with status fields
|
|
238
|
+
|
|
239
|
+
#### 3a-infer. Auto-Infer Resources from Entities (Convention/Override)
|
|
240
|
+
|
|
241
|
+
> **For convention and override depths, auto-generate resource details from entity definitions.**
|
|
242
|
+
> **The goal: produce a complete spec without manual input, that the client only validates.**
|
|
243
|
+
|
|
244
|
+
**Prerequisites:** Entity attributes must be defined (from step 6) OR anticipated from decomposition.
|
|
245
|
+
|
|
246
|
+
**Inference rules - Entity attribute → SmartTable column:**
|
|
247
|
+
|
|
248
|
+
| Attribute Type | Column Format | Sortable | Filterable | Notes |
|
|
249
|
+
|---|---|---|---|---|
|
|
250
|
+
| string + unique | text | yes | yes | clickAction: navigate:detail |
|
|
251
|
+
| string | text | yes | yes | — |
|
|
252
|
+
| enum / status | badge | yes | yes (multi-select) | colorMap from lifeCycles if exists |
|
|
253
|
+
| FK:Entity | text (join .name) | yes | yes (entity-select) | Display related entity name |
|
|
254
|
+
| decimal | currency | yes | no | — |
|
|
255
|
+
| int | number | yes | no | — |
|
|
256
|
+
| datetime | date-relative | yes | yes (date-range) | — |
|
|
257
|
+
| bool | boolean | yes | yes (toggle) | — |
|
|
258
|
+
| text (long) | — | no | no | Hidden in table, visible in detail |
|
|
259
|
+
|
|
260
|
+
**Inference rules - Entity attribute → SmartForm field:**
|
|
261
|
+
|
|
262
|
+
| Attribute Type | Component | Required from | Notes |
|
|
263
|
+
|---|---|---|---|
|
|
264
|
+
| string | Input | entity.required | — |
|
|
265
|
+
| string (multiline) | TextArea | entity.required | rows: 4 |
|
|
266
|
+
| enum | Select | entity.required | source: enum name |
|
|
267
|
+
| FK:Entity | EntitySelect | entity.required | source: target entity, searchable |
|
|
268
|
+
| decimal | NumberInput | entity.required | — |
|
|
269
|
+
| int | NumberInput | entity.required | — |
|
|
270
|
+
| datetime | DatePicker | entity.required | — |
|
|
271
|
+
| bool | Toggle | — | default: false |
|
|
272
|
+
|
|
273
|
+
**Auto-generated sections per featureType:**
|
|
274
|
+
|
|
275
|
+
| featureType | Sections generated |
|
|
276
|
+
|---|---|
|
|
277
|
+
| data-centric | list, create, detail |
|
|
278
|
+
| workflow | list, create, detail, edit |
|
|
279
|
+
| integration | list, detail, config |
|
|
280
|
+
| reporting | dashboard |
|
|
281
|
+
| full-module | list, create, detail, edit, dashboard |
|
|
282
|
+
|
|
283
|
+
**For each auto-generated section:**
|
|
284
|
+
|
|
285
|
+
1. **list section:** SmartTable with all non-long-text attributes as columns (convention or columnDefs based on depth), actions = [view, edit, delete], defaultSort = { createdAt, desc }
|
|
286
|
+
2. **create section:** SmartForm with all writable attributes as fields, component inferred from type
|
|
287
|
+
3. **detail section:** DetailCard with all attributes + child SmartTable for each 1:N relationship
|
|
288
|
+
4. **edit section:** Same as create but pre-filled (mode: edit)
|
|
289
|
+
5. **dashboard section:** Trigger 3d (dashboard specification)
|
|
290
|
+
|
|
291
|
+
**If entity has a status/enum field AND lifeCycles exists:**
|
|
292
|
+
- list section: status column gets `format: badge`, `colorMap: stateMachine:{Entity}`
|
|
293
|
+
- list section: rowActions get `showWhen` conditions based on state machine transitions
|
|
294
|
+
- detail section: add StatusBadge resource + transition action buttons
|
|
295
|
+
|
|
296
|
+
Write auto-generated sections to `specification.sections[]` via ba-writer.enrichSection()
|
|
297
|
+
|
|
298
|
+
#### 3a-state. Define Entity State Machine (Full Depth)
|
|
299
|
+
|
|
300
|
+
> **For full depth modules with entities that have a status/enum field, define the complete state machine.**
|
|
301
|
+
> **This drives conditional actions, badges, and transition effects throughout the UI.**
|
|
302
|
+
|
|
303
|
+
For each entity with a status-like attribute:
|
|
304
|
+
|
|
305
|
+
1. **Identify states** from the enum values or business rules:
|
|
306
|
+
```
|
|
307
|
+
Ask client: "Quels sont les états possibles pour {Entity}.{statusField} ?"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
2. **Define transitions** - for each state, ask:
|
|
311
|
+
```
|
|
312
|
+
Ask client: "Depuis l'état {state}, quelles transitions sont possibles ?"
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
3. **For each transition**, capture:
|
|
316
|
+
- `action`: verb label (submit, approve, reject, cancel, archive)
|
|
317
|
+
- `permission`: which permission is required
|
|
318
|
+
- `guards`: which BR must pass (reference existing BR-XXX from analysis)
|
|
319
|
+
- `effects`: what happens after (notification, email, field update)
|
|
320
|
+
- `confirm`: does the user need to confirm?
|
|
321
|
+
|
|
322
|
+
4. **Assign colors** to states for badge rendering:
|
|
323
|
+
- Draft/New → gray
|
|
324
|
+
- In Progress/Submitted → blue
|
|
325
|
+
- Approved/Active → green
|
|
326
|
+
- Warning/Pending → yellow
|
|
327
|
+
- Error/Rejected → red
|
|
328
|
+
- Archived/Cancelled → purple
|
|
329
|
+
|
|
330
|
+
5. **Store** in `specification.lifeCycles[]`:
|
|
331
|
+
```json
|
|
332
|
+
{
|
|
333
|
+
"entity": "{Entity}",
|
|
334
|
+
"field": "status",
|
|
335
|
+
"initialState": "{firstState}",
|
|
336
|
+
"states": [
|
|
337
|
+
{ "id": "draft", "displayName": "Brouillon", "color": "gray", "allowedTransitions": ["submitted"], "isTerminal": false }
|
|
338
|
+
],
|
|
339
|
+
"transitions": [
|
|
340
|
+
{
|
|
341
|
+
"from": "draft", "to": "submitted", "action": "submit",
|
|
342
|
+
"permission": "business.{app}.{module}.submit",
|
|
343
|
+
"guards": ["BR-VAL-{PREFIX}-001"],
|
|
344
|
+
"effects": [{ "type": "notification", "target": "role:manager", "template": "{module}-submitted" }],
|
|
345
|
+
"confirm": true
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
6. **Cross-validate:** Every `allowedTransitions` entry must have a matching `transitions[]` entry.
|
|
352
|
+
|
|
152
353
|
#### 3a-bis. Structure Sections with Resources (Levels 4 & 5)
|
|
153
354
|
|
|
355
|
+
> **DEPTH GATE:** Execute this section for **full** depth, or for individual sections flagged for customization in **override** depth. For **convention** depth, sections are auto-generated by 3a-infer — skip to 3b.
|
|
356
|
+
|
|
154
357
|
For EACH section confirmed in 3a, build the `specification.sections[]` structure:
|
|
155
358
|
|
|
156
359
|
1. For each resource in the section, determine:
|
|
@@ -169,29 +372,73 @@ For EACH section confirmed in 3a, build the `specification.sections[]` structure
|
|
|
169
372
|
- Map BR based on where it's enforced (validation BR → create/edit section, calc BR → detail section)
|
|
170
373
|
|
|
171
374
|
4. Build the section object:
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
|
|
375
|
+
|
|
376
|
+
> **STRUCTURE CARD: specification.sections[]** — Resources MUST include full depth definitions.
|
|
377
|
+
> ```json
|
|
378
|
+
> {
|
|
379
|
+
> "code": "list",
|
|
380
|
+
> "labels": { "fr": "Liste", "en": "List", "it": "Elenco", "de": "Liste" },
|
|
381
|
+
> "route": "/business/{app}/{module}/list",
|
|
382
|
+
> "icon": "list",
|
|
383
|
+
> "permission": "business.{app}.{module}.read",
|
|
384
|
+
> "wireframe": "{module}-list",
|
|
385
|
+
> "useCases": ["UC-{PREFIX}-001", "UC-{PREFIX}-002"],
|
|
386
|
+
> "businessRules": ["BR-VAL-{PREFIX}-001"],
|
|
387
|
+
> "resources": [
|
|
388
|
+
> {
|
|
389
|
+
> "code": "{module}-grid",
|
|
390
|
+
> "type": "SmartTable",
|
|
391
|
+
> "entity": "{MainEntity}",
|
|
392
|
+
> "permission": "business.{app}.{module}.read",
|
|
393
|
+
> "columns": ["name", "status", "createdAt"],
|
|
394
|
+
> "columnDefs": [
|
|
395
|
+
> { "field": "code", "label": {"fr": "Code", "en": "Code"}, "format": "text", "sortable": true, "filterable": true, "clickAction": "navigate:detail" },
|
|
396
|
+
> { "field": "name", "label": {"fr": "Nom", "en": "Name"}, "format": "text", "sortable": true, "filterable": true },
|
|
397
|
+
> { "field": "status", "label": {"fr": "Statut", "en": "Status"}, "format": "badge", "sortable": true, "filterable": true, "colorMap": "stateMachine:{Entity}" },
|
|
398
|
+
> { "field": "createdAt", "label": {"fr": "Créé le", "en": "Created"}, "format": "date-relative", "sortable": true }
|
|
399
|
+
> ],
|
|
400
|
+
> "actions": ["view", "edit", "delete"],
|
|
401
|
+
> "rowActions": [
|
|
402
|
+
> { "action": "view", "icon": "eye", "permission": "business.{app}.{module}.read" },
|
|
403
|
+
> { "action": "edit", "icon": "edit", "permission": "business.{app}.{module}.update", "showWhen": {"status": ["draft"]} },
|
|
404
|
+
> { "action": "delete", "icon": "trash", "permission": "business.{app}.{module}.delete", "confirm": true }
|
|
405
|
+
> ],
|
|
406
|
+
> "filters": ["status", "dateRange"],
|
|
407
|
+
> "defaultSort": { "field": "createdAt", "direction": "desc" },
|
|
408
|
+
> "defaultPageSize": 20,
|
|
409
|
+
> "emptyState": { "icon": "inbox", "message": {"fr": "Aucun enregistrement", "en": "No records"}, "createAction": true }
|
|
410
|
+
> }
|
|
411
|
+
> ]
|
|
412
|
+
> }
|
|
413
|
+
> ```
|
|
414
|
+
>
|
|
415
|
+
> **SmartForm resource example (for create/edit sections):**
|
|
416
|
+
> ```json
|
|
417
|
+
> {
|
|
418
|
+
> "code": "{module}-form",
|
|
419
|
+
> "type": "SmartForm",
|
|
420
|
+
> "entity": "{MainEntity}",
|
|
421
|
+
> "permission": "business.{app}.{module}.create",
|
|
422
|
+
> "fields": [
|
|
423
|
+
> { "name": "code", "component": "Input", "required": true, "validation": "Unique, auto-generated" },
|
|
424
|
+
> { "name": "name", "component": "Input", "required": true },
|
|
425
|
+
> { "name": "type", "component": "Select", "required": true, "source": "EntityTypeEnum" },
|
|
426
|
+
> { "name": "description", "component": "TextArea", "required": false },
|
|
427
|
+
> { "name": "parentId", "component": "EntitySelect", "source": "ParentEntity", "required": true },
|
|
428
|
+
> { "name": "startDate", "component": "DatePicker", "required": true },
|
|
429
|
+
> { "name": "isActive", "component": "Toggle", "default": true }
|
|
430
|
+
> ],
|
|
431
|
+
> "formLayout": {
|
|
432
|
+
> "type": "tabs",
|
|
433
|
+
> "tabs": [
|
|
434
|
+
> { "code": "general", "label": {"fr": "Général", "en": "General"}, "fields": ["code", "name", "type", "description"] },
|
|
435
|
+
> { "code": "details", "label": {"fr": "Détails", "en": "Details"}, "fields": ["parentId", "startDate", "isActive"] }
|
|
436
|
+
> ]
|
|
437
|
+
> }
|
|
438
|
+
> }
|
|
439
|
+
> ```
|
|
440
|
+
> **MANDATORY for SmartTable:** `columnDefs`, `rowActions`, `defaultSort`, `emptyState`
|
|
441
|
+
> **MANDATORY for SmartForm:** `fields` with `component` type, `formLayout`
|
|
195
442
|
|
|
196
443
|
5. Write `specification.sections[]` via ba-writer.enrichSection()
|
|
197
444
|
|
|
@@ -221,20 +468,39 @@ Example for a list section:
|
|
|
221
468
|
|
|
222
469
|
Store in specification.uiWireframes[] (**MANDATORY** for every section):
|
|
223
470
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
>
|
|
471
|
+
> **STRUCTURE CARD: specification.uiWireframes[]** — ALL fields below are MANDATORY.
|
|
472
|
+
> ```json
|
|
473
|
+
> {
|
|
474
|
+
> "screen": "{module}-{section}",
|
|
475
|
+
> "section": "{section}",
|
|
476
|
+
> "description": "Description of the screen",
|
|
477
|
+
> "mockupFormat": "ascii",
|
|
478
|
+
> "mockup": "╔═══...",
|
|
479
|
+
> "elements": ["DataGrid", "FilterBar", "Pagination", "CreateButton"],
|
|
480
|
+
> "actions": ["filter", "sort", "create", "view-detail"],
|
|
481
|
+
> "permissionsRequired": ["business.{app}.{module}.read"],
|
|
482
|
+
> "componentMapping": [
|
|
483
|
+
> { "wireframeElement": "DataGrid", "reactComponent": "SmartTable" },
|
|
484
|
+
> { "wireframeElement": "FilterBar", "reactComponent": "SmartFilter" },
|
|
485
|
+
> { "wireframeElement": "CreateButton", "reactComponent": "Button" }
|
|
486
|
+
> ],
|
|
487
|
+
> "layout": {
|
|
488
|
+
> "type": "page",
|
|
489
|
+
> "regions": [
|
|
490
|
+
> { "id": "toolbar", "position": "top", "components": [
|
|
491
|
+
> { "type": "FilterBar", "resourceRef": "{module}-filters" },
|
|
492
|
+
> { "type": "ActionMenu", "resourceRef": "{module}-actions", "permission": "business.{app}.{module}.create" }
|
|
493
|
+
> ]},
|
|
494
|
+
> { "id": "content", "position": "main", "span": 12, "components": [
|
|
495
|
+
> { "type": "SmartTable", "resourceRef": "{module}-grid" }
|
|
496
|
+
> ]}
|
|
497
|
+
> ]
|
|
498
|
+
> }
|
|
499
|
+
> }
|
|
500
|
+
> ```
|
|
501
|
+
> **REQUIRED fields:** `screen`, `mockup`, `elements`, `section`, `componentMapping`, `layout` are ALL mandatory.
|
|
502
|
+
> A wireframe without `componentMapping` or `layout` will FAIL validation in step 9.
|
|
503
|
+
> **layout.regions[].components[].resourceRef** MUST match a `sections[].resources[].code`.
|
|
238
504
|
|
|
239
505
|
Ask client to validate each mockup via AskUserQuestion (batch 2-3 mockups at once if possible).
|
|
240
506
|
|
|
@@ -332,7 +598,8 @@ When a "dashboard" section is selected, capture structured KPI and chart data **
|
|
|
332
598
|
"metric": "COUNT(entity)",
|
|
333
599
|
"format": "number",
|
|
334
600
|
"visualization": "kpi-card",
|
|
335
|
-
"dataSource": "Entity"
|
|
601
|
+
"dataSource": "Entity",
|
|
602
|
+
"thresholds": { "warning": 100, "critical": 50 }
|
|
336
603
|
},
|
|
337
604
|
{
|
|
338
605
|
"code": "items-by-status",
|
|
@@ -435,101 +702,374 @@ options:
|
|
|
435
702
|
description: "Pas de référence à {completedModule}"
|
|
436
703
|
```
|
|
437
704
|
|
|
438
|
-
### 6.
|
|
705
|
+
### 6. Analysis Section
|
|
439
706
|
|
|
440
|
-
|
|
707
|
+
#### 6a. Objectives
|
|
441
708
|
|
|
442
|
-
|
|
709
|
+
Define measurable business objectives for this module:
|
|
443
710
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
711
|
+
> **STRUCTURE CARD: analysis.objectives[]**
|
|
712
|
+
> ```json
|
|
713
|
+
> { "id": "OBJ-{PREFIX}-001", "objective": "Reduce order processing time", "metric": "Average time to fulfillment", "target": "< 4 hours" }
|
|
714
|
+
> ```
|
|
715
|
+
|
|
716
|
+
#### 6b. Entity Definition
|
|
717
|
+
|
|
718
|
+
Define entities for this module (business attributes, not technical):
|
|
719
|
+
|
|
720
|
+
> **STRUCTURE CARD: analysis.entities[]** — Field names are EXACT. Do NOT deviate.
|
|
721
|
+
> ```json
|
|
722
|
+
> {
|
|
723
|
+
> "name": "PascalCase",
|
|
724
|
+
> "description": "1-2 sentences describing the entity purpose",
|
|
725
|
+
> "attributes": [
|
|
726
|
+
> {
|
|
727
|
+
> "name": "attributeName",
|
|
728
|
+
> "description": "What this attribute represents",
|
|
729
|
+
> "required": true,
|
|
730
|
+
> "unique": false,
|
|
731
|
+
> "validation": "Format: XXX-NNNNN, max 100 chars, etc."
|
|
732
|
+
> }
|
|
733
|
+
> ],
|
|
734
|
+
> "relationships": [
|
|
735
|
+
> { "target": "OtherEntity", "type": "1:1|1:N|N:1|N:M", "description": "description" }
|
|
736
|
+
> ]
|
|
737
|
+
> }
|
|
738
|
+
> ```
|
|
739
|
+
> **FORBIDDEN fields in attributes:** Do NOT use `type`, `values`, `rules`.
|
|
740
|
+
> Use `description` to explain what the attribute is, `validation` for format/constraint rules, `unique` as boolean.
|
|
741
|
+
|
|
742
|
+
#### 6c. Process Flow
|
|
743
|
+
|
|
744
|
+
Define the main business process flow for this module (not lifecycle — that's in 8j):
|
|
745
|
+
|
|
746
|
+
> **STRUCTURE CARD: analysis.processFlow**
|
|
747
|
+
> ```json
|
|
748
|
+
> {
|
|
749
|
+
> "entryPoints": ["User navigates to module", "System event triggers action"],
|
|
750
|
+
> "mainFlow": [
|
|
751
|
+
> { "step": 1, "actor": "Manager", "action": "Opens the list", "system": "Displays filtered records" },
|
|
752
|
+
> { "step": 2, "actor": "Manager", "action": "Creates a record", "system": "Validates BR-VAL-{PREFIX}-001" },
|
|
753
|
+
> { "step": 3, "actor": "System", "action": "Saves record", "system": "Sends notification" }
|
|
754
|
+
> ],
|
|
755
|
+
> "decisionPoints": [
|
|
756
|
+
> { "condition": "Is amount > threshold?", "ifTrue": "Route to approver", "ifFalse": "Auto-approve", "rule": "BR-WF-{PREFIX}-001" }
|
|
757
|
+
> ],
|
|
758
|
+
> "alternativeFlows": ["Bulk import via CSV", "Automatic sync from SFTP"]
|
|
759
|
+
> }
|
|
760
|
+
> ```
|
|
761
|
+
> **FORBIDDEN:** Do NOT put lifecycle/state machine data here. Use `specification.lifeCycles[]` for that.
|
|
762
|
+
|
|
763
|
+
#### 6d. Data Lifecycle
|
|
764
|
+
|
|
765
|
+
Define data retention and lifecycle policies:
|
|
766
|
+
|
|
767
|
+
> **STRUCTURE CARD: analysis.dataLifecycle**
|
|
768
|
+
> ```json
|
|
769
|
+
> {
|
|
770
|
+
> "retentionPeriod": "7 years",
|
|
771
|
+
> "archiveStrategy": "Move to cold storage after 2 years",
|
|
772
|
+
> "gdprCompliance": "PII anonymized on request, data export available",
|
|
773
|
+
> "states": [
|
|
774
|
+
> { "name": "active", "transitions": ["archived", "deleted"] },
|
|
775
|
+
> { "name": "archived", "transitions": ["active"] },
|
|
776
|
+
> { "name": "deleted", "transitions": [] }
|
|
777
|
+
> ]
|
|
778
|
+
> }
|
|
779
|
+
> ```
|
|
456
780
|
|
|
457
781
|
### 7. Business Rules Extraction
|
|
458
782
|
|
|
459
783
|
Extract business rules specific to this module:
|
|
460
784
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
{
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
785
|
+
> **STRUCTURE CARD: analysis.businessRules[]** — Field names are EXACT. Do NOT deviate.
|
|
786
|
+
> ```json
|
|
787
|
+
> {
|
|
788
|
+
> "id": "BR-VAL-{PREFIX}-001",
|
|
789
|
+
> "name": "Short rule name",
|
|
790
|
+
> "category": "validation|calculation|workflow|security|data",
|
|
791
|
+
> "statement": "IF {condition} THEN {consequence} ELSE {alternative}",
|
|
792
|
+
> "priority": "must|should|could",
|
|
793
|
+
> "conditions": ["Condition 1", "Condition 2"],
|
|
794
|
+
> "examples": [{ "input": "Order total $5000, budget $2000", "expected": "Order rejected" }],
|
|
795
|
+
> "testability": "Via unit test with mock data / integration test"
|
|
796
|
+
> }
|
|
797
|
+
> ```
|
|
798
|
+
> **MANDATORY fields:** `id`, `name`, `category`, `statement`, `priority`
|
|
799
|
+
> **FORBIDDEN fields:** Do NOT use `rule`, `condition` (singular), `action`. Use `name` + `statement` (IF/THEN/ELSE format) + `conditions` (array).
|
|
800
|
+
> **ID PATTERN:** `BR-{CAT}-{PREFIX}-{NNN}` where CAT = VAL|CALC|WF|SEC|DATA, PREFIX = module initials (2-4 chars)
|
|
801
|
+
> **category values:** lowercase only: `validation`, `calculation`, `workflow`, `security`, `data`
|
|
475
802
|
|
|
476
803
|
### 8. Full Specification
|
|
477
804
|
|
|
478
|
-
Generate the complete specification for this module
|
|
805
|
+
Generate the complete specification for this module. **Each subsection below includes a STRUCTURE CARD showing the EXACT JSON format. Follow them precisely.**
|
|
479
806
|
|
|
480
807
|
#### 8a. Actors
|
|
481
808
|
|
|
482
|
-
Inherited from application roles → mapped to module permissions
|
|
483
|
-
|
|
484
|
-
|
|
809
|
+
Inherited from application roles → mapped to module permissions.
|
|
810
|
+
|
|
811
|
+
> **STRUCTURE CARD: specification.actors[]**
|
|
812
|
+
> ```json
|
|
813
|
+
> {
|
|
814
|
+
> "role": "Sales Manager",
|
|
815
|
+
> "description": "Creates and approves orders",
|
|
816
|
+
> "permissions": [
|
|
817
|
+
> "business.{app}.{module}.read",
|
|
818
|
+
> "business.{app}.{module}.create",
|
|
819
|
+
> "business.{app}.{module}.update"
|
|
820
|
+
> ]
|
|
821
|
+
> }
|
|
822
|
+
> ```
|
|
823
|
+
> **MANDATORY fields:** `role`, `permissions` (array of permission paths)
|
|
824
|
+
> **FORBIDDEN fields:** Do NOT use `systemRole`. Use `permissions` array.
|
|
825
|
+
|
|
826
|
+
#### 8b. Use Cases (UC-{PREFIX}-NNN)
|
|
485
827
|
|
|
486
828
|
Per section: list, create, read, update, delete, approve, etc.
|
|
487
829
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
830
|
+
> **STRUCTURE CARD: specification.useCases[]**
|
|
831
|
+
> ```json
|
|
832
|
+
> {
|
|
833
|
+
> "id": "UC-{PREFIX}-001",
|
|
834
|
+
> "name": "Create Order",
|
|
835
|
+
> "primaryActor": "Sales Representative",
|
|
836
|
+
> "permission": "business.{app}.{module}.create",
|
|
837
|
+
> "preconditions": ["Customer exists", "Products in stock"],
|
|
838
|
+
> "postconditions": ["Order created with Draft status"],
|
|
839
|
+
> "mainScenario": [
|
|
840
|
+
> "1. User navigates to creation form",
|
|
841
|
+
> "2. User fills in required fields",
|
|
842
|
+
> "3. System validates data (BR-VAL-{PREFIX}-001)",
|
|
843
|
+
> "4. System creates the record",
|
|
844
|
+
> "5. System displays confirmation"
|
|
845
|
+
> ],
|
|
846
|
+
> "alternativeScenarios": [
|
|
847
|
+
> { "name": "Validation failure", "steps": ["1. System detects invalid data", "2. System highlights errors"] }
|
|
848
|
+
> ],
|
|
849
|
+
> "errorScenarios": [
|
|
850
|
+
> { "name": "Server error", "steps": ["1. System shows error message", "2. Data preserved for retry"] }
|
|
851
|
+
> ],
|
|
852
|
+
> "linkedRules": ["BR-VAL-{PREFIX}-001", "BR-WF-{PREFIX}-002"]
|
|
853
|
+
> }
|
|
854
|
+
> ```
|
|
855
|
+
> **MANDATORY fields:** `id`, `name`, `primaryActor`, `permission`, `mainScenario`, `linkedRules`
|
|
856
|
+
> **FORBIDDEN fields:** Do NOT use `actor` (use `primaryActor`), `linkedBRs` (use `linkedRules`), `linkedFRs` (not in UC, FRs link to UCs instead)
|
|
857
|
+
|
|
858
|
+
#### 8c. Functional Requirements (FR-{PREFIX}-NNN)
|
|
859
|
+
|
|
860
|
+
Linked to BRs and UCs.
|
|
861
|
+
|
|
862
|
+
> **STRUCTURE CARD: specification.functionalRequirements[]**
|
|
863
|
+
> ```json
|
|
864
|
+
> {
|
|
865
|
+
> "id": "FR-{PREFIX}-001",
|
|
866
|
+
> "statement": "System MUST validate customer budget before order creation",
|
|
867
|
+
> "priority": "must|should|could",
|
|
868
|
+
> "linkedRules": ["BR-VAL-{PREFIX}-001"],
|
|
869
|
+
> "linkedUseCases": ["UC-{PREFIX}-001"],
|
|
870
|
+
> "acceptanceCriteria": [
|
|
871
|
+
> "Order rejected if total > budget",
|
|
872
|
+
> "Error message displayed with remaining budget"
|
|
873
|
+
> ]
|
|
874
|
+
> }
|
|
875
|
+
> ```
|
|
876
|
+
> **MANDATORY fields:** `id`, `statement`, `priority`, `linkedUseCases`
|
|
877
|
+
> **FORBIDDEN fields:** Do NOT use `name`/`description` (use `statement` with System MUST/SHOULD/COULD format), `linkedUCs` (use `linkedUseCases`), `linkedBRs` (use `linkedRules`)
|
|
491
878
|
|
|
492
879
|
#### 8d. Permission Matrix
|
|
493
880
|
|
|
494
|
-
Roles × resources × operations with full paths
|
|
881
|
+
Roles × resources × operations with full paths.
|
|
882
|
+
|
|
883
|
+
> **STRUCTURE CARD: specification.permissionMatrix**
|
|
884
|
+
> ```json
|
|
885
|
+
> {
|
|
886
|
+
> "permissions": [
|
|
887
|
+
> { "path": "business.{app}.{module}.read", "action": "read", "description": "View records" },
|
|
888
|
+
> { "path": "business.{app}.{module}.create", "action": "create", "description": "Create new records" },
|
|
889
|
+
> { "path": "business.{app}.{module}.update", "action": "update", "description": "Update existing records" },
|
|
890
|
+
> { "path": "business.{app}.{module}.delete", "action": "delete", "description": "Delete records" },
|
|
891
|
+
> { "path": "business.{app}.{module}.export", "action": "export", "description": "Export data" }
|
|
892
|
+
> ],
|
|
893
|
+
> "roleAssignments": [
|
|
894
|
+
> { "role": "{App} Admin", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update", "business.{app}.{module}.delete", "business.{app}.{module}.export"] },
|
|
895
|
+
> { "role": "{App} Manager", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update"] },
|
|
896
|
+
> { "role": "{App} Viewer", "permissions": ["business.{app}.{module}.read"] }
|
|
897
|
+
> ]
|
|
898
|
+
> }
|
|
899
|
+
> ```
|
|
900
|
+
> **STRUCTURE:** Object with 2 arrays: `permissions[]` and `roleAssignments[]`
|
|
901
|
+
> **FORBIDDEN:** Do NOT use a flat array with `resource`/`roles` fields. Always use the nested structure above.
|
|
495
902
|
|
|
496
903
|
#### 8e. Navigation
|
|
497
904
|
|
|
498
|
-
Module → Sections → Resources (levels 3-4-5 of the hierarchy)
|
|
905
|
+
Module → Sections → Resources (levels 3-4-5 of the hierarchy).
|
|
499
906
|
|
|
500
|
-
|
|
907
|
+
> **STRUCTURE CARD: specification.navigation**
|
|
908
|
+
> ```json
|
|
909
|
+
> {
|
|
910
|
+
> "entries": [
|
|
911
|
+
> { "level": "module", "code": "{module}", "labels": {"fr": "...", "en": "..."}, "route": "/business/{app}/{module}", "icon": "list" },
|
|
912
|
+
> { "level": "section", "code": "list", "labels": {"fr": "Liste", "en": "List", "it": "Elenco", "de": "Liste"}, "route": "/business/{app}/{module}/list", "icon": "list" },
|
|
913
|
+
> { "level": "section", "code": "dashboard", "labels": {"fr": "Dashboard", "en": "Dashboard"}, "route": "/business/{app}/{module}/dashboard", "icon": "chart-bar", "isNew": true }
|
|
914
|
+
> ]
|
|
915
|
+
> }
|
|
916
|
+
> ```
|
|
501
917
|
|
|
502
|
-
|
|
918
|
+
#### 8f. SeedData Core
|
|
503
919
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
920
|
+
5 MANDATORY typed arrays — each with structured objects, NOT flat strings or objects.
|
|
921
|
+
|
|
922
|
+
> **STRUCTURE CARD: specification.seedDataCore**
|
|
923
|
+
> ```json
|
|
924
|
+
> {
|
|
925
|
+
> "navigationModules": [
|
|
926
|
+
> { "code": "{module}", "label": "{Module Name}", "icon": "list", "route": "/business/{app}/{module}", "parentCode": "{app}", "sort": 1 }
|
|
927
|
+
> ],
|
|
928
|
+
> "navigationTranslations": [
|
|
929
|
+
> { "moduleCode": "{module}", "language": "fr", "label": "..." },
|
|
930
|
+
> { "moduleCode": "{module}", "language": "en", "label": "..." },
|
|
931
|
+
> { "moduleCode": "{module}", "language": "it", "label": "..." },
|
|
932
|
+
> { "moduleCode": "{module}", "language": "de", "label": "..." }
|
|
933
|
+
> ],
|
|
934
|
+
> "permissions": [
|
|
935
|
+
> { "path": "business.{app}.{module}.read", "action": "read", "description": "View {module}" },
|
|
936
|
+
> { "path": "business.{app}.{module}.create", "action": "create", "description": "Create {module}" }
|
|
937
|
+
> ],
|
|
938
|
+
> "rolePermissions": [
|
|
939
|
+
> { "role": "{App} Admin", "permissionPath": "business.{app}.{module}.*" },
|
|
940
|
+
> { "role": "{App} Manager", "permissionPath": "business.{app}.{module}.read" }
|
|
941
|
+
> ],
|
|
942
|
+
> "permissionConstants": [
|
|
943
|
+
> { "constantName": "{Module}Read", "path": "business.{app}.{module}.read" },
|
|
944
|
+
> { "constantName": "{Module}Create", "path": "business.{app}.{module}.create" }
|
|
945
|
+
> ]
|
|
946
|
+
> }
|
|
947
|
+
> ```
|
|
948
|
+
> **MANDATORY:** All 5 arrays must be present. Each element must be an object, NOT a string.
|
|
949
|
+
> **FORBIDDEN:** Do NOT use `navigationModule` (singular string), `permissions` as flat string array, `rolePermissions` as flat object, `permissionsConstants` as comma-separated string.
|
|
509
950
|
|
|
510
951
|
#### 8g. Gherkin Scenarios
|
|
511
952
|
|
|
512
|
-
BDD acceptance tests per UC
|
|
953
|
+
BDD acceptance tests per UC.
|
|
954
|
+
|
|
955
|
+
> **STRUCTURE CARD: specification.gherkinScenarios[]**
|
|
956
|
+
> ```json
|
|
957
|
+
> {
|
|
958
|
+
> "feature": "{Module} Management",
|
|
959
|
+
> "scenarios": [
|
|
960
|
+
> {
|
|
961
|
+
> "name": "Create a new record with valid data",
|
|
962
|
+
> "tags": ["@{module}", "@create", "@smoke"],
|
|
963
|
+
> "given": ["An authenticated user with role Manager", "No existing record with code 'TEST-001'"],
|
|
964
|
+
> "when": ["The user fills the creation form", "The user submits the form"],
|
|
965
|
+
> "then": ["The record is created with Draft status", "A success message is displayed"]
|
|
966
|
+
> }
|
|
967
|
+
> ]
|
|
968
|
+
> }
|
|
969
|
+
> ```
|
|
970
|
+
> **STRUCTURE:** Object with `feature` string + `scenarios[]` array. Each scenario has `given`, `when`, `then` as ARRAYS of strings.
|
|
971
|
+
> **FORBIDDEN:** Do NOT use flat arrays of `{uc, scenario, given, when, then}` where given/when/then are single strings.
|
|
513
972
|
|
|
514
973
|
#### 8h. Validations
|
|
515
974
|
|
|
516
|
-
Field validation rules
|
|
975
|
+
Field validation rules per entity.
|
|
976
|
+
|
|
977
|
+
> **STRUCTURE CARD: specification.validations[]**
|
|
978
|
+
> ```json
|
|
979
|
+
> {
|
|
980
|
+
> "entity": "Order",
|
|
981
|
+
> "field": "amount",
|
|
982
|
+
> "rules": ["required", "decimal", "min:0.01", "max:999999.99"],
|
|
983
|
+
> "errorMessageKey": "validation.{module}.amount.invalid"
|
|
984
|
+
> }
|
|
985
|
+
> ```
|
|
986
|
+
> **MANDATORY fields:** `entity`, `field`, `rules` (array), `errorMessageKey`
|
|
987
|
+
> **FORBIDDEN fields:** Do NOT use `rule` (singular string) or `message` (use `errorMessageKey`).
|
|
517
988
|
|
|
518
989
|
#### 8i. Business Messages
|
|
519
990
|
|
|
520
|
-
Minimum 4: success, error CRUD, error validation, error permission
|
|
991
|
+
Minimum 4: success, error CRUD, error validation, error permission.
|
|
992
|
+
|
|
993
|
+
> **STRUCTURE CARD: specification.messages[]**
|
|
994
|
+
> ```json
|
|
995
|
+
> {
|
|
996
|
+
> "code": "{MODULE}-SUCCESS-CREATE",
|
|
997
|
+
> "type": "success|error|warning|info",
|
|
998
|
+
> "title": "Record Created",
|
|
999
|
+
> "message": "The record {code} has been created successfully.",
|
|
1000
|
+
> "i18nKey": "message.{module}.created"
|
|
1001
|
+
> }
|
|
1002
|
+
> ```
|
|
1003
|
+
> **MANDATORY fields:** `code`, `type`, `message`, `i18nKey`
|
|
1004
|
+
> **FORBIDDEN:** Do NOT omit `title` or `i18nKey`. Every message MUST have an i18n key.
|
|
521
1005
|
|
|
522
1006
|
#### 8j. Entity Lifecycle
|
|
523
1007
|
|
|
524
|
-
State machines for entities with status/state
|
|
1008
|
+
State machines for entities with status/state.
|
|
1009
|
+
**Note:** If depth = full and 3a-state was executed, lifeCycles are already defined. Verify completeness and add any missing states/transitions.
|
|
1010
|
+
|
|
1011
|
+
> **STRUCTURE CARD: specification.lifeCycles[]**
|
|
1012
|
+
> ```json
|
|
1013
|
+
> {
|
|
1014
|
+
> "entity": "Order",
|
|
1015
|
+
> "field": "status",
|
|
1016
|
+
> "initialState": "draft",
|
|
1017
|
+
> "states": [
|
|
1018
|
+
> { "id": "draft", "displayName": "Brouillon", "color": "gray", "allowedTransitions": ["submitted"], "isTerminal": false },
|
|
1019
|
+
> { "id": "submitted", "displayName": "Soumis", "color": "blue", "allowedTransitions": ["approved", "rejected"], "isTerminal": false },
|
|
1020
|
+
> { "id": "approved", "displayName": "Approuvé", "color": "green", "allowedTransitions": ["archived"], "isTerminal": false },
|
|
1021
|
+
> { "id": "rejected", "displayName": "Rejeté", "color": "red", "allowedTransitions": [], "isTerminal": true },
|
|
1022
|
+
> { "id": "archived", "displayName": "Archivé", "color": "purple", "allowedTransitions": [], "isTerminal": true }
|
|
1023
|
+
> ],
|
|
1024
|
+
> "transitions": [
|
|
1025
|
+
> {
|
|
1026
|
+
> "from": "draft", "to": "submitted", "action": "submit",
|
|
1027
|
+
> "label": { "fr": "Soumettre", "en": "Submit" },
|
|
1028
|
+
> "permission": "business.{app}.{module}.update",
|
|
1029
|
+
> "guards": ["BR-VAL-{PREFIX}-001"],
|
|
1030
|
+
> "effects": [{ "type": "notification", "target": "role:manager", "template": "{module}-submitted" }],
|
|
1031
|
+
> "confirm": true
|
|
1032
|
+
> }
|
|
1033
|
+
> ]
|
|
1034
|
+
> }
|
|
1035
|
+
> ```
|
|
1036
|
+
> **MANDATORY:** `states` MUST be an array of OBJECTS with `id`, `displayName`, `color`, `allowedTransitions`, `isTerminal`. NEVER use flat string arrays.
|
|
1037
|
+
> **Colors:** gray (draft/new), blue (in-progress), green (active/approved), yellow (warning/pending), orange (review), red (error/rejected), purple (archived/terminal)
|
|
1038
|
+
> **FORBIDDEN:** Do NOT use `states: ["Active", "Inactive"]` (flat strings), `terminalStates` (use `isTerminal: true` on each state).
|
|
525
1039
|
|
|
526
1040
|
#### 8k. API Endpoints
|
|
527
1041
|
|
|
528
|
-
RESTful routes following SmartStack patterns
|
|
1042
|
+
RESTful routes following SmartStack patterns.
|
|
1043
|
+
|
|
1044
|
+
> **STRUCTURE CARD: specification.apiEndpoints[]**
|
|
1045
|
+
> ```json
|
|
1046
|
+
> {
|
|
1047
|
+
> "method": "GET|POST|PUT|PATCH|DELETE",
|
|
1048
|
+
> "path": "/api/business/{app}/{module}",
|
|
1049
|
+
> "permission": "business.{app}.{module}.read",
|
|
1050
|
+
> "requestDto": "Get{Module}Query",
|
|
1051
|
+
> "responseDto": "{Module}Dto[]",
|
|
1052
|
+
> "description": "List all records with pagination and filters"
|
|
1053
|
+
> }
|
|
1054
|
+
> ```
|
|
1055
|
+
> **MANDATORY fields:** `method`, `path`, `permission`, `description`
|
|
1056
|
+
> **Recommended:** Include `requestDto` and `responseDto` for implementation clarity.
|
|
529
1057
|
|
|
530
1058
|
#### 8l. i18n Keys
|
|
531
1059
|
|
|
532
|
-
Translation keys for all UI text (4 languages: fr, en, it, de)
|
|
1060
|
+
Translation keys for all UI text (4 languages: fr, en, it, de).
|
|
1061
|
+
|
|
1062
|
+
> **STRUCTURE CARD: specification.i18nKeys**
|
|
1063
|
+
> ```json
|
|
1064
|
+
> {
|
|
1065
|
+
> "title": { "fr": "{Module}", "en": "{Module}", "it": "{Module}", "de": "{Module}" },
|
|
1066
|
+
> "list": { "title": { "fr": "Liste", "en": "List" }, "empty": { "fr": "Aucun enregistrement", "en": "No records" } },
|
|
1067
|
+
> "create": { "title": { "fr": "Nouveau", "en": "New" } },
|
|
1068
|
+
> "detail": { "title": { "fr": "Détail", "en": "Detail" } },
|
|
1069
|
+
> "buttons": { "create": { "fr": "Créer", "en": "Create" }, "edit": { "fr": "Modifier", "en": "Edit" }, "delete": { "fr": "Supprimer", "en": "Delete" } },
|
|
1070
|
+
> "validation": { "required": { "fr": "Ce champ est requis", "en": "This field is required" } }
|
|
1071
|
+
> }
|
|
1072
|
+
> ```
|
|
533
1073
|
|
|
534
1074
|
### 9. Per-Module Validation
|
|
535
1075
|
|
|
@@ -587,6 +1127,48 @@ IF validation FAIL:
|
|
|
587
1127
|
description: "Accepter malgré les erreurs (risqué)"
|
|
588
1128
|
```
|
|
589
1129
|
|
|
1130
|
+
#### 9e. Write Module Validation Section (MANDATORY)
|
|
1131
|
+
|
|
1132
|
+
> **The module feature.json MUST have a `validation` section recording the results of steps 9a-9d.**
|
|
1133
|
+
|
|
1134
|
+
```
|
|
1135
|
+
ba-writer.enrichSection({
|
|
1136
|
+
featureId: {module_feature_id},
|
|
1137
|
+
section: "validation",
|
|
1138
|
+
data: {
|
|
1139
|
+
validatedAt: "{ISO timestamp}",
|
|
1140
|
+
completenessChecks: [
|
|
1141
|
+
{ "section": "useCases", "count": {count}, "minimum": 2, "status": "PASS|FAIL" },
|
|
1142
|
+
{ "section": "functionalRequirements", "count": {count}, "minimum": 4, "status": "PASS|FAIL" },
|
|
1143
|
+
{ "section": "wireframes", "count": {count}, "minimum": {section_count}, "status": "PASS|FAIL" },
|
|
1144
|
+
{ "section": "seedDataCore", "count": 5, "minimum": 5, "status": "PASS|FAIL" }
|
|
1145
|
+
],
|
|
1146
|
+
consistencyChecks: [
|
|
1147
|
+
{ "check": "UC-FR linkage", "passed": {n}, "warnings": {n}, "errors": {n}, "status": "PASS|FAIL" },
|
|
1148
|
+
{ "check": "BR references valid", "passed": {n}, "warnings": {n}, "errors": {n}, "status": "PASS|FAIL" },
|
|
1149
|
+
{ "check": "Permission path format", "passed": {n}, "warnings": {n}, "errors": {n}, "status": "PASS|FAIL" }
|
|
1150
|
+
],
|
|
1151
|
+
conventionChecks: [
|
|
1152
|
+
{ "check": "ID naming with module prefix", "status": "PASS|FAIL", "details": "..." },
|
|
1153
|
+
{ "check": "Entity names PascalCase", "status": "PASS|FAIL", "details": "..." }
|
|
1154
|
+
],
|
|
1155
|
+
semanticChecks: [
|
|
1156
|
+
{ "check": "orphan-permissions", "module": "{currentModule}", "status": "PASS|WARNING|ERROR", "details": "...", "autoFixed": false },
|
|
1157
|
+
{ "check": "uc-sans-fr", "module": "{currentModule}", "status": "PASS|WARNING|ERROR", "details": "...", "autoFixed": false },
|
|
1158
|
+
{ "check": "missing-wireframes", "module": "{currentModule}", "status": "PASS|WARNING|ERROR", "details": "...", "autoFixed": false }
|
|
1159
|
+
],
|
|
1160
|
+
warnings: ["List of non-blocking warnings"],
|
|
1161
|
+
decision: {
|
|
1162
|
+
"approved": true,
|
|
1163
|
+
"reason": "All checks passed",
|
|
1164
|
+
"approvalMode": "standard",
|
|
1165
|
+
"approvedBy": "Client",
|
|
1166
|
+
"approvedAt": "{ISO timestamp}"
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
})
|
|
1170
|
+
```
|
|
1171
|
+
|
|
590
1172
|
### 10. Module Summary with Roles & Permissions
|
|
591
1173
|
|
|
592
1174
|
Display comprehensive summary:
|
|
@@ -635,18 +1217,45 @@ options:
|
|
|
635
1217
|
### 11. Write Module Feature.json
|
|
636
1218
|
|
|
637
1219
|
```
|
|
1220
|
+
// Write analysis section with ALL subsections
|
|
638
1221
|
ba-writer.enrichSection({
|
|
639
1222
|
featureId: {module_feature_id},
|
|
640
|
-
section: "
|
|
641
|
-
data: {
|
|
1223
|
+
section: "analysis",
|
|
1224
|
+
data: {
|
|
1225
|
+
objectives: [{id, objective, metric, target}], // from 6a
|
|
1226
|
+
entities: [{name, description, attributes, relationships}], // from 6b — SCHEMA FORMAT
|
|
1227
|
+
businessRules: [{id, name, category, statement, priority, conditions, examples, testability}], // from 7 — SCHEMA FORMAT
|
|
1228
|
+
processFlow: {entryPoints, mainFlow, decisionPoints, alternativeFlows}, // from 6c
|
|
1229
|
+
dataLifecycle: {retentionPeriod, archiveStrategy, gdprCompliance, states} // from 6d
|
|
1230
|
+
}
|
|
642
1231
|
})
|
|
643
1232
|
|
|
1233
|
+
// Write specification section with ALL subsections
|
|
644
1234
|
ba-writer.enrichSection({
|
|
645
1235
|
featureId: {module_feature_id},
|
|
646
|
-
section: "
|
|
647
|
-
data: {
|
|
1236
|
+
section: "specification",
|
|
1237
|
+
data: {
|
|
1238
|
+
actors: [{role, description, permissions}], // 8a
|
|
1239
|
+
useCases: [{id, name, primaryActor, permission, mainScenario, linkedRules}], // 8b
|
|
1240
|
+
functionalRequirements: [{id, statement, priority, linkedRules, linkedUseCases, acceptanceCriteria}], // 8c
|
|
1241
|
+
permissionMatrix: {permissions: [], roleAssignments: []}, // 8d
|
|
1242
|
+
navigation: {entries: []}, // 8e
|
|
1243
|
+
seedDataCore: {navigationModules, navigationTranslations, permissions, rolePermissions, permissionConstants}, // 8f
|
|
1244
|
+
gherkinScenarios: [{feature, scenarios: [{name, tags, given, when, then}]}], // 8g
|
|
1245
|
+
validations: [{entity, field, rules, errorMessageKey}], // 8h
|
|
1246
|
+
messages: [{code, type, title, message, i18nKey}], // 8i
|
|
1247
|
+
lifeCycles: [{entity, field, initialState, states: [{id, displayName, color, allowedTransitions, isTerminal}], transitions}], // 8j
|
|
1248
|
+
apiEndpoints: [{method, path, permission, requestDto, responseDto, description}], // 8k
|
|
1249
|
+
i18nKeys: {...}, // 8l
|
|
1250
|
+
sections: [{code, labels, route, icon, permission, wireframe, useCases, businessRules, resources}], // from 3a-bis
|
|
1251
|
+
dashboards: [{code, title, kpis, filters, refreshMode}], // from 3d
|
|
1252
|
+
uiWireframes: [{screen, section, mockup, elements, actions, componentMapping, layout}] // from 3b
|
|
1253
|
+
}
|
|
648
1254
|
})
|
|
649
1255
|
|
|
1256
|
+
// Write validation results from step 9
|
|
1257
|
+
// (Already written in step 9e above)
|
|
1258
|
+
|
|
650
1259
|
ba-writer.updateStatus({module_feature_id}, "specified")
|
|
651
1260
|
|
|
652
1261
|
// Update master
|