@atlashub/smartstack-cli 3.43.0 → 3.45.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 (47) hide show
  1. package/dist/mcp-entry.mjs +201 -22
  2. package/dist/mcp-entry.mjs.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/agents/efcore/conflicts.md +22 -2
  5. package/templates/agents/efcore/migration.md +11 -0
  6. package/templates/agents/efcore/rebase-snapshot.md +7 -0
  7. package/templates/agents/efcore/scan.md +24 -2
  8. package/templates/agents/efcore/squash.md +7 -0
  9. package/templates/agents/gitflow/init.md +195 -12
  10. package/templates/skills/apex/SKILL.md +14 -9
  11. package/templates/skills/apex/_shared.md +3 -0
  12. package/templates/skills/apex/references/analysis-methods.md +1 -1
  13. package/templates/skills/apex/references/challenge-questions.md +21 -0
  14. package/templates/skills/apex/references/core-seed-data.md +59 -104
  15. package/templates/skills/apex/references/post-checks.md +289 -225
  16. package/templates/skills/apex/references/smartstack-api.md +33 -35
  17. package/templates/skills/apex/references/smartstack-frontend.md +99 -3
  18. package/templates/skills/apex/references/smartstack-layers.md +145 -23
  19. package/templates/skills/apex/steps/step-00-init.md +2 -2
  20. package/templates/skills/apex/steps/step-01-analyze.md +1 -0
  21. package/templates/skills/apex/steps/step-02-plan.md +4 -3
  22. package/templates/skills/apex/steps/step-03-execute.md +24 -24
  23. package/templates/skills/apex/steps/step-04-examine.md +64 -24
  24. package/templates/skills/apex/steps/step-05-deep-review.md +1 -1
  25. package/templates/skills/apex/steps/step-08-run-tests.md +21 -13
  26. package/templates/skills/application/references/application-roles-template.md +10 -15
  27. package/templates/skills/application/references/backend-entity-seeding.md +6 -5
  28. package/templates/skills/application/references/backend-seeding-and-dto-output.md +1 -1
  29. package/templates/skills/application/references/nav-fallback-procedure.md +14 -17
  30. package/templates/skills/application/references/provider-template.md +5 -5
  31. package/templates/skills/application/references/roles-client-project-handling.md +1 -1
  32. package/templates/skills/application/references/roles-fallback-procedure.md +10 -15
  33. package/templates/skills/application/steps/step-01-navigation.md +1 -1
  34. package/templates/skills/application/steps/step-02-permissions.md +3 -3
  35. package/templates/skills/application/steps/step-03b-provider.md +1 -0
  36. package/templates/skills/application/templates-seed.md +41 -47
  37. package/templates/skills/business-analyse/references/team-orchestration.md +2 -2
  38. package/templates/skills/controller/steps/step-04-perms.md +1 -1
  39. package/templates/skills/efcore/references/troubleshooting.md +2 -2
  40. package/templates/skills/efcore/steps/rebase-snapshot/step-00-init.md +2 -2
  41. package/templates/skills/efcore/steps/squash/step-00-init.md +2 -2
  42. package/templates/skills/apex/references/examine-build-validation.md +0 -82
  43. package/templates/skills/apex/references/execution-frontend-gates.md +0 -177
  44. package/templates/skills/apex/references/execution-frontend-patterns.md +0 -105
  45. package/templates/skills/apex/references/execution-layer1-rules.md +0 -96
  46. package/templates/skills/apex/references/initialization-challenge-flow.md +0 -110
  47. package/templates/skills/apex/references/planning-layer-mapping.md +0 -151
@@ -130,14 +130,51 @@ fi
130
130
 
131
131
  ---
132
132
 
133
- ## 4-5. Build & Migration Validation
133
+ ## 4. Build Verification
134
134
 
135
- > **Reference:** Load `references/examine-build-validation.md` for detailed procedures:
136
- > - Build verification (dotnet clean → restore → build + npm typecheck)
137
- > - Error classification (categories A-F per error-classification.md)
138
- > - Migration validation (pending changes, SQL Server apply, cleanup)
139
- > - Integration tests (real SQL Server LocalDB)
140
- > - Test database management
135
+ ```bash
136
+ # Backend
137
+ dotnet clean && dotnet restore && dotnet build
138
+ # Note: WSL bin\Debug cleanup handled by PostToolUse hook (wsl-dotnet-cleanup.sh)
139
+
140
+ # Frontend (if applicable)
141
+ npm run typecheck
142
+ ```
143
+
144
+ **BLOCKING:** Both must pass. If failure, classify error per `references/error-classification.md` (categories A-F).
145
+
146
+ ---
147
+
148
+ ## 5. Migration Validation (if needs_migration)
149
+
150
+ ```bash
151
+ INFRA_PROJECT=$(ls src/*Infrastructure*/*.csproj 2>/dev/null | head -1)
152
+ API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)
153
+
154
+ # Pending model changes check (BLOCKING if pending)
155
+ dotnet ef migrations has-pending-model-changes \
156
+ --project "$INFRA_PROJECT" \
157
+ --startup-project "$API_PROJECT"
158
+
159
+ # Migration application test (SQL Server LocalDB)
160
+ DB_NAME="SmartStack_Apex_Examine_$(date +%s)"
161
+ CONN_STRING="Server=(localdb)\\MSSQLLocalDB;Database=$DB_NAME;Integrated Security=true;TrustServerCertificate=true;Connect Timeout=120;"
162
+ dotnet ef database update \
163
+ --connection "$CONN_STRING" \
164
+ --project "$INFRA_PROJECT" \
165
+ --startup-project "$API_PROJECT"
166
+
167
+ # Integration tests on real SQL Server (if project exists)
168
+ INT_TEST_PROJECT=$(ls tests/*Tests.Integration*/*.csproj 2>/dev/null | head -1)
169
+ if [ -n "$INT_TEST_PROJECT" ]; then
170
+ dotnet test "$INT_TEST_PROJECT" --no-build --verbosity normal
171
+ fi
172
+
173
+ # Cleanup
174
+ sqlcmd -S "(localdb)\MSSQLLocalDB" -Q "IF DB_ID('$DB_NAME') IS NOT NULL BEGIN ALTER DATABASE [$DB_NAME] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; DROP DATABASE [$DB_NAME]; END" 2>/dev/null
175
+ ```
176
+
177
+ **BLOCKING** if migration fails on SQL Server (common: SQLite-only syntax, column type mismatches, missing FK targets).
141
178
 
142
179
  ---
143
180
 
@@ -145,11 +182,11 @@ fi
145
182
 
146
183
  | File | Checks |
147
184
  |------|--------|
148
- | NavigationApplicationSeedData | MUST be first, deterministic GUID for application (NOT for context context is looked up by code), 4 lang translations |
149
- | ApplicationRolesSeedData | 4 roles (admin, manager, contributor, viewer), deterministic GUIDs, references NavigationApplicationSeedData.ApplicationId |
150
- | NavigationModuleSeedData | Deterministic GUIDs (SHA256), 4 languages (fr, en, it, de), GetModuleEntry + GetTranslationEntries |
151
- | ↳ Section methods (same file) | (conditional: if sections exist) GetSectionEntries + GetSectionTranslationEntries, 4 languages, deterministic GUIDs, query actual module from DB for FK |
152
- | ↳ Resource methods (same file) | (conditional: if resources exist) GetResourceEntries + resource translations, 4 languages, deterministic GUIDs, query actual section from DB for FK |
185
+ | NavigationApplicationSeedData | MUST be first, random GUID via Guid.NewGuid() (resolved by Code at runtime), 4 lang translations |
186
+ | ApplicationRolesSeedData | 4 roles (admin, manager, contributor, viewer), random GUIDs, references NavigationApplicationSeedData.ApplicationId |
187
+ | NavigationModuleSeedData | Random GUIDs (`Guid.NewGuid()`), 4 languages (fr, en, it, de), GetModuleEntry + GetTranslationEntries |
188
+ | ↳ Section methods (same file) | (conditional: if sections exist) GetSectionEntries + GetSectionTranslationEntries, 4 languages, random GUIDs, query actual module from DB for FK |
189
+ | ↳ Resource methods (same file) | (conditional: if resources exist) GetResourceEntries + resource translations, 4 languages, random GUIDs, query actual section from DB for FK |
153
190
  | Permissions.cs | Static constants class with `public static class {Module} { Read, Create, Update, Delete }`, paths match PermissionsSeedData |
154
191
  | PermissionsSeedData | MCP generate_permissions used, paths match Permissions.cs, wildcard + CRUD |
155
192
  | RolesSeedData | Admin=wildcard(*), Manager=CRU, Contributor=CR, Viewer=R. Role-permission entries reference permission paths from PermissionsSeedData |
@@ -160,7 +197,10 @@ fi
160
197
 
161
198
  ## 6b. BLOCKING POST-CHECKs
162
199
 
163
- Load and execute all checks from `references/post-checks.md`.
200
+ > **MCP FIRST:** Run `validate_conventions`, `validate_security`, and `validate_frontend_routes` before bash checks.
201
+ > These 3 MCP tools cover ~10 additional checks automatically.
202
+
203
+ Load and execute all checks from `references/post-checks.md` (6 security defense-in-depth + 44 convention checks).
164
204
 
165
205
  **If ANY POST-CHECK fails → fix in step-03, re-validate.**
166
206
 
@@ -193,18 +233,18 @@ AC2: {criterion} → PASS / FAIL (evidence: {file:line or test})
193
233
  | DB tests | Integration tests on SQL Server | PASS / N/A |
194
234
  | Frontend | routes, lazy loading, forms as pages, i18n (4 langs + keys) | PASS / N/A |
195
235
  | Security | TenantId filter, RequirePermission, no Guid.Empty, no !.Value | PASS / N/A |
196
- | Seed data | completeness, deterministic GUIDs, no ContextId/RoleId constants | PASS / N/A |
236
+ | Seed data | completeness, random GUIDs (Guid.NewGuid()), no ContextId/RoleId constants | PASS / N/A |
197
237
  | Code quality | PaginatedResult, EntityLookup (no FK select/input), CSS vars, search param | PASS / N/A |
198
- | Migration completeness | ModelSnapshot covers ALL DbSet entities (POST-CHECK 44, 49) | PASS / N/A |
199
- | NavRoute kebab-case | NavRoute + permissions use kebab-case (POST-CHECK 48) | PASS / N/A |
200
- | DateOnly DTOs | Date fields use DateOnly not string (POST-CHECK 47) | PASS / N/A |
201
- | I18n registration | Namespaces registered in i18n config (POST-CHECK 45) | PASS / N/A |
202
- | Validators DI | FluentValidation registered in DI (POST-CHECK 46) | PASS / N/A |
203
- | Route/NavRoute conflict | No [Route] alongside [NavRoute] on controllers (POST-CHECK 50) | PASS / N/A |
204
- | Role-permission matrix | Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R (POST-CHECK 51) | PASS / N/A |
205
- | PermissionAction enum | No Enum.Parse, only typed enum values 0-10 (POST-CHECK 52) | PASS / N/A |
206
- | Navigation translations | 4 langs per level, section/resource translations present (POST-CHECK 53) | PASS / N/A |
207
- | POST-CHECKs | 53 checks from references/post-checks.md | PASS / N/A |
238
+ | Migration completeness | ModelSnapshot covers ALL DbSet entities (POST-CHECK 36, 40) | PASS / N/A |
239
+ | NavRoute kebab-case | NavRoute + permissions use kebab-case (POST-CHECK 32) | PASS / N/A |
240
+ | DateOnly DTOs | Date fields use DateOnly not string (POST-CHECK 39) | PASS / N/A |
241
+ | I18n registration | Namespaces registered in i18n config (POST-CHECK 37) | PASS / N/A |
242
+ | Validators DI | FluentValidation registered in DI (POST-CHECK 38) | PASS / N/A |
243
+ | Route/NavRoute conflict | No [Route] alongside [NavRoute] on controllers (POST-CHECK 41) | PASS / N/A |
244
+ | Role-permission matrix | Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R (POST-CHECK 42) | PASS / N/A |
245
+ | PermissionAction enum | No Enum.Parse, only typed enum values 0-10 (POST-CHECK 43) | PASS / N/A |
246
+ | Navigation translations | 4 langs per level, section/resource translations present (POST-CHECK 44) | PASS / N/A |
247
+ | POST-CHECKs | 3 MCP tools + 50 bash checks (6 security + 44 convention) | PASS / N/A |
208
248
  | Acceptance criteria | AC1..ACn | {X}/{Y} PASS |
209
249
  ```
210
250
 
@@ -54,7 +54,7 @@ For each changed file, check:
54
54
  - [ ] Frontend in correct hierarchy (App/Module)
55
55
 
56
56
  **SmartStack conventions:**
57
- - [ ] Deterministic GUIDs in seed data (not Guid.NewGuid())
57
+ - [ ] Random GUIDs in seed data via Guid.NewGuid() (no deterministic/sequential/fixed)
58
58
  - [ ] 4 languages in translations
59
59
  - [ ] CSS variables (not hardcoded colors)
60
60
  - [ ] SmartTable/SmartForm (not raw HTML tables/forms)
@@ -24,10 +24,25 @@ dotnet build --no-restore
24
24
 
25
25
  ---
26
26
 
27
- ## 2. Run Full Test Suite
27
+ ## 2. Run Full Test Suite (backend + frontend in parallel)
28
28
 
29
29
  ```bash
30
- dotnet test --no-build --verbosity normal
30
+ # Run backend and frontend tests in parallel when both exist
31
+ WEB_DIR=$(find . -name "vitest.config.ts" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
32
+
33
+ if [ -n "$WEB_DIR" ]; then
34
+ # Both exist → run in parallel
35
+ dotnet test --no-build --verbosity normal &
36
+ BACKEND_PID=$!
37
+ (cd "$WEB_DIR" && npm run test) &
38
+ FRONTEND_PID=$!
39
+ wait $BACKEND_PID; BACKEND_RC=$?
40
+ wait $FRONTEND_PID; FRONTEND_RC=$?
41
+ [ $BACKEND_RC -ne 0 ] || [ $FRONTEND_RC -ne 0 ] && echo "FAILURES DETECTED"
42
+ else
43
+ # Backend only
44
+ dotnet test --no-build --verbosity normal
45
+ fi
31
46
  ```
32
47
 
33
48
  ---
@@ -86,22 +101,15 @@ questions:
86
101
 
87
102
  ---
88
103
 
89
- ## 5. Frontend Tests + Typecheck (if applicable)
104
+ ## 5. Typecheck (if applicable)
90
105
 
91
- ```bash
92
- # Run frontend tests first
93
- WEB_DIR=$(find . -name "vitest.config.ts" -not -path "*/node_modules/*" -exec dirname {} \; 2>/dev/null | head -1)
94
- if [ -n "$WEB_DIR" ]; then
95
- cd "$WEB_DIR"
96
- npm run test
97
- cd -
98
- fi
106
+ > **Note:** Frontend tests already ran in parallel with backend tests in section 2.
99
107
 
100
- # Then typecheck
108
+ ```bash
101
109
  npm run typecheck
102
110
  ```
103
111
 
104
- **BOTH MUST PASS.** If frontend tests fail, apply the same fix loop as backend (fix CODE, not tests, max 5 iterations).
112
+ **MUST PASS.** If frontend tests failed in section 2, apply the same fix loop as backend (fix CODE, not tests, max 5 iterations).
105
113
 
106
114
  ---
107
115
 
@@ -22,7 +22,7 @@ var role = roles.FirstOrDefault(r => r.Code == mapping.RoleCode); // "admin", "
22
22
 
23
23
  ## Solution: Application Roles Seed Data
24
24
 
25
- Create application-scoped roles with deterministic GUIDs and valid `Code` values.
25
+ Create application-scoped roles with random GUIDs (`Guid.NewGuid()`) and valid `Code` values.
26
26
 
27
27
  ---
28
28
 
@@ -48,14 +48,13 @@ namespace {BaseNamespace}.Infrastructure.Persistence.Seeding.Data;
48
48
  /// </summary>
49
49
  public static class ApplicationRolesSeedData
50
50
  {
51
- // Deterministic GUIDs for application roles
52
- // Generated from: "role-{applicationId}-{roleType}"
51
+ // Random GUIDs idempotence is handled by Code-based lookups, not fixed IDs
53
52
  public static readonly Guid ApplicationId = NavigationApplicationSeedData.ApplicationId;
54
53
 
55
- public static readonly Guid AdminRoleId = GenerateRoleGuid("admin");
56
- public static readonly Guid ManagerRoleId = GenerateRoleGuid("manager");
57
- public static readonly Guid ContributorRoleId = GenerateRoleGuid("contributor");
58
- public static readonly Guid ViewerRoleId = GenerateRoleGuid("viewer");
54
+ public static readonly Guid AdminRoleId = Guid.NewGuid();
55
+ public static readonly Guid ManagerRoleId = Guid.NewGuid();
56
+ public static readonly Guid ContributorRoleId = Guid.NewGuid();
57
+ public static readonly Guid ViewerRoleId = Guid.NewGuid();
59
58
 
60
59
  /// <summary>
61
60
  /// Returns application-scoped role entries for seeding into core.auth_Roles.
@@ -111,12 +110,8 @@ public static class ApplicationRolesSeedData
111
110
  };
112
111
  }
113
112
 
114
- private static Guid GenerateRoleGuid(string roleType)
115
- {
116
- using var sha256 = System.Security.Cryptography.SHA256.Create();
117
- var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes($"role-{ApplicationId}-{roleType}"));
118
- return new Guid(hash.Take(16).ToArray());
119
- }
113
+ // No deterministic GUID generation — all IDs are random via Guid.NewGuid()
114
+ // Roles are resolved by Code at runtime, not by fixed GUIDs
120
115
  }
121
116
 
122
117
  /// <summary>Seed entry DTO for application role.</summary>
@@ -141,7 +136,7 @@ public class ApplicationRoleSeedEntry
141
136
  |-------------|-------------|---------|
142
137
  | `{BaseNamespace}` | Root namespace of the client project | `SmartStack.Modules.RessourcesHumaines` |
143
138
  | `{AppLabel}` | Human-readable application label (EN) | `Human Resources` |
144
- | `ApplicationId` | Deterministic GUID from `NavigationApplicationSeedData.ApplicationId` — NO placeholder needed | Auto-resolved |
139
+ | `ApplicationId` | From `NavigationApplicationSeedData.ApplicationId` — resolved at runtime via Code lookup | Auto-resolved |
145
140
 
146
141
  ---
147
142
 
@@ -194,7 +189,7 @@ public async Task SeedRolesAsync(ICoreDbContext context, CancellationToken ct)
194
189
  Before marking the task as completed, verify:
195
190
 
196
191
  - [ ] `ApplicationRolesSeedData.cs` created in `Infrastructure/Persistence/Seeding/Data/`
197
- - [ ] Deterministic GUIDs used (NEVER `Guid.NewGuid()`)
192
+ - [ ] Random GUIDs used via `Guid.NewGuid()` (no deterministic/sequential/fixed values)
198
193
  - [ ] 4 roles defined: Admin, Manager, Contributor, Viewer
199
194
  - [ ] Each role has a valid `Code` value ("admin", "manager", "contributor", "viewer")
200
195
  - [ ] Each role has `ApplicationId` set to the application GUID
@@ -8,16 +8,17 @@
8
8
 
9
9
  Follow SmartStack.app pattern:
10
10
  - Static class with `internal static IEnumerable<{EntityName}SeedItem> GetAll{EntityName}s()`
11
- - Use deterministic GUIDs (NEVER `Guid.NewGuid()`)
11
+ - ALWAYS use `Guid.NewGuid()` — avoids conflicts between projects/tenants/environments
12
+ - Idempotence is handled by `AnyAsync()` checks (by Code/Name), NOT by fixed IDs
12
13
  - Include 3-5 sample entities with varied, realistic data
13
14
  - For multi-tenant: organize by tenant using `GetTenant1{EntityName}s()` helpers
14
15
 
15
16
  ```csharp
16
17
  public static class {EntityName}SeedData
17
18
  {
18
- public static readonly Guid Sample1Id = Guid.Parse("...");
19
- public static readonly Guid Sample2Id = Guid.Parse("...");
20
- public static readonly Guid Sample3Id = Guid.Parse("...");
19
+ public static readonly Guid Sample1Id = Guid.NewGuid();
20
+ public static readonly Guid Sample2Id = Guid.NewGuid();
21
+ public static readonly Guid Sample3Id = Guid.NewGuid();
21
22
 
22
23
  internal static IEnumerable<{EntityName}SeedItem> GetAll{EntityName}s()
23
24
  {
@@ -59,7 +60,7 @@ private async Task Seed{EntityName}sAsync(CancellationToken cancellationToken)
59
60
  foreach (var seedItem in {EntityName}SeedData.GetAll{EntityName}s())
60
61
  {
61
62
  var entity = {EntityName}.Create(/* map seedItem properties */);
62
- typeof({EntityName}).GetProperty("Id")?.SetValue(entity, seedItem.Id);
63
+ // Factory method generates a random GUID — no need to override
63
64
  _context.{EntityName}s.Add(entity);
64
65
  createdCount++;
65
66
  }
@@ -23,7 +23,7 @@ questions:
23
23
  **If user selects YES:**
24
24
 
25
25
  See [references/backend-entity-seeding.md](../references/backend-entity-seeding.md) for the full seeding pattern:
26
- 1. **SeedData file** (`{EntityName}SeedData.cs`) — static class with deterministic GUIDs, 3-5 samples
26
+ 1. **SeedData file** (`{EntityName}SeedData.cs`) — static class with `Guid.NewGuid()`, 3-5 samples
27
27
  2. **DevDataSeeder update** — add `Seed{EntityName}sAsync()` method with idempotent check
28
28
 
29
29
  **If user selects NO:**
@@ -16,11 +16,10 @@
16
16
  Glob: **/Persistence/Configurations/Navigation/Navigation*Configuration.cs
17
17
  ```
18
18
 
19
- 2. **Read NavigationTranslationConfiguration.cs** - Find the last GUID index:
19
+ 2. **Read NavigationTranslationConfiguration.cs** - Check existing translations:
20
20
  ```
21
- Search for: the last call to GenerateGuid(index++)
22
- The index variable starts at 1 and increments per translation entry.
23
- Your new translations MUST continue from the next index value.
21
+ All translation IDs use Guid.NewGuid() — no sequence to track.
22
+ Just verify no duplicate EntityType+EntityId+LanguageCode combinations.
24
23
  ```
25
24
 
26
25
  3. **Read Navigation{Level}Configuration.cs** - Check existing entities:
@@ -51,18 +50,16 @@ Read the parent SeedData class and find the GUID matching `{parent_path}`.
51
50
 
52
51
  ## F3. Generate Navigation Entity GUID
53
52
 
54
- Generate a deterministic GUID for the new navigation entity:
53
+ Generate a random GUID for the new navigation entity:
55
54
 
56
55
  ```csharp
57
- // Use SHA256 hash of the full_path for deterministic generation
58
- using var sha256 = System.Security.Cryptography.SHA256.Create();
59
- var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes("navigation-{level}-{full_path}"));
60
- var guid = new Guid(hash.Take(16).ToArray());
56
+ // ALWAYS use Guid.NewGuid() avoids conflicts between projects/tenants/environments
57
+ var guid = Guid.NewGuid();
61
58
  ```
62
59
 
63
60
  **Rules:**
64
- - NEVER use `Guid.NewGuid()`
65
- - Read existing SeedData GUIDs to verify no collision
61
+ - ALWAYS use `Guid.NewGuid()` — no deterministic, no sequential, no fixed values
62
+ - Idempotence is handled by Code-based lookups, not by fixed IDs
66
63
  - Store result as `{navigation_guid}`
67
64
 
68
65
  ## F4. Write Navigation Entity Seed
@@ -128,7 +125,7 @@ Add 4 translation entries to `NavigationTranslationConfiguration.cs`:
128
125
 
129
126
  // {level}: {code} translations
130
127
  translations.Add(new {
131
- Id = GenerateGuid(index++),
128
+ Id = Guid.NewGuid(),
132
129
  EntityType = NavigationEntityType.{Level},
133
130
  EntityId = Navigation{Level}SeedData.{PascalCode}Id, // or Guid.Parse("{navigation_guid}")
134
131
  LanguageCode = "fr",
@@ -137,7 +134,7 @@ translations.Add(new {
137
134
  CreatedAt = seedDate
138
135
  });
139
136
  translations.Add(new {
140
- Id = GenerateGuid(index++),
137
+ Id = Guid.NewGuid(),
141
138
  EntityType = NavigationEntityType.{Level},
142
139
  EntityId = Navigation{Level}SeedData.{PascalCode}Id,
143
140
  LanguageCode = "en",
@@ -146,7 +143,7 @@ translations.Add(new {
146
143
  CreatedAt = seedDate
147
144
  });
148
145
  translations.Add(new {
149
- Id = GenerateGuid(index++),
146
+ Id = Guid.NewGuid(),
150
147
  EntityType = NavigationEntityType.{Level},
151
148
  EntityId = Navigation{Level}SeedData.{PascalCode}Id,
152
149
  LanguageCode = "it",
@@ -155,7 +152,7 @@ translations.Add(new {
155
152
  CreatedAt = seedDate
156
153
  });
157
154
  translations.Add(new {
158
- Id = GenerateGuid(index++),
155
+ Id = Guid.NewGuid(),
159
156
  EntityType = NavigationEntityType.{Level},
160
157
  EntityId = Navigation{Level}SeedData.{PascalCode}Id,
161
158
  LanguageCode = "de",
@@ -175,9 +172,9 @@ translations.Add(new {
175
172
  ## F7. Validation Checklist
176
173
 
177
174
  Before proceeding, verify:
178
- - [ ] Deterministic GUID generated (not NewGuid())
175
+ - [ ] Random GUID generated via Guid.NewGuid()
179
176
  - [ ] 4 languages present (fr, en, it, de)
180
- - [ ] Translation index continues existing sequence (no gaps, no collisions)
177
+ - [ ] No duplicate EntityType+EntityId+LanguageCode combinations
181
178
  - [ ] Parent GUID correctly references existing entity
182
179
  - [ ] Route path matches `/{app}/{module}` pattern
183
180
  - [ ] DisplayOrder is consistent with existing entities
@@ -86,11 +86,11 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
86
86
  // t => t.EntityId == secEntry.Id && t.EntityType == NavigationEntityType.Section, ct))
87
87
 
88
88
  // --- Resources (idempotent — use ACTUAL section IDs from DB) ---
89
- // CRITICAL: NavigationSection.Create() generates its own ID. Deterministic seed GUIDs
90
- // do NOT match actual SectionId in DB FK_nav_Resources_nav_Sections_SectionId violation.
91
- // MUST query actual section: var actualSection = await context.NavigationSections
89
+ // CRITICAL: NavigationSection.Create() generates its own random ID.
90
+ // MUST query actual section from DB to get real ID for FK references:
91
+ // var actualSection = await context.NavigationSections
92
92
  // .FirstAsync(s => s.Code == secEntry.Code && s.ModuleId == modEntity.Id, ct);
93
- // Then use actualSection.Id (NOT secEntry.Id) for NavigationResource.Create() and AnyAsync
93
+ // Then use actualSection.Id for NavigationResource.Create() and AnyAsync
94
94
  }
95
95
 
96
96
  public async Task SeedRolesAsync(ICoreDbContext context, CancellationToken ct)
@@ -172,6 +172,6 @@ services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>();
172
172
  3. **Translation guard pattern**: `if (!await context.NavigationTranslations.AnyAsync(t => t.EntityId == {id} && t.EntityType == ..., ct))` — MANDATORY before every translation batch insert
173
173
  4. **SaveChangesAsync per group**: Navigation → save → Roles → save → Permissions → save → RolePermissions → save
174
174
  4. **Execution order**: `SeedRolesAsync()` MUST be called BEFORE `SeedRolePermissionsAsync()` (roles must exist before mapping)
175
- 5. **Deterministic GUIDs**: Use IDs from SeedData classes (not `Guid.NewGuid()`)
175
+ 5. **Random GUIDs**: ALWAYS use `Guid.NewGuid()` — resolve FKs by Code lookup, not fixed IDs
176
176
  6. **Resolve FK by Code**: Parent modules and roles are found by `Code`, not hardcoded GUID
177
177
  7. **Order property**: Use `100` as default. If multiple providers exist, they run in Order sequence
@@ -15,7 +15,7 @@
15
15
  See [references/application-roles-template.md](../references/application-roles-template.md) for the complete template.
16
16
 
17
17
  **Key requirements:**
18
- - Deterministic GUIDs based on `role-{applicationId}-{roleType}`
18
+ - Random GUIDs via `Guid.NewGuid()` — roles are resolved by Code at runtime
19
19
  - 4 roles: Admin, Manager, Contributor, Viewer
20
20
  - Each role has a valid `Code` property ("admin", "manager", "contributor", "viewer")
21
21
  - `ApplicationId` references the navigation application GUID
@@ -24,26 +24,21 @@ Read the file to determine:
24
24
 
25
25
  | Role | GUID |
26
26
  |------|------|
27
- | SuperAdmin | `11111111-1111-1111-1111-111111111111` |
28
- | PlatformAdmin | `22222222-2222-2222-2222-222222222222` |
29
- | TenantAdmin | `33333333-3333-3333-3333-333333333333` |
30
- | StandardUser | `44444444-4444-4444-4444-444444444444` |
27
+ | SuperAdmin | Resolved by Code at runtime (NEVER hardcoded) |
28
+ | PlatformAdmin | Resolved by Code at runtime (NEVER hardcoded) |
29
+ | TenantAdmin | Resolved by Code at runtime (NEVER hardcoded) |
30
+ | StandardUser | Resolved by Code at runtime (NEVER hardcoded) |
31
31
 
32
32
  **IMPORTANT:** Read the actual `RoleSeedData.cs` or `RoleConfiguration.cs` in the target project to confirm the actual role GUIDs. The above are defaults; the project may use different values.
33
33
 
34
- **Application-scoped roles** (deterministic GUIDs based on application):
34
+ **Application-scoped roles** (resolved by Code at runtime):
35
35
 
36
36
  ```csharp
37
- // Read the existing GenerateDeterministicGuid method in RolePermissionConfiguration.cs
38
- // Typically uses MD5 hash:
39
- private static Guid GenerateDeterministicGuid(Guid applicationId, string roleType)
40
- {
41
- using var md5 = System.Security.Cryptography.MD5.Create();
42
- var input = $"{applicationId}-{roleType}";
43
- var hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));
44
- return new Guid(hash);
45
- }
46
- // roleType values: "admin", "manager", "contributor", "viewer"
37
+ // ALWAYS resolve roles by Code at runtime — NEVER use deterministic/hardcoded GUIDs
38
+ // Role IDs are generated via Guid.NewGuid() at seed time
39
+ // Lookups use:
40
+ var role = await context.Roles.FirstOrDefaultAsync(r => r.Code == "admin", ct);
41
+ // roleCode values: "admin", "manager", "contributor", "viewer"
47
42
  ```
48
43
 
49
44
  Find the `applicationId` from `NavigationApplicationSeedData.cs` matching `{full_path}`.
@@ -141,7 +141,7 @@ The SeedData files will be consumed by the `IClientSeedDataProvider` generated a
141
141
  See [references/nav-fallback-procedure.md](../references/nav-fallback-procedure.md) for the complete 8-step fallback:
142
142
  - **F1:** Read existing Configuration/SeedData files to determine state
143
143
  - **F2:** Determine parent GUID by level
144
- - **F3:** Generate deterministic GUID (SHA256, never NewGuid())
144
+ - **F3:** Generate random GUID via Guid.NewGuid()
145
145
  - **F4:** Write navigation entity seed (SeedData class or inline HasData)
146
146
  - **F5:** Write 4 translation entries (continue existing index sequence)
147
147
  - **F6-F8:** Store result, validation checklist, summary
@@ -63,7 +63,7 @@ Args:
63
63
  The tool returns:
64
64
  - Permissions.cs nested class structure
65
65
  - PermissionConfiguration.cs HasData() entries
66
- - Deterministic GUIDs for each permission
66
+ - Random GUIDs via Guid.NewGuid() for each permission
67
67
 
68
68
  ### 4. Present Permissions.cs Output
69
69
 
@@ -130,7 +130,7 @@ Write it as usual.
130
130
  Instead, create:
131
131
  - `Infrastructure/Persistence/Seeding/Data/{Domain}/{Module}PermissionSeedData.cs`
132
132
 
133
- Content: static class with deterministic GUIDs and method `GetPermissionEntries()`.
133
+ Content: static class with `Guid.NewGuid()` and method `GetPermissionEntries()`.
134
134
  These entries will be consumed by the `IClientSeedDataProvider` at step 03b.
135
135
 
136
136
  ### 4. Store Permission GUIDs
@@ -179,7 +179,7 @@ If MCP call fails:
179
179
  - MCP generate_permissions called successfully
180
180
  - Permissions.cs code displayed
181
181
  - PermissionConfiguration.cs HasData displayed
182
- - Deterministic GUIDs (not placeholders)
182
+ - Random GUIDs via Guid.NewGuid() (not placeholders, not deterministic)
183
183
  - Permission GUIDs stored for role assignment
184
184
  - Proceeded to step-03-roles.md
185
185
 
@@ -84,6 +84,7 @@ Adapt the template:
84
84
  - Replace `{app_code}` with the kebab-case application code
85
85
  - Fill in the actual navigation, permission, and role-permission creation logic
86
86
  using the helper methods from the SeedData classes
87
+ - **CRITICAL:** Follow the 7 critical rules: factory methods, idempotence, execution order, SaveChangesAsync order, random GUIDs via Guid.NewGuid(), FK by Code, Order property
87
88
 
88
89
  ### 3. Register in DI
89
90