---
name: step-04-backend
description: Generate backend code using MCP scaffold_extension
prev_step: steps/step-03-roles.md
next_step: steps/step-05-frontend.md
---

# Step 4: Backend Generation

## MANDATORY EXECUTION RULES

- ALWAYS use MCP `scaffold_extension` tool - NEVER use templates
- ALWAYS generate Entity + Service + Controller as a unit
- NEVER skip controller generation - API is required
- YOU ARE AN ORCHESTRATOR calling MCP, not a generator
- **NEVER use Write on appsettings*.json** - ALWAYS use Edit (see _resources/config-safety.md)
- **Replace secret VALUES with `<CONFIGURE_HERE>`** - NEVER delete keys or sections

## YOUR TASK

Call the SmartStack MCP `scaffold_extension` tool with type "feature" to generate:
1. Domain Entity with EF Configuration
2. Application Service (Interface + Implementation)
3. API Controller with NavRoute attribute
4. DTOs (Response, Create, Update)

---

## AVAILABLE STATE

From previous steps:

| Variable | Description |
|----------|-------------|
| `{level}` | context, application, module, or section |
| `{code}` | kebab-case identifier |
| `{full_path}` | Complete navigation path (navRoute) |
| `{labels}` | Object with fr, en, it, de |

---

## EXECUTION SEQUENCE

### 1. Derive Entity Name

Convert `{code}` to PascalCase for entity name:

```
code: "products"        → entityName: "Product"
code: "order-items"     → entityName: "OrderItem"
code: "user-profiles"   → entityName: "UserProfile"
```

### 2. Determine Table Prefix and Controller Folder

**Table Prefix priority:**
1. **If a `feature.json` exists** with `metadata.tablePrefix` → use that prefix (e.g., `rh_`, `fi_`)
2. **Otherwise**, derive from navigation context using the fallback table below

**Fallback table (when no feature.json tablePrefix is available):**

| Context | Table Prefix | Controller Folder |
|---------|--------|-------------------|
| platform.administration | `auth_` or `cfg_` | `Admin` |
| platform.support | `support_` | `Support` |
| business.* | `ref_` or domain-specific | `Business` |
| personal.* | `usr_` | `User` |

```
# Check for feature.json tablePrefix
Search for feature.json in:
  - docs/business/{application}/business-analyse/*/feature.json
  - Read metadata.tablePrefix if exists

IF metadata.tablePrefix exists:
  {prefix} = metadata.tablePrefix   # e.g., "rh_"
ELSE:
  {prefix} = derived from context table above
```

Store: `{controller_folder}` = the Controller Folder from the table above.

### 3. Call MCP scaffold_extension

```
Tool: mcp__smartstack__scaffold_extension
Args:
  type: "feature"
  name: "{entityName}"  # PascalCase
  options:
    navRoute: "{full_path}"
    tablePrefix: "{prefix}"
    schema: "core"
    withDtos: true
    withValidation: true
    withRepository: false  # Use service pattern
    skipComponent: true    # Frontend in next step
    dryRun: false
```

### 4. Parse MCP Response

The tool generates (paths organized by navRoute hierarchy `{context}.{application}.{module}`):
- `Domain/{Context}/{Application}/{Module}/{EntityName}.cs` - Entity with BaseEntity
- `Infrastructure/Persistence/Configurations/{Context}/{Application}/{Module}/{EntityName}Configuration.cs` - EF Config
- `Application/Common/Interfaces/I{EntityName}Service.cs` - Service Interface
- `Infrastructure/Services/{Context}/{Application}/{Module}/{EntityName}Service.cs` - Service Implementation
- `Api/Controllers/{controller_folder}/{Application}/{EntityName}Controller.cs` - REST Controller
- `Application/{Context}/{Application}/{Module}/DTOs/{EntityName}ResponseDto.cs` - Response DTO
- `Application/{Context}/{Application}/{Module}/DTOs/Create{EntityName}Dto.cs` - Create request
- `Application/{Context}/{Application}/{Module}/DTOs/Update{EntityName}Dto.cs` - Update request

### 5. Present Output to User

```markdown
## Backend Code Generated

### Domain Layer
- `Domain/{Context}/{Application}/{Module}/{EntityName}.cs`

### Infrastructure Layer
- `Persistence/Configurations/{Context}/{Application}/{Module}/{EntityName}Configuration.cs`
- `Services/{Context}/{Application}/{Module}/{EntityName}Service.cs`

### Application Layer
- `Common/Interfaces/I{EntityName}Service.cs`
- `{Context}/{Application}/{Module}/DTOs/{EntityName}ResponseDto.cs`
- `{Context}/{Application}/{Module}/DTOs/Create{EntityName}Dto.cs`
- `{Context}/{Application}/{Module}/DTOs/Update{EntityName}Dto.cs`

### API Layer
- `Controllers/{controller_folder}/{Application}/{EntityName}Controller.cs`
  - NavRoute: `{full_path}`
  - Endpoints:
    - GET /api/{code} - List all
    - GET /api/{code}/{id} - Get by ID
    - POST /api/{code} - Create
    - PUT /api/{code}/{id} - Update
    - DELETE /api/{code}/{id} - Delete

### Next Steps
1. Add DbSet to ICoreDbContext: `public DbSet<{EntityName}> {EntityName}s => Set<{EntityName}>();`
2. Register service in DI: `services.AddScoped<I{EntityName}Service, {EntityName}Service>();`
3. Run: `dotnet ef migrations add core_vX.X.X_XXX_Add{EntityName}`
```

### 6. Entity Seeding (Optional)

> Ask the user if they want to seed initial data for the entity.
> This creates runtime seed data (applied at startup via DevDataSeeder), following the same
> architecture as core (SeedData provider pattern).

```yaml
questions:
  - header: "Seed Data"
    question: "Would you like to generate initial seed data for {EntityName}?"
    options:
      - label: "Yes - Generate SeedData provider"
        description: "Creates {EntityName}SeedData.cs + registers in DevDataSeeder (same pattern as core)"
      - label: "No - Skip seeding"
        description: "Entity starts empty (can add seed data later)"
    multiSelect: false
```

#### If User Selects YES:

See [references/backend-entity-seeding.md](../references/backend-entity-seeding.md) for the full seeding pattern:
1. **SeedData file** (`{EntityName}SeedData.cs`) — static class with deterministic GUIDs, 3-5 samples
2. **DevDataSeeder update** — add `Seed{EntityName}sAsync()` method with idempotent check

#### If User Selects NO:

Skip this section and proceed to storing entity info.

```markdown
> Skipping entity seed data. You can generate it later using the SeedData provider pattern
> documented in templates-seed.md.
```

### 7. Store Entity Info

Store entity information for frontend generation:

```
{entity_name} = "{EntityName}"
{entity_code} = "{code}"
{api_route} = "/api/{code}"
{has_seed_data} = true/false  // Whether SeedData provider was generated
```

---

## CONTROLLER NAVROUTE AND FOLDER HIERARCHY

See [references/backend-controller-hierarchy.md](../references/backend-controller-hierarchy.md) for the complete reference:
- Controller file organization (Admin/Business/Support/User folders)
- Context-to-folder mapping table
- NavRoute attribute C# template with RequirePermission

---

## MCP RESPONSE HANDLING

### Success Case

If MCP returns successfully:
- Display all generated files
- Show DbSet and DI registration instructions
- Ask about entity seeding (section 6)
- Store entity info for frontend
- Proceed to step-05-frontend.md

### Error Case

If MCP call fails:
- Display error message
- Suggest checking entity name format
- Do NOT proceed automatically

---

## POST-GENERATION VERIFICATION (MANDATORY)

**Before proceeding to step-05, run ALL checks.**

See [references/backend-verification.md](../references/backend-verification.md) for the complete verification checklist:

| Check | Type | What |
|-------|------|------|
| 1. Backend Build | BLOCKING | `dotnet build --no-restore` must succeed |
| 2. DbSet Registration | BLOCKING | `DbSet<{EntityName}>` in DbContext |
| 3. DI Registration | BLOCKING | `I{EntityName}Service` in DependencyInjection.cs |
| 4. RequirePermission | BLOCKING | All HTTP actions have `[RequirePermission]` |
| 5. Entity Configuration | BLOCKING | Table prefix, HasKey, HasIndex |
| 5b. Seeding Infrastructure | BLOCKING (first entity) | SeedConstants + DevDataSeeder + DI |
| 5c. SqlObjects Directory | BLOCKING (first entity) | SqlObjectHelper + Functions/ + .csproj EmbeddedResource |
| 6. Convention Validation | RECOMMENDED | `mcp__smartstack__validate_conventions` |

IF any BLOCKING check fails: Fix before proceeding to step-05.

---

## SUCCESS METRICS

- MCP scaffold_extension called successfully
- Entity, Service, Controller generated
- DTOs generated
- NavRoute attribute included
- Entity seeding offered to user (SeedData.cs + DevDataSeeder if accepted)
- Entity info stored for frontend
- Post-generation verification passed (all 7 checks: 5 original + 5b Seeding + 5c SqlObjects)
- Proceeded to step-05-frontend.md

## FAILURE MODES

- MCP call failed (display error, stop)
- Invalid entity name (must be PascalCase)
- Invalid navRoute format

---

## NEXT STEP

After backend code is generated and entity seeding is handled,
proceed to `./step-05-frontend.md`
