@atlashub/smartstack-cli 3.37.0 → 3.38.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 +16 -24
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +201 -256
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/scripts/extract-api-endpoints.ts +5 -5
- package/scripts/generate-doc-with-mock-ui.ts +10 -17
- package/templates/agents/ba-reader.md +9 -9
- package/templates/agents/ba-writer.md +12 -15
- package/templates/agents/code-reviewer.md +1 -1
- package/templates/agents/docs-context-reader.md +1 -1
- package/templates/agents/gitflow/merge.md +0 -4
- package/templates/agents/gitflow/pr.md +0 -4
- package/templates/agents/gitflow/start.md +30 -5
- package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +20 -20
- package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +16 -24
- package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +2 -2
- package/templates/skills/_resources/mcp-validate-documentation-spec.md +3 -3
- package/templates/skills/_shared.md +15 -17
- package/templates/skills/ai-prompt/SKILL.md +1 -1
- package/templates/skills/ai-prompt/steps/step-00-init.md +47 -0
- package/templates/skills/apex/SKILL.md +3 -4
- package/templates/skills/apex/_shared.md +10 -20
- package/templates/skills/apex/references/analysis-methods.md +141 -0
- package/templates/skills/apex/references/challenge-questions.md +1 -21
- package/templates/skills/apex/references/core-seed-data.md +35 -57
- package/templates/skills/apex/references/examine-build-validation.md +87 -0
- package/templates/skills/apex/references/execution-frontend-gates.md +177 -0
- package/templates/skills/apex/references/execution-frontend-patterns.md +105 -0
- package/templates/skills/apex/references/execution-layer1-rules.md +96 -0
- package/templates/skills/apex/references/initialization-challenge-flow.md +110 -0
- package/templates/skills/apex/references/planning-layer-mapping.md +151 -0
- package/templates/skills/apex/references/post-checks.md +145 -40
- package/templates/skills/apex/references/smartstack-api.md +35 -51
- package/templates/skills/apex/references/smartstack-frontend.md +17 -17
- package/templates/skills/apex/references/smartstack-layers.md +38 -62
- package/templates/skills/apex/steps/step-00-init.md +14 -26
- package/templates/skills/apex/steps/step-01-analyze.md +10 -143
- package/templates/skills/apex/steps/step-02-plan.md +10 -92
- package/templates/skills/apex/steps/step-03-execute.md +47 -249
- package/templates/skills/apex/steps/step-04-examine.md +14 -78
- package/templates/skills/apex/steps/step-05-deep-review.md +2 -2
- package/templates/skills/apex/steps/step-08-run-tests.md +2 -0
- package/templates/skills/application/SKILL.md +6 -7
- package/templates/skills/application/references/backend-controller-hierarchy.md +16 -16
- package/templates/skills/application/references/backend-seeding-and-dto-output.md +83 -0
- package/templates/skills/application/references/backend-table-prefix-mapping.md +79 -0
- package/templates/skills/application/references/backend-verification.md +1 -1
- package/templates/skills/application/references/frontend-i18n-and-output.md +67 -0
- package/templates/skills/application/references/frontend-route-naming.md +117 -0
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +107 -0
- package/templates/skills/application/references/frontend-verification.md +12 -12
- package/templates/skills/application/references/init-parameter-detection.md +120 -0
- package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -0
- package/templates/skills/application/references/nav-fallback-procedure.md +5 -6
- package/templates/skills/application/references/provider-template.md +2 -6
- package/templates/skills/application/references/roles-client-project-handling.md +55 -0
- package/templates/skills/application/references/roles-fallback-procedure.md +149 -0
- package/templates/skills/application/references/test-coverage-requirements.md +213 -0
- package/templates/skills/application/references/test-frontend.md +3 -3
- package/templates/skills/application/steps/step-00-init.md +11 -141
- package/templates/skills/application/steps/step-01-navigation.md +3 -3
- package/templates/skills/application/steps/step-02-permissions.md +4 -4
- package/templates/skills/application/steps/step-03-roles.md +18 -175
- package/templates/skills/application/steps/step-03b-provider.md +1 -2
- package/templates/skills/application/steps/step-04-backend.md +19 -110
- package/templates/skills/application/steps/step-05-frontend.md +17 -143
- package/templates/skills/application/steps/step-06-migration.md +12 -60
- package/templates/skills/application/steps/step-07-tests.md +9 -76
- package/templates/skills/application/templates-backend.md +29 -27
- package/templates/skills/application/templates-frontend.md +48 -48
- package/templates/skills/application/templates-seed.md +57 -131
- package/templates/skills/business-analyse/SKILL.md +27 -30
- package/templates/skills/business-analyse/_architecture.md +6 -6
- package/templates/skills/business-analyse/_shared.md +60 -88
- package/templates/skills/business-analyse/questionnaire/04-data.md +3 -3
- package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
- package/templates/skills/business-analyse/questionnaire/13-cross-module.md +1 -1
- package/templates/skills/business-analyse/react/application-viewer.md +12 -12
- package/templates/skills/business-analyse/react/components.md +8 -12
- package/templates/skills/business-analyse/react/schema.md +11 -11
- package/templates/skills/business-analyse/references/agent-module-prompt.md +2 -3
- package/templates/skills/business-analyse/references/analysis-semantic-checks.md +190 -0
- package/templates/skills/business-analyse/references/cache-warming-strategy.md +2 -2
- package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +41 -0
- package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +74 -0
- package/templates/skills/business-analyse/references/cadrage-shared-modules.md +69 -0
- package/templates/skills/business-analyse/references/cadrage-structure-cards.md +1 -1
- package/templates/skills/business-analyse/references/compilation-structure-cards.md +297 -0
- package/templates/skills/business-analyse/references/consolidation-structural-checks.md +2 -2
- package/templates/skills/business-analyse/references/deploy-modes.md +5 -5
- package/templates/skills/business-analyse/references/detection-strategies.md +7 -7
- package/templates/skills/business-analyse/references/handoff-file-templates.md +14 -22
- package/templates/skills/business-analyse/references/handoff-mappings.md +4 -4
- package/templates/skills/business-analyse/references/handoff-seeddata-generation.md +312 -0
- package/templates/skills/business-analyse/references/init-schema-deployment.md +3 -3
- package/templates/skills/business-analyse/references/naming-conventions.md +22 -24
- package/templates/skills/business-analyse/references/prd-generation.md +2 -2
- package/templates/skills/business-analyse/references/review-data-mapping.md +2 -2
- package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
- package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
- package/templates/skills/business-analyse/references/team-orchestration.md +49 -6
- package/templates/skills/business-analyse/references/ui-dashboard-spec.md +1 -1
- package/templates/skills/business-analyse/references/ui-resource-cards.md +18 -18
- package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -2
- package/templates/skills/business-analyse/references/validation-checklist.md +2 -2
- package/templates/skills/business-analyse/schemas/application-schema.json +4 -5
- package/templates/skills/business-analyse/schemas/project-schema.json +1 -6
- package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -3
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +4 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +8 -17
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +35 -198
- package/templates/skills/business-analyse/steps/step-01b-applications.md +16 -20
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +1 -1
- package/templates/skills/business-analyse/steps/step-03a1-setup.md +4 -4
- package/templates/skills/business-analyse/steps/step-03a2-analysis.md +1 -1
- package/templates/skills/business-analyse/steps/step-03b-ui.md +4 -4
- package/templates/skills/business-analyse/steps/step-03c-compile.md +66 -140
- package/templates/skills/business-analyse/steps/step-03d-validate.md +2 -2
- package/templates/skills/business-analyse/steps/step-04a-collect.md +2 -2
- package/templates/skills/business-analyse/steps/step-04b-analyze.md +42 -160
- package/templates/skills/business-analyse/steps/step-04c-decide.md +1 -1
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +74 -104
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +13 -11
- package/templates/skills/business-analyse/steps/step-06-review.md +3 -3
- package/templates/skills/business-analyse/templates/tpl-frd.md +13 -13
- package/templates/skills/business-analyse/templates/tpl-handoff.md +12 -12
- package/templates/skills/business-analyse/templates-frd.md +25 -25
- package/templates/skills/business-analyse/templates-react.md +15 -21
- package/templates/skills/controller/SKILL.md +1 -1
- package/templates/skills/controller/postman-templates.md +1 -1
- package/templates/skills/controller/references/controller-code-templates.md +2 -2
- package/templates/skills/controller/references/mcp-scaffold-workflow.md +209 -0
- package/templates/skills/controller/references/permission-sync-templates.md +13 -16
- package/templates/skills/controller/steps/step-00-init.md +11 -11
- package/templates/skills/controller/steps/step-03-generate.md +64 -103
- package/templates/skills/controller/templates.md +67 -71
- package/templates/skills/debug/SKILL.md +13 -218
- package/templates/skills/debug/steps/step-00-init.md +57 -0
- package/templates/skills/debug/steps/step-01-analyze.md +219 -0
- package/templates/skills/debug/steps/step-02-resolve.md +85 -0
- package/templates/skills/documentation/SKILL.md +49 -345
- package/templates/skills/documentation/data-schema.md +11 -8
- package/templates/skills/documentation/steps/step-00-init.md +70 -0
- package/templates/skills/documentation/steps/step-01-scan.md +113 -0
- package/templates/skills/documentation/steps/step-02-generate.md +231 -0
- package/templates/skills/documentation/steps/step-03-validate.md +238 -0
- package/templates/skills/documentation/templates.md +480 -322
- package/templates/skills/efcore/references/both-contexts.md +32 -0
- package/templates/skills/efcore/references/database-operations.md +67 -0
- package/templates/skills/efcore/references/destructive-operations.md +38 -0
- package/templates/skills/efcore/references/reset-operations.md +81 -0
- package/templates/skills/efcore/references/seed-methods.md +86 -0
- package/templates/skills/efcore/references/shared-init-functions.md +250 -0
- package/templates/skills/efcore/references/sql-objects-injection.md +61 -0
- package/templates/skills/efcore/references/troubleshooting.md +81 -0
- package/templates/skills/efcore/steps/db/step-deploy.md +1 -32
- package/templates/skills/efcore/steps/db/step-reset.md +7 -103
- package/templates/skills/efcore/steps/db/step-seed.md +10 -132
- package/templates/skills/efcore/steps/db/step-status.md +5 -44
- package/templates/skills/efcore/steps/migration/step-03-validate.md +8 -62
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +1 -57
- package/templates/skills/efcore/steps/shared/step-00-init.md +11 -254
- package/templates/skills/efcore/steps/squash/step-03-create.md +1 -58
- package/templates/skills/feature-full/SKILL.md +1 -1
- package/templates/skills/feature-full/steps/step-00-init.md +57 -0
- package/templates/skills/feature-full/steps/step-01-implementation.md +1 -1
- package/templates/skills/gitflow/SKILL.md +1 -1
- package/templates/skills/gitflow/_shared.md +23 -0
- package/templates/skills/gitflow/references/commit-message-generation.md +58 -0
- package/templates/skills/gitflow/references/commit-migration-validation.md +49 -0
- package/templates/skills/gitflow/references/finish-cleanup.md +51 -0
- package/templates/skills/gitflow/references/finish-version-bumping.md +45 -0
- package/templates/skills/gitflow/references/init-environment-detection.md +41 -0
- package/templates/skills/gitflow/references/init-questions.md +185 -0
- package/templates/skills/gitflow/references/init-structure-creation.md +71 -0
- package/templates/skills/gitflow/references/init-version-detection.md +21 -0
- package/templates/skills/gitflow/references/init-workspace-detection.md +43 -0
- package/templates/skills/gitflow/references/merge-ci-status.md +36 -0
- package/templates/skills/gitflow/references/merge-execution.md +62 -0
- package/templates/skills/gitflow/references/merge-pr-context.md +76 -0
- package/templates/skills/gitflow/references/pr-build-checks.md +60 -0
- package/templates/skills/gitflow/references/pr-generation.md +58 -0
- package/templates/skills/gitflow/references/start-branch-normalization.md +28 -0
- package/templates/skills/gitflow/references/start-worktree-creation.md +50 -0
- package/templates/skills/gitflow/references/sync-push-verify.md +44 -0
- package/templates/skills/gitflow/references/sync-rebase-conflicts.md +38 -0
- package/templates/skills/gitflow/steps/step-commit.md +12 -91
- package/templates/skills/gitflow/steps/step-finish.md +15 -159
- package/templates/skills/gitflow/steps/step-init.md +24 -326
- package/templates/skills/gitflow/steps/step-merge.md +17 -176
- package/templates/skills/gitflow/steps/step-pr.md +10 -116
- package/templates/skills/gitflow/steps/step-start.md +16 -109
- package/templates/skills/gitflow/steps/step-sync.md +6 -69
- package/templates/skills/ralph-loop/SKILL.md +6 -0
- package/templates/skills/ralph-loop/references/category-completeness.md +185 -0
- package/templates/skills/ralph-loop/references/compact-loop.md +1 -1
- package/templates/skills/ralph-loop/references/init-resume-recovery.md +127 -0
- package/templates/skills/ralph-loop/references/module-transition.md +151 -0
- package/templates/skills/ralph-loop/references/multi-module-queue.md +171 -0
- package/templates/skills/ralph-loop/references/parallel-execution.md +246 -0
- package/templates/skills/ralph-loop/references/task-transform-legacy.md +6 -9
- package/templates/skills/ralph-loop/references/team-orchestration.md +45 -3
- package/templates/skills/ralph-loop/steps/step-00-init.md +36 -109
- package/templates/skills/ralph-loop/steps/step-01-task.md +15 -163
- package/templates/skills/ralph-loop/steps/step-02-execute.md +8 -154
- package/templates/skills/ralph-loop/steps/step-04-check.md +21 -73
- package/templates/skills/review-code/references/owasp-api-top10.md +5 -5
- package/templates/skills/review-code/references/smartstack-conventions.md +11 -11
- package/templates/skills/validate-feature/references/api-smoke-tests.md +140 -0
- package/templates/skills/validate-feature/references/db-validation-checks.md +180 -0
- package/templates/skills/validate-feature/steps/step-01-compile.md +5 -2
- package/templates/skills/validate-feature/steps/step-04-api-smoke.md +34 -145
- package/templates/skills/validate-feature/steps/step-05-db-validation.md +74 -260
- package/templates/skills/workflow/SKILL.md +1 -1
- package/templates/skills/workflow/steps/step-00-init.md +57 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Migration: Checklist & Troubleshooting
|
|
2
|
+
|
|
3
|
+
> Referenced from `steps/step-06-migration.md` — Migration verification and common issues.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Pre-Migration Build Verification (BLOCKING)
|
|
8
|
+
|
|
9
|
+
**CRITICAL:** The backend MUST build successfully before creating a migration.
|
|
10
|
+
EF Core tools compile the project internally; a build failure produces confusing errors
|
|
11
|
+
that do not point to the actual source file.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
dotnet build {SolutionName}.sln --no-restore
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Common causes at this stage:**
|
|
18
|
+
- Missing DbSet registration (should have been caught in step-04 Check 2)
|
|
19
|
+
- Missing DI registration (should have been caught in step-04 Check 3)
|
|
20
|
+
- Circular references between generated services
|
|
21
|
+
- Missing package references (e.g., FluentValidation)
|
|
22
|
+
- Frontend changes that modified shared files
|
|
23
|
+
|
|
24
|
+
**After build succeeds:** Continue to migration name suggestion.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Migration Content Verification
|
|
29
|
+
|
|
30
|
+
The migration should include:
|
|
31
|
+
- Navigation entity (Application/Module/Section)
|
|
32
|
+
- Navigation translations (4 languages)
|
|
33
|
+
- Permissions (CRUD + wildcard)
|
|
34
|
+
- RolePermissions (role assignments)
|
|
35
|
+
- Domain entity table
|
|
36
|
+
- Indexes and constraints
|
|
37
|
+
- SQL Objects injection (if any .sql files exist)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## SQL Objects Injection
|
|
42
|
+
|
|
43
|
+
Check if any SQL object files exist:
|
|
44
|
+
```
|
|
45
|
+
Glob: **/Persistence/SqlObjects/Functions/*.sql
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If SQL files are found, the migration's `Up()` method should include a call to re-apply all SQL objects:
|
|
49
|
+
```csharp
|
|
50
|
+
// At the end of the Up() method:
|
|
51
|
+
SqlObjectHelper.ApplyAll(migrationBuilder);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This ensures SQL functions/views are re-applied with each migration (`CREATE OR ALTER` = idempotent).
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Troubleshooting
|
|
59
|
+
|
|
60
|
+
### Common Issues
|
|
61
|
+
|
|
62
|
+
| Issue | Solution |
|
|
63
|
+
|-------|----------|
|
|
64
|
+
| Migration conflicts | Run `/efcore:conflicts` to analyze |
|
|
65
|
+
| Permission 403 errors | Verify Permissions.cs and PermissionConfiguration.cs are in sync |
|
|
66
|
+
| Navigation not visible | Check user role has appropriate permissions |
|
|
67
|
+
| Route not found | Verify nested route structure in routes.tsx |
|
|
68
|
+
| i18n missing | Check locale files exist and are properly loaded |
|
|
69
|
+
| EF Core compilation error | Check DbSet and DI registration |
|
|
70
|
+
| FK constraint errors | Verify all entity references exist in seed data |
|
|
71
|
+
|
|
72
|
+
### Quick Fixes
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Rebuild and restart
|
|
76
|
+
dotnet build
|
|
77
|
+
dotnet ef database update
|
|
78
|
+
|
|
79
|
+
# Clear frontend cache
|
|
80
|
+
cd web && rm -rf node_modules/.cache && npm run dev
|
|
81
|
+
|
|
82
|
+
# Reset database (development only)
|
|
83
|
+
dotnet ef database drop --context CoreDbContext --force
|
|
84
|
+
dotnet ef database update --context CoreDbContext
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Final Checklist
|
|
90
|
+
|
|
91
|
+
- [ ] Pre-migration build passed
|
|
92
|
+
- [ ] Migration name suggested via MCP
|
|
93
|
+
- [ ] Migration created with correct context
|
|
94
|
+
- [ ] Migration includes navigation, permissions, and entity table
|
|
95
|
+
- [ ] SQL objects injected (if applicable)
|
|
96
|
+
- [ ] Migration applied successfully
|
|
97
|
+
- [ ] Database updated without errors
|
|
98
|
+
- [ ] DbSet registered in DbContext
|
|
99
|
+
- [ ] DI registration in place
|
|
100
|
+
- [ ] Application starts without errors
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
|
|
26
26
|
3. **Read Navigation{Level}Configuration.cs** - Check existing entities:
|
|
27
27
|
```
|
|
28
|
-
Read the Configuration for the target level (
|
|
28
|
+
Read the Configuration for the target level (Application, Module, Section).
|
|
29
29
|
Check if it already references a SeedData class: builder.HasData(Navigation{Level}SeedData.GetSeedData())
|
|
30
30
|
If yes: Read the corresponding SeedData class to find existing entries.
|
|
31
31
|
If no: You will need to add HasData() call.
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
|
|
40
40
|
## F2. Determine Parent GUID
|
|
41
41
|
|
|
42
|
-
For non-
|
|
42
|
+
For non-application levels, find the parent entity GUID:
|
|
43
43
|
|
|
44
44
|
| Level | Parent | Where to Find Parent GUID |
|
|
45
45
|
|-------|--------|---------------------------|
|
|
46
|
-
| application |
|
|
46
|
+
| application | (none — top level) | — |
|
|
47
47
|
| module | application | `NavigationApplicationSeedData.cs` → e.g. `AdministrationAppId` |
|
|
48
48
|
| section | module | `NavigationModuleSeedData.cs` → e.g. `UsersModuleId` |
|
|
49
49
|
|
|
@@ -99,8 +99,7 @@ new {
|
|
|
99
99
|
|
|
100
100
|
| Level | FK Property | References |
|
|
101
101
|
|-------|-------------|------------|
|
|
102
|
-
|
|
|
103
|
-
| application | `ContextId` | NavigationContextSeedData.{Parent}Id |
|
|
102
|
+
| application | (none — top level) | — |
|
|
104
103
|
| module | `ApplicationId` | NavigationApplicationSeedData.{Parent}Id |
|
|
105
104
|
| section | `ModuleId` | NavigationModuleSeedData.{Parent}Id |
|
|
106
105
|
|
|
@@ -180,7 +179,7 @@ Before proceeding, verify:
|
|
|
180
179
|
- [ ] 4 languages present (fr, en, it, de)
|
|
181
180
|
- [ ] Translation index continues existing sequence (no gaps, no collisions)
|
|
182
181
|
- [ ] Parent GUID correctly references existing entity
|
|
183
|
-
- [ ] Route path matches `/{
|
|
182
|
+
- [ ] Route path matches `/{app}/{module}` pattern
|
|
184
183
|
- [ ] DisplayOrder is consistent with existing entities
|
|
185
184
|
- [ ] Code is WRITTEN to files, not just displayed
|
|
186
185
|
|
|
@@ -31,7 +31,7 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
|
31
31
|
public async Task SeedNavigationAsync(ICoreDbContext context, CancellationToken ct)
|
|
32
32
|
{
|
|
33
33
|
// --- Application (idempotent — reuse if already exists) ---
|
|
34
|
-
var appEntry = NavigationApplicationSeedData.GetApplicationEntry(
|
|
34
|
+
var appEntry = NavigationApplicationSeedData.GetApplicationEntry();
|
|
35
35
|
var existingApp = await context.NavigationApplications
|
|
36
36
|
.FirstOrDefaultAsync(a => a.Code == appEntry.Code, ct);
|
|
37
37
|
|
|
@@ -42,12 +42,8 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
|
|
|
42
42
|
}
|
|
43
43
|
else
|
|
44
44
|
{
|
|
45
|
-
var parentContext = await context.NavigationContexts
|
|
46
|
-
.FirstAsync(c => c.Code == "{context_code}", ct);
|
|
47
|
-
|
|
48
|
-
appEntry = NavigationApplicationSeedData.GetApplicationEntry(parentContext.Id);
|
|
49
45
|
app = NavigationApplication.Create(
|
|
50
|
-
appEntry.
|
|
46
|
+
appEntry.Code, appEntry.Label,
|
|
51
47
|
appEntry.Description, appEntry.Icon, appEntry.IconType,
|
|
52
48
|
appEntry.Route, appEntry.DisplayOrder);
|
|
53
49
|
context.NavigationApplications.Add(app);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Step 3: Client Project Handling (seeding_strategy = "provider")
|
|
2
|
+
|
|
3
|
+
> Referenced from `steps/step-03-roles.md` — Specific handling for client projects.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ApplicationRolesSeedData.cs (ONCE per application)
|
|
8
|
+
|
|
9
|
+
**File:** `Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs`
|
|
10
|
+
|
|
11
|
+
**Purpose:** Defines the 4 standard application-scoped roles (Admin, Manager, Contributor, Viewer) with valid `Code` values.
|
|
12
|
+
|
|
13
|
+
**CRITICAL:** Without this file, role-permission mappings in `SeedRolePermissionsAsync()` will fail silently because `roles.FirstOrDefault(r => r.Code == mapping.RoleCode)` will return null.
|
|
14
|
+
|
|
15
|
+
See [references/application-roles-template.md](../references/application-roles-template.md) for the complete template.
|
|
16
|
+
|
|
17
|
+
**Key requirements:**
|
|
18
|
+
- Deterministic GUIDs based on `role-{applicationId}-{roleType}`
|
|
19
|
+
- 4 roles: Admin, Manager, Contributor, Viewer
|
|
20
|
+
- Each role has a valid `Code` property ("admin", "manager", "contributor", "viewer")
|
|
21
|
+
- `ApplicationId` references the navigation application GUID
|
|
22
|
+
- `IsSystem = false` (application-scoped, not system roles)
|
|
23
|
+
|
|
24
|
+
**Detection:** Check if ApplicationRolesSeedData.cs exists. If yes, skip creation (already exists from Module 1). If no, create it.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## {Module}RolePermissionSeedData.cs (PER module)
|
|
29
|
+
|
|
30
|
+
**File:** `Infrastructure/Persistence/Seeding/Data/{Domain}/{Module}RolePermissionSeedData.cs`
|
|
31
|
+
|
|
32
|
+
**Purpose:** Maps permissions to roles by Code (e.g., "admin" → "{navRoute}.*").
|
|
33
|
+
|
|
34
|
+
Content: static class with method `GetRolePermissionEntries()` that returns the role-permission mapping data.
|
|
35
|
+
These entries will be consumed by the `IClientSeedDataProvider` at step 03b.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Default Role Mapping Table
|
|
40
|
+
|
|
41
|
+
Based on navigation application prefix:
|
|
42
|
+
|
|
43
|
+
| Application prefix | PlatformAdmin | TenantAdmin | StandardUser |
|
|
44
|
+
|---------|---------------|-------------|--------------|
|
|
45
|
+
| `administration.*` | Full CRUD | Read only | None |
|
|
46
|
+
| `*` (business apps) | Full CRUD | Full CRUD | Read only |
|
|
47
|
+
| `myspace.*` | None | Full CRUD | Full CRUD |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Summary
|
|
52
|
+
|
|
53
|
+
After creating both files:
|
|
54
|
+
- Proceed to step-03b-provider.md (which will skip for core projects)
|
|
55
|
+
- The provider will consume these SeedData files to seed roles and permissions at runtime
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Role-Permission Generation: Fallback Procedure (When MCP Unavailable)
|
|
2
|
+
|
|
3
|
+
> Reference for step-03-roles.md — Generates role-permission HasData entries following SmartStack.app patterns.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## F1. Read Existing RolePermissionConfiguration.cs
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Glob: **/Persistence/Configurations/Authorization/RolePermissionConfiguration.cs
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Read the file to determine:
|
|
14
|
+
- Existing role-permission mappings
|
|
15
|
+
- The GetSeedData() method structure
|
|
16
|
+
- Which roles already have which permissions
|
|
17
|
+
- The GUID generation method used (deterministic or hardcoded)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## F2. Read Role GUIDs
|
|
22
|
+
|
|
23
|
+
**System-level roles** (well-known GUIDs):
|
|
24
|
+
|
|
25
|
+
| Role | GUID |
|
|
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` |
|
|
31
|
+
|
|
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
|
+
|
|
34
|
+
**Application-scoped roles** (deterministic GUIDs based on application):
|
|
35
|
+
|
|
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"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Find the `applicationId` from `NavigationApplicationSeedData.cs` matching `{full_path}`.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## F3. Determine Application-Based Default Mappings
|
|
54
|
+
|
|
55
|
+
Based on `{full_path}` application prefix:
|
|
56
|
+
|
|
57
|
+
| Application Prefix | SuperAdmin | PlatformAdmin | App Admin | App Manager | App Contributor | App Viewer |
|
|
58
|
+
|----------------|------------|---------------|-----------|-------------|-----------------|------------|
|
|
59
|
+
| `administration.*` | wildcard | Full CRUD | Full CRUD | CRU | CR | R |
|
|
60
|
+
| `*` (business apps) | wildcard | Full CRUD | Full CRUD | CRU | CR | R |
|
|
61
|
+
| `myspace.*` | wildcard | None | Full CRUD | CRU | CR | R |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## F4. Generate RolePermission HasData Entries
|
|
66
|
+
|
|
67
|
+
Using `{permission_guids}` from step-02:
|
|
68
|
+
|
|
69
|
+
```csharp
|
|
70
|
+
// In RolePermissionConfiguration.cs - GetSeedData() method
|
|
71
|
+
var seedDate = SeedConstants.SeedDate;
|
|
72
|
+
|
|
73
|
+
// ============================================================
|
|
74
|
+
// {MODULE_NAME} PERMISSIONS
|
|
75
|
+
// ============================================================
|
|
76
|
+
|
|
77
|
+
// SuperAdmin: already has *.* wildcard - no individual entries needed
|
|
78
|
+
|
|
79
|
+
// PlatformAdmin (for platform.* context)
|
|
80
|
+
rolePermissions.Add(new { RoleId = platformAdminRoleId, PermissionId = {permission_guids.read}, AssignedAt = seedDate });
|
|
81
|
+
rolePermissions.Add(new { RoleId = platformAdminRoleId, PermissionId = {permission_guids.create}, AssignedAt = seedDate });
|
|
82
|
+
rolePermissions.Add(new { RoleId = platformAdminRoleId, PermissionId = {permission_guids.update}, AssignedAt = seedDate });
|
|
83
|
+
rolePermissions.Add(new { RoleId = platformAdminRoleId, PermissionId = {permission_guids.delete}, AssignedAt = seedDate });
|
|
84
|
+
|
|
85
|
+
// Application-scoped: Admin → wildcard
|
|
86
|
+
rolePermissions.Add(new { RoleId = appAdminRoleId, PermissionId = {permission_guids.wildcard}, AssignedAt = seedDate });
|
|
87
|
+
|
|
88
|
+
// Application-scoped: Manager → CRU (read + create + update — no delete)
|
|
89
|
+
rolePermissions.Add(new { RoleId = appManagerRoleId, PermissionId = {permission_guids.read}, AssignedAt = seedDate });
|
|
90
|
+
rolePermissions.Add(new { RoleId = appManagerRoleId, PermissionId = {permission_guids.create}, AssignedAt = seedDate });
|
|
91
|
+
rolePermissions.Add(new { RoleId = appManagerRoleId, PermissionId = {permission_guids.update}, AssignedAt = seedDate });
|
|
92
|
+
|
|
93
|
+
// Application-scoped: Contributor → CR
|
|
94
|
+
rolePermissions.Add(new { RoleId = appContributorRoleId, PermissionId = {permission_guids.read}, AssignedAt = seedDate });
|
|
95
|
+
rolePermissions.Add(new { RoleId = appContributorRoleId, PermissionId = {permission_guids.create}, AssignedAt = seedDate });
|
|
96
|
+
|
|
97
|
+
// Application-scoped: Viewer → R
|
|
98
|
+
rolePermissions.Add(new { RoleId = appViewerRoleId, PermissionId = {permission_guids.read}, AssignedAt = seedDate });
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## F5. Write Code to RolePermissionConfiguration.cs
|
|
104
|
+
|
|
105
|
+
**CRITICAL:** Do NOT just display code. WRITE it to the actual file.
|
|
106
|
+
|
|
107
|
+
1. Open `RolePermissionConfiguration.cs`
|
|
108
|
+
2. Find the `GetSeedData()` method
|
|
109
|
+
3. Add the new role-permission entries to the list
|
|
110
|
+
4. Add necessary permission GUID references (import from PermissionConfiguration or use inline)
|
|
111
|
+
5. Add comments grouping the new entries: `// {MODULE_NAME} PERMISSIONS`
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## F6. Present Summary
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
## Role-Permission Mappings Generated (Fallback)
|
|
119
|
+
|
|
120
|
+
| Role | Permissions |
|
|
121
|
+
|------|-------------|
|
|
122
|
+
| SuperAdmin | Already has wildcard access |
|
|
123
|
+
| PlatformAdmin | {full_path}.read, .create, .update, .delete |
|
|
124
|
+
| App Admin | {full_path}.* (wildcard) |
|
|
125
|
+
| App Manager | {full_path}.read, .create, .update |
|
|
126
|
+
| App Contributor | {full_path}.read, .create |
|
|
127
|
+
| App Viewer | {full_path}.read |
|
|
128
|
+
|
|
129
|
+
Written to: RolePermissionConfiguration.cs
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## F7. Offer User Adjustment
|
|
135
|
+
|
|
136
|
+
If user selects "Custom adjustments", ask which roles/permissions to change and update the file accordingly.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Validation Checklist
|
|
141
|
+
|
|
142
|
+
Before marking as completed, verify:
|
|
143
|
+
|
|
144
|
+
- [ ] All role GUIDs correctly identified (system and application-scoped)
|
|
145
|
+
- [ ] Role-permission mappings follow application hierarchy
|
|
146
|
+
- [ ] Code WRITTEN to files (not just displayed)
|
|
147
|
+
- [ ] Permission GUID references correct
|
|
148
|
+
- [ ] Comments added for module grouping
|
|
149
|
+
- [ ] No gaps or missing permissions
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Test Generation: Coverage Requirements & Categories
|
|
2
|
+
|
|
3
|
+
> Referenced from `steps/step-07-tests.md` — Test coverage minimums and category definitions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Minimum Test Coverage Per Category
|
|
8
|
+
|
|
9
|
+
| Category | Minimum Tests | Focus Areas |
|
|
10
|
+
|----------|---------------|------------|
|
|
11
|
+
| Controller (mock) | 10 | CRUD routing, auth/tenant handling, error responses |
|
|
12
|
+
| Controller (real integration) | 8 | CRUD with actual DB persistence, tenant isolation, 404/409 cases |
|
|
13
|
+
| Service | 8 | Business logic, CRUD, error handling, edge cases |
|
|
14
|
+
| Entity | 5 | Factory method, property updates, validation, soft delete |
|
|
15
|
+
| Validator | 8 | Code validation, name validation, security rules |
|
|
16
|
+
| Repository | 8 | CRUD, tenant filtering, pagination, indexes |
|
|
17
|
+
| Security | 10 | Auth bypass attempts, injection attacks, header validation |
|
|
18
|
+
|
|
19
|
+
**Total minimum:** ~67 tests per entity
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Real Integration Test Coverage
|
|
24
|
+
|
|
25
|
+
Integration tests (with actual DB):
|
|
26
|
+
- GET all → 200 with list
|
|
27
|
+
- GET by ID → 200 when exists, 404 when not
|
|
28
|
+
- POST → 201/200 when valid, persist to DB, read back to verify
|
|
29
|
+
- POST → 400 when invalid data
|
|
30
|
+
- POST → 409 when duplicate code
|
|
31
|
+
- PUT → 200 when valid, persist changes, read back to verify
|
|
32
|
+
- PUT → 404 when not exists
|
|
33
|
+
- DELETE → 204 when exists
|
|
34
|
+
- DELETE → 404 when not exists
|
|
35
|
+
- Tenant isolation → create in tenant A, invisible in tenant B (REAL DB)
|
|
36
|
+
- Authorization → 401 when not authenticated
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Test Naming Convention (BLOCKING)
|
|
41
|
+
|
|
42
|
+
All test methods MUST follow: `{Method}_When{Condition}_Should{Result}`
|
|
43
|
+
|
|
44
|
+
**FORBIDDEN patterns:**
|
|
45
|
+
- `Test1`, `Test2`, `TestMethod`, `MyTest`
|
|
46
|
+
- `Should_Return_OK`, `test_get_all`
|
|
47
|
+
|
|
48
|
+
**REQUIRED pattern:**
|
|
49
|
+
```csharp
|
|
50
|
+
GetAll_WhenCalled_ShouldReturn200WithList
|
|
51
|
+
Create_WhenDuplicateCode_ShouldThrowException
|
|
52
|
+
Delete_WhenNotAuthenticated_ShouldReturn401
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Test Structure (BLOCKING)
|
|
58
|
+
|
|
59
|
+
All tests MUST follow Arrange-Act-Assert:
|
|
60
|
+
|
|
61
|
+
```csharp
|
|
62
|
+
// CORRECT
|
|
63
|
+
[Fact]
|
|
64
|
+
public async Task GetById_WhenExists_ShouldReturn200()
|
|
65
|
+
{
|
|
66
|
+
// Arrange
|
|
67
|
+
var id = Guid.NewGuid();
|
|
68
|
+
// ... setup
|
|
69
|
+
|
|
70
|
+
// Act
|
|
71
|
+
var response = await _client.GetAsync($"/api/{entityCode}/{id}");
|
|
72
|
+
|
|
73
|
+
// Assert
|
|
74
|
+
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// FORBIDDEN - No structure
|
|
78
|
+
[Fact]
|
|
79
|
+
public void TestGetById()
|
|
80
|
+
{
|
|
81
|
+
var response = _client.GetAsync("/api/product/1");
|
|
82
|
+
Assert.Equal(200, response.StatusCode);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Dependencies Check (BLOCKING)
|
|
89
|
+
|
|
90
|
+
Verify test project uses:
|
|
91
|
+
- `FluentAssertions` (NOT `Assert.Equal`)
|
|
92
|
+
- `Moq` (NOT manual fakes)
|
|
93
|
+
- `xunit` (NOT NUnit or MSTest)
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Test Categories
|
|
98
|
+
|
|
99
|
+
### 1. Controller Mock Tests
|
|
100
|
+
|
|
101
|
+
Unit tests with mocked dependencies:
|
|
102
|
+
- Routing validation
|
|
103
|
+
- Authentication/Authorization
|
|
104
|
+
- Error response formatting
|
|
105
|
+
- Input validation
|
|
106
|
+
|
|
107
|
+
```csharp
|
|
108
|
+
[Fact]
|
|
109
|
+
public async Task GetAll_WhenCalled_ShouldReturn200WithList()
|
|
110
|
+
{
|
|
111
|
+
// Mock service
|
|
112
|
+
_mockService.Setup(s => s.GetAllAsync(It.IsAny<CancellationToken>()))
|
|
113
|
+
.ReturnsAsync(new List<ProductDto>());
|
|
114
|
+
|
|
115
|
+
// Act & Assert
|
|
116
|
+
...
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 2. Controller Integration Tests
|
|
121
|
+
|
|
122
|
+
REAL tests with actual DB (via WebApplicationFactory):
|
|
123
|
+
- Full HTTP flow
|
|
124
|
+
- Database persistence
|
|
125
|
+
- Tenant isolation
|
|
126
|
+
- Query validation
|
|
127
|
+
|
|
128
|
+
### 3. Service Tests
|
|
129
|
+
|
|
130
|
+
Unit tests for business logic:
|
|
131
|
+
- CRUD operations
|
|
132
|
+
- Error handling
|
|
133
|
+
- Validation logic
|
|
134
|
+
|
|
135
|
+
### 4. Entity Tests
|
|
136
|
+
|
|
137
|
+
Domain model tests:
|
|
138
|
+
- Factory methods
|
|
139
|
+
- Property validation
|
|
140
|
+
- State transitions
|
|
141
|
+
- Soft delete
|
|
142
|
+
|
|
143
|
+
### 5. Validator Tests
|
|
144
|
+
|
|
145
|
+
Input validation:
|
|
146
|
+
- Code format validation
|
|
147
|
+
- Name constraints
|
|
148
|
+
- Security rules (XSS, SQL injection detection)
|
|
149
|
+
|
|
150
|
+
### 6. Repository Tests
|
|
151
|
+
|
|
152
|
+
Data access tests:
|
|
153
|
+
- Query correctness
|
|
154
|
+
- Tenant filtering
|
|
155
|
+
- Pagination
|
|
156
|
+
- Indexes
|
|
157
|
+
|
|
158
|
+
### 7. Security Tests
|
|
159
|
+
|
|
160
|
+
OWASP coverage:
|
|
161
|
+
- Authentication bypass attempts
|
|
162
|
+
- Authorization bypass attempts
|
|
163
|
+
- SQL injection attempts
|
|
164
|
+
- XSS payload handling
|
|
165
|
+
- CSRF token validation
|
|
166
|
+
- Tenant isolation breach attempts
|
|
167
|
+
- Header injection attempts
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Build & Run Checks (BLOCKING)
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Build
|
|
175
|
+
dotnet build tests/{SolutionName}.Tests/{SolutionName}.Tests.csproj
|
|
176
|
+
|
|
177
|
+
# Run
|
|
178
|
+
dotnet test tests/{SolutionName}.Tests/{SolutionName}.Tests.csproj --no-build --verbosity normal
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**ALL tests MUST pass.** If tests fail:
|
|
182
|
+
1. Read the failure output carefully
|
|
183
|
+
2. Fix the failing tests or the code they test
|
|
184
|
+
3. Re-run until all tests pass
|
|
185
|
+
4. Do NOT proceed to the next step until all tests are green
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Frontend Test Categories
|
|
190
|
+
|
|
191
|
+
| File | Category | Focus |
|
|
192
|
+
|------|----------|-------|
|
|
193
|
+
| `{EntityName}Page.test.tsx` | Page | Loading, error, render with data |
|
|
194
|
+
| `{EntityName}ListView.test.tsx` | List | Pagination, filtering, view toggle |
|
|
195
|
+
| `{EntityName}DetailPage.test.tsx` | Detail | Tab switching, back navigation |
|
|
196
|
+
| `use{EntityName}Preferences.test.ts` | Hooks | State persistence, local storage |
|
|
197
|
+
| `{entityName}Api.test.ts` | API Client | MSW mocking, HTTP methods |
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Validation Checklist
|
|
202
|
+
|
|
203
|
+
- [ ] All test methods follow `{Method}_When{Condition}_Should{Result}` naming
|
|
204
|
+
- [ ] All tests use Arrange-Act-Assert structure
|
|
205
|
+
- [ ] FluentAssertions used throughout (not Assert.Equal)
|
|
206
|
+
- [ ] Moq used for mock-based tests only
|
|
207
|
+
- [ ] Minimum test count met per category
|
|
208
|
+
- [ ] Real integration tests verify DB persistence
|
|
209
|
+
- [ ] Security tests cover OWASP top 10 issues
|
|
210
|
+
- [ ] Backend tests build successfully
|
|
211
|
+
- [ ] **ALL backend tests pass**
|
|
212
|
+
- [ ] Frontend tests build successfully
|
|
213
|
+
- [ ] **ALL frontend tests pass**
|
|
@@ -53,9 +53,9 @@ Args:
|
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
This generates:
|
|
56
|
-
- `src/pages/{
|
|
57
|
-
- `src/pages/{
|
|
58
|
-
- `src/pages/{
|
|
56
|
+
- `src/pages/{application}/__tests__/{EntityName}Page.test.tsx` - Page rendering, loading, error states
|
|
57
|
+
- `src/pages/{application}/__tests__/{EntityName}ListView.test.tsx` - List display, pagination, view toggle
|
|
58
|
+
- `src/pages/{application}/__tests__/{EntityName}DetailPage.test.tsx` - Detail view, tabs, back navigation
|
|
59
59
|
- `src/hooks/__tests__/use{EntityName}Preferences.test.ts` - Preference get/set
|
|
60
60
|
- `src/services/api/__tests__/{entityName}Api.test.ts` - API client calls with MSW
|
|
61
61
|
|