---
name: audit
description: Audit du code genere contre les conventions SmartStack (i18n, React, structure, routing dynamique, RBAC, securite)
group: DEBUG
allowed-tools: [Read, Glob, Grep]
---

# Skill: Audit — Detect convention violations in generated code

## Role

Tu es un agent d'audit. Tu scans le code du worktree client et detectes les violations
des conventions SmartStack listees dans `CLAUDE.md`. Tu **corriges** automatiquement
les violations mécaniques. Pour les violations ambigues, tu les **rapportes** avec une
suggestion.

## Scope

### Frontend (`web/{appcode}-web/src/`)

**i18n (CRITICAL)** :
- [ ] **Aucune chaine FR/EN hardcodee** dans JSX/TSX. Chaque string visible user DOIT passer par `t('key')`.
  - Regex de detection : `<\w+[^>]*>[A-Za-zÀ-ÿ][^<>{]{3,}</`
  - Ignorer : icons, className, testid, `key=`, commentaires
- [ ] **Chaque cle `t('x.y.z')` DOIT exister dans les 4 locales** : `fr.json`, `en.json`, `it.json`, `de.json`
- [ ] **Pas de cle de validation reutilisee hors de son contexte** (ex: `lastNameRequired` pour un champ qui n'est pas lastName)

**Dynamic Routing (CRITICAL — SmartStack architecture)** :
- [ ] **Aucune route statique `<Route path="...">`** hors de `DynamicRouter` ou des fichiers fournis par `@atlashub/smartstack`. SmartStack est DB-driven.
  - Regex de detection : `<Route\s+path=` dans `src/` (hors `App.tsx` si minimal) → violation
- [ ] **`useParams<{ id: string }>()`** est le SEUL pattern accepte. Rejeter `useParams<{ userId: string }>()`, `:ticketId`, etc.
  - Regex de detection : `useParams<\{\s*(?!id\s*:)` ou `:[\w]+Id\b` dans JSX
- [ ] **`componentRegistry.generated.ts` OU `*Registry.ts`** importe dans `src/main.tsx` AVANT `createRoot(...)`.
  - Grep : `grep -c "Registry" src/main.tsx` → doit etre >= 1
- [ ] **Chaque page scaffoldee** a un `PageRegistry.register('{app}.{module}.{section}[.{view}]', Lazy)` dans son fichier Registry.
  - Grep croise : extraire les clés du menu API + les clés registrées → diff doit etre vide dans un sens au moins (tolere les keys registrées sans entrée menu)
- [ ] **`PageRegistry.register` + `lazyWithRetry(() => import(...))`** (ou legacy `lazy(`) : chaque entree doit etre lazy. Rejeter les imports directs synchrones pour les pages. Nouveau code DOIT utiliser `lazyWithRetry` (export `@atlashub/smartstack`) pour absorber les chunk-load races.
- [ ] **ComponentKey dot-separated** : `{app}.{module}.{section}[.{view}]` avec chaque segment en kebab-case commencant par une lettre.
  - Regex : `PageRegistry\.register\('([^']+)'` → chaque clé matche `/^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*){1,3}$/`
- [ ] **Pas d'import de `@/router/smartstackRoutes` ni de `mergeRoutes`** (deprecated, supprimes).
- [ ] **Pas d'import de `navRoutes.generated.ts`** (supprime, utiliser `@atlashub/smartstack` menu API).

**React** :
- [ ] `useCallback` ne doit pas contenir dans ses deps des valeurs qui forcent un re-fetch
- [ ] `useEffect` cleanup explicite quand on abonne a un event / timer
- [ ] Props typees (pas de `any`)
- [ ] `useParams` retour null-checke (pas `id!` sans garde au-dessus)

**Structure** :
- [ ] Composants pages : pas d'import direct `services/`
- [ ] Composants UI : pas d'import de `services/` ni `stores/`
- [ ] Logique metier : uniquement dans `business/`

### Backend (`src/{AppCode}.*`)

**Clean Architecture** :
- [ ] Clean Architecture 4-layers : Domain ← Application ← Infrastructure → Api
- [ ] Domain : ZERO `using` de `Application`/`Infrastructure`/`Api`
- [ ] Controllers retournent `ActionResult<T>` ou `ActionResult` — pas `IActionResult` nu
- [ ] Services enregistres dans DI via `AddScoped`/`AddSingleton`
- [ ] Migrations EF Core : 1 par feature, 3 fichiers (`.cs`, `.Designer.cs`, `ModelSnapshot.cs`)

**Tables & schemas** :
- [ ] Tables prefixees par domaine : `auth_`, `nav_`, `usr_`, `wkf_`, `cfg_`, `ai_`, `entra_`, `ref_`, `support_`, `loc_`
- [ ] Schema `core` via `SchemaConstants.Core` (pas de `ToTable("X", "auth")`)
- [ ] Raw SQL uniquement via `SqlObjectHelper` + fichiers `.sql` embarques

**RBAC / Permissions (CRITICAL)** :
- [ ] Permissions format `{app}.{module}.{section}.{action}` strict.
  - Regex : `"([a-z][a-z0-9-]*)(\.[a-z][a-z0-9-]*){3}"` pour les string literals de permissions
- [ ] Actions dans le set : `access`, `read`, `create`, `update`, `delete`, `export`, `import`, `approve`, `reject`, `assign`, `execute`
- [ ] `[RequirePermission(...)]` present sur chaque endpoint non-public
- [ ] Permissions declarees dans `{Module}Permissions.cs` (pas hardcodees dans controller)
- [ ] NavRoute sur controller match le componentKey frontend pour le meme endpoint

**Security — GUIDs** :
- [ ] Aucun GUID predictable dans les seed / tests / code :
  - Rejeter : `00000000-0000-0000-0000-000000000001`
  - Rejeter : `aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee` (repete)
  - Rejeter : suites sequentielles `00000001`, `00000002`, ...
- [ ] Les GUIDs doivent etre `Guid.NewGuid()` (une fois en `static readonly` pour idempotence, ou a l'execution)
- [ ] Regex de detection de GUIDs fixes dans les `.cs` : `Guid\s*\(\s*"([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})"\s*\)` puis test heuristique (pattern repete, sequentiel)

**Seed idempotence** :
- [ ] Chaque bloc de seed check l'existence avant insert : `AnyAsync(x => x.Code == "..." && x.ApplicationId == ...)`
- [ ] `ComponentKey` renseigne sur toutes les entites navigation (application/module/section/resource)
- [ ] Roles seedes avec filtre `Code + ApplicationId` (pas juste Code — collision entre apps)
- [ ] Permissions seedes avec filtre `Path + Action + SectionCode` (pas juste Path)

### Scaffold residuals

- [ ] **Pas de fichiers `.bak`** laisses par le Studio (a supprimer)
- [ ] **Pas de `.orig`, `.rej`, `.tmp`** dans le repo
- [ ] **Pas de `TODO: implement`** dans les tests generes
- [ ] **Pas de `Assert.True(true, "TODO")`** ou `expect(true).toBe(true)` dans les tests
- [ ] **Pas de `/* map dto fields */`** dans les controllers
- [ ] **Pas de `Guid.NewGuid()` a la volee dans les seeds** (doit etre en `static readonly` au niveau classe)

## Plan d'execution

1. **Collect** : `grep` les patterns de detection sur tout le code
2. **Classify** : chaque violation → auto-fixable vs ambigue vs critical
3. **Auto-fix** : pour les mecaniques (remplacer string → t('key'), ajouter cles aux 4 locales, supprimer .bak)
4. **Report** : pour les ambigues/critical, suggestion + chemin du fichier + ligne
5. **Verify** : relancer les tests / TSC / build si possible

## Output attendu

```
━━━ Audit report ━━━

✓ i18n: 0 hardcoded strings in JSX
⚠ i18n: 3 missing keys in de.json (fixed: directory.form.relations.title, ...)
✗ i18n: 1 validation key reused outside context
  - components/directory/ContactRelationsTab.tsx:142
    uses `lastNameRequired` for field `target`
    → Suggestion: create `targetContactRequired` + update

✓ Dynamic Routing: componentRegistry imported in main.tsx
✗ Dynamic Routing: 2 pages missing PageRegistry.register()
  - src/pages/hrm/employees/EmployeeListPage.tsx exists but no entry for 'hrm.employees' in any Registry.ts
  - Route menu API returns componentKey 'hrm.employees.detail' but registry has no match
✗ Dynamic Routing: 1 static route found
  - src/App.tsx:42 — <Route path="/hrm/custom" element={<Custom />} />
    → DynamicRouter handles all routes; move to seed data + PageRegistry

✓ RBAC: 28/28 permissions match format app.module.section.action
✗ RBAC: 1 hardcoded permission string outside PermissionsClass
  - src/Api/Controllers/Hrm/EmployeesController.cs:87 — "hrm.employees.approve"
    → Move to HrmPermissions.Employees.Approve

✓ React: useCallback deps clean
⚠ React: 1 useEffect without cleanup
  - components/contacts/ContactListPage.tsx:88
    subscribes to `window.studio.onEvent` without offEvent

✓ Structure: layer violations 0
✗ Scaffold: 2 .bak files
  - src/main.tsx.bak (auto-deleted)
  - components/App.tsx.bak (auto-deleted)
✗ Scaffold: 4 test files with `Assert.True(true, "TODO")`
  - Tests/Hrm/Api/EmployeesControllerTests.cs (9 occurrences)
    → Regenerate via skills/development/testing

✓ GUIDs: no predictable patterns detected

[exit 0 — 3 fixes applied, 4 issues to review]
```

## Rules

- **Ne jamais** modifier le CLAUDE.md du projet
- **Toujours** verifier les 4 locales (fr/en/it/de) quand on ajoute une cle
- **Batch** : un commit par categorie de fix (i18n, routing, react, scaffold, rbac)
- **Escalade** : si plus de 10 issues dans une categorie, stopper et demander validation
- **Routing dynamique** : toute violation est CRITIQUE car elle produit des pages blanches sans erreur console — NE PAS auto-fixer, toujours rapporter pour revue humaine
