@atlashub/smartstack-cli 3.28.0 → 3.30.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/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
- package/templates/project/api.ts.template +4 -2
- package/templates/project/appsettings.json.template +1 -1
- package/templates/skills/apex/_shared.md +13 -0
- package/templates/skills/apex/references/post-checks.md +228 -6
- package/templates/skills/apex/references/smartstack-api.md +67 -17
- package/templates/skills/apex/references/smartstack-frontend.md +41 -1
- package/templates/skills/apex/references/smartstack-layers.md +40 -10
- package/templates/skills/apex/steps/step-02-plan.md +16 -11
- package/templates/skills/apex/steps/step-03-execute.md +6 -0
- package/templates/skills/apex/steps/step-04-examine.md +4 -2
- package/templates/skills/application/references/frontend-verification.md +26 -1
- package/templates/skills/application/steps/step-03-roles.md +1 -1
- package/templates/skills/application/steps/step-05-frontend.md +24 -8
- package/templates/skills/application/templates-frontend.md +41 -22
- package/templates/skills/application/templates-seed.md +53 -16
- package/templates/skills/business-analyse/SKILL.md +4 -2
- package/templates/skills/business-analyse/_shared.md +17 -4
- package/templates/skills/business-analyse/react/schema.md +1 -1
- package/templates/skills/business-analyse/references/agent-module-prompt.md +40 -11
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +4 -3
- package/templates/skills/business-analyse/references/deploy-modes.md +1 -1
- package/templates/skills/business-analyse/references/handoff-file-templates.md +4 -4
- package/templates/skills/business-analyse/references/robustness-checks.md +12 -9
- package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
- package/templates/skills/business-analyse/references/team-orchestration.md +57 -23
- package/templates/skills/business-analyse/references/ui-resource-cards.md +3 -3
- package/templates/skills/business-analyse/references/validation-checklist.md +21 -3
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -5
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +12 -0
- package/templates/skills/business-analyse/steps/step-03b-ui.md +14 -2
- package/templates/skills/business-analyse/steps/step-03c-compile.md +17 -9
- package/templates/skills/business-analyse/steps/step-03d-validate.md +42 -2
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +5 -3
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +23 -15
- package/templates/skills/business-analyse/templates/tpl-handoff.md +10 -8
- package/templates/skills/business-analyse/templates/tpl-progress.md +7 -6
- package/templates/skills/ralph-loop/references/category-rules.md +50 -6
- package/templates/skills/ralph-loop/references/compact-loop.md +16 -1
- package/templates/skills/ralph-loop/references/core-seed-data.md +158 -38
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +3 -3
- package/templates/skills/ralph-loop/steps/step-02-execute.md +109 -1
|
@@ -236,16 +236,18 @@ Roles × resources × operations with full paths.
|
|
|
236
236
|
> { "path": "business.{app}.{module}.create", "action": "create", "description": "Create new records" },
|
|
237
237
|
> { "path": "business.{app}.{module}.update", "action": "update", "description": "Update existing records" },
|
|
238
238
|
> { "path": "business.{app}.{module}.delete", "action": "delete", "description": "Delete records" },
|
|
239
|
-
> { "path": "business.{app}.{module}.export", "action": "export", "description": "Export data" }
|
|
239
|
+
> { "path": "business.{app}.{module}.export", "action": "export", "description": "Export data" },
|
|
240
|
+
> { "path": "business.{app}.{module}.dashboard.read", "action": "read", "description": "View dashboard (section-level)" }
|
|
240
241
|
> ],
|
|
241
242
|
> "roleAssignments": [
|
|
242
|
-
> { "role": "{App} Admin", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update", "business.{app}.{module}.delete", "business.{app}.{module}.export"] },
|
|
243
|
-
> { "role": "{App} Manager", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update"] },
|
|
243
|
+
> { "role": "{App} Admin", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update", "business.{app}.{module}.delete", "business.{app}.{module}.export", "business.{app}.{module}.dashboard.read"] },
|
|
244
|
+
> { "role": "{App} Manager", "permissions": ["business.{app}.{module}.read", "business.{app}.{module}.create", "business.{app}.{module}.update", "business.{app}.{module}.dashboard.read"] },
|
|
244
245
|
> { "role": "{App} Viewer", "permissions": ["business.{app}.{module}.read"] }
|
|
245
246
|
> ]
|
|
246
247
|
> }
|
|
247
248
|
> ```
|
|
248
249
|
> **STRUCTURE:** Object with 2 arrays: `permissions[]` and `roleAssignments[]`
|
|
250
|
+
> **Permission levels:** Module-level = `business.{app}.{module}.{action}` (4 segments). Section-level = `business.{app}.{module}.{section}.{action}` (5 segments, for sections needing distinct access like dashboard, approve, import).
|
|
249
251
|
> **FORBIDDEN:** Do NOT use a flat array with `resource`/`roles` fields. Always use the nested structure above.
|
|
250
252
|
|
|
251
253
|
#### 8e. Navigation
|
|
@@ -257,7 +259,7 @@ Module → Sections → Resources (levels 3-4-5 of the hierarchy).
|
|
|
257
259
|
> {
|
|
258
260
|
> "entries": [
|
|
259
261
|
> { "level": "module", "code": "{module}", "labels": {"fr": "...", "en": "..."}, "route": "/business/{app}/{module}", "icon": "list" },
|
|
260
|
-
> { "level": "section", "code": "list", "labels": {"fr": "Liste", "en": "List", "it": "Elenco", "de": "Liste"}, "route": "/business/{app}/{module}
|
|
262
|
+
> { "level": "section", "code": "list", "labels": {"fr": "Liste", "en": "List", "it": "Elenco", "de": "Liste"}, "route": "/business/{app}/{module}", "icon": "list" },
|
|
261
263
|
> { "level": "section", "code": "dashboard", "labels": {"fr": "Dashboard", "en": "Dashboard"}, "route": "/business/{app}/{module}/dashboard", "icon": "chart-bar", "isNew": true }
|
|
262
264
|
> ]
|
|
263
265
|
> }
|
|
@@ -274,13 +276,12 @@ Module → Sections → Resources (levels 3-4-5 of the hierarchy).
|
|
|
274
276
|
> { "code": "{module}", "label": "{Module Name}", "icon": "list", "route": "/business/{app}/{module}", "parentCode": "{app}", "sort": 1 }
|
|
275
277
|
> ],
|
|
276
278
|
> "navigationSections": [
|
|
277
|
-
> { "code": "list", "label": "Liste", "icon": "List", "route": "/business/{app}/{module}
|
|
278
|
-
> { "code": "detail", "label": "Détail", "icon": "FileText", "route": "/business/{app}/{module}
|
|
279
|
-
> { "code": "
|
|
279
|
+
> { "code": "list", "label": "Liste", "icon": "List", "route": "/business/{app}/{module}", "parentCode": "{module}", "permission": "business.{app}.{module}.read", "sort": 1 },
|
|
280
|
+
> { "code": "detail", "label": "Détail", "icon": "FileText", "route": "/business/{app}/{module}/:id", "parentCode": "{module}", "permission": "business.{app}.{module}.read", "sort": 2, "navigation": "hidden" },
|
|
281
|
+
> { "code": "dashboard", "label": "Dashboard", "icon": "BarChart", "route": "/business/{app}/{module}/dashboard", "parentCode": "{module}", "permission": "business.{app}.{module}.dashboard.read", "sort": 3 }
|
|
280
282
|
> ],
|
|
281
283
|
> "navigationResources": [
|
|
282
284
|
> { "code": "{module}-grid", "type": "SmartTable", "entity": "{Entity}", "parentCode": "list", "permission": "business.{app}.{module}.read" },
|
|
283
|
-
> { "code": "{module}-form", "type": "SmartForm", "entity": "{Entity}", "parentCode": "create", "permission": "business.{app}.{module}.create" },
|
|
284
285
|
> { "code": "{module}-detail-card", "type": "DetailCard", "entity": "{Entity}", "parentCode": "detail", "permission": "business.{app}.{module}.read" }
|
|
285
286
|
> ],
|
|
286
287
|
> "navigationTranslations": [
|
|
@@ -291,7 +292,8 @@ Module → Sections → Resources (levels 3-4-5 of the hierarchy).
|
|
|
291
292
|
> ],
|
|
292
293
|
> "permissions": [
|
|
293
294
|
> { "path": "business.{app}.{module}.read", "action": "read", "description": "View {module}" },
|
|
294
|
-
> { "path": "business.{app}.{module}.create", "action": "create", "description": "Create {module}" }
|
|
295
|
+
> { "path": "business.{app}.{module}.create", "action": "create", "description": "Create {module}" },
|
|
296
|
+
> { "path": "business.{app}.{module}.dashboard.read", "action": "read", "description": "View {module} dashboard (section-level)" }
|
|
295
297
|
> ],
|
|
296
298
|
> "rolePermissions": [
|
|
297
299
|
> { "role": "{App} Admin", "permissionPath": "business.{app}.{module}.*" },
|
|
@@ -305,7 +307,13 @@ Module → Sections → Resources (levels 3-4-5 of the hierarchy).
|
|
|
305
307
|
> ```
|
|
306
308
|
> **MANDATORY:** All 7 arrays must be present. Each element must be an object, NOT a string.
|
|
307
309
|
> **CRITICAL:** `navigationSections` and `navigationResources` are DERIVED from `specification.sections[]` — use the transform algorithm below (section 8f-bis).
|
|
310
|
+
> **IMPORTANT:** `create` and `edit` are NEVER sections — they are action pages reached via buttons. Do NOT include them in `navigationSections`. Only include actual sidebar sections (list, dashboard, approve, import, etc.) and hidden route sections (detail).
|
|
308
311
|
> **FORBIDDEN:** Do NOT use `navigationModule` (singular string), `permissions` as flat string array, `rolePermissions` as flat object, `permissionsConstants` as comma-separated string.
|
|
312
|
+
>
|
|
313
|
+
> **FORBIDDEN in navigation routes:**
|
|
314
|
+
> - `/business/{app}/{module}/list` → use `/business/{app}/{module}` (list IS the module route)
|
|
315
|
+
> - `/business/{app}/{module}/detail/:id` → use `/business/{app}/{module}/:id`
|
|
316
|
+
> - Navigation routes must match React Router paths exactly
|
|
309
317
|
|
|
310
318
|
#### 8f-bis. Transform Sections into Navigation SeedData
|
|
311
319
|
|
|
@@ -15,6 +15,21 @@ next_step: steps/step-03a1-setup.md OR steps/step-04a-collect.md (conditional)
|
|
|
15
15
|
- This step VALIDATES the specification from step-03c, writes it to feature.json, and decides loop continuation
|
|
16
16
|
- ALWAYS verify specification completeness before writing
|
|
17
17
|
- ALL communication in `{language}`
|
|
18
|
+
|
|
19
|
+
## MODE DETECTION (inherited from step-03a1)
|
|
20
|
+
|
|
21
|
+
> **CRITICAL: Re-check your execution mode before proceeding.**
|
|
22
|
+
|
|
23
|
+
**IF you are running as a TEAM AGENT** (your prompt contains `PROPOSE & REVIEW` or `team-lead` as recipient):
|
|
24
|
+
→ **NEVER** use `AskUserQuestion` in ANY section below (sections 9d, 10, 12)
|
|
25
|
+
→ Section 9d: if validation fails, AUTO-CORRECT silently (no user options)
|
|
26
|
+
→ Section 12: **SKIP ENTIRELY** — go directly to section 12-bis (Agent Mode)
|
|
27
|
+
→ After writing feature.json, send `PROPOSAL_READY` to team lead via SendMessage
|
|
28
|
+
→ NEVER present options/menus to the user — you are an autonomous agent
|
|
29
|
+
|
|
30
|
+
**IF you are running in the MAIN CONVERSATION** (classic inline mode):
|
|
31
|
+
→ Normal interactive mode — use `AskUserQuestion` as documented
|
|
32
|
+
→ Section 12-bis does NOT apply to you
|
|
18
33
|
- **ID NAMING RULE (MANDATORY, NO EXCEPTION):**
|
|
19
34
|
All IDs MUST include a module prefix to guarantee application-wide uniqueness.
|
|
20
35
|
The prefix is derived from the module code initials (2-4 chars):
|
|
@@ -85,7 +100,7 @@ IF failures.length > 0:
|
|
|
85
100
|
- Every FR has ≥1 linked BR
|
|
86
101
|
- All BR references exist in analysis.businessRules
|
|
87
102
|
- All actors appear in permissionMatrix
|
|
88
|
-
- Permission paths use
|
|
103
|
+
- Permission paths use correct format: module-level `business.{app}.{module}.{action}` or section-level `business.{app}.{module}.{section}.{action}`
|
|
89
104
|
- rolePermissions paths match permissions paths
|
|
90
105
|
- API routes use consistent prefix
|
|
91
106
|
|
|
@@ -167,6 +182,10 @@ if (entityAutoFixCount > 0) {
|
|
|
167
182
|
|
|
168
183
|
#### 9d. Decision
|
|
169
184
|
|
|
185
|
+
> **TEAM AGENT MODE:** If running as team agent, SKIP AskUserQuestion. On FAIL → auto-correct silently. On PASS → proceed directly to section 11 (write). NEVER present options to the user.
|
|
186
|
+
|
|
187
|
+
**INLINE MODE ONLY (main conversation):**
|
|
188
|
+
|
|
170
189
|
IF validation PASS:
|
|
171
190
|
Display summary, ask client for confirmation
|
|
172
191
|
|
|
@@ -482,6 +501,10 @@ Uses the **same mapping** as step-05b-deploy.md — only difference is `moduleSp
|
|
|
482
501
|
|
|
483
502
|
### 12. Loop Decision
|
|
484
503
|
|
|
504
|
+
> **TEAM AGENT MODE: SKIP THIS ENTIRE SECTION.** If you are a team agent (your prompt contains `PROPOSE & REVIEW`), go directly to **section 12-bis** below. Section 12 is for inline mode ONLY. You MUST NOT load the next step or advance the module loop — the team lead handles orchestration.
|
|
505
|
+
|
|
506
|
+
**INLINE MODE ONLY (main conversation):**
|
|
507
|
+
|
|
485
508
|
```
|
|
486
509
|
ba-writer.advanceModuleLoop({feature_id})
|
|
487
510
|
→ Increments currentModuleIndex
|
|
@@ -595,7 +618,24 @@ SendMessage({
|
|
|
595
618
|
})
|
|
596
619
|
```
|
|
597
620
|
|
|
598
|
-
|
|
621
|
+
Then WAIT — the team lead will send you a `shutdown_request`.
|
|
622
|
+
Do NOT loop to next module. The team lead handles module ordering and will spawn a new agent for the next module.
|
|
623
|
+
|
|
624
|
+
### E. Shutdown (MANDATORY)
|
|
625
|
+
|
|
626
|
+
When you receive a `shutdown_request` from the team lead:
|
|
627
|
+
|
|
628
|
+
```
|
|
629
|
+
SendMessage({
|
|
630
|
+
type: "shutdown_response",
|
|
631
|
+
request_id: "{requestId from the shutdown_request message}",
|
|
632
|
+
approve: true
|
|
633
|
+
})
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
This terminates your process. Do NOT output any text after `shutdown_response`.
|
|
637
|
+
|
|
638
|
+
**Sequence reminder:** APPROVED → MODULE_COMPLETE → shutdown_request → shutdown_response (4 separate steps, never skip).
|
|
599
639
|
|
|
600
640
|
---
|
|
601
641
|
|
|
@@ -36,13 +36,15 @@ FOR each module in completedModules:
|
|
|
36
36
|
|
|
37
37
|
**3b. Permission Path Format**
|
|
38
38
|
|
|
39
|
-
Verify all permission paths follow
|
|
40
|
-
`business.{app}.{module}.{
|
|
39
|
+
Verify all permission paths follow one of these patterns:
|
|
40
|
+
- Module-level: `business.{app}.{module}.{action}` (4 segments)
|
|
41
|
+
- Section-level: `business.{app}.{module}.{section}.{action}` (5 segments)
|
|
41
42
|
|
|
42
43
|
Check for:
|
|
43
44
|
- Inconsistent app prefix → ERROR
|
|
44
45
|
- Missing module segment → ERROR
|
|
45
|
-
-
|
|
46
|
+
- Fewer than 4 segments (shortcut paths) → ERROR
|
|
47
|
+
- More than 5 segments → ERROR
|
|
46
48
|
|
|
47
49
|
**3c. Role Hierarchy Coherence**
|
|
48
50
|
|
|
@@ -17,7 +17,7 @@ next_step: steps/step-05b-deploy.md
|
|
|
17
17
|
- **NEVER** invent entities/FRs/BRs not in feature.json
|
|
18
18
|
- **ALL** API routes from specification.apiEndpoints (exact copy)
|
|
19
19
|
- **Permission** paths from specification.permissionMatrix (full format)
|
|
20
|
-
- **ALWAYS** generate
|
|
20
|
+
- **ALWAYS** generate CORE SeedData entries: 2 app-level (NavigationApplication + ApplicationRoles) + per module (NavigationModule + NavigationSections + Permissions + Roles)
|
|
21
21
|
|
|
22
22
|
## YOUR TASK
|
|
23
23
|
|
|
@@ -197,7 +197,7 @@ See [references/handoff-file-templates.md](../references/handoff-file-templates.
|
|
|
197
197
|
| **4.3 Infrastructure** | `analysis.entities[]` | EF Configurations, DbSet, DI. **DEPENDENCY:** Each EF config task MUST `dependsOn` its corresponding domain entity task. |
|
|
198
198
|
| **4.4 API** | `specification.apiEndpoints[]` | Controllers with `{ContextShort}` mapping |
|
|
199
199
|
| **4.5 Frontend** | `specification.uiWireframes[]` | Pages, Components, Hooks + wireframe traceability |
|
|
200
|
-
| **4.6 SeedData** | `specification.seedDataCore` |
|
|
200
|
+
| **4.6 SeedData** | `specification.seedDataCore` | 2 app-level + per module CORE (NavigationModule + NavigationSections + Permissions + Roles) + business + IClientSeedDataProvider |
|
|
201
201
|
| **4.7 Tests** | All layers | Unit, Integration, Security tests |
|
|
202
202
|
|
|
203
203
|
#### Route Convention (CRITICAL)
|
|
@@ -252,7 +252,7 @@ For NavigationSeedData tasks in `handoff.filesToCreate`, add:
|
|
|
252
252
|
**Critical rules:**
|
|
253
253
|
- All backend paths include `{ContextPascal}/{ApplicationName}/` hierarchy
|
|
254
254
|
- Frontend pages MUST have `linkedWireframes[]` + `wireframeAcceptanceCriteria`
|
|
255
|
-
- SeedData:
|
|
255
|
+
- SeedData: 2 app-level CORE (NavigationApplication + ApplicationRoles) + per-module CORE (NavigationModule + NavigationSections + Permissions + Roles) + IClientSeedDataProvider for client projects
|
|
256
256
|
- **Acceptance Criteria Mapping:** Each task's `acceptanceCriteria` MUST be derived from its own `linkedFRs[]` entries (lookup FR → `acceptanceCriteria`). NEVER map by sequential FR index — use the task's explicit linkedFRs to resolve the correct criteria.
|
|
257
257
|
- Path convention: `Persistence/Seeding/Data/` (NEVER `Data/SeedData/`)
|
|
258
258
|
|
|
@@ -462,7 +462,7 @@ const seedDataCore = {
|
|
|
462
462
|
description: m.description,
|
|
463
463
|
icon: inferIconFromModule(m) || "folder", // MUST be non-null — use sensible default
|
|
464
464
|
iconType: "lucide",
|
|
465
|
-
route:
|
|
465
|
+
route: `/${contextCode}/${toKebabCase(appCode)}/${toKebabCase(m.code)}`,
|
|
466
466
|
displayOrder: (i + 1) * 10
|
|
467
467
|
})),
|
|
468
468
|
|
|
@@ -472,7 +472,11 @@ const seedDataCore = {
|
|
|
472
472
|
code: s.code,
|
|
473
473
|
label: s.description?.split(':')[0] || s.code,
|
|
474
474
|
description: s.description || "",
|
|
475
|
-
route: s.code === "
|
|
475
|
+
route: s.code === "list"
|
|
476
|
+
? `/${contextCode}/${toKebabCase(appCode)}/${toKebabCase(m.code)}`
|
|
477
|
+
: s.code === "detail"
|
|
478
|
+
? `/${contextCode}/${toKebabCase(appCode)}/${toKebabCase(m.code)}/:id`
|
|
479
|
+
: `/${contextCode}/${toKebabCase(appCode)}/${toKebabCase(m.code)}/${toKebabCase(s.code)}`,
|
|
476
480
|
displayOrder: (j + 1) * 10,
|
|
477
481
|
navigation: s.code === "detail" ? "hidden" : "visible"
|
|
478
482
|
}))
|
|
@@ -500,22 +504,26 @@ const seedDataCore = {
|
|
|
500
504
|
}));
|
|
501
505
|
}),
|
|
502
506
|
|
|
503
|
-
permissions: master.
|
|
504
|
-
master.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
507
|
+
permissions: master.modules.flatMap(m => {
|
|
508
|
+
const basePath = `business.${master.metadata.application.toLowerCase()}.${m.code.toLowerCase()}`;
|
|
509
|
+
const actions = ['read', 'create', 'update', 'delete'];
|
|
510
|
+
return [
|
|
511
|
+
{ path: `${basePath}.*`, action: '*', description: `Full ${m.name || m.code} access` },
|
|
512
|
+
...actions.map(action => ({
|
|
513
|
+
path: `${basePath}.${action}`,
|
|
514
|
+
action: action,
|
|
515
|
+
description: `${action.charAt(0).toUpperCase() + action.slice(1)} ${m.name || m.code}`
|
|
516
|
+
}))
|
|
517
|
+
];
|
|
518
|
+
}),
|
|
511
519
|
|
|
512
520
|
rolePermissions: master.cadrage.applicationRoles.map(role => ({
|
|
513
521
|
role: role.role,
|
|
514
522
|
level: role.level,
|
|
515
523
|
permissions: master.modules.map(m => `business.${master.metadata.application.toLowerCase()}.${m.code.toLowerCase()}.${
|
|
516
524
|
role.level === 'admin' ? '*' :
|
|
517
|
-
role.level === 'manager' ? 'read,create,update
|
|
518
|
-
role.level === 'contributor' ? 'read,create
|
|
525
|
+
role.level === 'manager' ? 'read,create,update' :
|
|
526
|
+
role.level === 'contributor' ? 'read,create' : 'read'
|
|
519
527
|
}`)
|
|
520
528
|
})),
|
|
521
529
|
|
|
@@ -84,16 +84,17 @@ FRONTEND:
|
|
|
84
84
|
### 3.2 SeedData Core (CRITICAL -- without these, module is invisible and returns 403)
|
|
85
85
|
|
|
86
86
|
> **Source:** `feature.json.specification.seedDataCore` (generated in step-02)
|
|
87
|
-
> **5
|
|
88
|
-
> Derive content EXACTLY from `specification.seedDataCore` sections (navigationModules, navigationTranslations, permissions, rolePermissions, permissionConstants).
|
|
87
|
+
> **5 core files + NavigationSectionSeedData when sections are defined** for every new module.
|
|
88
|
+
> Derive content EXACTLY from `specification.seedDataCore` sections (navigationModules, navigationSections, navigationTranslations, permissions, rolePermissions, permissionConstants).
|
|
89
89
|
|
|
90
90
|
| # | File | Layer | Content |
|
|
91
91
|
|---|------|-------|---------|
|
|
92
92
|
| 1 | `NavigationModuleConfiguration.cs` | Infrastructure (HasData) | Module entry in `nav_Modules` |
|
|
93
|
-
| 2 | `
|
|
94
|
-
| 3 | `
|
|
95
|
-
| 4 | `
|
|
96
|
-
| 5 | `
|
|
93
|
+
| 2 | `NavigationSectionSeedData.cs` | Infrastructure (HasData) | Section entries (list, dashboard, etc.) with full absolute routes. **MANDATORY when sections defined.** |
|
|
94
|
+
| 3 | `NavigationTranslationConfiguration.cs` | Infrastructure (HasData) | 4 translations (fr, en, it, de) per nav entity |
|
|
95
|
+
| 4 | `PermissionConfiguration.cs` | Infrastructure (HasData) | Wildcard + CRUD permissions in `nav_Permissions` |
|
|
96
|
+
| 5 | `Permissions.cs` | Application (code) | Compile-time constants for `[RequirePermission]` |
|
|
97
|
+
| 6 | `RolePermissionConfiguration.cs` | Infrastructure (HasData) | Role->Permission for {App} Admin, {App} Manager, {App} Contributor, {App} Viewer |
|
|
97
98
|
|
|
98
99
|
### 3.3 Frontend
|
|
99
100
|
|
|
@@ -136,7 +137,7 @@ From: `feature.specification.seedDataCore` (5 core files), `feature.specificatio
|
|
|
136
137
|
> **IMPORTANT :** Les données des 5 fichiers SeedData Core doivent être dérivées de `specification.seedDataCore` :
|
|
137
138
|
> - `navigationModules` → NavigationModuleConfiguration.cs
|
|
138
139
|
> - `navigationTranslations` → NavigationTranslationConfiguration.cs
|
|
139
|
-
> - `permissions` → PermissionConfiguration.cs (
|
|
140
|
+
> - `permissions` → PermissionConfiguration.cs (module-level: `business.{app}.{module}.{action}`, section-level: `business.{app}.{module}.{section}.{action}`)
|
|
140
141
|
> - `rolePermissions` → RolePermissionConfiguration.cs
|
|
141
142
|
> - `permissionConstants` → Permissions.cs (PascalCase constants)
|
|
142
143
|
|
|
@@ -163,8 +164,9 @@ From: `feature.specification.seedDataCore` (5 core files), `feature.specificatio
|
|
|
163
164
|
|
|
164
165
|
**SeedData Core (CRITICAL):**
|
|
165
166
|
- [ ] Navigation module entry (HasData in NavigationModuleConfiguration.cs)
|
|
167
|
+
- [ ] Navigation section entries (NavigationSectionSeedData.cs — MANDATORY when sections defined, with full absolute routes)
|
|
166
168
|
- [ ] Navigation translations (4 languages in NavigationTranslationConfiguration.cs)
|
|
167
|
-
- [ ] Permissions (HasData in PermissionConfiguration.cs: wildcard + CRUD)
|
|
169
|
+
- [ ] Permissions (HasData in PermissionConfiguration.cs: wildcard + CRUD + section-level)
|
|
168
170
|
- [ ] Permission constants (Permissions.cs in Application layer)
|
|
169
171
|
- [ ] Role-Permission assignments (HasData in RolePermissionConfiguration.cs: 4 roles)
|
|
170
172
|
- [ ] EF Core migration created (includes all HasData seeds)
|
|
@@ -28,12 +28,13 @@
|
|
|
28
28
|
□ Total: X tasks
|
|
29
29
|
|
|
30
30
|
[SEEDDATA-CORE] Core Configuration (MANDATORY)
|
|
31
|
-
□
|
|
32
|
-
□
|
|
33
|
-
□
|
|
34
|
-
□
|
|
35
|
-
□
|
|
36
|
-
|
|
31
|
+
□ NavigationApplicationSeedData - Application navigation entry (once per app)
|
|
32
|
+
□ ApplicationRolesSeedData - Application-scoped roles (once per app)
|
|
33
|
+
□ NavigationModuleSeedData - Module navigation structure (per module)
|
|
34
|
+
□ PermissionsSeedData - RBAC permissions (per module)
|
|
35
|
+
□ RolesSeedData - Role-permission mappings (per module)
|
|
36
|
+
□ {App}SeedDataProvider - IClientSeedDataProvider (4 methods)
|
|
37
|
+
Total: 2 app-level + 3 per-module + 1 provider
|
|
37
38
|
|
|
38
39
|
[SEEDDATA] Business Reference Data
|
|
39
40
|
□ Seed {Entity1} reference data
|
|
@@ -79,25 +79,50 @@ Execution sequence:
|
|
|
79
79
|
> "PermissionsSeedData", "RolesSeedData", or "IClientSeedDataProvider":
|
|
80
80
|
> **THEN read `references/core-seed-data.md`** — this is MANDATORY, DO NOT improvise.
|
|
81
81
|
|
|
82
|
-
**
|
|
83
|
-
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
|
|
82
|
+
**Seed Data Chain (9 files minimum):**
|
|
83
|
+
|
|
84
|
+
Application-level (created ONCE, shared across modules):
|
|
85
|
+
- **NavigationApplicationSeedData.cs**: Application navigation entry (MUST be first). Provides ApplicationId.
|
|
86
|
+
- **ApplicationRolesSeedData.cs**: 4 application-scoped roles (admin, manager, contributor, viewer). Provides role entries for SeedRolesAsync().
|
|
87
|
+
|
|
88
|
+
Per-module:
|
|
89
|
+
- **NavigationModuleSeedData.cs**: deterministic GUIDs (SHA256), 4 languages (fr, en, it, de)
|
|
90
|
+
- **Permissions.cs**: Static permission constants (`Permissions.{Module}.Read`). Referenced by `[RequirePermission]`.
|
|
91
|
+
- **PermissionsSeedData.cs**: MCP `generate_permissions` first, fallback to template
|
|
92
|
+
- **RolesSeedData.cs**: code-based role-permission mapping (Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R)
|
|
93
|
+
|
|
94
|
+
Per-module (MANDATORY when `seedDataCore.navigationSections` exists in feature.json):
|
|
95
|
+
- **NavigationSectionSeedData**: section entries, section translations (4 languages), section-level permissions, and section-level role mappings — all within `NavigationModuleSeedData.cs`, `PermissionsSeedData.cs`, and `RolesSeedData.cs`
|
|
96
|
+
- Section-level permissions: wildcard + CRUD per section (same pattern as module-level)
|
|
97
|
+
- Section-level role mappings: Admin=wildcard, Manager=CRU, Contributor=CR, Viewer=R per section
|
|
98
|
+
|
|
99
|
+
Infrastructure:
|
|
100
|
+
- **SeedConstants.cs**: shared deterministic GUIDs (ApplicationId, ModuleIds)
|
|
101
|
+
- **{App}SeedDataProvider.cs**: implements IClientSeedDataProvider with 4 methods
|
|
88
102
|
- DI: `services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>()`
|
|
89
103
|
|
|
104
|
+
**Rules:**
|
|
105
|
+
- IClientSeedDataProvider: SeedNavigationAsync + SeedRolesAsync + SeedPermissionsAsync + SeedRolePermissionsAsync
|
|
106
|
+
- Admin=wildcard(*), Manager=CRU (read+create+update), Contributor=CR (read+create), Viewer=R (read only)
|
|
107
|
+
|
|
90
108
|
**Business seed data (DevDataSeeder):**
|
|
91
109
|
- ALL seeded business entities MUST include `TenantId = {tenantGuid}`
|
|
92
110
|
- Reference entities (types, categories, statuses) MUST set TenantId
|
|
93
111
|
- Use deterministic TenantId from SeedConstants (NEVER hardcoded inline)
|
|
94
112
|
- DevDataSeeder MUST implement `IDevDataSeeder` with idempotent `SeedAsync()` method
|
|
95
113
|
|
|
114
|
+
**Section route conventions (BLOCKING):**
|
|
115
|
+
- `list` section route = module route (e.g., `/business/human-resources/employees`) — NO `/list` suffix
|
|
116
|
+
- `detail` section route = module route + `/:id` (e.g., `/business/human-resources/employees/:id`) — NOT `/detail/:id`
|
|
117
|
+
- Other sections (dashboard, approve, import) = module route + `/{section-kebab}` (normal)
|
|
118
|
+
- FORBIDDEN: `/{module}/list`, `/{module}/detail/:id` — these are CRUD view modes, not sub-areas
|
|
119
|
+
|
|
96
120
|
**FORBIDDEN:**
|
|
97
121
|
- `Guid.NewGuid()` → use deterministic GUIDs
|
|
98
122
|
- Empty seed data classes with only GUIDs and no seeding methods
|
|
99
123
|
- Missing translations (must have all 4 languages)
|
|
100
124
|
- Seeding business entities WITHOUT `TenantId`
|
|
125
|
+
- Navigation section routes ending in `/list` or `/detail/:id`
|
|
101
126
|
|
|
102
127
|
### POST-CHECK: Navigation translations diacritical marks
|
|
103
128
|
|
|
@@ -302,6 +327,13 @@ fi
|
|
|
302
327
|
- Reference/lookup entities (types, categories, statuses) MUST also have controllers — they are needed for dropdowns and configuration
|
|
303
328
|
- Count: `controllers created >= entities in module`. If fewer → FAIL
|
|
304
329
|
|
|
330
|
+
**Section-level controllers (CONDITIONAL: when `navSections[]` defined in feature.json):**
|
|
331
|
+
- File path: `Api/Controllers/{ContextShort}/{App}/{Section}Controller.cs`
|
|
332
|
+
- NavRoute attribute: `[NavRoute("{context}.{app}.{module}.{section}")]`
|
|
333
|
+
- Permission attribute: `[RequirePermission(Permissions.{Module}.{Section}.{Action})]`
|
|
334
|
+
- Route prefix: `api/{context}/{app}/{module}/{section}`
|
|
335
|
+
- Each section gets its own controller with CRUD endpoints scoped to the section
|
|
336
|
+
|
|
305
337
|
**FORBIDDEN:**
|
|
306
338
|
- `[Authorize]` without specific permission → use `[RequirePermission]`
|
|
307
339
|
- Returning domain entities directly
|
|
@@ -374,6 +406,18 @@ fi
|
|
|
374
406
|
- Navigation seed data Route values MUST also use kebab-case
|
|
375
407
|
- The POST-CHECK in step-02 will BLOCK if frontend routes don't match backend kebab-case convention
|
|
376
408
|
|
|
409
|
+
**Section-level pages (CONDITIONAL: when `navSections[]` defined in feature.json):**
|
|
410
|
+
- Page file: `src/pages/{ContextPascal}/{AppPascal}/{Module}/{Section}Page.tsx`
|
|
411
|
+
- Route: nested as child of module route in App.tsx (e.g., `/business/human-resources/projects/timesheets`)
|
|
412
|
+
- Add to `contextRoutes.{context}[]` (Pattern A) or as nested `<Route>` (Pattern B)
|
|
413
|
+
- Each section page has its own route and permission check
|
|
414
|
+
|
|
415
|
+
**React Router mapping for sections:**
|
|
416
|
+
- `list` section → already the module's `index: true` route (NO separate `path: 'list'`)
|
|
417
|
+
- `detail` section → already the module's `path: ':id'` route (NO separate `path: 'detail'`)
|
|
418
|
+
- Other sections → `path: '{section-kebab}'` as child of module route
|
|
419
|
+
- FORBIDDEN frontend paths: `path: 'list'`, `path: 'detail'` — these are handled by the module's index and :id routes
|
|
420
|
+
|
|
377
421
|
**CSS:** Variables ONLY → `bg-[var(--bg-card)]`, `text-[var(--text-primary)]`
|
|
378
422
|
|
|
379
423
|
**Form error handling (MANDATORY):**
|
|
@@ -309,7 +309,22 @@ Batch: {batch.length} [{firstCategory}] → {batch.map(t => `[${t.id}] ${t.descr
|
|
|
309
309
|
```
|
|
310
310
|
If FAIL → migration is broken → fix → rebuild → DO NOT commit
|
|
311
311
|
|
|
312
|
-
5bis. **
|
|
312
|
+
5bis. **Navigation section route CRUD suffix check (BLOCKING — if seed data tasks in batch):**
|
|
313
|
+
```bash
|
|
314
|
+
# Detect /list or /detail/:id in navigation section routes
|
|
315
|
+
SEED_NAV_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" 2>/dev/null)
|
|
316
|
+
if [ -n "$SEED_NAV_FILES" ]; then
|
|
317
|
+
CRUD_ROUTES=$(grep -rn 'Route.*=.*\/list\b\|Route.*=.*\/detail' $SEED_NAV_FILES 2>/dev/null | grep -v '//.*Route')
|
|
318
|
+
if [ -n "$CRUD_ROUTES" ]; then
|
|
319
|
+
echo "BLOCKING: Navigation section routes contain /list or /detail/:id suffixes"
|
|
320
|
+
echo "Convention: list → module route (no suffix), detail → module route + /:id"
|
|
321
|
+
echo "$CRUD_ROUTES"
|
|
322
|
+
# FIX REQUIRED before commit
|
|
323
|
+
fi
|
|
324
|
+
fi
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
5ter. **Core Seed Data Integrity (BLOCKING — if seed data tasks in batch):**
|
|
313
328
|
```bash
|
|
314
329
|
# Verify NavigationApplicationSeedData.cs exists
|
|
315
330
|
APP_SEED=$(find . -path "*/Seeding/Data/NavigationApplicationSeedData.cs" 2>/dev/null | head -1)
|