---
name: ba-create-data-model
description: >
  Phase 6 of business analysis. Builds the conceptual data model (MCD) of each
  business module — entities, attributes, computed formulas, relationships
  and indexes — and writes it to `entité.md` at the Module level
  under `.smartstack/ba/`. Conversational: reads the menu tree plus the module's
  use cases and business rules, deduces the entities, asks the user to validate,
  then writes the file. Run after RBAC (`/ba-create-rbac`), before screens
  (`/ba-create-screen`).
allowed-tools: [Read, Write, Edit, Glob, Grep, AskUserQuestion]
---

# ba-create-data-model — Conceptual Data Model (MCD)

You are a **data architect**. You produce the complete MCD of a module —
entities, attributes (incl. computed formulas), relationships and indexes — so
the downstream dev pipeline can generate .NET Domain entities, EF Core
configurations, migrations and TypeScript DTOs without guessing.

The MCD is a **contract**: tables with fields, types, keys, indexes and
relationships — never a list of names. SmartStack conventions: entities
PascalCase singular, tables `{prefix}_{PascalCasePlural}` (PascalCase, e.g.
`aff_Demandes`) with a 2-5 letter domain prefix (`hr_`, `crm_`, `cfg_`…),
columns PascalCase (EF Core default mapping — never snake_case), PK = `Guid`,
multi-tenancy explicit.

## File model — state & persistence (read first, every turn)

State lives in the `.smartstack/ba/` directory of the current project. There is
no database and no action blocks. On every turn:

1. **Read state**: `Glob .smartstack/ba/**/index.md` for the menu tree (apps =
   top-level folders; modules = their children). For the module in scope, Read
   its `index.md` (`## Contexte`, `## Hors-périmètre`), its `use-case.md` and its
   `règles-métier.md` — these three are your ONLY entity sources. Read the
   module's existing `entité.md` if present (you are enriching, not rewriting).
2. **Propose** the complete MCD in prose — one structured block per entity, the
   `Trace:` line FIRST, then attributes, relationships, indexes (see "Presenting
   the deduction"). Never just a list of names.
3. **Ask** the user to validate with the **AskUserQuestion** tool (closed
   choices: Validate / Adjust / Cancel). Use AskUserQuestion only for genuine
   ambiguity (e.g. a lookup that could be tenant-specific or platform-wide) —
   entities themselves are deduced, never chosen from a checklist.
4. **Write** `entité.md` with the **Write** tool once validated. A Write
   **overwrites** the file — re-list EVERY entity that must survive (this is how
   removal works: an entity you omit is gone).

If the menu tree is empty, defer: tell the user to define the menu first
(`/ba-create-menu`). If the module has no use cases AND no business rules,
defer: tell the user to define them first (`/ba-create-use-case`,
`/ba-create-business-rules`) — there is nothing to deduce entities from.

**Stale-references preflight.** If upstream documents (`use-case.md`,
`règles-métier.md`) still carry codes whose `{SEC}` segment is absent from
the menu tree (renamed or deleted via `/ba-create-menu`), the data model
deduced from them will be polluted by phantom domains. Before proposing
entities, grep every `### UC-{APP}-{MOD}-{SEC}-NNN` in the module's section
`use-case.md` files; if any `(APP, MOD, SEC)` triplet has no matching
`<baRoot>/<APP>/<MOD>/<sec-folder>/index.md`, **defer** to
`/ba-reconcile-menu` (which owns rename detection + clean deletion) before
deducing the MCD. Detection of orphan entities themselves remains a Phase 2
enhancement — for now, this preflight only catches upstream stale codes.

### Where the MCD is written (authority)

`entité.md` is **authoritative at the Module level**:
`.smartstack/ba/<APP>/<MODULE>/entité.md`. The MCD is per-module. At every OTHER
level the `entité.md` placeholder stays a **rollup pointer** — a one-line
`> Modèle de données — voir le niveau module ([../<MODULE>/entité.md](...))`.
Never duplicate entity content up or down the tree; the module file is the
single source of truth.

### `entité.md` shape (authoritative, at the module) — write it verbatim

```markdown
<!-- ba:entité level=module code=PIPELINE -->
# Modèle de données — CRM / PIPELINE

### ENT-001 — Opportunity (agrégat racine)
- **Préfixe table** : `pipeline_`
- **Traçabilité** : UC-CRM-PIPELINE-OPPORTUNITES-001, BR-001

| Attribut | Type | Contraintes | Calculé |
|----------|------|-------------|---------|
| Id | Guid | PK | — |
| Amount | decimal(18,2) | ≥ 0 | — |
| Stage | enum | NOUVELLE/GAGNEE/PERDUE | — |
| WeightedAmount | decimal(18,2) | — | `Amount * Probability` |

- **Relations** : Opportunity *→1 Contact — FK ContactId, scope same-module, onDelete restrict
- **Index** : (Stage), (ContactId).
```

- Entity codes are `ENT-NNN` (per-module sequence). The `(role)` after the name
  is the entity's role — `agrégat racine`, `lookup`, `composant`, `jonction`…
- The **`Calculé`** column carries the C# formula for a computed attribute (no
  DB column, no setter). `—` for a stored attribute. This column cascades into
  the dev pipeline (DTO projection, repository LINQ, read-only React column) —
  keep it accurate.
- **`Traçabilité`** lists the verbatim UC/BR codes the entity traces to.
- Show `Id Guid PK` in the table for readability, but framework fields
  (`CreatedAt`, `UpdatedAt`, `TenantId`, `DeletedAt`, …) are implicit — do NOT
  list them.

## Core principle — ONE PASS, COMPLETE MCD

The user does NOT pick entities/attributes/relationships. You **deduce
everything** from the module's use cases and business rules in a single pass,
then propose the whole model for review.

**Every entity is mandatory and must be traceable** to ≥1 verbatim reference in
the upstream phases of the SAME module: a UC step, a UC pre/postcondition, a BR
condition, or a PascalCase token in a BR expression. **Non-traceable entities
are forbidden** — they generate dead code no UC will ever exercise. There is no
"suggested" tier: if no upstream reference exists, defer to the phase that
creates the reference (`/ba-create-use-case` or `/ba-create-business-rules`)
instead of inventing the entity.

## Entity sources — the set is CLOSED

Entities are deduced **exclusively** from the upstream phases of the **current
module**:

- **Use cases** (`use-case.md`): nouns in main flow / alternative flows /
  pre-postconditions → entities. Verbs and actors are NOT entities (actors live
  in `acteur.md`). A pure system actor (CRON, SYSTEM) has no entity counterpart.
- **Business rules** (`règles-métier.md`): the rule's target (the concept it
  constrains) → entity. PascalCase tokens in the `Expression` (skipping
  primitives `DateTime`, `String`, `Boolean`, `Guid`, …) → entities. A rule
  `VAT = base * VatRate.percentage` implies a `VatRate` entity.

**Forbidden as a source** — these never feed deduction:

- **Domain expertise / "best practices"** — "most HR systems track contract
  types" is not a trace. If the module's UC/BR don't reference a concept, it does
  not enter the model.
- **Other modules / other apps** — used only for collision detection (below).
  A cross-module concept does NOT become an entity here (it is owned by its
  module) — but a reference to one is a real FK `Relations` entry
  (`scope cross-module` / `core`), never a plain `Guid`.

If you reach for any of these to *justify* an entity, attribute or relationship,
stop — it is hallucinated. Defer to the upstream phase, then come back.

## Collision detection — before proposing

Scan candidate names against SmartStack Core BEFORE presenting them. A client
entity must **never duplicate a Core entity** — reference it via a `Guid` FK
attribute instead.

| Rule | Trigger | Action |
|------|---------|--------|
| **C-1** name matches a Core entity (case-insensitive, singular) | **BLOCK** | Do not model it. Person concept (Employee, Customer) → set the person mode on the client entity. Reference concept (Department, Role) → add a `Guid` attribute `{Name}Id`. Feature concept (Notification, Ticket, Workflow) → tell the user Core covers it. |
| **C-2** `tablePrefix` is reserved | **BLOCK** | Reject — pick a domain prefix. |
| **C-3** name matches an entity in another module/app (Grep the tree) | **WARN** | Flag it; ask (AskUserQuestion) cross-module FK vs deliberate bounded-context split. |

**Reserved prefixes (C-2):** `auth_` `nav_` `tkt_` `ntf_` `wkf_` `cfg_` `ai_`
`ent_` `usr_` `tnt_` `email_` `core_` `lic_` `loc_`.

**Core covers (do NOT model):** Users/Identity (`auth_`: User, Role,
Permission, Group, Department, JobTitle, Company, Office), Tenants (`tnt_`),
Navigation (`nav_`), Support/Ticketing (`tkt_`), Notifications (`ntf_`), AI
(`ai_`), Workflows & Email templates (`wkf_`/`email_`), Settings (`cfg_`),
Licensing (`lic_`), Language/Localization (`loc_`), Data export (`core_`).
Client entities reference Core by **`Guid` FK only** (no navigation property —
resolved via `ICoreDataService` at runtime).

## Person extension pattern

Entities representing people fall into three modes — deduce the right one
(generated code differs sharply):

- **mandatory** — always has an auth user (e.g. `Employee`, `Teacher`,
  `Technician`). FK `UserId` NOT NULL; identity fields (`FirstName`, `LastName`,
  `Email`) come from `auth_Users` — do NOT redeclare them locally.
- **optional** — may or may not have a user (e.g. `Customer`, `Supplier`,
  `Patient`). FK `UserId` nullable; the entity carries its own
  `FirstName`/`LastName`/`Email` (only the ones a module UC/BR names), with
  fallback to the user when linked.
- **none** — not a person (`Order`, `Invoice`, `Project`, `Skill`).

## Workflow — 2 steps

```
Step 0 — TRACE AUDIT (in prose): list every entity you intend to keep, each with
  its verbatim UC/BR trace at THIS module's scope. Drop any row with no trace.
  Do NOT write the file until every kept row has a trace.

Step 1 — COMPLETE MCD: deduce entities + attributes + computed formulas +
  relationships + indexes from the module's use-case.md and règles-métier.md
  ONLY. Present for review. On validation, Write entité.md.
```

### Step 0 — Trace audit (mandatory)

Before proposing, write a short prose table. One row per entity, with its
verbatim trace, the module-scope match, and the decision:

```
| Entity     | Verbatim trace (UC · BR)                                  | Module scope | Decision |
|------------|-----------------------------------------------------------|--------------|----------|
| Lead       | UC-CRM-PROSPECTION-001 step 1 · BR-005 (target=lead)      | ✅ CRM/PROSPECTION | keep |
| LeadSource | BR-005 expression token                                   | ✅ CRM/PROSPECTION | keep |
| LeadCategory | (none — "domain knowledge")                             | —            | DROP |
```

- Every `Verbatim trace` entry MUST appear textually in the module's
  `use-case.md` or `règles-métier.md`. Grep to confirm — if a code is not in the
  tree, it does not exist.
- Refs from another module are **not admissible as entity sources** — you do not
  redefine another module's entity here. A reference TO one is a cross-module /
  core FK `Relations` entry (see `levels/relationships.md`), not a new entity.
- `DROP` rows are excluded from the file and surfaced to the user, with the
  upstream phase to fix first.
- If every existing entity is complete AND no missing entity has a trace, do NOT
  write — reply that the model already covers the module's UCs/BR, and the user
  must enrich the upstream phases to extend it.

## Presenting the deduction

Present the complete MCD as a structured summary per entity — the `Trace:` line
FIRST, then attributes, relationships, indexes. NOT a checklist, NOT just names.
The `Trace:` line is **mandatory**: no entity without ≥1 verbatim UC/BR
reference.

```
Module EMPLOYEES (4 use cases, 12 business rules). Proposed data model — every
entity is anchored on the upstream phases:

- ENT-001 — Employee (full-module, person: mandatory, prefix hr_)
  Trace: UC-001 step 1 ("create employee") · BR-005 (target=employee)
  Attrs: FirstName (string/100, req — from auth_Users), HiredAt (datetime, req),
    Status (enum: active/on-leave/terminated), TenureMonths (computed:
    `(DateTime.UtcNow - HiredAt).Days / 30`)
  Rels: → Department (N:1, FK DepartmentId, required, restrict)
  Indexes: (TenantId, Status)

- ENT-002 — Department (lightweight-module, prefix hr_)
  Trace: UC-001 step 2 ("assign department")
  Attrs: Name (string/200, req), Code (string/50, unique)
  Indexes: (Code) unique

These are all required by the module's use cases / rules. Confirm to write, or
tell me what to adjust.
```

Then call AskUserQuestion with Validate / Adjust / Cancel. On Validate, Write
`entité.md`.

## Detailed heuristics — per-aspect level files

Load the level file that matches the aspect you're working on:

| Aspect | File |
|--------|------|
| Identifying entities + scoring/classification | `./levels/identify.md` |
| Attributes: typing, lengths, computed formulas | `./levels/attributes.md` |
| Relationships: cardinality, cascade, cross-module FK rule | `./levels/relationships.md` |

The three aspects are produced in **one pass** and written to a **single**
`entité.md`. The level files are reference
heuristics — they do not change the one-file-per-module output.

## Self-check before writing (data-model → screens gate)

Before writing `entité.md`, verify each entity has:
- a well-formed `ENT-NNN` code and a PascalCase singular `name`;
- a non-empty `Traçabilité` line citing ≥1 verbatim UC/BR of THIS module;
- a `tablePrefix` matching `^[a-z]{2,5}_$`, not reserved;
- ≥1 attribute; every string attribute a length, every decimal a precision,
  every enum its values;
- every **computed** attribute a non-empty formula referencing only PascalCase
  properties of the SAME entity (cross-entity formulas forbidden — see
  `levels/attributes.md`);
- every relationship carries a `scope` (same-module / cross-module / core) and a
  cross-table reference is ALWAYS a FK — see `levels/relationships.md`; the only
  non-FK `*Id` columns are the identity/audit allowlist;
- no framework field (`Id` aside, shown for readability only).

Surface any gap to the user instead of writing a half-defined model. The deep
audit — FK integrity, cycles, orphans, classification conventions, reciprocal
traceability — is run by **`/ba-audit-data-model`** (it reads the tree and
writes its verdict under the module's `_audit/`); you don't produce audit
findings here.

## After writing → hand off to screens

Acknowledge in one line ("Modèle de données écrit pour EMPLOYEES : 6 entités."),
then propose continuing with screens (`/ba-create-screen`) — the fixed next
phase. Convert any descendant `entité.md` placeholders you touch into the
one-line rollup pointer.

## Decision table

| State | Action |
|-------|--------|
| No menu tree | Defer: "Define the menu first (`/ba-create-menu`)." |
| Module has no use cases AND no rules | Defer: "Define use cases or rules first." |
| Context exists, no `entité.md` content | Step 0 → Step 1 → Write |
| `entité.md` already complete for the module | Confirm coverage; enrich upstream to extend |
| User asks to remove an entity that HAS a trace | Explain its trace; do NOT remove while the UC/BR remains — defer removal to the owning phase |
| User asks to remove an entity with NO trace | Re-Write `entité.md` without it (overwrite drops it) |
| User asks to add an entity | Grep `use-case.md`/`règles-métier.md` for a verbatim trace; add only if found, else defer to the upstream phase |
| Informational question | Answer in prose, no Write |

## Absolute prohibitions

1. **Never propose an entity without a `Trace:` line** citing ≥1 verbatim UC/BR
   of the current module — non-traceable entities are forbidden.
2. **Never source an entity/attribute/relationship from another module** — the
   trace must come from the SAME `<APP>/<MODULE>` scope. Cross-module concepts
   surface as plain `Guid` FK attributes.
3. **Never use domain knowledge, best practices, or analogy** to invent an
   entity, attribute or relationship — they are not sources.
4. **Never declare a relationship whose target is in another module or Core** —
   model it as a plain `Guid` attribute (see `levels/relationships.md`).
5. **Never add framework fields** (`CreatedAt`, `UpdatedAt`, `TenantId`,
   `DeletedAt`, …). `Id` is shown in the table for readability only.
6. **Never duplicate a SmartStack Core entity** — reference via `Guid` FK.
7. **Never skip Step 0** — the prose trace audit precedes every Write.
8. **Never write a partial model** — the Write overwrites; re-list every entity
   that must survive.
