@atlashub/smartstack-cli 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.documentation/business-analyse.html +1503 -1058
- package/dist/index.js +74 -45
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
- package/templates/skills/business-analyse/questionnaire/03-scope.md +7 -7
- package/templates/skills/business-analyse/questionnaire/12-migration.md +1 -1
- package/templates/skills/business-analyse/react/schema.md +175 -27
- package/templates/skills/business-analyse/schemas/feature-schema.json +213 -43
- package/templates/skills/business-analyse/steps/step-01-analyse.md +19 -1
- package/templates/skills/business-analyse/steps/step-02-specify.md +68 -2
- package/templates/skills/business-analyse/steps/step-03-validate.md +148 -1
- package/templates/skills/business-analyse/steps/step-04-handoff.md +384 -175
- package/templates/skills/business-analyse/templates/tpl-handoff.md +11 -2
|
@@ -227,7 +227,7 @@
|
|
|
227
227
|
"required": ["target", "type"],
|
|
228
228
|
"properties": {
|
|
229
229
|
"target": { "type": "string" },
|
|
230
|
-
"type": { "type": "string", "enum": ["1:1", "1:N", "N:M"] },
|
|
230
|
+
"type": { "type": "string", "enum": ["1:1", "1:N", "N:1", "N:M"] },
|
|
231
231
|
"description": { "type": "string" }
|
|
232
232
|
}
|
|
233
233
|
}
|
|
@@ -521,6 +521,118 @@
|
|
|
521
521
|
"permissionsRequired": { "type": "array", "items": { "type": "string" } }
|
|
522
522
|
}
|
|
523
523
|
}
|
|
524
|
+
},
|
|
525
|
+
"messages": {
|
|
526
|
+
"type": "array",
|
|
527
|
+
"description": "Business messages (success, error, warning, info) with i18n keys. MANDATORY: ≥4 messages.",
|
|
528
|
+
"items": {
|
|
529
|
+
"type": "object",
|
|
530
|
+
"required": ["code", "type", "i18nKey"],
|
|
531
|
+
"properties": {
|
|
532
|
+
"code": { "type": "string", "description": "SCREAMING_SNAKE_CASE identifier (e.g., VEHICLE_CREATED_SUCCESS)" },
|
|
533
|
+
"type": { "type": "string", "enum": ["success", "error", "warning", "info"] },
|
|
534
|
+
"title": { "type": "string" },
|
|
535
|
+
"message": { "type": "string", "description": "User-facing message with {placeholders}" },
|
|
536
|
+
"i18nKey": { "type": "string", "description": "Dot-separated i18n key (e.g., freebike.messages.vehicleCreated)" }
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
"lifeCycles": {
|
|
541
|
+
"type": "array",
|
|
542
|
+
"description": "Per-entity state machines for entities with Status fields. MANDATORY: ≥1 entity.",
|
|
543
|
+
"items": {
|
|
544
|
+
"type": "object",
|
|
545
|
+
"required": ["entity", "states"],
|
|
546
|
+
"properties": {
|
|
547
|
+
"entity": { "type": "string", "description": "PascalCase entity name" },
|
|
548
|
+
"states": {
|
|
549
|
+
"type": "array",
|
|
550
|
+
"items": {
|
|
551
|
+
"type": "object",
|
|
552
|
+
"required": ["id", "allowedTransitions"],
|
|
553
|
+
"properties": {
|
|
554
|
+
"id": { "type": "string", "description": "State code (e.g., Draft, Active, Completed)" },
|
|
555
|
+
"displayName": { "type": "string" },
|
|
556
|
+
"description": { "type": "string" },
|
|
557
|
+
"allowedTransitions": { "type": "array", "items": { "type": "string" } },
|
|
558
|
+
"isTerminal": { "type": "boolean", "default": false }
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
"seedDataCore": {
|
|
566
|
+
"type": "object",
|
|
567
|
+
"description": "5 mandatory SmartStack core SeedData definitions derived from navigation + permissionMatrix. CRITICAL: without these, module is invisible (403).",
|
|
568
|
+
"properties": {
|
|
569
|
+
"navigationModules": {
|
|
570
|
+
"type": "array",
|
|
571
|
+
"description": "Entries for nav_Modules table (HasData). Derived from navigation.entries.",
|
|
572
|
+
"items": {
|
|
573
|
+
"type": "object",
|
|
574
|
+
"required": ["code", "label", "icon", "route"],
|
|
575
|
+
"properties": {
|
|
576
|
+
"code": { "type": "string" },
|
|
577
|
+
"label": { "type": "string" },
|
|
578
|
+
"icon": { "type": "string" },
|
|
579
|
+
"route": { "type": "string" },
|
|
580
|
+
"parentCode": { "type": ["string", "null"] },
|
|
581
|
+
"sort": { "type": "integer" }
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
"navigationTranslations": {
|
|
586
|
+
"type": "array",
|
|
587
|
+
"description": "Translations for nav_Translations table (HasData). One entry per module per language.",
|
|
588
|
+
"items": {
|
|
589
|
+
"type": "object",
|
|
590
|
+
"required": ["moduleCode", "language", "label"],
|
|
591
|
+
"properties": {
|
|
592
|
+
"moduleCode": { "type": "string" },
|
|
593
|
+
"language": { "type": "string", "enum": ["fr", "en", "it", "de"] },
|
|
594
|
+
"label": { "type": "string" }
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
"permissions": {
|
|
599
|
+
"type": "array",
|
|
600
|
+
"description": "Entries for nav_Permissions table (HasData). Full paths from permissionMatrix.permissions.",
|
|
601
|
+
"items": {
|
|
602
|
+
"type": "object",
|
|
603
|
+
"required": ["path", "action"],
|
|
604
|
+
"properties": {
|
|
605
|
+
"path": { "type": "string", "description": "Full permission path (business.{app}.{module}.{resource}.{action})" },
|
|
606
|
+
"action": { "type": "string" },
|
|
607
|
+
"description": { "type": "string" }
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
"rolePermissions": {
|
|
612
|
+
"type": "array",
|
|
613
|
+
"description": "Entries for auth_RolePermissions table (HasData). Derived from permissionMatrix.roleAssignments.",
|
|
614
|
+
"items": {
|
|
615
|
+
"type": "object",
|
|
616
|
+
"required": ["role", "permissionPath"],
|
|
617
|
+
"properties": {
|
|
618
|
+
"role": { "type": "string" },
|
|
619
|
+
"permissionPath": { "type": "string", "description": "Full permission path (must match permissions[].path)" }
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
"permissionConstants": {
|
|
624
|
+
"type": "array",
|
|
625
|
+
"description": "Compile-time constants for Permissions.cs (Application layer). Used in [RequirePermission] attributes.",
|
|
626
|
+
"items": {
|
|
627
|
+
"type": "object",
|
|
628
|
+
"required": ["constantName", "path"],
|
|
629
|
+
"properties": {
|
|
630
|
+
"constantName": { "type": "string", "description": "PascalCase constant (e.g., VehiclesRead)" },
|
|
631
|
+
"path": { "type": "string", "description": "Matching permission path" }
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
524
636
|
}
|
|
525
637
|
}
|
|
526
638
|
},
|
|
@@ -529,53 +641,74 @@
|
|
|
529
641
|
"type": "object",
|
|
530
642
|
"description": "Enriched by step-03-validate",
|
|
531
643
|
"properties": {
|
|
532
|
-
"decision": { "type": "string", "enum": ["approved", "rejected", "pending"] },
|
|
533
644
|
"validatedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
534
|
-
"
|
|
535
|
-
"type": "
|
|
536
|
-
"
|
|
537
|
-
|
|
538
|
-
"
|
|
539
|
-
"
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
645
|
+
"completenessChecks": {
|
|
646
|
+
"type": "array",
|
|
647
|
+
"description": "Per-section completeness verification",
|
|
648
|
+
"items": {
|
|
649
|
+
"type": "object",
|
|
650
|
+
"properties": {
|
|
651
|
+
"section": { "type": "string" },
|
|
652
|
+
"count": { "type": "integer" },
|
|
653
|
+
"minimum": { "type": "integer" },
|
|
654
|
+
"status": { "type": "string", "enum": ["PASS", "FAIL", "WARNING"] }
|
|
655
|
+
}
|
|
543
656
|
}
|
|
544
657
|
},
|
|
545
|
-
"
|
|
546
|
-
"type": "
|
|
547
|
-
"description": "Cross-reference
|
|
548
|
-
"
|
|
549
|
-
"
|
|
550
|
-
"
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
658
|
+
"consistencyChecks": {
|
|
659
|
+
"type": "array",
|
|
660
|
+
"description": "Cross-reference consistency checks (UC↔FR, FR↔BR, Actor↔Matrix, etc.)",
|
|
661
|
+
"items": {
|
|
662
|
+
"type": "object",
|
|
663
|
+
"properties": {
|
|
664
|
+
"check": { "type": "string" },
|
|
665
|
+
"passed": { "type": "integer" },
|
|
666
|
+
"warnings": { "type": "integer" },
|
|
667
|
+
"errors": { "type": "integer" },
|
|
668
|
+
"status": { "type": "string", "enum": ["PASS", "FAIL", "WARNING"] }
|
|
669
|
+
}
|
|
554
670
|
}
|
|
555
671
|
},
|
|
556
|
-
"
|
|
557
|
-
"type": "
|
|
558
|
-
"description": "SmartStack convention validation",
|
|
559
|
-
"
|
|
560
|
-
"
|
|
561
|
-
"
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
672
|
+
"conventionChecks": {
|
|
673
|
+
"type": "array",
|
|
674
|
+
"description": "SmartStack convention validation (naming, permissions, routes, etc.)",
|
|
675
|
+
"items": {
|
|
676
|
+
"type": "object",
|
|
677
|
+
"properties": {
|
|
678
|
+
"check": { "type": "string" },
|
|
679
|
+
"status": { "type": "string", "enum": ["PASS", "FAIL", "WARNING"] },
|
|
680
|
+
"details": { "type": "string" }
|
|
681
|
+
}
|
|
566
682
|
}
|
|
567
683
|
},
|
|
568
|
-
"
|
|
684
|
+
"riskAssessments": {
|
|
569
685
|
"type": "array",
|
|
686
|
+
"description": "Scope and complexity risk evaluation",
|
|
570
687
|
"items": {
|
|
571
688
|
"type": "object",
|
|
572
689
|
"properties": {
|
|
573
|
-
"
|
|
574
|
-
"
|
|
575
|
-
"
|
|
576
|
-
"
|
|
690
|
+
"risk": { "type": "string" },
|
|
691
|
+
"value": { "type": "integer" },
|
|
692
|
+
"threshold": { "type": "integer" },
|
|
693
|
+
"status": { "type": "string", "enum": ["ACCEPTABLE", "WARNING", "CRITICAL", "MONITORED"] }
|
|
577
694
|
}
|
|
578
695
|
}
|
|
696
|
+
},
|
|
697
|
+
"warnings": {
|
|
698
|
+
"type": "array",
|
|
699
|
+
"description": "Non-blocking warnings and observations",
|
|
700
|
+
"items": { "type": "string" }
|
|
701
|
+
},
|
|
702
|
+
"decision": {
|
|
703
|
+
"type": "object",
|
|
704
|
+
"description": "Final approval decision",
|
|
705
|
+
"properties": {
|
|
706
|
+
"approved": { "type": "boolean" },
|
|
707
|
+
"reason": { "type": "string" },
|
|
708
|
+
"approvalMode": { "type": "string", "enum": ["standard", "micro", "delta", "force"] },
|
|
709
|
+
"approvedBy": { "type": "string" },
|
|
710
|
+
"approvedAt": { "type": "string", "format": "date-time" }
|
|
711
|
+
}
|
|
579
712
|
}
|
|
580
713
|
}
|
|
581
714
|
},
|
|
@@ -599,12 +732,40 @@
|
|
|
599
732
|
},
|
|
600
733
|
"brToCodeMapping": {
|
|
601
734
|
"type": "array",
|
|
735
|
+
"description": "Maps each business rule to its implementation points across layers. Derived from analysis.businessRules[].",
|
|
736
|
+
"items": {
|
|
737
|
+
"type": "object",
|
|
738
|
+
"required": ["ruleId", "implementationPoints"],
|
|
739
|
+
"properties": {
|
|
740
|
+
"ruleId": { "type": "string", "description": "BR-XXX identifier from analysis.businessRules" },
|
|
741
|
+
"title": { "type": "string", "description": "Business rule title" },
|
|
742
|
+
"implementationPoints": {
|
|
743
|
+
"type": "array",
|
|
744
|
+
"items": {
|
|
745
|
+
"type": "object",
|
|
746
|
+
"required": ["layer", "component"],
|
|
747
|
+
"properties": {
|
|
748
|
+
"layer": { "type": "string", "description": "Architecture layer (Domain, Application, Infrastructure, API, Frontend)" },
|
|
749
|
+
"component": { "type": "string", "description": "File name (e.g., Order.cs, OrdersController.cs)" },
|
|
750
|
+
"method": { "type": "string", "description": "Method or attribute (e.g., Validate(), [Authorize])" },
|
|
751
|
+
"implementation": { "type": "string", "description": "How the rule is enforced" }
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
},
|
|
758
|
+
"apiEndpointSummary": {
|
|
759
|
+
"type": "array",
|
|
760
|
+
"description": "Subset of specification.apiEndpoints enriched with linkedUC. MUST use EXACT same routes as specification.",
|
|
602
761
|
"items": {
|
|
603
762
|
"type": "object",
|
|
604
763
|
"properties": {
|
|
605
|
-
"
|
|
606
|
-
"
|
|
607
|
-
"
|
|
764
|
+
"operation": { "type": "string" },
|
|
765
|
+
"method": { "type": "string", "enum": ["GET", "POST", "PUT", "DELETE", "PATCH"] },
|
|
766
|
+
"route": { "type": "string", "description": "MUST match specification.apiEndpoints[].path exactly" },
|
|
767
|
+
"linkedUC": { "type": "string" },
|
|
768
|
+
"permissions": { "type": "string" }
|
|
608
769
|
}
|
|
609
770
|
}
|
|
610
771
|
},
|
|
@@ -619,7 +780,7 @@
|
|
|
619
780
|
"properties": {
|
|
620
781
|
"id": { "type": "integer" },
|
|
621
782
|
"description": { "type": "string" },
|
|
622
|
-
"category": { "type": "string", "enum": ["domain", "application", "infrastructure", "api", "frontend", "i18n", "test", "validation"] },
|
|
783
|
+
"category": { "type": "string", "enum": ["domain", "seedData", "seedDataCore", "application", "infrastructure", "api", "frontend", "i18n", "test", "validation"] },
|
|
623
784
|
"dependencies": { "type": "array", "items": { "type": "integer" } },
|
|
624
785
|
"acceptanceCriteria": { "type": "string" }
|
|
625
786
|
}
|
|
@@ -654,15 +815,18 @@
|
|
|
654
815
|
|
|
655
816
|
"changelog": {
|
|
656
817
|
"type": "array",
|
|
657
|
-
"description": "Version history and change tracking",
|
|
818
|
+
"description": "Version history and change tracking. Each step adds an entry.",
|
|
658
819
|
"items": {
|
|
659
820
|
"type": "object",
|
|
660
|
-
"required": ["
|
|
821
|
+
"required": ["timestamp", "changes"],
|
|
661
822
|
"properties": {
|
|
662
|
-
"
|
|
823
|
+
"step": { "type": "string", "description": "Step identifier (e.g., step-01-analyse, step-02-specify, step-03-validate, step-04-handoff)" },
|
|
824
|
+
"version": { "type": "string", "description": "Feature version at this point" },
|
|
663
825
|
"timestamp": { "type": "string", "format": "date-time" },
|
|
664
826
|
"author": { "type": "string" },
|
|
665
|
-
"changes": { "type": "array", "items": { "type": "string" } }
|
|
827
|
+
"changes": { "type": "array", "items": { "type": "string" } },
|
|
828
|
+
"warnings": { "type": "array", "items": { "type": "string" }, "description": "Non-blocking warnings from this step" },
|
|
829
|
+
"decision": { "type": "string", "description": "Step decision outcome (e.g., approved, rejected)" }
|
|
666
830
|
}
|
|
667
831
|
}
|
|
668
832
|
}
|
|
@@ -679,8 +843,14 @@
|
|
|
679
843
|
},
|
|
680
844
|
"fileSpec": {
|
|
681
845
|
"type": "object",
|
|
846
|
+
"required": ["path", "type"],
|
|
682
847
|
"properties": {
|
|
683
848
|
"path": { "type": "string", "description": "Relative file path" },
|
|
849
|
+
"type": { "type": "string", "description": "File type (Entity, Service, DTO, Repository, Migration, HasData, Constants, ApiController, Page, Component, ApiClient, ReduxSlice, UnitTests, IntegrationTests, Enum)" },
|
|
850
|
+
"linkedFRs": { "type": "array", "items": { "type": "string" }, "description": "Linked functional requirement IDs (FR-XXX)" },
|
|
851
|
+
"linkedUCs": { "type": "array", "items": { "type": "string" }, "description": "Linked use case IDs (UC-XXX)" },
|
|
852
|
+
"category": { "type": "string", "enum": ["core", "business"], "description": "SeedData category: core (navigation/permissions) or business (lookup tables)" },
|
|
853
|
+
"source": { "type": "string", "description": "Source path in feature.json for derivation (e.g., specification.seedDataCore.permissions)" },
|
|
684
854
|
"description": { "type": "string" },
|
|
685
855
|
"pattern": { "type": "string", "description": "Reference pattern from existing codebase" },
|
|
686
856
|
"instructions": { "type": "string" }
|
|
@@ -150,7 +150,7 @@ Skip categories already answered in previous version.
|
|
|
150
150
|
**ULTRATHINK checkpoints during elicitation:**
|
|
151
151
|
- After Q1: If answer is solution-oriented → reframe to problem
|
|
152
152
|
- After Q2: If only 1-2 stakeholder types → probe for hidden users
|
|
153
|
-
- After Q3: If > 5 Must-Have → ask to prioritize
|
|
153
|
+
- After Q3: If > 5 Must-Have → ask to prioritize implementation order
|
|
154
154
|
- If answer is vague → apply Technique 3 (Concrete Scenario)
|
|
155
155
|
- If any answer contains permission attributes → flag as RBAC violation
|
|
156
156
|
|
|
@@ -428,6 +428,24 @@ Use **ba-writer** agent to enrich:
|
|
|
428
428
|
- `discovery` section: problem, asIs, toBe, trigger, stakeholders, scope, risks, codebaseContext, openQuestions
|
|
429
429
|
- `analysis` section: objectives, businessRules, entities, processFlow, integrations, crossModuleImpact, dataLifecycle, suggestions
|
|
430
430
|
- Update `metadata.steps.analyse.status = "completed"`
|
|
431
|
+
- **Initialize changelog** with first entry:
|
|
432
|
+
|
|
433
|
+
```json
|
|
434
|
+
{
|
|
435
|
+
"changelog": [
|
|
436
|
+
{
|
|
437
|
+
"step": "step-01-analyse",
|
|
438
|
+
"timestamp": "2025-02-01T09:00:00Z",
|
|
439
|
+
"changes": [
|
|
440
|
+
"Discovery: {stakeholder_count} stakeholders, {scope_must} must-haves",
|
|
441
|
+
"Analysis: {br_count} business rules, {entity_count} entities, {obj_count} objectives",
|
|
442
|
+
"Suggestions: {accepted_count}/{total_count} accepted",
|
|
443
|
+
"Risks: {risk_count} identified ({critical_count} critical)"
|
|
444
|
+
]
|
|
445
|
+
}
|
|
446
|
+
]
|
|
447
|
+
}
|
|
448
|
+
```
|
|
431
449
|
|
|
432
450
|
---
|
|
433
451
|
|
|
@@ -386,6 +386,55 @@ These tables are:
|
|
|
386
386
|
|
|
387
387
|
**Micro mode:** Minimal: Status and Category only. Skip Priority, Type, Department.
|
|
388
388
|
|
|
389
|
+
### 6.4 SeedData Core (OBLIGATOIRE)
|
|
390
|
+
|
|
391
|
+
> **CRITIQUE :** Sans ces SeedData, le module sera invisible dans la navigation et toutes les API retourneront 403.
|
|
392
|
+
|
|
393
|
+
En plus des 5 tables metier ci-dessus, generer une section `specification.seedDataCore` derivee automatiquement de `specification.navigation` et `specification.permissionMatrix` :
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"seedDataCore": {
|
|
398
|
+
"navigationModules": [
|
|
399
|
+
{
|
|
400
|
+
"code": "fleet",
|
|
401
|
+
"label": "Fleet Management",
|
|
402
|
+
"icon": "Truck",
|
|
403
|
+
"route": "/business/freebike/fleet",
|
|
404
|
+
"parentCode": "freebike",
|
|
405
|
+
"sort": 1
|
|
406
|
+
}
|
|
407
|
+
],
|
|
408
|
+
"navigationTranslations": [
|
|
409
|
+
{ "moduleCode": "fleet", "language": "fr", "label": "Gestion de Flotte" },
|
|
410
|
+
{ "moduleCode": "fleet", "language": "en", "label": "Fleet Management" }
|
|
411
|
+
],
|
|
412
|
+
"permissions": [
|
|
413
|
+
{ "path": "business.freebike.fleetmanagement.vehicles.read", "action": "read", "description": "Consulter vehicules" }
|
|
414
|
+
],
|
|
415
|
+
"rolePermissions": [
|
|
416
|
+
{ "role": "FreeBike Admin", "permissionPath": "business.freebike.fleetmanagement.*" },
|
|
417
|
+
{ "role": "FreeBike Manager", "permissionPath": "business.freebike.fleetmanagement.vehicles.read" }
|
|
418
|
+
],
|
|
419
|
+
"permissionConstants": [
|
|
420
|
+
{ "constantName": "VehiclesRead", "path": "business.freebike.fleetmanagement.vehicles.read" }
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Regles de derivation :**
|
|
427
|
+
|
|
428
|
+
1. **navigationModules** : Prendre chaque entree de `specification.navigation.entries[]` avec level = module ou section
|
|
429
|
+
2. **navigationTranslations** : Prendre chaque entree de navigation et generer une traduction par langue definie dans `labels`
|
|
430
|
+
3. **permissions** : Copier EXACTEMENT `specification.permissionMatrix.permissions[]` (chemins complets)
|
|
431
|
+
4. **rolePermissions** : Pour chaque `roleAssignments[]`, expander les wildcards et raccourcis en chemins complets. Chaque `permissionPath` DOIT correspondre a un `permissions[].path` existant
|
|
432
|
+
5. **permissionConstants** : Pour chaque permission, generer un nom PascalCase (ex: `business.freebike.fleetmanagement.vehicles.read` → `VehiclesRead`)
|
|
433
|
+
|
|
434
|
+
**Verification :** Chaque `rolePermissions[].permissionPath` doit exister dans `permissions[].path`. Si un raccourci est utilise (ex: `vehicles.read` au lieu du chemin complet), c'est une ERREUR.
|
|
435
|
+
|
|
436
|
+
**Micro mode :** Generer avec les permissions CRUD minimales pour le role Admin uniquement.
|
|
437
|
+
|
|
389
438
|
---
|
|
390
439
|
|
|
391
440
|
## 7. Section 5: UI Wireframes
|
|
@@ -578,7 +627,15 @@ For each input field, specify validation rules:
|
|
|
578
627
|
}
|
|
579
628
|
```
|
|
580
629
|
|
|
581
|
-
### 9.2 Business Messages
|
|
630
|
+
### 9.2 Business Messages (OBLIGATOIRE - minimum 4 messages)
|
|
631
|
+
|
|
632
|
+
> **OBLIGATOIRE :** Generer au minimum 4 messages metier dans `specification.messages[]` :
|
|
633
|
+
> - 1 success (ex: RESOURCE_CREATED_SUCCESS)
|
|
634
|
+
> - 1 error CRUD (ex: RESOURCE_CREATION_FAILED)
|
|
635
|
+
> - 1 error validation (ex: RESOURCE_NOT_FOUND)
|
|
636
|
+
> - 1 error permission (ex: PERMISSION_DENIED)
|
|
637
|
+
>
|
|
638
|
+
> Pour les modules complexes, ajouter des messages warning (ex: STOCK_LOW_WARNING, SYNC_FAILED_WARNING).
|
|
582
639
|
|
|
583
640
|
Define user-facing messages for operations:
|
|
584
641
|
|
|
@@ -621,7 +678,11 @@ Define user-facing messages for operations:
|
|
|
621
678
|
|
|
622
679
|
## 10. Section 8: Data Lifecycle & Cross-Module Patterns
|
|
623
680
|
|
|
624
|
-
### 10.1 Entity Lifecycle States
|
|
681
|
+
### 10.1 Entity Lifecycle States (OBLIGATOIRE - minimum 1 entite)
|
|
682
|
+
|
|
683
|
+
> **OBLIGATOIRE :** Pour chaque entite ayant un attribut `Status` ou `State` (enum), definir une state machine dans `specification.lifeCycles[]`.
|
|
684
|
+
> Identifier les entites candidates en parcourant `analysis.entities[].attributes[]` pour trouver celles avec un champ de type enum representant un statut.
|
|
685
|
+
> Minimum : 1 entite avec state machine. Pour un full-module, typiquement 2-4 entites.
|
|
625
686
|
|
|
626
687
|
Define state transitions for key entities:
|
|
627
688
|
|
|
@@ -776,6 +837,8 @@ Ensure:
|
|
|
776
837
|
|
|
777
838
|
Use `ba-writer.updateSpecification()` to write:
|
|
778
839
|
|
|
840
|
+
> **INTERDIT :** Ne JAMAIS generer de fichier `specification.json` separe. Toute la specification DOIT rester dans `feature.json.specification`. Un fichier specification.json separe cree une double source de verite et sera ecrase/ignore.
|
|
841
|
+
|
|
779
842
|
```json
|
|
780
843
|
{
|
|
781
844
|
"specification": {
|
|
@@ -790,6 +853,7 @@ Use `ba-writer.updateSpecification()` to write:
|
|
|
790
853
|
"validations": [...],
|
|
791
854
|
"messages": [...],
|
|
792
855
|
"lifeCycles": [...],
|
|
856
|
+
"seedDataCore": {...},
|
|
793
857
|
"crossModuleDependencies": [...],
|
|
794
858
|
"auditingPolicy": {...},
|
|
795
859
|
"archivalPolicy": {...}
|
|
@@ -813,6 +877,8 @@ Use cases created: 8 (UC-001 → UC-008)
|
|
|
813
877
|
Requirements: 12 FRs linked to business rules
|
|
814
878
|
Permission matrix: 3 resources × 4 actors
|
|
815
879
|
SeedData tables: 5 mandatory (Status, Priority, Category, Type, Department)
|
|
880
|
+
SeedData Core: 5 files (Navigation, Translations, Permissions, RolePermissions, Constants)
|
|
881
|
+
Messages: 6 business messages (success, error, warning)
|
|
816
882
|
UI screens: 6 wireframes (List, Create, Detail, Reports, etc.)
|
|
817
883
|
Gherkin scenarios: 18 scenarios across all UCs
|
|
818
884
|
Validations: 24 field validation rules
|
|
@@ -123,6 +123,56 @@ Validate 5 mandatory SeedData tables defined in navigationHierarchy:
|
|
|
123
123
|
|
|
124
124
|
**Issue:** Missing SeedData table → validation ERROR, must specify before approval.
|
|
125
125
|
|
|
126
|
+
### 2.4 SeedData Core Presence (BLOQUANT)
|
|
127
|
+
|
|
128
|
+
> **CRITIQUE :** Cette validation est BLOQUANTE. Si `specification.seedDataCore` est absent ou incomplet, la validation DOIT echouer avec une ERREUR (pas un warning). Sans ces fichiers, le module sera invisible et toutes les API retourneront 403.
|
|
129
|
+
|
|
130
|
+
Verifier la presence et le contenu de `specification.seedDataCore` :
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"seedDataCoreChecks": [
|
|
135
|
+
{
|
|
136
|
+
"section": "navigationModules",
|
|
137
|
+
"minimum": 1,
|
|
138
|
+
"status": "PASS|FAIL",
|
|
139
|
+
"description": "Au moins 1 entree de navigation module"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"section": "navigationTranslations",
|
|
143
|
+
"minimum": 1,
|
|
144
|
+
"status": "PASS|FAIL",
|
|
145
|
+
"description": "Au moins 1 traduction par module"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"section": "permissions",
|
|
149
|
+
"minimum": 3,
|
|
150
|
+
"status": "PASS|FAIL",
|
|
151
|
+
"description": "Au moins 3 permissions (Read, Create, Update minimum)"
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
"section": "rolePermissions",
|
|
155
|
+
"minimum": 2,
|
|
156
|
+
"status": "PASS|FAIL",
|
|
157
|
+
"description": "Au moins 2 associations role-permission (Admin + 1 autre role)"
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"section": "permissionConstants",
|
|
161
|
+
"minimum": 3,
|
|
162
|
+
"status": "PASS|FAIL",
|
|
163
|
+
"description": "Au moins 3 constantes compile-time"
|
|
164
|
+
}
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Regles :**
|
|
170
|
+
- Chaque `rolePermissions[].permissionPath` DOIT exister dans `permissions[].path` → ERREUR sinon
|
|
171
|
+
- Chaque `permissions[].path` DOIT utiliser le format complet `business.{app}.{module}.{resource}.{action}` → ERREUR sinon
|
|
172
|
+
- Les `permissionConstants[].path` DOIVENT correspondre a `permissions[].path` → ERREUR sinon
|
|
173
|
+
|
|
174
|
+
**Issue:** Section seedDataCore absente ou incomplete → validation ERREUR BLOQUANTE, retour a step-02.
|
|
175
|
+
|
|
126
176
|
---
|
|
127
177
|
|
|
128
178
|
## 3. Consistency Checks
|
|
@@ -307,6 +357,63 @@ Cross-check all BR references:
|
|
|
307
357
|
- ✓ PASS: UC has ≥2 scenarios
|
|
308
358
|
- ✗ FAIL: Add Gherkin scenarios or remove UC
|
|
309
359
|
|
|
360
|
+
### 3.7 API Routes Format Consistency
|
|
361
|
+
|
|
362
|
+
**Rule:** All routes in `specification.apiEndpoints[].path` MUST use the same prefix format. No mixing of `/api/freebike/...`, `/api/v1/...`, and `/api/...` in the same specification.
|
|
363
|
+
|
|
364
|
+
```json
|
|
365
|
+
{
|
|
366
|
+
"checks": [
|
|
367
|
+
{
|
|
368
|
+
"check": "API route prefix consistency",
|
|
369
|
+
"prefixes": ["/api/freebike/"],
|
|
370
|
+
"inconsistent": [],
|
|
371
|
+
"status": "PASS"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
"check": "API route prefix consistency",
|
|
375
|
+
"prefixes": ["/api/freebike/", "/api/v1/"],
|
|
376
|
+
"inconsistent": ["GET /api/v1/vehicles conflicts with POST /api/freebike/vehicles"],
|
|
377
|
+
"status": "FAIL"
|
|
378
|
+
}
|
|
379
|
+
]
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
**Resolution:**
|
|
384
|
+
- ✓ PASS: All routes use the same prefix
|
|
385
|
+
- ✗ FAIL: Harmonize all routes to use a single prefix pattern
|
|
386
|
+
|
|
387
|
+
### 3.8 Permission Format Consistency
|
|
388
|
+
|
|
389
|
+
**Rule:** All permissions in `permissionMatrix.roleAssignments[].permissions[]` MUST use full path format matching `permissionMatrix.permissions[].path`. No shortcuts (e.g., `vehicles.read` instead of `business.freebike.fleetmanagement.vehicles.read`).
|
|
390
|
+
|
|
391
|
+
```json
|
|
392
|
+
{
|
|
393
|
+
"checks": [
|
|
394
|
+
{
|
|
395
|
+
"check": "Permission path format in roleAssignments",
|
|
396
|
+
"fullPaths": 15,
|
|
397
|
+
"shortcuts": 0,
|
|
398
|
+
"status": "PASS"
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"check": "Permission path format in roleAssignments",
|
|
402
|
+
"fullPaths": 5,
|
|
403
|
+
"shortcuts": 10,
|
|
404
|
+
"inconsistentExamples": ["vehicles.read should be business.freebike.fleetmanagement.vehicles.read"],
|
|
405
|
+
"status": "FAIL"
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Exception:** Le wildcard `business.{app}.{module}.*` est accepte pour le role Admin.
|
|
412
|
+
|
|
413
|
+
**Resolution:**
|
|
414
|
+
- ✓ PASS: All roleAssignment permissions use full paths
|
|
415
|
+
- ✗ FAIL: Replace shortcuts with full paths from permissionMatrix.permissions[].path
|
|
416
|
+
|
|
310
417
|
---
|
|
311
418
|
|
|
312
419
|
## 4. SmartStack Convention Validation
|
|
@@ -441,6 +548,22 @@ Check role escalation:
|
|
|
441
548
|
}
|
|
442
549
|
```
|
|
443
550
|
|
|
551
|
+
### 4.5 Orphan File Detection
|
|
552
|
+
|
|
553
|
+
**Rule:** The feature.json is the SINGLE source of truth. No separate JSON files should exist.
|
|
554
|
+
|
|
555
|
+
```
|
|
556
|
+
CHECK orphan files:
|
|
557
|
+
- specification.json exists in output directory → WARNING ⚠
|
|
558
|
+
"Double source of vérité détectée : specification.json est un fichier orphelin.
|
|
559
|
+
Toute la spécification doit être dans feature.json.specification.
|
|
560
|
+
SUPPRIMER specification.json et vérifier que feature.json.specification est complet."
|
|
561
|
+
- analysis.json exists in output directory → WARNING ⚠
|
|
562
|
+
"Fichier analysis.json orphelin détecté. L'analyse doit être dans feature.json.analysis."
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Action :** Si un fichier orphelin est détecté, ajouter un WARNING dans `validation.warnings[]` et recommander la suppression.
|
|
566
|
+
|
|
444
567
|
---
|
|
445
568
|
|
|
446
569
|
## 5. Risk Assessment
|
|
@@ -836,7 +959,31 @@ Use `ba-writer.updateStatus("approved")` to mark validation complete.
|
|
|
836
959
|
|
|
837
960
|
(Or keep status as "specified" if rejected.)
|
|
838
961
|
|
|
839
|
-
### 9.3
|
|
962
|
+
### 9.3 Update Changelog
|
|
963
|
+
|
|
964
|
+
**OBLIGATOIRE :** Ajouter une entrée changelog pour step-03 via `ba-writer` :
|
|
965
|
+
|
|
966
|
+
```json
|
|
967
|
+
{
|
|
968
|
+
"changelog": [
|
|
969
|
+
{
|
|
970
|
+
"step": "step-03-validate",
|
|
971
|
+
"timestamp": "2025-02-01T10:35:00Z",
|
|
972
|
+
"changes": [
|
|
973
|
+
"Validation complétude : X/Y sections présentes",
|
|
974
|
+
"Validation cohérence : X cross-references vérifiées",
|
|
975
|
+
"Validation conventions : nommage, RBAC, structure",
|
|
976
|
+
"Évaluation risques : NIVEAU (détails)",
|
|
977
|
+
"Décision : APPROVED/REJECTED (mode: standard/micro/force)"
|
|
978
|
+
],
|
|
979
|
+
"warnings": ["Liste des warnings éventuels"],
|
|
980
|
+
"decision": "approved"
|
|
981
|
+
}
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
```
|
|
985
|
+
|
|
986
|
+
### 9.4 User Confirmation (Standard Mode)
|
|
840
987
|
|
|
841
988
|
```
|
|
842
989
|
✓ Validation complete - APPROVED
|