@atlashub/smartstack-cli 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/package.json +1 -1
  2. package/templates/agents/ba-writer.md +178 -0
  3. package/templates/skills/application/references/application-roles-template.md +227 -0
  4. package/templates/skills/application/references/provider-template.md +30 -6
  5. package/templates/skills/application/steps/step-03-roles.md +45 -7
  6. package/templates/skills/application/steps/step-03b-provider.md +13 -6
  7. package/templates/skills/business-analyse/SKILL.md +56 -4
  8. package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +477 -0
  9. package/templates/skills/business-analyse/references/cache-warming-strategy.md +578 -0
  10. package/templates/skills/business-analyse/references/robustness-checks.md +538 -0
  11. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -1
  12. package/templates/skills/business-analyse/steps/step-00-init.md +166 -0
  13. package/templates/skills/business-analyse/steps/step-03a-data.md +36 -0
  14. package/templates/skills/business-analyse/steps/step-03c-compile.md +71 -2
  15. package/templates/skills/business-analyse/steps/step-03d-validate.md +274 -0
  16. package/templates/skills/business-analyse/steps/step-04-consolidation.md +166 -0
  17. package/templates/skills/business-analyse/steps/step-05a-handoff.md +44 -0
  18. package/templates/skills/business-analyse/steps/step-05b-deploy.md +21 -2
  19. package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +526 -0
  20. package/templates/skills/controller/steps/step-03-generate.md +184 -24
  21. package/templates/skills/controller/templates.md +11 -2
  22. package/templates/skills/ralph-loop/references/core-seed-data.md +173 -21
@@ -1,48 +1,189 @@
1
1
  ---
2
2
  name: step-03-generate
3
- description: Generate controller file and DTOs
3
+ description: Generate controller using MCP scaffold_extension with NavRoute
4
4
  next_step: steps/step-04-perms.md
5
5
  ---
6
6
 
7
7
  # Step 3: Generate Controller
8
8
 
9
- ## YOUR TASK:
9
+ ## MANDATORY EXECUTION RULES
10
10
 
11
- Generate the controller file following SmartStack conventions. Use templates from `templates.md`.
11
+ - ALWAYS use MCP `scaffold_extension` tool - NEVER use templates
12
+ - ALWAYS generate Controller + DTOs as a unit
13
+ - ALWAYS include NavRoute attribute for frontend/backend sync
14
+ - YOU ARE AN ORCHESTRATOR calling MCP, not a generator
15
+ - MCP is the SOURCE OF TRUTH for code generation
12
16
 
13
- **ULTRA THINK about security and patterns.**
17
+ ## YOUR TASK
18
+
19
+ Call the SmartStack MCP `scaffold_extension` tool with type "controller" to generate:
20
+ 1. API Controller with NavRoute attribute
21
+ 2. DTOs (Response, Create, Update)
22
+
23
+ ---
24
+
25
+ ## AVAILABLE STATE
26
+
27
+ From previous steps:
28
+
29
+ | Variable | Description |
30
+ |----------|-------------|
31
+ | `{area}` | Controller folder (Admin, Business, Support, User) |
32
+ | `{module}` | kebab-case module identifier |
33
+ | `{entity}` | Entity name (PascalCase) |
34
+ | `{permission_path}` | Complete navigation path (navRoute) |
35
+ | `{controller_type}` | crud, readonly, custom, auth |
14
36
 
15
37
  ---
16
38
 
17
- ## EXECUTION SEQUENCE:
39
+ ## EXECUTION SEQUENCE
18
40
 
19
- ### 1. Load Templates
41
+ ### 1. Derive Entity Name
20
42
 
21
- **Read template file:**
43
+ Convert `{module}` to PascalCase for entity name:
22
44
 
23
45
  ```
24
- Read: templates/templates.md
46
+ module: "products" → entityName: "Product"
47
+ module: "order-items" → entityName: "OrderItem"
48
+ module: "user-profiles" → entityName: "UserProfile"
25
49
  ```
26
50
 
27
- **Select appropriate template based on {controller_type}:**
28
- - CRUD Controller template
29
- - Auth Controller template
30
- - ReadOnly Controller template
51
+ ### 2. Determine Table Prefix
52
+
53
+ Based on navigation context extracted from `{permission_path}`:
54
+
55
+ | Context | Table Prefix | Controller Folder |
56
+ |---------|--------------|-------------------|
57
+ | platform.administration | `auth_` or `cfg_` | `Admin` |
58
+ | platform.support | `support_` | `Support` |
59
+ | business.* | `ref_` or domain-specific | `Business` |
60
+ | personal.* | `usr_` | `User` |
61
+
62
+ ### 3. Call MCP scaffold_extension (TWO CALLS)
63
+
64
+ **First call: Generate DTOs**
65
+
66
+ ```
67
+ Tool: mcp__smartstack__scaffold_extension
68
+ Args:
69
+ type: "dto"
70
+ name: "{entityName}" # PascalCase from step 1
71
+ options:
72
+ navRoute: "{permission_path}" # For proper namespace hierarchy
73
+ schema: "core"
74
+ dryRun: false
75
+ ```
31
76
 
32
- ### 2. Generate Controller File
77
+ **Second call: Generate Controller with NavRoute**
33
78
 
34
- **Target path:**
35
79
  ```
36
- src/SmartStack.Api/Controllers/{ContextShort}/{Application}/{entity}Controller.cs
80
+ Tool: mcp__smartstack__scaffold_extension
81
+ Args:
82
+ type: "controller"
83
+ name: "{entityName}" # PascalCase from step 1
84
+ options:
85
+ navRoute: "{permission_path}" # MANDATORY for NavRoute attribute
86
+ navRouteSuffix: null # Optional (e.g., "details" → [NavRoute("path", Suffix = "details")])
87
+ dryRun: false
37
88
  ```
38
- > Context mapping: `business` → `Business`, `platform` → `Admin`, `personal` → `User`
39
89
 
40
- See [references/controller-code-templates.md](../references/controller-code-templates.md) for all C# templates:
41
- - **Controller class** with DI constructor (IApplicationDbContext, ICurrentUserService, ILogger)
42
- - **GET endpoint** with pagination (PagedResult, AsNoTracking)
43
- - **DTOs** (CreateDto, UpdateDto, ResponseDto with entity mapping constructor)
44
- - **Security logging** (Create/Update at Info, Delete at Warning)
45
- - **System account protection** guard (UserType.System/LocalAdmin)
90
+ **CRITICAL: NavRoute is MANDATORY** - Without it, frontend/backend sync will fail.
91
+
92
+ **Why two calls?**
93
+ - The skill `/controller` assumes the Entity already exists (verified in step-01-analyze.md)
94
+ - Type "dto" generates DTOs without regenerating the Entity
95
+ - Type "controller" generates the Controller with NavRoute and references to DTOs
96
+
97
+ ### 4. Parse MCP Responses
98
+
99
+ **From first call (DTOs):**
100
+ - `Application/{Context}/{Application}/{Module}/DTOs/{entityName}ResponseDto.cs` - Response DTO
101
+ - `Application/{Context}/{Application}/{Module}/DTOs/Create{entityName}Dto.cs` - Create request
102
+ - `Application/{Context}/{Application}/{Module}/DTOs/Update{entityName}Dto.cs` - Update request
103
+
104
+ **From second call (Controller):**
105
+ - `Api/Controllers/{area}/{entityName}Controller.cs` - REST Controller **with [NavRoute]**
106
+
107
+ ### 5. Present Output to User
108
+
109
+ ```markdown
110
+ ## Controller Generated via MCP
111
+
112
+ ### API Layer
113
+ - `Controllers/{area}/{entityName}Controller.cs`
114
+ - **NavRoute: `{permission_path}`** ✅
115
+ - Endpoints:
116
+ - GET /api/{module} - List all
117
+ - GET /api/{module}/{id} - Get by ID
118
+ - POST /api/{module} - Create
119
+ - PUT /api/{module}/{id} - Update
120
+ - DELETE /api/{module}/{id} - Delete
121
+
122
+ ### Application Layer (DTOs)
123
+ - `{Context}/{Application}/{Module}/DTOs/{entityName}ResponseDto.cs`
124
+ - `{Context}/{Application}/{Module}/DTOs/Create{entityName}Dto.cs`
125
+ - `{Context}/{Application}/{Module}/DTOs/Update{entityName}Dto.cs`
126
+
127
+ ### ✅ NavRoute Integration
128
+ The controller uses `[NavRoute("{permission_path}")]` which enables:
129
+ - ✅ Automatic frontend route generation
130
+ - ✅ Permission-based navigation sync
131
+ - ✅ Dynamic API routing from Navigation entities
132
+
133
+ ### Next Steps
134
+ 1. Permissions will be synchronized in step-04-perms.md
135
+ 2. Validate conventions with MCP `validate_conventions`
136
+ ```
137
+
138
+ ---
139
+
140
+ ## MCP RESPONSE HANDLING
141
+
142
+ ### Success Case
143
+
144
+ **After first call (DTOs):**
145
+ - Display all generated DTO files
146
+ - Verify DTOs match entity properties
147
+ - Continue to second call
148
+
149
+ **After second call (Controller):**
150
+ - Display controller file
151
+ - Show NavRoute attribute included
152
+ - Highlight frontend/backend sync enabled
153
+ - Store controller info for permission sync
154
+ - Proceed to step-04-perms.md
155
+
156
+ ### Error Case
157
+
158
+ **If first call (DTOs) fails:**
159
+ - Display error message
160
+ - Suggest checking entity name format
161
+ - Verify entity properties are defined
162
+ - Verify MCP server is running (`/mcp:healthcheck`)
163
+ - Do NOT proceed to second call
164
+
165
+ **If second call (Controller) fails:**
166
+ - Display error message
167
+ - Note that DTOs were generated successfully
168
+ - Suggest checking navRoute format
169
+ - Verify MCP server is running (`/mcp:healthcheck`)
170
+ - Do NOT proceed to step-04-perms.md
171
+
172
+ ---
173
+
174
+ ## NAVROUTE VALIDATION
175
+
176
+ **After generation, verify NavRoute is present:**
177
+
178
+ ```
179
+ Generated controller MUST contain:
180
+ [NavRoute("{permission_path}")]
181
+
182
+ WITHOUT NavRoute:
183
+ ❌ Frontend routes will be hardcoded
184
+ ❌ No automatic permission sync
185
+ ❌ Manual navigation management required
186
+ ```
46
187
 
47
188
  ---
48
189
 
@@ -53,7 +194,7 @@ Generated Files:
53
194
 
54
195
  | File | Path | Status |
55
196
  |------|------|--------|
56
- | Controller | src/.../Controllers/{area}/{module}Controller.cs | ✅ Created |
197
+ | Controller | src/.../Controllers/{area}/{entity}Controller.cs | ✅ Created with [NavRoute] |
57
198
  | CreateDto | src/.../DTOs/{module}/{entity}CreateDto.cs | ✅ Created |
58
199
  | UpdateDto | src/.../DTOs/{module}/{entity}UpdateDto.cs | ✅ Created |
59
200
  | ResponseDto | src/.../DTOs/{module}/{entity}ResponseDto.cs | ✅ Created |
@@ -63,6 +204,25 @@ Generated Files:
63
204
 
64
205
  ---
65
206
 
207
+ ## SUCCESS METRICS
208
+
209
+ - MCP scaffold_extension called successfully (DTOs)
210
+ - DTOs generated (ResponseDto, CreateDto, UpdateDto)
211
+ - MCP scaffold_extension called successfully (Controller)
212
+ - Controller generated with **[NavRoute]** attribute
213
+ - NavRoute matches permission_path
214
+ - Controller references DTOs correctly
215
+ - Proceeded to step-04-perms.md
216
+
217
+ ## FAILURE MODES
218
+
219
+ - MCP call failed (display error, run /mcp:healthcheck, stop)
220
+ - Invalid entity name (must be PascalCase)
221
+ - Invalid navRoute format
222
+ - MCP server not running
223
+
224
+ ---
225
+
66
226
  ## NEXT STEP:
67
227
 
68
- After generation complete, proceed to `./step-04-perms.md`
228
+ After controller generation complete, proceed to `./step-04-perms.md`
@@ -1,7 +1,16 @@
1
1
  # SmartStack Controller Templates
2
2
 
3
- > **Note:** These templates are used by the `controller` skill and `/controller:create` command.
4
- > Adapt variables `{Area}`, `{Module}`, `{Entity}`, `{PermissionPath}` according to context.
3
+ > **⚠️ OBSOLETE - DO NOT USE THESE TEMPLATES MANUALLY**
4
+ >
5
+ > **The `/controller` skill now uses the MCP `scaffold_extension` tool to generate controllers.**
6
+ > These templates are kept for reference only. All controller generation MUST go through the MCP to ensure:
7
+ > - ✅ `[NavRoute]` attribute is included for frontend/backend sync
8
+ > - ✅ Permissions are correctly generated
9
+ > - ✅ Consistency with SmartStack conventions
10
+ >
11
+ > **To generate a controller, use:** `/controller` skill which calls MCP `scaffold_extension` automatically.
12
+ >
13
+ > **If you modify these templates, they will NOT be used.** The MCP templates in `templates/mcp-scaffolding/controller.cs.hbs` are the source of truth.
5
14
 
6
15
  ---
7
16
 
@@ -279,7 +279,129 @@ If MCP `generate_permissions` fails, use the template above directly with values
279
279
 
280
280
  ---
281
281
 
282
- ## 4. RolesSeedData.cs
282
+ ## 4. ApplicationRolesSeedData.cs (Application-Level, Once per Application)
283
+
284
+ **File:** `Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs`
285
+
286
+ ### Purpose
287
+
288
+ Creates the 4 standard application-scoped roles: Admin, Manager, Contributor, Viewer.
289
+
290
+ **CRITICAL:** This file is created **ONCE per application** (not per module).
291
+ Without these roles, role-permission mappings in `SeedRolePermissionsAsync()` will fail silently.
292
+
293
+ ### GUID Generation Rule
294
+
295
+ ```csharp
296
+ // Deterministic GUID from application ID + role type
297
+ private static Guid GenerateRoleGuid(string roleType)
298
+ {
299
+ using var sha256 = System.Security.Cryptography.SHA256.Create();
300
+ var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes($"role-{ApplicationId}-{roleType}"));
301
+ return new Guid(hash.Take(16).ToArray());
302
+ }
303
+ // roleType values: "admin", "manager", "contributor", "viewer"
304
+ ```
305
+
306
+ ### Template
307
+
308
+ ```csharp
309
+ using SmartStack.Domain.Platform.Administration.Roles;
310
+
311
+ namespace {BaseNamespace}.Infrastructure.Persistence.Seeding.Data;
312
+
313
+ /// <summary>
314
+ /// Application-scoped role seed data for {AppLabel}.
315
+ /// Defines the 4 standard application roles: Admin, Manager, Contributor, Viewer.
316
+ /// Consumed by IClientSeedDataProvider at application startup.
317
+ /// </summary>
318
+ public static class ApplicationRolesSeedData
319
+ {
320
+ // Application ID from NavigationApplicationSeedData
321
+ private static readonly Guid ApplicationId = {ApplicationGuid};
322
+
323
+ public static readonly Guid AdminRoleId = GenerateRoleGuid("admin");
324
+ public static readonly Guid ManagerRoleId = GenerateRoleGuid("manager");
325
+ public static readonly Guid ContributorRoleId = GenerateRoleGuid("contributor");
326
+ public static readonly Guid ViewerRoleId = GenerateRoleGuid("viewer");
327
+
328
+ public static IEnumerable<ApplicationRoleSeedEntry> GetRoleEntries()
329
+ {
330
+ yield return new ApplicationRoleSeedEntry
331
+ {
332
+ Id = AdminRoleId,
333
+ Code = "admin",
334
+ Name = "{AppLabel} Admin",
335
+ Description = "Full administrative access to {AppLabel}",
336
+ ApplicationId = ApplicationId,
337
+ IsSystem = false,
338
+ IsActive = true,
339
+ DisplayOrder = 1
340
+ };
341
+
342
+ yield return new ApplicationRoleSeedEntry
343
+ {
344
+ Id = ManagerRoleId,
345
+ Code = "manager",
346
+ Name = "{AppLabel} Manager",
347
+ Description = "Management access to {AppLabel} (Create, Read, Update)",
348
+ ApplicationId = ApplicationId,
349
+ IsSystem = false,
350
+ IsActive = true,
351
+ DisplayOrder = 2
352
+ };
353
+
354
+ yield return new ApplicationRoleSeedEntry
355
+ {
356
+ Id = ContributorRoleId,
357
+ Code = "contributor",
358
+ Name = "{AppLabel} Contributor",
359
+ Description = "Contributor access to {AppLabel} (Create, Read)",
360
+ ApplicationId = ApplicationId,
361
+ IsSystem = false,
362
+ IsActive = true,
363
+ DisplayOrder = 3
364
+ };
365
+
366
+ yield return new ApplicationRoleSeedEntry
367
+ {
368
+ Id = ViewerRoleId,
369
+ Code = "viewer",
370
+ Name = "{AppLabel} Viewer",
371
+ Description = "Read-only access to {AppLabel}",
372
+ ApplicationId = ApplicationId,
373
+ IsSystem = false,
374
+ IsActive = true,
375
+ DisplayOrder = 4
376
+ };
377
+ }
378
+
379
+ private static Guid GenerateRoleGuid(string roleType)
380
+ {
381
+ using var sha256 = System.Security.Cryptography.SHA256.Create();
382
+ var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes($"role-{ApplicationId}-{roleType}"));
383
+ return new Guid(hash.Take(16).ToArray());
384
+ }
385
+ }
386
+
387
+ public class ApplicationRoleSeedEntry
388
+ {
389
+ public Guid Id { get; init; }
390
+ public string Code { get; init; } = null!;
391
+ public string Name { get; init; } = null!;
392
+ public string Description { get; init; } = null!;
393
+ public Guid ApplicationId { get; init; }
394
+ public bool IsSystem { get; init; }
395
+ public bool IsActive { get; init; }
396
+ public int DisplayOrder { get; init; }
397
+ }
398
+ ```
399
+
400
+ **Replace placeholders** with values from PRD and navigation metadata.
401
+
402
+ ---
403
+
404
+ ## 5. {Module}RolesSeedData.cs (Per Module)
283
405
 
284
406
  **File:** `Infrastructure/Persistence/Seeding/Data/{ModulePascal}/RolesSeedData.cs`
285
407
 
@@ -335,7 +457,7 @@ public class RolePermissionSeedEntry
335
457
 
336
458
  ---
337
459
 
338
- ## 5. IClientSeedDataProvider Implementation
460
+ ## 6. IClientSeedDataProvider Implementation
339
461
 
340
462
  **File:** `Infrastructure/Persistence/Seeding/{AppPascalName}SeedDataProvider.cs`
341
463
 
@@ -343,10 +465,11 @@ public class RolePermissionSeedEntry
343
465
 
344
466
  | Rule | Description |
345
467
  |------|-------------|
346
- | Factory methods | `NavigationModule.Create(...)`, `Permission.CreateForModule(...)`, `RolePermission.Create(...)` — NEVER `new Entity()` |
468
+ | Factory methods | `NavigationModule.Create(...)`, `Role.Create(...)`, `Permission.CreateForModule(...)`, `RolePermission.Create(...)` — NEVER `new Entity()` |
347
469
  | Idempotence | Each Seed method checks existence before inserting |
348
- | SaveChanges per group | Navigation -> save -> Permissions -> save -> RolePermissions -> save |
349
- | FK resolution by Code | Parent entities found by `Code`, not hardcoded GUID |
470
+ | Execution order | Navigation Roles Permissions RolePermissions (roles MUST exist before mapping) |
471
+ | SaveChanges per group | Navigation -> save -> Roles -> save -> Permissions -> save -> RolePermissions -> save |
472
+ | FK resolution by Code | Parent entities (modules, roles) found by `Code`, not hardcoded GUID |
350
473
  | DI registration | `services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>()` |
351
474
 
352
475
  ### Template
@@ -357,13 +480,14 @@ using SmartStack.Application.Common.Interfaces;
357
480
  using SmartStack.Application.Common.Interfaces.Seeding;
358
481
  using SmartStack.Domain.Navigation;
359
482
  using SmartStack.Domain.Platform.Administration.Roles;
483
+ using {BaseNamespace}.Infrastructure.Persistence.Seeding.Data;
360
484
  using {BaseNamespace}.Infrastructure.Persistence.Seeding.Data.{Module1Pascal};
361
485
  // using {BaseNamespace}.Infrastructure.Persistence.Seeding.Data.{Module2Pascal}; // Add per module
362
486
 
363
487
  namespace {BaseNamespace}.Infrastructure.Persistence.Seeding;
364
488
 
365
489
  /// <summary>
366
- /// Seeds {AppLabel} navigation, permissions, and role-permission data
490
+ /// Seeds {AppLabel} navigation, roles, permissions, and role-permission data
367
491
  /// into the SmartStack Core schema at application startup.
368
492
  /// </summary>
369
493
  public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
@@ -420,6 +544,28 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
420
544
  await ((DbContext)context).SaveChangesAsync(ct);
421
545
  }
422
546
 
547
+ public async Task SeedRolesAsync(ICoreDbContext context, CancellationToken ct)
548
+ {
549
+ // Check idempotence
550
+ var applicationId = ApplicationRolesSeedData.ApplicationId;
551
+ var exists = await context.Roles
552
+ .AnyAsync(r => r.ApplicationId == applicationId, ct);
553
+ if (exists) return;
554
+
555
+ // Create application-scoped roles (Admin, Manager, Contributor, Viewer)
556
+ foreach (var entry in ApplicationRolesSeedData.GetRoleEntries())
557
+ {
558
+ var role = Role.Create(
559
+ entry.Code,
560
+ entry.Name,
561
+ entry.Description,
562
+ entry.ApplicationId,
563
+ entry.IsSystem);
564
+ context.Roles.Add(role);
565
+ }
566
+ await ((DbContext)context).SaveChangesAsync(ct);
567
+ }
568
+
423
569
  public async Task SeedPermissionsAsync(ICoreDbContext context, CancellationToken ct)
424
570
  {
425
571
  var exists = await context.Permissions
@@ -495,43 +641,49 @@ services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>();
495
641
 
496
642
  ---
497
643
 
498
- ## 6. Multi-Module Handling
644
+ ## 7. Multi-Module Handling
499
645
 
500
646
  When processing multiple modules in the same ralph-loop run:
501
647
 
502
648
  ### Module 1 (first): Creates everything from scratch
503
649
 
504
- 1. `{Module1}NavigationSeedData.cs`
505
- 2. `{Module1}PermissionsSeedData.cs`
506
- 3. `{Module1}RolesSeedData.cs`
507
- 4. `{AppPascalName}SeedDataProvider.cs` (new)
508
- 5. DI registration (new)
650
+ 1. `ApplicationRolesSeedData.cs` (application-level, once per app)
651
+ 2. `{Module1}NavigationSeedData.cs`
652
+ 3. `{Module1}PermissionsSeedData.cs`
653
+ 4. `{Module1}RolesSeedData.cs`
654
+ 5. `{AppPascalName}SeedDataProvider.cs` (new, with 4 methods)
655
+ 6. DI registration (new)
509
656
 
510
657
  ### Module 2+ (subsequent): Append to existing provider
511
658
 
512
- 1. `{Module2}NavigationSeedData.cs` (new file)
513
- 2. `{Module2}PermissionsSeedData.cs` (new file)
514
- 3. `{Module2}RolesSeedData.cs` (new file)
515
- 4. `{AppPascalName}SeedDataProvider.cs` (**modify** — add using, add entries in each Seed method)
516
- 5. DI registration (already exists skip)
659
+ 1. `ApplicationRolesSeedData.cs` (already exists — skip)
660
+ 2. `{Module2}NavigationSeedData.cs` (new file)
661
+ 3. `{Module2}PermissionsSeedData.cs` (new file)
662
+ 4. `{Module2}RolesSeedData.cs` (new file)
663
+ 5. `{AppPascalName}SeedDataProvider.cs` (**modify**add using, add entries in Navigation/Permissions/RolePermissions methods)
664
+ 6. DI registration (already exists — skip)
517
665
 
518
- **Detection:** Check if `{AppPascalName}SeedDataProvider.cs` exists. If yes, READ it and ADD the new module's entries to each of the 3 methods.
666
+ **Detection:** Check if `{AppPascalName}SeedDataProvider.cs` exists. If yes, READ it and ADD the new module's entries to the appropriate methods (Navigation, Permissions, RolePermissions). Do NOT modify SeedRolesAsync().
519
667
 
520
668
  ---
521
669
 
522
- ## 7. Verification Checklist (BLOCKING)
670
+ ## 8. Verification Checklist (BLOCKING)
523
671
 
524
672
  Before marking the task as completed, verify ALL:
525
673
 
526
674
  - [ ] Deterministic GUIDs (NEVER `Guid.NewGuid()`) — SHA256 of path
527
675
  - [ ] 4 languages for each navigation entity (fr, en, it, de)
676
+ - [ ] `ApplicationRolesSeedData.cs` created (once per application)
677
+ - [ ] 4 application roles defined: Admin, Manager, Contributor, Viewer
678
+ - [ ] Each role has a valid `Code` value ("admin", "manager", "contributor", "viewer")
528
679
  - [ ] `Permissions.cs` constants match seed data paths
529
680
  - [ ] MCP `generate_permissions` called (or fallback used)
530
681
  - [ ] Role-permission mappings assigned (Admin, Manager, Contributor, Viewer)
531
- - [ ] `IClientSeedDataProvider` generated with 3 methods
682
+ - [ ] `IClientSeedDataProvider` generated with 4 methods (Navigation, Roles, Permissions, RolePermissions)
683
+ - [ ] Execution order: Navigation → Roles → Permissions → RolePermissions
532
684
  - [ ] Each Seed method is idempotent (checks existence before inserting)
533
685
  - [ ] Factory methods used throughout (NEVER `new Entity()`)
534
- - [ ] `SaveChangesAsync` called per group (Navigation → Permissions → RolePermissions)
686
+ - [ ] `SaveChangesAsync` called per group (Navigation → Roles → Permissions → RolePermissions)
535
687
  - [ ] DI registration added: `services.AddScoped<IClientSeedDataProvider, ...>()`
536
688
  - [ ] `dotnet build` passes after generation
537
689