@atlashub/smartstack-cli 3.8.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.
- package/dist/index.js +365 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/templates/agents/action.md +1 -0
- package/templates/agents/ba-writer.md +211 -0
- package/templates/agents/explore-codebase.md +1 -0
- package/templates/agents/explore-docs.md +1 -0
- package/templates/agents/fix-grammar.md +1 -0
- package/templates/agents/snipper.md +1 -0
- package/templates/skills/admin/SKILL.md +6 -0
- package/templates/skills/ai-prompt/SKILL.md +32 -136
- package/templates/skills/ai-prompt/steps/step-01-implementation.md +122 -0
- package/templates/skills/apex/SKILL.md +120 -0
- package/templates/skills/apex/_shared.md +86 -0
- package/templates/skills/apex/references/agent-teams-protocol.md +164 -0
- package/templates/skills/apex/references/smartstack-layers.md +173 -0
- package/templates/skills/apex/steps/step-00-init.md +156 -0
- package/templates/skills/apex/steps/step-01-analyze.md +169 -0
- package/templates/skills/apex/steps/step-02-plan.md +160 -0
- package/templates/skills/apex/steps/step-03-execute.md +166 -0
- package/templates/skills/apex/steps/step-04-validate.md +138 -0
- package/templates/skills/apex/steps/step-05-examine.md +124 -0
- package/templates/skills/apex/steps/step-06-resolve.md +105 -0
- package/templates/skills/apex/steps/step-07-tests.md +130 -0
- package/templates/skills/apex/steps/step-08-run-tests.md +115 -0
- package/templates/skills/application/SKILL.md +10 -0
- package/templates/skills/application/references/application-roles-template.md +227 -0
- package/templates/skills/application/references/backend-controller-hierarchy.md +58 -0
- package/templates/skills/application/references/backend-entity-seeding.md +72 -0
- package/templates/skills/application/references/backend-verification.md +88 -0
- package/templates/skills/application/references/frontend-verification.md +111 -0
- package/templates/skills/application/references/nav-fallback-procedure.md +200 -0
- package/templates/skills/application/references/provider-template.md +158 -0
- package/templates/skills/application/references/test-frontend.md +73 -0
- package/templates/skills/application/references/test-prerequisites.md +72 -0
- package/templates/skills/application/steps/step-01-navigation.md +7 -198
- package/templates/skills/application/steps/step-03-roles.md +45 -7
- package/templates/skills/application/steps/step-03b-provider.md +15 -132
- package/templates/skills/application/steps/step-04-backend.md +20 -350
- package/templates/skills/application/steps/step-05-frontend.md +12 -101
- package/templates/skills/application/steps/step-07-tests.md +12 -132
- package/templates/skills/business-analyse/SKILL.md +67 -6
- package/templates/skills/business-analyse/html/ba-interactive.html +176 -14
- package/templates/skills/business-analyse/html/src/scripts/01-data-init.js +1 -0
- package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +16 -4
- package/templates/skills/business-analyse/html/src/scripts/06-render-consolidation.js +7 -2
- package/templates/skills/business-analyse/html/src/scripts/09-export.js +103 -0
- package/templates/skills/business-analyse/html/src/scripts/10-comments.js +12 -6
- package/templates/skills/business-analyse/html/src/scripts/11-review-panel.js +24 -2
- package/templates/skills/business-analyse/html/src/styles/08-review-panel.css +12 -0
- package/templates/skills/business-analyse/html/src/template.html +1 -0
- package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +477 -0
- package/templates/skills/business-analyse/references/cache-warming-strategy.md +578 -0
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +78 -0
- package/templates/skills/business-analyse/references/cadrage-vibe-coding.md +97 -0
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +92 -0
- package/templates/skills/business-analyse/references/deploy-data-build.md +121 -0
- package/templates/skills/business-analyse/references/deploy-modes.md +49 -0
- package/templates/skills/business-analyse/references/handoff-file-templates.md +119 -0
- package/templates/skills/business-analyse/references/handoff-mappings.md +81 -0
- package/templates/skills/business-analyse/references/html-data-mapping.md +10 -2
- package/templates/skills/business-analyse/references/init-schema-deployment.md +65 -0
- package/templates/skills/business-analyse/references/review-data-mapping.md +363 -0
- package/templates/skills/business-analyse/references/robustness-checks.md +538 -0
- package/templates/skills/business-analyse/references/spec-auto-inference.md +57 -0
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +85 -0
- package/templates/skills/business-analyse/references/ui-resource-cards.md +110 -0
- package/templates/skills/business-analyse/references/validate-incremental-html.md +55 -0
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +33 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +186 -53
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +5 -194
- package/templates/skills/business-analyse/steps/step-03a-data.md +42 -49
- package/templates/skills/business-analyse/steps/step-03b-ui.md +12 -178
- package/templates/skills/business-analyse/steps/step-03c-compile.md +71 -2
- package/templates/skills/business-analyse/steps/step-03d-validate.md +277 -48
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +175 -104
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +66 -438
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +35 -184
- package/templates/skills/business-analyse/steps/step-05c-ralph-readiness.md +526 -0
- package/templates/skills/business-analyse/steps/step-06-review.md +277 -0
- package/templates/skills/cc-agent/references/agent-behavior-patterns.md +95 -0
- package/templates/skills/cc-agent/steps/step-02-generate.md +5 -78
- package/templates/skills/check-version/SKILL.md +7 -0
- package/templates/skills/controller/references/controller-code-templates.md +159 -0
- package/templates/skills/controller/references/permission-sync-templates.md +152 -0
- package/templates/skills/controller/steps/step-03-generate.md +166 -158
- package/templates/skills/controller/steps/step-04-perms.md +5 -144
- package/templates/skills/controller/templates.md +11 -2
- package/templates/skills/debug/SKILL.md +7 -0
- package/templates/skills/explore/SKILL.md +6 -0
- package/templates/skills/feature-full/SKILL.md +39 -142
- package/templates/skills/feature-full/steps/step-01-implementation.md +120 -0
- package/templates/skills/gitflow/references/init-config-template.md +135 -0
- package/templates/skills/gitflow/references/init-name-normalization.md +103 -0
- package/templates/skills/gitflow/references/plan-template.md +69 -0
- package/templates/skills/gitflow/references/start-efcore-preflight.md +70 -0
- package/templates/skills/gitflow/references/start-local-config.md +110 -0
- package/templates/skills/gitflow/steps/step-init.md +18 -289
- package/templates/skills/gitflow/steps/step-plan.md +6 -63
- package/templates/skills/gitflow/steps/step-start.md +16 -126
- package/templates/skills/mcp/SKILL.md +9 -213
- package/templates/skills/mcp/steps/step-01-healthcheck.md +108 -0
- package/templates/skills/mcp/steps/step-02-tools.md +73 -0
- package/templates/skills/notification/SKILL.md +7 -0
- package/templates/skills/quick-search/SKILL.md +5 -0
- package/templates/skills/ralph-loop/SKILL.md +99 -381
- package/templates/skills/ralph-loop/references/category-rules.md +259 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +182 -0
- package/templates/skills/ralph-loop/references/core-seed-data.md +173 -21
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +259 -0
- package/templates/skills/ralph-loop/references/team-orchestration.md +189 -0
- package/templates/skills/ralph-loop/steps/step-00-init.md +111 -383
- package/templates/skills/ralph-loop/steps/step-01-task.md +79 -896
- package/templates/skills/ralph-loop/steps/step-02-execute.md +68 -680
- package/templates/skills/ralph-loop/steps/step-03-commit.md +47 -277
- package/templates/skills/ralph-loop/steps/step-04-check.md +124 -607
- package/templates/skills/ralph-loop/steps/step-05-report.md +68 -367
- package/templates/skills/refactor/SKILL.md +12 -176
- package/templates/skills/refactor/steps/step-01-discover.md +60 -0
- package/templates/skills/refactor/steps/step-02-execute.md +67 -0
- package/templates/skills/review-code/SKILL.md +19 -257
- package/templates/skills/review-code/steps/step-01-smartstack.md +96 -0
- package/templates/skills/review-code/steps/step-02-detailed-review.md +80 -0
- package/templates/skills/review-code/steps/step-03-react.md +44 -0
- package/templates/skills/ui-components/SKILL.md +7 -0
- package/templates/skills/utils/SKILL.md +6 -0
- package/templates/skills/validate/SKILL.md +6 -0
- package/templates/skills/validate-feature/SKILL.md +8 -0
- package/templates/skills/workflow/SKILL.md +40 -118
- package/templates/skills/workflow/steps/step-01-implementation.md +84 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Frontend Test Infrastructure & Generation
|
|
2
|
+
|
|
3
|
+
> Reference for step-07-tests.md — Vitest + Testing Library + MSW setup and component test generation.
|
|
4
|
+
|
|
5
|
+
## 1. Check Frontend Test Infrastructure
|
|
6
|
+
|
|
7
|
+
Verify that the frontend project has Vitest + Testing Library configured:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Check if vitest.config.ts exists in the web/frontend project
|
|
11
|
+
ls {WebProjectPath}/vitest.config.ts 2>/dev/null
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
If NOT found, deploy the test infrastructure:
|
|
15
|
+
|
|
16
|
+
### Install packages
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
cd {WebProjectPath}
|
|
20
|
+
npm install -D vitest @testing-library/react @testing-library/jest-dom @testing-library/user-event jsdom msw
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Copy infrastructure files from SmartStack templates
|
|
24
|
+
|
|
25
|
+
| Template Source | Destination |
|
|
26
|
+
|----------------|-------------|
|
|
27
|
+
| `templates/project/test-frontend/vitest.config.ts` | `{WebProjectPath}/vitest.config.ts` |
|
|
28
|
+
| `templates/project/test-frontend/setup.ts` | `{WebProjectPath}/src/test/setup.ts` |
|
|
29
|
+
| `templates/project/test-frontend/test-utils.tsx` | `{WebProjectPath}/src/test/test-utils.tsx` |
|
|
30
|
+
| `templates/project/test-frontend/msw/server.ts` | `{WebProjectPath}/src/test/msw/server.ts` |
|
|
31
|
+
| `templates/project/test-frontend/msw/handlers.ts` | `{WebProjectPath}/src/test/msw/handlers.ts` |
|
|
32
|
+
|
|
33
|
+
### Add test scripts to `package.json` (if missing)
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"test:coverage": "vitest run --coverage"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 2. Generate Frontend Tests
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Tool: mcp__smartstack__scaffold_frontend_tests
|
|
49
|
+
Args:
|
|
50
|
+
name: "{entity_name}"
|
|
51
|
+
components: ["all"]
|
|
52
|
+
apiRoute: "/api/{entity_code}"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This generates:
|
|
56
|
+
- `src/pages/{context}/{application}/__tests__/{EntityName}Page.test.tsx` - Page rendering, loading, error states
|
|
57
|
+
- `src/pages/{context}/{application}/__tests__/{EntityName}ListView.test.tsx` - List display, pagination, view toggle
|
|
58
|
+
- `src/pages/{context}/{application}/__tests__/{EntityName}DetailPage.test.tsx` - Detail view, tabs, back navigation
|
|
59
|
+
- `src/hooks/__tests__/use{EntityName}Preferences.test.ts` - Preference get/set
|
|
60
|
+
- `src/services/api/__tests__/{entityName}Api.test.ts` - API client calls with MSW
|
|
61
|
+
|
|
62
|
+
## 3. Run Frontend Tests (BLOCKING)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd {WebProjectPath}
|
|
66
|
+
npx vitest run --reporter=default
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**ALL frontend tests MUST pass.** If tests fail:
|
|
70
|
+
1. Read the failure output carefully
|
|
71
|
+
2. Fix the failing tests or the components they test
|
|
72
|
+
3. Re-run until all tests pass
|
|
73
|
+
4. Do NOT proceed to the next step until all tests are green
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Test Infrastructure Prerequisites
|
|
2
|
+
|
|
3
|
+
> Reference for step-07-tests.md — verify and scaffold test project before generating tests.
|
|
4
|
+
|
|
5
|
+
## 1. Verify Test Project Exists
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Look for existing test project
|
|
9
|
+
ls *Tests*/*.csproj 2>/dev/null || ls tests/*/*.csproj 2>/dev/null
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
If NO test project exists, create one:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
dotnet new xunit -n {SolutionName}.Tests -o tests/{SolutionName}.Tests
|
|
16
|
+
dotnet sln add tests/{SolutionName}.Tests/{SolutionName}.Tests.csproj
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 2. Required NuGet Packages
|
|
20
|
+
|
|
21
|
+
| Package | Purpose |
|
|
22
|
+
|---------|---------|
|
|
23
|
+
| `xunit` | Test framework |
|
|
24
|
+
| `FluentAssertions` | Assertion library |
|
|
25
|
+
| `Moq` | Mocking framework |
|
|
26
|
+
| `Microsoft.AspNetCore.Mvc.Testing` | Integration test support |
|
|
27
|
+
| `Microsoft.EntityFrameworkCore.Sqlite` | SQLite in-memory for REAL integration tests |
|
|
28
|
+
| `Microsoft.Data.Sqlite` | SQLite connection support |
|
|
29
|
+
| `Microsoft.EntityFrameworkCore.InMemory` | In-memory DB for repository tests |
|
|
30
|
+
| `FluentValidation.TestHelper` | Validator testing support |
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cd tests/{SolutionName}.Tests
|
|
34
|
+
dotnet add package FluentAssertions
|
|
35
|
+
dotnet add package Moq
|
|
36
|
+
dotnet add package Microsoft.AspNetCore.Mvc.Testing
|
|
37
|
+
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
|
|
38
|
+
dotnet add package Microsoft.Data.Sqlite
|
|
39
|
+
dotnet add package Microsoft.EntityFrameworkCore.InMemory
|
|
40
|
+
dotnet add package FluentValidation.TestHelper
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 3. Project References
|
|
44
|
+
|
|
45
|
+
The test project MUST reference the API project (for WebApplicationFactory):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd tests/{SolutionName}.Tests
|
|
49
|
+
dotnet add reference ../../src/{SolutionName}.Api/{SolutionName}.Api.csproj
|
|
50
|
+
dotnet add reference ../../src/{SolutionName}.Application/{SolutionName}.Application.csproj
|
|
51
|
+
dotnet add reference ../../src/{SolutionName}.Domain/{SolutionName}.Domain.csproj
|
|
52
|
+
dotnet add reference ../../src/{SolutionName}.Infrastructure/{SolutionName}.Infrastructure.csproj
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 4. Program.cs Accessibility (BLOCKING)
|
|
56
|
+
|
|
57
|
+
The API project's `Program` class must be accessible for `WebApplicationFactory<Program>`.
|
|
58
|
+
|
|
59
|
+
Check if `Program.cs` ends with `public partial class Program { }`. If not, add it:
|
|
60
|
+
|
|
61
|
+
```csharp
|
|
62
|
+
// At the very end of Program.cs
|
|
63
|
+
public partial class Program { }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Alternatively**, add to the API `.csproj`:
|
|
67
|
+
|
|
68
|
+
```xml
|
|
69
|
+
<ItemGroup>
|
|
70
|
+
<InternalsVisibleTo Include="{SolutionName}.Tests" />
|
|
71
|
+
</ItemGroup>
|
|
72
|
+
```
|
|
@@ -138,204 +138,13 @@ The SeedData files will be consumed by the `IClientSeedDataProvider` generated a
|
|
|
138
138
|
|
|
139
139
|
## FALLBACK PROCEDURE (When MCP Unavailable)
|
|
140
140
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
### F1. Read Existing Configuration Files
|
|
149
|
-
|
|
150
|
-
**CRITICAL:** Before generating any code, read existing files to determine state:
|
|
151
|
-
|
|
152
|
-
1. **Find the Navigation Configuration directory:**
|
|
153
|
-
```
|
|
154
|
-
Glob: **/Persistence/Configurations/Navigation/Navigation*Configuration.cs
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
2. **Read NavigationTranslationConfiguration.cs** - Find the last GUID index:
|
|
158
|
-
```
|
|
159
|
-
Search for: the last call to GenerateGuid(index++)
|
|
160
|
-
The index variable starts at 1 and increments per translation entry.
|
|
161
|
-
Your new translations MUST continue from the next index value.
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
3. **Read Navigation{Level}Configuration.cs** - Check existing entities:
|
|
165
|
-
```
|
|
166
|
-
Read the Configuration for the target level (Context, Application, Module, Section).
|
|
167
|
-
Check if it already references a SeedData class: builder.HasData(Navigation{Level}SeedData.GetSeedData())
|
|
168
|
-
If yes: Read the corresponding SeedData class to find existing entries.
|
|
169
|
-
If no: You will need to add HasData() call.
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
4. **Read existing SeedData files** (if they exist):
|
|
173
|
-
```
|
|
174
|
-
Glob: **/Seeding/Data/Navigation/Navigation{Level}SeedData.cs
|
|
175
|
-
Check for existing entity IDs to avoid collisions.
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### F2. Determine Parent GUID
|
|
179
|
-
|
|
180
|
-
For non-context levels, find the parent entity GUID:
|
|
181
|
-
|
|
182
|
-
| Level | Parent | Where to Find Parent GUID |
|
|
183
|
-
|-------|--------|---------------------------|
|
|
184
|
-
| application | context | `NavigationContextSeedData.cs` → e.g. `PlatformContextId` |
|
|
185
|
-
| module | application | `NavigationApplicationSeedData.cs` → e.g. `AdministrationAppId` |
|
|
186
|
-
| section | module | `NavigationModuleSeedData.cs` → e.g. `UsersModuleId` |
|
|
187
|
-
|
|
188
|
-
Read the parent SeedData class and find the GUID matching `{parent_path}`.
|
|
189
|
-
|
|
190
|
-
### F3. Generate Navigation Entity GUID
|
|
191
|
-
|
|
192
|
-
Generate a deterministic GUID for the new navigation entity:
|
|
193
|
-
|
|
194
|
-
```csharp
|
|
195
|
-
// Use SHA256 hash of the full_path for deterministic generation
|
|
196
|
-
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
|
197
|
-
var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes("navigation-{level}-{full_path}"));
|
|
198
|
-
var guid = new Guid(hash.Take(16).ToArray());
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
**Rules:**
|
|
202
|
-
- NEVER use `Guid.NewGuid()`
|
|
203
|
-
- Read existing SeedData GUIDs to verify no collision
|
|
204
|
-
- Store result as `{navigation_guid}`
|
|
205
|
-
|
|
206
|
-
### F4. Write Navigation Entity Seed
|
|
207
|
-
|
|
208
|
-
Based on `{level}`, write the seed entry.
|
|
209
|
-
|
|
210
|
-
**Option A: Project uses SeedData classes (SmartStack.app pattern)**
|
|
211
|
-
|
|
212
|
-
If `Navigation{Level}SeedData.cs` exists, add the new entity:
|
|
213
|
-
|
|
214
|
-
```csharp
|
|
215
|
-
// In Infrastructure/Persistence/Seeding/Data/Navigation/Navigation{Level}SeedData.cs
|
|
216
|
-
|
|
217
|
-
// Add static GUID field
|
|
218
|
-
public static readonly Guid {PascalCode}Id = Guid.Parse("{navigation_guid}");
|
|
219
|
-
|
|
220
|
-
// Add to GetSeedData() return array
|
|
221
|
-
new {
|
|
222
|
-
Id = {PascalCode}Id,
|
|
223
|
-
ParentFk = Navigation{ParentLevel}SeedData.{ParentPascalCode}Id, // FK varies by level
|
|
224
|
-
Code = "{code}",
|
|
225
|
-
Label = "{labels.en}",
|
|
226
|
-
Description = "{descriptions.en}",
|
|
227
|
-
Icon = "{icon}",
|
|
228
|
-
IconType = IconType.Lucide,
|
|
229
|
-
Route = "/{full_path_with_slashes}",
|
|
230
|
-
DisplayOrder = {display_order},
|
|
231
|
-
IsActive = true,
|
|
232
|
-
CreatedAt = SeedConstants.SeedDate
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
**FK property by level:**
|
|
237
|
-
|
|
238
|
-
| Level | FK Property | References |
|
|
239
|
-
|-------|-------------|------------|
|
|
240
|
-
| context | (none) | - |
|
|
241
|
-
| application | `ContextId` | NavigationContextSeedData.{Parent}Id |
|
|
242
|
-
| module | `ApplicationId` | NavigationApplicationSeedData.{Parent}Id |
|
|
243
|
-
| section | `ModuleId` | NavigationModuleSeedData.{Parent}Id |
|
|
244
|
-
|
|
245
|
-
**Option B: Project uses inline HasData**
|
|
246
|
-
|
|
247
|
-
If no SeedData class exists, add directly to `Navigation{Level}Configuration.cs`:
|
|
248
|
-
|
|
249
|
-
```csharp
|
|
250
|
-
// In Configure method, add:
|
|
251
|
-
builder.HasData(new {
|
|
252
|
-
Id = Guid.Parse("{navigation_guid}"),
|
|
253
|
-
// ... same properties as Option A
|
|
254
|
-
});
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
### F5. Write Translation Entries
|
|
258
|
-
|
|
259
|
-
Add 4 translation entries to `NavigationTranslationConfiguration.cs`:
|
|
260
|
-
|
|
261
|
-
1. Read the file to find the current highest `index` value
|
|
262
|
-
2. Continue from `index + 1`
|
|
263
|
-
3. Use the SAME `GenerateGuid` method already defined in the file:
|
|
264
|
-
|
|
265
|
-
```csharp
|
|
266
|
-
// In GetSeedData() method, add at the end before return:
|
|
267
|
-
|
|
268
|
-
// {level}: {code} translations
|
|
269
|
-
translations.Add(new {
|
|
270
|
-
Id = GenerateGuid(index++),
|
|
271
|
-
EntityType = NavigationEntityType.{Level},
|
|
272
|
-
EntityId = Navigation{Level}SeedData.{PascalCode}Id, // or Guid.Parse("{navigation_guid}")
|
|
273
|
-
LanguageCode = "fr",
|
|
274
|
-
Label = "{labels.fr}",
|
|
275
|
-
Description = "{descriptions.fr}",
|
|
276
|
-
CreatedAt = seedDate
|
|
277
|
-
});
|
|
278
|
-
translations.Add(new {
|
|
279
|
-
Id = GenerateGuid(index++),
|
|
280
|
-
EntityType = NavigationEntityType.{Level},
|
|
281
|
-
EntityId = Navigation{Level}SeedData.{PascalCode}Id,
|
|
282
|
-
LanguageCode = "en",
|
|
283
|
-
Label = "{labels.en}",
|
|
284
|
-
Description = "{descriptions.en}",
|
|
285
|
-
CreatedAt = seedDate
|
|
286
|
-
});
|
|
287
|
-
translations.Add(new {
|
|
288
|
-
Id = GenerateGuid(index++),
|
|
289
|
-
EntityType = NavigationEntityType.{Level},
|
|
290
|
-
EntityId = Navigation{Level}SeedData.{PascalCode}Id,
|
|
291
|
-
LanguageCode = "it",
|
|
292
|
-
Label = "{labels.it}",
|
|
293
|
-
Description = "{descriptions.it}",
|
|
294
|
-
CreatedAt = seedDate
|
|
295
|
-
});
|
|
296
|
-
translations.Add(new {
|
|
297
|
-
Id = GenerateGuid(index++),
|
|
298
|
-
EntityType = NavigationEntityType.{Level},
|
|
299
|
-
EntityId = Navigation{Level}SeedData.{PascalCode}Id,
|
|
300
|
-
LanguageCode = "de",
|
|
301
|
-
Label = "{labels.de}",
|
|
302
|
-
Description = "{descriptions.de}",
|
|
303
|
-
CreatedAt = seedDate
|
|
304
|
-
});
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
### F6. Store Result
|
|
308
|
-
|
|
309
|
-
```
|
|
310
|
-
{navigation_guid} = [generated GUID]
|
|
311
|
-
{seed_method} = "fallback" // Indicates MCP was not used
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
### F7. Validation Checklist
|
|
315
|
-
|
|
316
|
-
Before proceeding, verify:
|
|
317
|
-
- [ ] Deterministic GUID generated (not NewGuid())
|
|
318
|
-
- [ ] 4 languages present (fr, en, it, de)
|
|
319
|
-
- [ ] Translation index continues existing sequence (no gaps, no collisions)
|
|
320
|
-
- [ ] Parent GUID correctly references existing entity
|
|
321
|
-
- [ ] Route path matches `/{context}/{app}/{module}` pattern
|
|
322
|
-
- [ ] DisplayOrder is consistent with existing entities
|
|
323
|
-
- [ ] Code is WRITTEN to files, not just displayed
|
|
324
|
-
|
|
325
|
-
### F8. Present Summary
|
|
326
|
-
|
|
327
|
-
```markdown
|
|
328
|
-
## Navigation Seeds Generated (Fallback)
|
|
329
|
-
|
|
330
|
-
**Entity:** {level} - {code}
|
|
331
|
-
**GUID:** {navigation_guid}
|
|
332
|
-
**Path:** {full_path}
|
|
333
|
-
|
|
334
|
-
### Files Updated
|
|
335
|
-
|
|
336
|
-
1. **Navigation{Level}SeedData.cs** (or Configuration.cs) - New entity entry
|
|
337
|
-
2. **NavigationTranslationConfiguration.cs** - 4 translation entries added
|
|
338
|
-
```
|
|
141
|
+
See [references/nav-fallback-procedure.md](../references/nav-fallback-procedure.md) for the complete 8-step fallback:
|
|
142
|
+
- **F1:** Read existing Configuration/SeedData files to determine state
|
|
143
|
+
- **F2:** Determine parent GUID by level
|
|
144
|
+
- **F3:** Generate deterministic GUID (SHA256, never NewGuid())
|
|
145
|
+
- **F4:** Write navigation entity seed (SeedData class or inline HasData)
|
|
146
|
+
- **F5:** Write 4 translation entries (continue existing index sequence)
|
|
147
|
+
- **F6-F8:** Store result, validation checklist, summary
|
|
339
148
|
|
|
340
149
|
---
|
|
341
150
|
|
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: step-03-roles
|
|
3
|
-
description: Generate role-permission mappings using MCP scaffold_role_permissions (with fallback)
|
|
3
|
+
description: Generate application roles and role-permission mappings using MCP scaffold_role_permissions (with fallback)
|
|
4
4
|
prev_step: steps/step-02-permissions.md
|
|
5
5
|
next_step: steps/step-03b-provider.md
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
# Step 3: Role-Permission Mapping
|
|
8
|
+
# Step 3: Application Roles & Role-Permission Mapping
|
|
9
9
|
|
|
10
10
|
## MANDATORY EXECUTION RULES
|
|
11
11
|
|
|
12
|
+
- For **client projects** (`seeding_strategy = "provider"`): Generate ApplicationRolesSeedData.cs and module role mappings
|
|
13
|
+
- For **core projects** (`seeding_strategy = "hasdata"`): Use RolePermissionConfiguration.cs
|
|
12
14
|
- PREFER MCP `scaffold_role_permissions` tool as the primary method
|
|
13
15
|
- If MCP is unavailable or the call fails, use the FALLBACK PROCEDURE below
|
|
14
16
|
- ALWAYS assign permissions to default roles
|
|
15
17
|
- NEVER leave permissions without role assignments
|
|
16
|
-
- ALWAYS WRITE generated code to the actual
|
|
18
|
+
- ALWAYS WRITE generated code to the actual files
|
|
17
19
|
|
|
18
20
|
## YOUR TASK
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
For **client projects**:
|
|
23
|
+
1. **ApplicationRolesSeedData.cs** (once per application) — defines the 4 application-scoped roles
|
|
24
|
+
2. **{Module}RolePermissionSeedData.cs** (per module) — maps permissions to roles by Code
|
|
25
|
+
|
|
26
|
+
For **core projects**:
|
|
21
27
|
1. RolePermissionConfiguration.cs HasData() entries
|
|
22
28
|
2. Default role assignments (SuperAdmin, PlatformAdmin, TenantAdmin, StandardUser)
|
|
23
29
|
3. Application-scoped role assignments (Admin, Manager, Contributor, Viewer)
|
|
@@ -131,13 +137,38 @@ If MCP call fails or `{mcp_available}` = false:
|
|
|
131
137
|
**For core (`{seeding_strategy}` = "hasdata"):** Write in RolePermissionConfiguration.cs (existing pattern)
|
|
132
138
|
|
|
133
139
|
**For client (`{seeding_strategy}` = "provider"):** DO NOT write in RolePermissionConfiguration.cs (does not exist in client projects).
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
|
|
141
|
+
Instead, create TWO files:
|
|
142
|
+
|
|
143
|
+
### 1. ApplicationRolesSeedData.cs (ONCE per application)
|
|
144
|
+
|
|
145
|
+
**File:** `Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs`
|
|
146
|
+
|
|
147
|
+
**Purpose:** Defines the 4 standard application-scoped roles (Admin, Manager, Contributor, Viewer) with valid `Code` values.
|
|
148
|
+
|
|
149
|
+
**CRITICAL:** Without this file, role-permission mappings in `SeedRolePermissionsAsync()` will fail silently because `roles.FirstOrDefault(r => r.Code == mapping.RoleCode)` will return null.
|
|
150
|
+
|
|
151
|
+
See [references/application-roles-template.md](../references/application-roles-template.md) for the complete template.
|
|
152
|
+
|
|
153
|
+
**Key requirements:**
|
|
154
|
+
- Deterministic GUIDs based on `role-{applicationId}-{roleType}`
|
|
155
|
+
- 4 roles: Admin, Manager, Contributor, Viewer
|
|
156
|
+
- Each role has a valid `Code` property ("admin", "manager", "contributor", "viewer")
|
|
157
|
+
- `ApplicationId` references the navigation application GUID
|
|
158
|
+
- `IsSystem = false` (application-scoped, not system roles)
|
|
159
|
+
|
|
160
|
+
**Detection:** Check if ApplicationRolesSeedData.cs exists. If yes, skip creation (already exists from Module 1). If no, create it.
|
|
161
|
+
|
|
162
|
+
### 2. {Module}RolePermissionSeedData.cs (PER module)
|
|
163
|
+
|
|
164
|
+
**File:** `Infrastructure/Persistence/Seeding/Data/{Domain}/{Module}RolePermissionSeedData.cs`
|
|
165
|
+
|
|
166
|
+
**Purpose:** Maps permissions to roles by Code (e.g., "admin" → "{navRoute}.*").
|
|
136
167
|
|
|
137
168
|
Content: static class with method `GetRolePermissionEntries()` that returns the role-permission mapping data.
|
|
138
169
|
These entries will be consumed by the `IClientSeedDataProvider` at step 03b.
|
|
139
170
|
|
|
140
|
-
**After creating
|
|
171
|
+
**After creating both files:** Proceed to step-03b-provider.md (which will skip for core projects).
|
|
141
172
|
|
|
142
173
|
---
|
|
143
174
|
|
|
@@ -280,6 +311,13 @@ If user selects "Custom adjustments", ask which roles/permissions to change and
|
|
|
280
311
|
|
|
281
312
|
## SUCCESS METRICS
|
|
282
313
|
|
|
314
|
+
**For client projects:**
|
|
315
|
+
- ApplicationRolesSeedData.cs created (once per application)
|
|
316
|
+
- {Module}RolePermissionSeedData.cs created with role-permission mappings
|
|
317
|
+
- All 4 application roles defined with valid Code values
|
|
318
|
+
- Proceeded to step-03b-provider.md
|
|
319
|
+
|
|
320
|
+
**For core projects:**
|
|
283
321
|
- Role-permission mappings generated (via MCP or fallback)
|
|
284
322
|
- RolePermissionConfiguration.cs WRITTEN with new entries
|
|
285
323
|
- All default roles have appropriate access
|
|
@@ -49,134 +49,11 @@ From previous steps:
|
|
|
49
49
|
|
|
50
50
|
## FILES TO GENERATE
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
**Pattern:**
|
|
59
|
-
|
|
60
|
-
```csharp
|
|
61
|
-
using Microsoft.EntityFrameworkCore;
|
|
62
|
-
using SmartStack.Application.Common.Interfaces;
|
|
63
|
-
using SmartStack.Domain.Navigation;
|
|
64
|
-
using SmartStack.Domain.Platform.Administration.Roles;
|
|
65
|
-
|
|
66
|
-
namespace {BaseNamespace}.Infrastructure.Persistence.Seeding;
|
|
67
|
-
|
|
68
|
-
/// <summary>
|
|
69
|
-
/// Seeds {AppLabel} navigation, permissions, and role-permission data
|
|
70
|
-
/// into the SmartStack Core schema at application startup.
|
|
71
|
-
/// Implements <see cref="IClientSeedDataProvider"/> for runtime seeding
|
|
72
|
-
/// (no Core migrations required).
|
|
73
|
-
/// </summary>
|
|
74
|
-
public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
75
|
-
{
|
|
76
|
-
public int Order => 100;
|
|
77
|
-
|
|
78
|
-
public async Task SeedNavigationAsync(ICoreDbContext context, CancellationToken ct)
|
|
79
|
-
{
|
|
80
|
-
// Check idempotence
|
|
81
|
-
var exists = await context.NavigationApplications
|
|
82
|
-
.AnyAsync(a => a.Code == "{app_code}", ct);
|
|
83
|
-
if (exists) return;
|
|
84
|
-
|
|
85
|
-
// 1. Retrieve the parent context ("business", "platform", etc.)
|
|
86
|
-
var parentContext = await context.NavigationContexts
|
|
87
|
-
.FirstAsync(c => c.Code == "{context_code}", ct);
|
|
88
|
-
|
|
89
|
-
// 2. Create the application
|
|
90
|
-
var app = NavigationApplication.Create(
|
|
91
|
-
parentContext.Id,
|
|
92
|
-
"{app_code}",
|
|
93
|
-
"{app_label_en}",
|
|
94
|
-
"{app_desc_en}",
|
|
95
|
-
"{app_icon}",
|
|
96
|
-
IconType.Lucide,
|
|
97
|
-
"/{context_code}/{app_code}",
|
|
98
|
-
{display_order});
|
|
99
|
-
context.NavigationApplications.Add(app);
|
|
100
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
101
|
-
|
|
102
|
-
// 3. Create modules
|
|
103
|
-
// Use GUIDs and data from {Module}NavigationSeedData.cs
|
|
104
|
-
foreach (var moduleData in GetModuleSeedEntries(app.Id))
|
|
105
|
-
{
|
|
106
|
-
var module = NavigationModule.Create(
|
|
107
|
-
moduleData.ApplicationId,
|
|
108
|
-
moduleData.Code,
|
|
109
|
-
moduleData.Label,
|
|
110
|
-
moduleData.Description,
|
|
111
|
-
moduleData.Icon,
|
|
112
|
-
IconType.Lucide,
|
|
113
|
-
moduleData.Route,
|
|
114
|
-
moduleData.DisplayOrder);
|
|
115
|
-
context.NavigationModules.Add(module);
|
|
116
|
-
}
|
|
117
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
118
|
-
|
|
119
|
-
// 4. Create translations (4 languages per entity)
|
|
120
|
-
// Use data from {Module}NavigationTranslationSeedData.cs
|
|
121
|
-
// ...
|
|
122
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
public async Task SeedPermissionsAsync(ICoreDbContext context, CancellationToken ct)
|
|
126
|
-
{
|
|
127
|
-
// Check idempotence
|
|
128
|
-
var exists = await context.Permissions
|
|
129
|
-
.AnyAsync(p => p.Path == "{full_path}.*", ct);
|
|
130
|
-
if (exists) return;
|
|
131
|
-
|
|
132
|
-
// Retrieve modules by Code for FK resolution
|
|
133
|
-
// Use data from {Module}PermissionSeedData.cs
|
|
134
|
-
// Create via Permission.CreateForModule(...) and Permission.CreateWildcard(...)
|
|
135
|
-
// ...
|
|
136
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
public async Task SeedRolePermissionsAsync(ICoreDbContext context, CancellationToken ct)
|
|
140
|
-
{
|
|
141
|
-
// Check idempotence
|
|
142
|
-
var exists = await context.RolePermissions
|
|
143
|
-
.AnyAsync(rp => rp.Permission!.Path.StartsWith("{full_path}."), ct);
|
|
144
|
-
if (exists) return;
|
|
145
|
-
|
|
146
|
-
// Retrieve existing roles and created permissions
|
|
147
|
-
// Use data from {Module}RolePermissionSeedData.cs
|
|
148
|
-
// Create via RolePermission.Create(roleId, permissionId, "system")
|
|
149
|
-
// ...
|
|
150
|
-
await ((DbContext)context).SaveChangesAsync(ct);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Private helper methods fed by SeedData classes
|
|
154
|
-
// ...
|
|
155
|
-
}
|
|
156
|
-
```
|
|
157
|
-
|
|
158
|
-
### 2. DI Registration
|
|
159
|
-
|
|
160
|
-
Modify `Infrastructure/DependencyInjection.cs` of the client project:
|
|
161
|
-
|
|
162
|
-
```csharp
|
|
163
|
-
// Add using:
|
|
164
|
-
using SmartStack.Application.Common.Interfaces;
|
|
165
|
-
|
|
166
|
-
// In the registration method:
|
|
167
|
-
services.AddScoped<IClientSeedDataProvider, {AppPascalName}SeedDataProvider>();
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
## CRITICAL RULES
|
|
173
|
-
|
|
174
|
-
1. **Factory methods mandatory**: `NavigationModule.Create(...)`, `Permission.CreateForModule(...)`, `RolePermission.Create(...)` - NEVER `new Entity()`
|
|
175
|
-
2. **Idempotence**: Each Seed method checks existence before inserting
|
|
176
|
-
3. **SaveChangesAsync per group**: Navigation -> save -> Permissions -> save -> RolePermissions -> save
|
|
177
|
-
4. **Deterministic GUIDs**: Use IDs from SeedData classes (not Guid.NewGuid())
|
|
178
|
-
5. **Resolve FK by Code**: Parent modules are found by `Code`, not hardcoded GUID
|
|
179
|
-
6. **Order property**: Use `100` as default. If multiple providers exist, they run in Order sequence
|
|
52
|
+
See [references/provider-template.md](../references/provider-template.md) for the complete implementation:
|
|
53
|
+
- **ApplicationRolesSeedData.cs** (once per application) — defines application-scoped roles (Admin, Manager, Contributor, Viewer)
|
|
54
|
+
- **Provider class** (`{AppPascalName}SeedDataProvider.cs`) with 4 seed methods (Navigation, Roles, Permissions, RolePermissions)
|
|
55
|
+
- **DI registration** pattern for `Infrastructure/DependencyInjection.cs`
|
|
56
|
+
- **7 critical rules** (factory methods, idempotence, execution order, SaveChangesAsync order, deterministic GUIDs, FK by Code, Order property)
|
|
180
57
|
|
|
181
58
|
---
|
|
182
59
|
|
|
@@ -188,9 +65,11 @@ Identify all SeedData files created in previous steps:
|
|
|
188
65
|
|
|
189
66
|
```
|
|
190
67
|
Glob: **/Persistence/Seeding/Data/{Domain}/*SeedData.cs
|
|
68
|
+
Glob: **/Persistence/Seeding/Data/ApplicationRolesSeedData.cs
|
|
191
69
|
```
|
|
192
70
|
|
|
193
71
|
Expected files:
|
|
72
|
+
- `ApplicationRolesSeedData.cs` (application-level, once per app)
|
|
194
73
|
- `{Module}NavigationSeedData.cs` (from step 01)
|
|
195
74
|
- `{Module}NavigationTranslationSeedData.cs` (from step 01)
|
|
196
75
|
- `{Module}PermissionSeedData.cs` (from step 02)
|
|
@@ -220,9 +99,11 @@ Add the `IClientSeedDataProvider` registration.
|
|
|
220
99
|
### 4. Verify
|
|
221
100
|
|
|
222
101
|
Before proceeding to step-04, verify:
|
|
223
|
-
- [ ]
|
|
102
|
+
- [ ] ApplicationRolesSeedData.cs created (once per application)
|
|
103
|
+
- [ ] Provider generated with 4 methods (SeedNavigationAsync, SeedRolesAsync, SeedPermissionsAsync, SeedRolePermissionsAsync)
|
|
104
|
+
- [ ] Execution order: Navigation → Roles → Permissions → RolePermissions
|
|
224
105
|
- [ ] Registered in DI (`services.AddScoped<IClientSeedDataProvider, ...>()`)
|
|
225
|
-
- [ ] Consumes SeedData classes from steps 01-03
|
|
106
|
+
- [ ] Consumes SeedData classes from steps 01-03 + ApplicationRolesSeedData
|
|
226
107
|
- [ ] Idempotent (check existence before insert)
|
|
227
108
|
- [ ] Uses factory methods (no `new Entity()`)
|
|
228
109
|
|
|
@@ -230,9 +111,11 @@ Before proceeding to step-04, verify:
|
|
|
230
111
|
|
|
231
112
|
## SUCCESS METRICS
|
|
232
113
|
|
|
233
|
-
-
|
|
114
|
+
- ApplicationRolesSeedData.cs created (application-level)
|
|
115
|
+
- Provider class generated with all 4 seed methods (Navigation, Roles, Permissions, RolePermissions)
|
|
116
|
+
- Correct execution order enforced
|
|
234
117
|
- DI registration added
|
|
235
|
-
- SeedData classes from steps 01-03 properly consumed
|
|
118
|
+
- SeedData classes from steps 01-03 + ApplicationRolesSeedData properly consumed
|
|
236
119
|
- All methods are idempotent
|
|
237
120
|
- Factory methods used throughout
|
|
238
121
|
- Proceeded to step-04-backend.md
|