@atlashub/smartstack-cli 4.74.0 → 4.75.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 +111 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +14 -3
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/ba-reader.md +17 -15
- package/templates/agents/ba-writer.md +49 -51
- package/templates/skills/apex/_shared.md +1 -1
- package/templates/skills/apex/references/checks/backend-checks.sh +21 -7
- package/templates/skills/apex/references/checks/infrastructure-checks.sh +47 -10
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/apex/references/post-checks.md +5 -2
- package/templates/skills/apex/references/smartstack-frontend.md +53 -7
- package/templates/skills/apex/steps/step-00-init.md +74 -0
- package/templates/skills/apex/steps/step-03-execute.md +16 -4
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +39 -6
- package/templates/skills/apex/steps/step-03c-layer2-backend.md +50 -5
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +102 -2
- package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +3 -0
- package/templates/skills/business-analyse/SKILL.md +14 -0
- package/templates/skills/business-analyse/_shared.md +27 -0
- package/templates/skills/business-analyse/patterns/suggestion-catalog.md +34 -26
- package/templates/skills/business-analyse/questionnaire/01-context.md +13 -9
- package/templates/skills/business-analyse/questionnaire/02-stakeholders-scope.md +20 -27
- package/templates/skills/business-analyse/questionnaire.md +86 -9
- package/templates/skills/business-analyse/references/03-json-schemas.md +213 -0
- package/templates/skills/business-analyse/references/03-post-check-validation.md +144 -0
- package/templates/skills/business-analyse/references/03-smartstack-entity-guards.md +32 -0
- package/templates/skills/business-analyse/references/04-cross-module-validation.md +95 -0
- package/templates/skills/business-analyse/references/04-file-allocation.md +162 -0
- package/templates/skills/business-analyse/references/04-naming-audit-checks.md +174 -0
- package/templates/skills/business-analyse/references/04-semantic-validation-matrix.md +118 -0
- package/templates/skills/business-analyse/references/domain-research-playbook.md +234 -0
- package/templates/skills/business-analyse/references/entity-sourcing-presentation.md +166 -0
- package/templates/skills/business-analyse/references/init-resume-logic.md +70 -0
- package/templates/skills/business-analyse/references/module-completeness-challenge.md +174 -0
- package/templates/skills/business-analyse/references/multi-app-detection.md +149 -0
- package/templates/skills/business-analyse/references/portal-classification.md +52 -0
- package/templates/skills/business-analyse/references/validation-checklist.md +30 -1
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +37 -4
- package/templates/skills/business-analyse/steps/step-00-init.md +22 -190
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +365 -269
- package/templates/skills/business-analyse/steps/step-02-structure.md +98 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +652 -229
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +308 -287
- package/templates/skills/business-analyse-design/SKILL.md +10 -0
- package/templates/skills/business-analyse-design/references/screens-post-check.md +221 -0
- package/templates/skills/business-analyse-design/references/screens-type-mapping.md +138 -0
- package/templates/skills/business-analyse-design/references/smartcomponents-templates.md +225 -0
- package/templates/skills/{business-analyse → business-analyse-design}/references/spec-auto-inference.md +117 -117
- package/templates/skills/business-analyse-design/steps/step-01-screens.md +36 -162
- package/templates/skills/business-analyse-design/steps/step-02-wireframes.md +8 -7
- package/templates/skills/business-analyse-design/steps/step-03-navigation.md +89 -42
- package/templates/skills/business-analyse-develop/references/compact-loop.md +9 -0
- package/templates/skills/business-analyse-develop/references/handoff-quality-gate.md +132 -0
- package/templates/skills/business-analyse-develop/references/prd-v3-transformation.md +326 -0
- package/templates/skills/business-analyse-develop/references/report-reconciliation.md +140 -0
- package/templates/skills/business-analyse-develop/references/report-template.md +142 -0
- package/templates/skills/business-analyse-develop/steps/step-01-task.md +5 -177
- package/templates/skills/business-analyse-develop/steps/step-02-execute.md +17 -4
- package/templates/skills/business-analyse-develop/steps/step-03-commit.md +6 -2
- package/templates/skills/business-analyse-develop/steps/step-04-check.md +6 -0
- package/templates/skills/business-analyse-develop/steps/step-05-report.md +3 -269
- package/templates/skills/business-analyse-handoff/SKILL.md +10 -0
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +208 -0
- package/templates/skills/business-analyse-handoff/references/context-isolation-pattern.md +47 -0
- package/templates/skills/business-analyse-handoff/references/handoff-file-inventory.md +49 -0
- package/templates/skills/business-analyse-handoff/references/handoff-global-validation.md +142 -0
- package/templates/skills/business-analyse-handoff/references/prd-validation-checks.md +125 -0
- package/templates/skills/business-analyse-handoff/references/project-index-update.md +98 -0
- package/templates/skills/business-analyse-handoff/steps/step-01-transform.md +9 -160
- package/templates/skills/business-analyse-handoff/steps/step-02-export.md +10 -99
- package/templates/skills/business-analyse-html/SKILL.md +10 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +306 -81
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +15 -2
- package/templates/skills/business-analyse-html/html/src/scripts/02-navigation.js +6 -46
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +88 -33
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +116 -0
- package/templates/skills/business-analyse-html/html/src/styles/10-diagrams.css +73 -0
- package/templates/skills/business-analyse-html/html/src/template.html +2 -0
- package/templates/skills/business-analyse-html/references/02-embedded-artifacts-building.md +144 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +141 -0
- package/templates/skills/business-analyse-html/references/02-mapping-tables.md +442 -0
- package/templates/skills/business-analyse-html/references/02-normalization-helpers.md +139 -0
- package/templates/skills/business-analyse-html/references/02-screen-format-detection.md +283 -0
- package/templates/skills/business-analyse-html/references/02-self-check-validation.md +199 -0
- package/templates/skills/business-analyse-html/references/data-build.md +22 -1
- package/templates/skills/business-analyse-html/references/data-mapping.md +40 -5
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +12 -555
- package/templates/skills/business-analyse-review/SKILL.md +10 -0
- package/templates/skills/business-analyse-status/SKILL.md +8 -0
- package/templates/skills/dev-start/SKILL.md +143 -307
- package/templates/skills/efcore/SKILL.md +13 -0
package/package.json
CHANGED
|
@@ -12,9 +12,10 @@ You are a business analysis reader agent specialized in extracting and synthesiz
|
|
|
12
12
|
|
|
13
13
|
Read index.json and thematic JSON files at both application-level and module-level, and provide structured answers, context summaries, or cross-feature insights. Support discovery, documentation, and skill orchestration.
|
|
14
14
|
|
|
15
|
-
**File locations:**
|
|
16
|
-
-
|
|
17
|
-
-
|
|
15
|
+
**File locations (ba-006):**
|
|
16
|
+
- Project-level: `docs/{projectSlug}/v{X.Y}/index.json` + thematic files
|
|
17
|
+
- Application-level: `docs/{projectSlug}/v{X.Y}/{appKebab}/index.json` + thematic files
|
|
18
|
+
- Module-level: `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/index.json` + thematic files
|
|
18
19
|
|
|
19
20
|
## Core Operations
|
|
20
21
|
|
|
@@ -27,12 +28,12 @@ Locate a feature by ID and return its latest version path (index.json).
|
|
|
27
28
|
- Optional: scope ("application" | "module" | "any") — default: "any"
|
|
28
29
|
|
|
29
30
|
**Process:**
|
|
30
|
-
1. Glob pattern: `docs
|
|
31
|
+
1. Glob pattern: `docs/*/v*/index.json` AND `docs/*/v*/*/*/index.json` (project + module levels)
|
|
31
32
|
2. Read each index.json and check id field
|
|
32
33
|
3. If scope filter provided, also check scope field
|
|
33
34
|
4. If multiple versions exist, sort numerically by version
|
|
34
35
|
5. Return highest matching version path
|
|
35
|
-
6. If not found, check legacy
|
|
36
|
+
6. If not found, check legacy `docs/**/business-analyse/*/index.json` format
|
|
36
37
|
|
|
37
38
|
**Output:**
|
|
38
39
|
- Full path to index.json
|
|
@@ -49,7 +50,7 @@ Locate the master (application-level) index.json for a given app.
|
|
|
49
50
|
- OR featureId: FEAT-NNN
|
|
50
51
|
|
|
51
52
|
**Process:**
|
|
52
|
-
1. Glob: `docs
|
|
53
|
+
1. Glob: `docs/*/v*/{appKebab}/index.json` (where appKebab = toKebabCase(app))
|
|
53
54
|
2. Read and verify scope = "application"
|
|
54
55
|
3. Return latest version path
|
|
55
56
|
|
|
@@ -244,8 +245,8 @@ Get the highest version number for a feature or module.
|
|
|
244
245
|
|
|
245
246
|
**Process:**
|
|
246
247
|
1. Glob paths:
|
|
247
|
-
- Single feature: `docs
|
|
248
|
-
- Module: `docs
|
|
248
|
+
- Single feature: `docs/*/v*/index.json` AND `docs/*/v*/*/*/index.json` filtered by ID
|
|
249
|
+
- Module: `docs/*/v*/{appKebab}/{moduleKebab}/index.json`
|
|
249
250
|
2. Extract version numbers from index.json files (v1.0, v1.5, v2.1, etc.)
|
|
250
251
|
3. Sort numerically
|
|
251
252
|
4. Return highest version path and number
|
|
@@ -322,14 +323,14 @@ Generate compact context for use by other skills and agents.
|
|
|
322
323
|
|
|
323
324
|
## Search Priority
|
|
324
325
|
|
|
325
|
-
When searching for feature data:
|
|
326
|
+
When searching for feature data (ba-006 paths):
|
|
326
327
|
|
|
327
|
-
1. **Primary (
|
|
328
|
-
2. **Primary (
|
|
329
|
-
3. **
|
|
330
|
-
|
|
328
|
+
1. **Primary (project/app):** `docs/*/v*/index.json` (scope: project or application)
|
|
329
|
+
2. **Primary (app in multi-app):** `docs/*/v*/*/index.json` (scope: application within project)
|
|
330
|
+
3. **Primary (module):** `docs/*/v*/*/*/index.json` (scope: module)
|
|
331
|
+
4. **Fallback:** `docs/**/business-analyse/*/index.json` (legacy pre-ba-006 format)
|
|
331
332
|
- Warn user about old format
|
|
332
|
-
- Suggest
|
|
333
|
+
- Suggest re-running /business-analyse to migrate
|
|
333
334
|
|
|
334
335
|
## Cross-Reference Resolution
|
|
335
336
|
|
|
@@ -347,9 +348,10 @@ When encountering ID references, resolve them by reading appropriate thematic fi
|
|
|
347
348
|
|
|
348
349
|
## Error Handling
|
|
349
350
|
|
|
351
|
+
- **EISDIR (directory path passed to Read):** NEVER use the Read tool on a directory path. If a path does not end with `.json` or a known file extension, use Glob to list its contents first, then Read specific files. This is the #1 source of silent failures.
|
|
350
352
|
- If featureId not found: suggest similar IDs or search for feature by keyword
|
|
351
353
|
- If legacy format detected: show warning and offer to display legacy content
|
|
352
|
-
- If thematic file not found: list available thematic files in the feature version directory
|
|
354
|
+
- If thematic file not found: list available thematic files in the feature version directory (use Glob, NOT Read)
|
|
353
355
|
- If version not found: list available versions
|
|
354
356
|
- Return helpful suggestions for refinement
|
|
355
357
|
|
|
@@ -12,10 +12,10 @@ You are a business analysis writer agent specialized in managing granular JSON f
|
|
|
12
12
|
|
|
13
13
|
Write and update granular JSON files for project-level (multi-app), application-level (master), and module-level documents. Handle progressive enrichment of features as they move through analysis phases, manage versioning for refactoring, and enforce schema consistency.
|
|
14
14
|
|
|
15
|
-
**Directory structure (3-tier hierarchy):**
|
|
16
|
-
- Project-level (multi-app only): `docs/
|
|
17
|
-
- Application-level: `docs/{
|
|
18
|
-
- Module-level: `docs/{
|
|
15
|
+
**Directory structure (ba-006, 3-tier hierarchy):**
|
|
16
|
+
- Project-level (multi-app only): `docs/{projectSlug}/v{X.Y}/index.json` + thematic files
|
|
17
|
+
- Application-level: `docs/{projectSlug}/v{X.Y}/{appKebab}/index.json` + thematic files
|
|
18
|
+
- Module-level: `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/index.json` + thematic files
|
|
19
19
|
|
|
20
20
|
**Thematic files (v2 granular architecture):**
|
|
21
21
|
- `index.json` — metadata, version, hash manifest, module registry (ALL scopes)
|
|
@@ -31,7 +31,7 @@ Write and update granular JSON files for project-level (multi-app), application-
|
|
|
31
31
|
- `handoff.json` — complexity, file catalog, BR-to-code mapping (**MODULE ONLY**)
|
|
32
32
|
- `review.json` — preserved review comments and change summary (ALL scopes)
|
|
33
33
|
|
|
34
|
-
> **
|
|
34
|
+
> **Single-app mode:** If only 1 application, the project level is NOT created. The application-level index.json at `docs/{projectSlug}/v{X.Y}/index.json` remains the master.
|
|
35
35
|
|
|
36
36
|
## Core Operations
|
|
37
37
|
|
|
@@ -48,10 +48,11 @@ Create initial index.json and empty thematic files with metadata and draft statu
|
|
|
48
48
|
**Process:**
|
|
49
49
|
1. Read `.business-analyse/config.json` to get lastFeatureId (or lastProjectId for scope = "project")
|
|
50
50
|
2. Increment FEAT-NNN (or PROJ-NNN) identifier
|
|
51
|
-
3. Create directory structure based on scope:
|
|
52
|
-
- If scope = "project": `docs/
|
|
53
|
-
- If scope = "application": `docs/{
|
|
54
|
-
- If scope = "module": `docs/{
|
|
51
|
+
3. Create directory structure based on scope (ba-006 paths — NO `business-analyse/` intermediate directory):
|
|
52
|
+
- If scope = "project": `docs/{projectSlug}/v1.0/`
|
|
53
|
+
- If scope = "application": `docs/{projectSlug}/v{X.Y}/{appKebab}/`
|
|
54
|
+
- If scope = "module": `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/`
|
|
55
|
+
**IMPORTANT:** Use Bash `mkdir -p` to create directories before writing files.
|
|
55
56
|
4. Generate index.json with:
|
|
56
57
|
- **`$schema`**: relative path to the deployed schema file (MANDATORY — see $schema rules below)
|
|
57
58
|
- id: FEAT-NNN (from config)
|
|
@@ -74,7 +75,7 @@ Create initial index.json and empty thematic files with metadata and draft statu
|
|
|
74
75
|
a. Read master index.json (via applicationRef FEAT-NNN)
|
|
75
76
|
b. Find module in modules[] where code === moduleCode
|
|
76
77
|
c. Set module.indexJsonPath to the relative path of the created index.json
|
|
77
|
-
(relative from
|
|
78
|
+
(relative from project root, e.g. "{appKebab}/{moduleKebab}/index.json")
|
|
78
79
|
d. Update master index.json with new module reference
|
|
79
80
|
8. Return feature ID, path, and confirmation
|
|
80
81
|
|
|
@@ -100,9 +101,9 @@ Create a project-level index.json for multi-application analysis. Only used when
|
|
|
100
101
|
**Process:**
|
|
101
102
|
1. Read `.business-analyse/config.json` to get lastProjectId (default: 0)
|
|
102
103
|
2. Increment PROJ-NNN identifier
|
|
103
|
-
3. Create directory: `docs/
|
|
104
|
+
3. Create directory: `docs/{projectSlug}/v1.0/` (use Bash `mkdir -p`)
|
|
104
105
|
4. Generate index.json with:
|
|
105
|
-
- `$schema`: `"
|
|
106
|
+
- `$schema`: `"schemas/project-schema.json"`
|
|
106
107
|
- id: PROJ-NNN
|
|
107
108
|
- version: "1.0"
|
|
108
109
|
- status: "draft"
|
|
@@ -114,7 +115,7 @@ Create a project-level index.json for multi-application analysis. Only used when
|
|
|
114
115
|
5. Create thematic files — **EXACTLY 3 files, NO OTHERS:** cadrage.json, validation.json, consolidation.json
|
|
115
116
|
**FORBIDDEN at project level:** entities.json, rules.json, usecases.json, permissions.json, screens.json, handoff.json — these exist ONLY at module level.
|
|
116
117
|
6. Update `.business-analyse/config.json` with new lastProjectId
|
|
117
|
-
7. Deploy schemas to `docs/
|
|
118
|
+
7. Deploy schemas to `docs/{projectSlug}/v{X.Y}/schemas/` (including project-schema.json)
|
|
118
119
|
8. Return project ID (PROJ-NNN) and path
|
|
119
120
|
|
|
120
121
|
### enrichApplicationRegistry
|
|
@@ -521,38 +522,31 @@ Perform these structural checks before every write:
|
|
|
521
522
|
- OPTIONAL: `indexJsonPath`
|
|
522
523
|
- FORBIDDEN: missing `dependencies`/`dependents`/`sortOrder`
|
|
523
524
|
|
|
524
|
-
## Directory Structure
|
|
525
|
+
## Directory Structure (ba-006)
|
|
525
526
|
|
|
526
527
|
```
|
|
527
|
-
docs/
|
|
528
|
-
|
|
529
|
-
index.json ← PROJECT metadata
|
|
528
|
+
docs/{projectSlug}/
|
|
529
|
+
v{X.Y}/
|
|
530
|
+
index.json ← PROJECT metadata (or APPLICATION if single-app)
|
|
530
531
|
cadrage.json
|
|
531
532
|
validation.json
|
|
532
533
|
consolidation.json
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
v1.0/
|
|
546
|
-
index.json ← MODULE metadata
|
|
547
|
-
entities.json
|
|
548
|
-
rules.json
|
|
549
|
-
usecases.json
|
|
550
|
-
permissions.json
|
|
551
|
-
screens.json
|
|
552
|
-
validation.json
|
|
553
|
-
handoff.json
|
|
534
|
+
schemas/ ← Deployed JSON schemas
|
|
535
|
+
{appKebab}/ ← Application directory (kebab-case)
|
|
536
|
+
index.json ← APPLICATION metadata
|
|
537
|
+
{moduleKebab}/ ← Module directory (kebab-case)
|
|
538
|
+
index.json ← MODULE metadata
|
|
539
|
+
entities.json
|
|
540
|
+
rules.json
|
|
541
|
+
usecases.json
|
|
542
|
+
permissions.json
|
|
543
|
+
screens.json
|
|
544
|
+
validation.json
|
|
545
|
+
handoff.json
|
|
554
546
|
```
|
|
555
547
|
|
|
548
|
+
> **No `business-analyse/` intermediate directory.** All data lives directly under `docs/{projectSlug}/v{X.Y}/`.
|
|
549
|
+
|
|
556
550
|
Versions are stored as separate directories. Each directory contains index.json + thematic files.
|
|
557
551
|
|
|
558
552
|
## Hash Manifest (index.json fileHashes)
|
|
@@ -639,6 +633,7 @@ Before EVERY enrichSection() call for specification or handoff sections, validat
|
|
|
639
633
|
7. **Timestamp management** - always set metadata.updatedAt to current ISO timestamp on write
|
|
640
634
|
8. **Idempotency** - calling the same operation twice with same data should produce same result
|
|
641
635
|
9. **Hash updates** - calculate and store MD5 hash for every thematic file write
|
|
636
|
+
10. **Directory creation** - Before writing ANY file, verify parent directory exists. If not, create it with `mkdir -p` via the Bash tool. The Write tool does NOT create parent directories automatically. This is CRITICAL — skipping this step causes silent write failures.
|
|
642
637
|
|
|
643
638
|
## File Size Management (CRITICAL)
|
|
644
639
|
|
|
@@ -677,6 +672,7 @@ if (estimatedNewSize > 500 * 1024) { // 500KB
|
|
|
677
672
|
|
|
678
673
|
## Error Handling
|
|
679
674
|
|
|
675
|
+
- **EISDIR prevention:** Before any Read operation, verify the path points to a FILE (ends with `.json`), not a directory. Use Glob to discover files in a directory, then Read individual files. Never pass a directory path to the Read tool.
|
|
680
676
|
- Return clear validation errors with line numbers
|
|
681
677
|
- Suggest fixes for schema violations
|
|
682
678
|
- Prevent writing invalid JSON
|
|
@@ -686,29 +682,31 @@ if (estimatedNewSize > 500 * 1024) { // 500KB
|
|
|
686
682
|
## $schema Reference Rules (MANDATORY)
|
|
687
683
|
|
|
688
684
|
> **Every index.json MUST include a `$schema` field** pointing to the deployed schema file via relative path.
|
|
689
|
-
> Schemas are deployed by step-00-init to: `docs/{
|
|
685
|
+
> Schemas are deployed by step-00-init to: `docs/{projectSlug}/v{X.Y}/schemas/`
|
|
690
686
|
|
|
691
|
-
**$schema paths by scope:**
|
|
687
|
+
**$schema paths by scope (ba-006):**
|
|
692
688
|
|
|
693
689
|
| Scope | index.json location | $schema value |
|
|
694
690
|
|-------|----------------------|---------------|
|
|
695
|
-
| project | `docs/
|
|
696
|
-
| application | `docs/{
|
|
697
|
-
|
|
|
691
|
+
| project | `docs/{projectSlug}/v{X.Y}/index.json` | `"schemas/project-schema.json"` |
|
|
692
|
+
| application (single-app) | `docs/{projectSlug}/v{X.Y}/index.json` | `"schemas/application-schema.json"` |
|
|
693
|
+
| application (multi-app) | `docs/{projectSlug}/v{X.Y}/{appKebab}/index.json` | `"../schemas/application-schema.json"` |
|
|
694
|
+
| module | `docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/index.json` | `"../../schemas/feature-schema.json"` |
|
|
698
695
|
|
|
699
696
|
**Rules:**
|
|
700
697
|
- `$schema` is ALWAYS the FIRST field in index.json (before `id`)
|
|
701
|
-
- Path is RELATIVE from the index.json file to the schemas directory
|
|
702
|
-
- For
|
|
703
|
-
- For
|
|
698
|
+
- Path is RELATIVE from the index.json file to the schemas directory at `docs/{projectSlug}/v{X.Y}/schemas/`
|
|
699
|
+
- For project/single-app: schemas/ is in the same directory
|
|
700
|
+
- For multi-app application: go up 1 level ({appKebab}/) → schemas/
|
|
701
|
+
- For module: go up 2 levels ({moduleKebab}/ → {appKebab}/) → schemas/
|
|
704
702
|
- If schemas directory not found → WARNING (schemas may not have been deployed by step-00)
|
|
705
703
|
|
|
706
704
|
## Example index.json Structure
|
|
707
705
|
|
|
708
|
-
**Module-level:**
|
|
706
|
+
**Module-level:** (`docs/{projectSlug}/v{X.Y}/{appKebab}/{moduleKebab}/index.json`)
|
|
709
707
|
```json
|
|
710
708
|
{
|
|
711
|
-
"$schema": "
|
|
709
|
+
"$schema": "../../schemas/feature-schema.json",
|
|
712
710
|
"id": "FEAT-001",
|
|
713
711
|
"version": "1.0",
|
|
714
712
|
"status": "draft",
|
|
@@ -743,7 +741,7 @@ if (estimatedNewSize > 500 * 1024) { // 500KB
|
|
|
743
741
|
}
|
|
744
742
|
```
|
|
745
743
|
|
|
746
|
-
**Application-level:**
|
|
744
|
+
**Application-level:** (`docs/{projectSlug}/v{X.Y}/{appKebab}/index.json` or `docs/{projectSlug}/v{X.Y}/index.json` for single-app)
|
|
747
745
|
```json
|
|
748
746
|
{
|
|
749
747
|
"$schema": "../schemas/application-schema.json",
|
|
@@ -778,10 +776,10 @@ if (estimatedNewSize > 500 * 1024) { // 500KB
|
|
|
778
776
|
}
|
|
779
777
|
```
|
|
780
778
|
|
|
781
|
-
**Project-level (multi-app only):**
|
|
779
|
+
**Project-level (multi-app only):** (`docs/{projectSlug}/v{X.Y}/index.json`)
|
|
782
780
|
```json
|
|
783
781
|
{
|
|
784
|
-
"$schema": "
|
|
782
|
+
"$schema": "schemas/project-schema.json",
|
|
785
783
|
"id": "PROJ-001",
|
|
786
784
|
"version": "1.0",
|
|
787
785
|
"status": "draft",
|
|
@@ -156,7 +156,7 @@ Write back to {delegate_prd_path}
|
|
|
156
156
|
| `scaffold_extension` | Create files manually following `smartstack-api.md` entity/service/controller patterns |
|
|
157
157
|
| `suggest_migration` | Name format: `{context}_v{version}_{sequence}_{Description}` (see existing migrations for version) |
|
|
158
158
|
| `generate_permissions` | Write `HasData()` code manually following `core-seed-data.md` permission section |
|
|
159
|
-
| `scaffold_routes` | Create `componentRegistry.generated.ts`
|
|
159
|
+
| `scaffold_routes` | Create `componentRegistry.generated.ts` manually. Keys MUST use DOT notation: `PageRegistry.register('{app_code}.{module_code}.{section_code}', lazy(...))`. Example: `PageRegistry.register('rh.employes.list', lazy(() => import('../pages/Rh/Employes/EmployeesListPage')));` — NEVER use hyphens as hierarchy separator. For client projects: `import { PageRegistry } from '@atlashub/smartstack';`. For SmartStack core: `import { PageRegistry } from '@/extensions/PageRegistry';`. See `frontend-route-wiring-app-tsx.md` §Client SDK |
|
|
160
160
|
| `validate_frontend_routes` | Run POST-CHECK bash scripts from `post-checks.md` |
|
|
161
161
|
| `validate_security` | Run security POST-CHECKs S1-S6 from `post-checks.md` |
|
|
162
162
|
| `check_migrations` | Run `dotnet ef migrations has-pending-model-changes` manually |
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# POST-CHECK: Backend — Entity, Service & Controller Checks
|
|
5
|
-
# V1-V2, C8, C12, C14, C28-C31, C54: Entity validation, API contracts, pagination, code generation
|
|
5
|
+
# V1-V2, C8, C12, C14, C28-C31, C54, C62: Entity validation, API contracts, pagination, code generation, tenant exceptions
|
|
6
6
|
|
|
7
7
|
FAIL=false
|
|
8
8
|
|
|
@@ -10,9 +10,9 @@ FAIL=false
|
|
|
10
10
|
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
11
11
|
if [ -n "$CTRL_FILES" ]; then
|
|
12
12
|
for f in $CTRL_FILES; do
|
|
13
|
-
HAS_WRITE=$(grep -cE "\[Http(Post|Put)\]" "$f")
|
|
13
|
+
HAS_WRITE=$(grep -cE "\[Http(Post|Put)\]" "$f" || true)
|
|
14
14
|
if [ "$HAS_WRITE" -gt 0 ]; then
|
|
15
|
-
DTOS=$(grep -
|
|
15
|
+
DTOS=$(grep -oE '(Create|Update)[A-Za-z0-9_]+Dto' "$f" | sort -u || true)
|
|
16
16
|
for DTO in $DTOS; do
|
|
17
17
|
VALIDATOR_NAME=$(echo "$DTO" | sed 's/Dto$/Validator/')
|
|
18
18
|
VALIDATOR_FILE=$(find src/ -path "*/Validators/*" -name "${VALIDATOR_NAME}.cs" 2>/dev/null)
|
|
@@ -60,7 +60,7 @@ if [ -n "$WEB_DIR" ]; then
|
|
|
60
60
|
LOOKUP_FILES=$(grep -rl "EntityLookup" "$WEB_DIR/src/pages/" "$WEB_DIR/src/components/" 2>/dev/null | grep -v node_modules | grep -v "\.test\." || true)
|
|
61
61
|
if [ -n "$LOOKUP_FILES" ]; then
|
|
62
62
|
for f in $LOOKUP_FILES; do
|
|
63
|
-
ENDPOINTS=$(grep -
|
|
63
|
+
ENDPOINTS=$(grep -oE "apiEndpoint=['\"][^'\"]+['\"]" "$f" 2>/dev/null | sed "s/apiEndpoint=//;s/['\"]//g" || true)
|
|
64
64
|
for ep in $ENDPOINTS; do
|
|
65
65
|
ENTITY=$(echo "$ep" | sed 's|.*/||' | sed 's/.*/\u&/')
|
|
66
66
|
CTRL=$(find src/ -path "*/Controllers/*${ENTITY}*Controller.cs" 2>/dev/null | head -1)
|
|
@@ -77,7 +77,7 @@ fi
|
|
|
77
77
|
# POST-CHECK C12: GetAll methods must return PaginatedResult<T>
|
|
78
78
|
SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
|
|
79
79
|
if [ -n "$SERVICE_FILES" ]; then
|
|
80
|
-
BAD_RETURNS=$(grep -
|
|
80
|
+
BAD_RETURNS=$(grep -nE 'Task<\s*(List|IEnumerable|IList|ICollection|IReadOnlyList|IReadOnlyCollection)<.*GetAll' $SERVICE_FILES 2>/dev/null || true)
|
|
81
81
|
if [ -n "$BAD_RETURNS" ]; then
|
|
82
82
|
echo "WARNING: GetAll methods must return PaginatedResult<T>, not List/IEnumerable"
|
|
83
83
|
echo "$BAD_RETURNS"
|
|
@@ -114,7 +114,7 @@ SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Se
|
|
|
114
114
|
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
115
115
|
ALL_FILES="$SERVICE_FILES $CTRL_FILES"
|
|
116
116
|
if [ -n "$(echo $ALL_FILES | tr -d ' ')" ]; then
|
|
117
|
-
BAD_NAMES=$(grep -
|
|
117
|
+
BAD_NAMES=$(grep -nE 'PagedResult<|PaginatedResultDto<|PaginatedResponse<|PageResultDto<' $ALL_FILES 2>/dev/null || true)
|
|
118
118
|
if [ -n "$BAD_NAMES" ]; then
|
|
119
119
|
echo "WARNING: Pagination type must be PaginatedResult<T> — found non-canonical names"
|
|
120
120
|
echo "$BAD_NAMES"
|
|
@@ -179,7 +179,7 @@ fi
|
|
|
179
179
|
# POST-CHECK C54: No helper method calls inside .Select() on IQueryable (BLOCKING)
|
|
180
180
|
SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
|
|
181
181
|
if [ -n "$SERVICE_FILES" ]; then
|
|
182
|
-
BAD_SELECT=$(grep -
|
|
182
|
+
BAD_SELECT=$(grep -nE '\.Select\([[:space:]]*[a-z]+[[:space:]]*=>[[:space:]]*[A-Z][A-Za-z0-9_]+\(' $SERVICE_FILES 2>/dev/null | grep -v '=>\s*new\s' || true)
|
|
183
183
|
if [ -n "$BAD_SELECT" ]; then
|
|
184
184
|
echo "BLOCKING: Helper method call inside .Select() on IQueryable — EF Core cannot translate to SQL"
|
|
185
185
|
echo "$BAD_SELECT"
|
|
@@ -189,6 +189,20 @@ if [ -n "$SERVICE_FILES" ]; then
|
|
|
189
189
|
fi
|
|
190
190
|
fi
|
|
191
191
|
|
|
192
|
+
# POST-CHECK C62: Services must use TenantContextRequiredException, NOT InvalidOperationException for tenant (WARNING)
|
|
193
|
+
SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
|
|
194
|
+
if [ -n "$SERVICE_FILES" ]; then
|
|
195
|
+
for f in $SERVICE_FILES; do
|
|
196
|
+
BAD_TENANT=$(grep -nE 'throw new InvalidOperationException.*[Tt]enant' "$f" 2>/dev/null || true)
|
|
197
|
+
if [ -n "$BAD_TENANT" ]; then
|
|
198
|
+
echo "WARNING: Service uses InvalidOperationException for tenant check (returns 500 instead of 400): $f"
|
|
199
|
+
echo " $BAD_TENANT"
|
|
200
|
+
echo " Fix: Use 'throw new TenantContextRequiredException()' instead"
|
|
201
|
+
echo " TenantContextRequiredException returns 400 via GlobalExceptionHandlerMiddleware"
|
|
202
|
+
fi
|
|
203
|
+
done
|
|
204
|
+
fi
|
|
205
|
+
|
|
192
206
|
if [ "$FAIL" = true ]; then
|
|
193
207
|
exit 1
|
|
194
208
|
fi
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
set -euo pipefail
|
|
3
3
|
|
|
4
4
|
# POST-CHECK: Infrastructure — Migration & Build
|
|
5
|
-
# C13, C38-C43, C50-C51, C56: Database migrations, DI registration, routing uniqueness
|
|
5
|
+
# C13, C38-C43, C50-C51, C56, C60-C61: Database migrations, DI registration, routing uniqueness, MCP compliance
|
|
6
6
|
|
|
7
7
|
FAIL=false
|
|
8
8
|
|
|
@@ -27,10 +27,10 @@ fi
|
|
|
27
27
|
SNAPSHOT=$(find src/ -name "*ModelSnapshot.cs" -path "*/Migrations/*" 2>/dev/null | head -1)
|
|
28
28
|
DBCONTEXT=$(find src/ -name "*DbContext.cs" -path "*/Persistence/*" ! -name "*DesignTime*" 2>/dev/null | head -1)
|
|
29
29
|
if [ -n "$SNAPSHOT" ] && [ -n "$DBCONTEXT" ]; then
|
|
30
|
-
DBSET_ENTITIES=$(grep -
|
|
30
|
+
DBSET_ENTITIES=$(grep -o 'DbSet<[A-Za-z0-9_]*>' "$DBCONTEXT" 2>/dev/null | sed 's/DbSet<//;s/>//' | sort -u || true)
|
|
31
31
|
FAIL_C38=false
|
|
32
32
|
for ENTITY in $DBSET_ENTITIES; do
|
|
33
|
-
if echo "$ENTITY" | grep -
|
|
33
|
+
if echo "$ENTITY" | grep -qE '^(Navigation|Tenant|User|Role|Permission|AuditLog|ApplicationTracking)'; then
|
|
34
34
|
continue
|
|
35
35
|
fi
|
|
36
36
|
if ! grep -q "Entity<$ENTITY>" "$SNAPSHOT" 2>/dev/null; then
|
|
@@ -103,7 +103,7 @@ DTO_FILES=$(find src/ -name "*Dto.cs" -path "*/DTOs/*" 2>/dev/null)
|
|
|
103
103
|
if [ -n "$DTO_FILES" ]; then
|
|
104
104
|
FAIL_C41=false
|
|
105
105
|
for f in $DTO_FILES; do
|
|
106
|
-
BAD_DATES=$(grep -
|
|
106
|
+
BAD_DATES=$(grep -nE 'string\??\s+[A-Za-z0-9_]*[Dd]ate[A-Za-z0-9_]*\s*[{;,]' "$f" 2>/dev/null | grep -vi "Updated\|Created\|format\|pattern\|string\|parse" || true)
|
|
107
107
|
if [ -n "$BAD_DATES" ]; then
|
|
108
108
|
echo "WARNING: DTO has string type for date field — must use DateOnly: $f"
|
|
109
109
|
echo "$BAD_DATES"
|
|
@@ -114,7 +114,7 @@ if [ -n "$DTO_FILES" ]; then
|
|
|
114
114
|
fi
|
|
115
115
|
|
|
116
116
|
# POST-CHECK C42: Every module with entities must have a migration covering them (BLOCKING)
|
|
117
|
-
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null | grep -v test)
|
|
117
|
+
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null | grep -v test || true)
|
|
118
118
|
MIGRATION_DIR=$(find src/ -path "*/Migrations" -type d 2>/dev/null | head -1)
|
|
119
119
|
if [ -n "$ENTITY_FILES" ] && [ -n "$MIGRATION_DIR" ]; then
|
|
120
120
|
MIGRATION_FILES=$(find "$MIGRATION_DIR" -name "*.cs" ! -name "*ModelSnapshot*" ! -name "*DesignTime*" 2>/dev/null)
|
|
@@ -125,7 +125,7 @@ if [ -n "$ENTITY_FILES" ] && [ -n "$MIGRATION_DIR" ]; then
|
|
|
125
125
|
FAIL_C42=false
|
|
126
126
|
for EF in $ENTITY_FILES; do
|
|
127
127
|
ENTITY_NAME=$(basename "$EF" .cs)
|
|
128
|
-
if grep -
|
|
128
|
+
if grep -qE '^\s*(public\s+)?(abstract|interface)\s' "$EF" 2>/dev/null; then continue; fi
|
|
129
129
|
FOUND=$(grep -l "$ENTITY_NAME" $MIGRATION_FILES 2>/dev/null || true)
|
|
130
130
|
if [ -z "$FOUND" ]; then
|
|
131
131
|
echo "BLOCKING: Entity '$ENTITY_NAME' ($EF) not found in any migration file"
|
|
@@ -148,8 +148,8 @@ if [ -n "$CTRL_FILES" ]; then
|
|
|
148
148
|
HAS_NAVROUTE=$(grep -c '\[NavRoute(' "$f" 2>/dev/null || true)
|
|
149
149
|
HAS_ROUTE=$(grep -c '\[Route(' "$f" 2>/dev/null || true)
|
|
150
150
|
if [ "$HAS_NAVROUTE" -gt 0 ] && [ "$HAS_ROUTE" -gt 0 ]; then
|
|
151
|
-
NAVROUTE_VAL=$(grep -
|
|
152
|
-
ROUTE_VAL=$(grep -
|
|
151
|
+
NAVROUTE_VAL=$(grep -o 'NavRoute("[^"]*"' "$f" 2>/dev/null | head -1 || true)
|
|
152
|
+
ROUTE_VAL=$(grep -o 'Route("[^"]*"' "$f" 2>/dev/null | head -1 || true)
|
|
153
153
|
echo "BLOCKING: Controller has BOTH [Route] and [NavRoute] — remove [Route]: $f"
|
|
154
154
|
echo " Found: [$ROUTE_VAL] + [$NAVROUTE_VAL]"
|
|
155
155
|
echo " In SmartStack, [NavRoute] resolves routes dynamically from the database."
|
|
@@ -166,7 +166,7 @@ fi
|
|
|
166
166
|
# POST-CHECK C50: NavRoute Uniqueness — no duplicate NavRoute values (BLOCKING)
|
|
167
167
|
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
168
168
|
if [ -n "$CTRL_FILES" ]; then
|
|
169
|
-
NAVROUTES=$(grep -
|
|
169
|
+
NAVROUTES=$(grep -n '\[NavRoute("' $CTRL_FILES 2>/dev/null | sed 's/.*\[NavRoute("\([^"]*\)".*/\1/' | sort || true)
|
|
170
170
|
DUPLICATES=$(echo "$NAVROUTES" | uniq -d || true)
|
|
171
171
|
if [ -n "$DUPLICATES" ]; then
|
|
172
172
|
echo "BLOCKING: Duplicate NavRoute values detected:"
|
|
@@ -185,7 +185,7 @@ fi
|
|
|
185
185
|
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
186
186
|
if [ -n "$CTRL_FILES" ]; then
|
|
187
187
|
for f in $CTRL_FILES; do
|
|
188
|
-
NAVROUTE=$(grep -
|
|
188
|
+
NAVROUTE=$(grep -o 'NavRoute("[^"]*"' "$f" 2>/dev/null | sed 's/NavRoute("//;s/"//' | head -1 || true)
|
|
189
189
|
if [ -z "$NAVROUTE" ]; then continue; fi
|
|
190
190
|
|
|
191
191
|
DOTS=$(echo "$NAVROUTE" | tr -cd '.' | wc -c)
|
|
@@ -250,6 +250,43 @@ if [ -n "${ENTITIES:-}" ] && [ -n "${SECTIONS:-}" ]; then
|
|
|
250
250
|
fi
|
|
251
251
|
fi
|
|
252
252
|
|
|
253
|
+
# POST-CHECK C60: Controllers must inject ISender _mediator, NOT direct business services (BLOCKING)
|
|
254
|
+
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
255
|
+
if [ -n "$CTRL_FILES" ]; then
|
|
256
|
+
FAIL_C60=false
|
|
257
|
+
for f in $CTRL_FILES; do
|
|
258
|
+
# Detect direct business service injection (I{Entity}Service pattern)
|
|
259
|
+
# Exclude infrastructure services: ICurrentTenantService, ICurrentUserService, IStringLocalizer
|
|
260
|
+
DIRECT_SVC=$(grep -E 'private readonly I[A-Za-z0-9_]+Service ' "$f" 2>/dev/null | grep -v 'ICurrentTenantService\|ICurrentUserService\|IStringLocalizer' || true)
|
|
261
|
+
if [ -n "$DIRECT_SVC" ] && ! grep -q 'ISender' "$f"; then
|
|
262
|
+
echo "BLOCKING: Controller injects business service directly instead of ISender _mediator: $f"
|
|
263
|
+
echo " Found: $(echo "$DIRECT_SVC" | head -1 | xargs)"
|
|
264
|
+
echo " SmartStack convention: Controllers use MediatR (ISender) for CQRS dispatch"
|
|
265
|
+
echo " Fix: Regenerate via mcp__smartstack__scaffold_extension(type: 'controller')"
|
|
266
|
+
FAIL_C60=true
|
|
267
|
+
fi
|
|
268
|
+
done
|
|
269
|
+
if [ "$FAIL_C60" = true ]; then
|
|
270
|
+
FAIL=true
|
|
271
|
+
fi
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
# POST-CHECK C61: Controllers with [NavRoute] must have [Authorize] attribute (BLOCKING)
|
|
275
|
+
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
|
|
276
|
+
if [ -n "$CTRL_FILES" ]; then
|
|
277
|
+
FAIL_C61=false
|
|
278
|
+
for f in $CTRL_FILES; do
|
|
279
|
+
if grep -q '\[NavRoute' "$f" && ! grep -q '\[.*Authorize\]' "$f"; then
|
|
280
|
+
echo "BLOCKING: Controller with [NavRoute] missing [Authorize]: $f"
|
|
281
|
+
echo " Fix: Add [Microsoft.AspNetCore.Authorization.Authorize] on class"
|
|
282
|
+
FAIL_C61=true
|
|
283
|
+
fi
|
|
284
|
+
done
|
|
285
|
+
if [ "$FAIL_C61" = true ]; then
|
|
286
|
+
FAIL=true
|
|
287
|
+
fi
|
|
288
|
+
fi
|
|
289
|
+
|
|
253
290
|
if [ "$FAIL" = true ]; then
|
|
254
291
|
exit 1
|
|
255
292
|
fi
|
|
@@ -48,6 +48,9 @@ import './extensions/componentRegistry.generated';
|
|
|
48
48
|
|
|
49
49
|
## For Client SDK Pages
|
|
50
50
|
|
|
51
|
+
> **CRITICAL:** Keys use DOT notation (`rh.employes.list`), NEVER hyphens (`rh-employes-list`).
|
|
52
|
+
> Dots are hierarchy separators matching `NavigationService.ComponentKey` computation at runtime.
|
|
53
|
+
|
|
51
54
|
Clients register their own pages directly:
|
|
52
55
|
|
|
53
56
|
```tsx
|
|
@@ -39,7 +39,7 @@ bash references/checks/infrastructure-checks.sh
|
|
|
39
39
|
| S8 | BLOCKING | Write endpoints must NOT use Read permissions | security-checks.sh |
|
|
40
40
|
| S9 | BLOCKING | FK relationships must enforce tenant isolation | security-checks.sh |
|
|
41
41
|
|
|
42
|
-
### Backend — Entity, Service & Controller Checks (V1-V2, C8, C12, C14, C28-C31, C54)
|
|
42
|
+
### Backend — Entity, Service & Controller Checks (V1-V2, C8, C12, C14, C28-C31, C54, C62)
|
|
43
43
|
|
|
44
44
|
| ID | Severity | Description | Script |
|
|
45
45
|
|----|----------|-------------|--------|
|
|
@@ -53,6 +53,7 @@ bash references/checks/infrastructure-checks.sh
|
|
|
53
53
|
| C30 | BLOCKING | Code regex must support hyphens | backend-checks.sh |
|
|
54
54
|
| C31 | WARNING | CreateDto must NOT have Code field when service uses ICodeGenerator | backend-checks.sh |
|
|
55
55
|
| C54 | BLOCKING | No helper method calls inside .Select() on IQueryable | backend-checks.sh |
|
|
56
|
+
| C62 | WARNING | Services must use TenantContextRequiredException for tenant check, NOT InvalidOperationException | backend-checks.sh |
|
|
56
57
|
|
|
57
58
|
### Frontend — CSS, Forms, Components, I18n (C3a, C3-C7, C9, C11, C24-C27, C36-C37, C49, C52)
|
|
58
59
|
|
|
@@ -117,7 +118,7 @@ bash references/checks/infrastructure-checks.sh
|
|
|
117
118
|
| A7 | WARNING | No direct repository usage in controllers | architecture-checks.sh |
|
|
118
119
|
| A8 | BLOCKING | API endpoints must match handoff apiEndpointSummary | architecture-checks.sh |
|
|
119
120
|
|
|
120
|
-
### Infrastructure — Migration & Build (C13, C38-C43, C50-C51, C56)
|
|
121
|
+
### Infrastructure — Migration & Build (C13, C38-C43, C50-C51, C56, C60-C61)
|
|
121
122
|
|
|
122
123
|
| ID | Severity | Description | Script |
|
|
123
124
|
|----|----------|-------------|--------|
|
|
@@ -131,6 +132,8 @@ bash references/checks/infrastructure-checks.sh
|
|
|
131
132
|
| C50 | BLOCKING | NavRoute Uniqueness — no duplicate NavRoute values | infrastructure-checks.sh |
|
|
132
133
|
| C51 | WARNING | NavRoute Segments vs Controller Hierarchy (depth matching) | infrastructure-checks.sh |
|
|
133
134
|
| C56 | BLOCKING | Hierarchy Artifact Completeness — current run only (entities + sections) | infrastructure-checks.sh |
|
|
135
|
+
| C60 | BLOCKING | Controllers must inject ISender _mediator, NOT direct business services | infrastructure-checks.sh |
|
|
136
|
+
| C61 | BLOCKING | Controllers with [NavRoute] must have [Authorize] attribute | infrastructure-checks.sh |
|
|
134
137
|
|
|
135
138
|
---
|
|
136
139
|
|