# Specs Checker

> Vérifie qu'une implémentation respecte les specs de PLANING.MD (source de vérité Fidely). Déclencher quand : ajout feature, modification composable/page, avant commit important, si une règle métier semble violée, si un élément hors-scope est introduit. Mots-clés : client_id immuable, points ≥ 0, surplus récompense, RGPD, IndexedDB, QR code reset, Zod validation, light mode, switch mode, confirmation suppression, CardForm, useDB, consumeReward, updatePoints, hors-scope, PLANING.MD.

- Skill: `chawkitariq/specs-checker` (Agent Skill)
- Install (CLI): `npx skillmds@latest add chawkitariq/specs-checker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chawkitariq/specs-checker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: chawkitariq (https://skillmd.com/u/chawkitariq)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chawkitariq/specs-checker

---


# Skill : Vérificateur de specs (PLANING.MD)

Quand l'utilisateur demande d'ajouter une fonctionnalité, de modifier du code existant, ou avant tout commit important, passer en revue cette checklist contre `PLANING.MD` (source de vérité).

---

## Étape 1 — Lire les sources de vérité

Avant toute vérification, lire dans l'ordre :
1. `PLANING.MD` — vision, fonctionnalités, règles métier, hors scope, décisions
2. `CLAUDE.md` — conventions de code et interdictions
3. Le code concerné par la modification

---

## Étape 2 — Vérifier les 9 règles métier critiques

Ces règles ne doivent **jamais** être violées. Cocher chaque point.

### Règle 1 — `client_id` immuable
```
[ ] Le client_id est généré une seule fois (première ouverture)
[ ] Aucune fonction ne permet de le réinitialiser
[ ] Pas de bouton "reset" exposé sur /me
[ ] Stocké dans IndexedDB object store `config` (clé 'client_id') — via useClient()
```
> ✅ **Conforme** : `client_id` est dans IndexedDB `config` store via `useClient().getOrCreateClientId()`.

### Règle 2 — Points ≥ 0
```
[ ] updatePoints() utilise Math.max(0, current + delta)
[ ] Aucun chemin de code ne peut produire un solde négatif
[ ] Le bouton "−1" est désactivé (disabled) quand points === 0
```

### Règle 3 — Surplus de récompense conservé
```
[ ] consumeReward() = current - reward_points (pas de remise à zéro)
[ ] Si current > reward_points, le surplus (current - reward_points) est conservé
[ ] Exemple : 8 pts, seuil 6 → il reste 2 pts après consommation
[ ] consumeReward() lève une erreur si current < reward_points (pas de solde négatif)
```

### Règle 4 — Zéro donnée personnelle
```
[ ] Aucun champ nom / email / téléphone / adresse dans les formulaires
[ ] Aucune PII dans IndexedDB (cards, clients)
[ ] Les identifiants = UUID anonymes uniquement
[ ] Aucun appel réseau ou tracking
```

### Règle 5 — Données 100% locales (IndexedDB)
```
[ ] Aucune requête HTTP vers un serveur externe
[ ] Aucun cookie posé
[ ] Aucune donnée métier en localStorage (sauf mode UI temporaire — toléré)
[ ] Pas d'intégration analytics (GA, Plausible, Sentry…)
```

### Règle 6 — QR code sans reset
```
[ ] /me n'affiche pas de bouton "Nouveau QR code" ou "Réinitialiser"
[ ] La valeur du QR code est toujours le client_id existant
[ ] Aucune action utilisateur ne peut modifier le client_id
```

### Règle 7 — Validation Zod obligatoire
```
[ ] CardForm.vue utilise cardSchema (utils/validators.ts) avant persistance
[ ] Les champs validés : title (non vide), reward_points (≥ 1), reward (non vide)
[ ] Les erreurs Zod sont affichées via UFormField (name correspondant à la clé state)
[ ] Aucun addCard() / updateCard() appelé sans validation préalable
```
> ✅ **Conforme** : `CardForm.vue` utilise `cardSchema` + `UForm :validate` + `UFormField`.

### Règle 8 — Light mode forcé
```
[ ] Aucun composant UColorModeButton présent
[ ] Aucune classe dark: dans les templates
[ ] Aucun appel useColorMode() pour switcher
[ ] colorMode: { preference: 'light', fallback: 'light' } si ajouté à nuxt.config.ts
```

### Règle 9 — Switch de mode visible partout
```
[ ] Un bouton de switch mode Pro↔Client est présent sur TOUTES les pages
[ ] /merchant → bouton vers /me (mode client)
[ ] /me → bouton vers /merchant (mode commerçant)
[ ] /scan → bouton de retour visible (+ accès switch si besoin)
[ ] /client/[id] → navigation claire vers /scan ou /merchant
```

---

## Étape 3 — Vérifier le hors-scope

Signaler immédiatement si une modification introduit l'un de ces éléments :

```
❌ Authentification (login, password, session, JWT)
❌ Synchronisation cloud ou multi-appareils
❌ Notifications push (Web Push, FCM…)
❌ Historique des transactions
❌ Statistiques / analytics / dashboard
❌ Multi-langue (i18n)
❌ Dark mode
❌ Backend / API routes SSR / base de données distante
```

Si l'un de ces points est présent → **stopper et demander confirmation** à l'utilisateur avant de continuer.

---

## Étape 4 — Vérifier les décisions techniques actées

| Décision | Vérification |
|---|---|
| IndexedDB uniquement | Pas de `localStorage` pour données métier |
| Zod pour validation | `utils/validators.ts` utilisé dans les formulaires |
| `html5-qrcode` pour scan | Import dynamique dans `onMounted` uniquement |
| Nuxt UI pour les composants | Pas de shadcn, Vuetify, Headless UI |
| Light mode forcé | Pas de `useColorMode()` ni classe `dark:` |
| Pas de backend | Aucun fichier dans `server/api/` sans discussion |

---

## Étape 5 — Vérifier la checklist MVP (PLANING.MD)

Pour chaque modification, identifier quelles cases de la checklist sont concernées et vérifier qu'elles sont correctement implémentées.

**Switch de mode**
- Mémorisation du mode → `localStorage` (`fidely_mode`) — conforme PLANING.MD règle 5
- Visible sur toutes les pages

**Mode Professionnel — Cartes**
- ✅ `CardForm.vue` séparé dans `app/components/`
- ✅ Validation Zod via `app/utils/validators.ts` (`cardSchema`)
- ✅ CRUD complet : `getAllCards`, `addCard`, `updateCard`, `deleteCard` dans `useDB`
- ✅ Pages dédiées `/merchant/new` et `/merchant/[id]/edit`

**Mode Professionnel — Points**
- ✅ Scan → redirect `/client/[id]` → actions ➕ ➖ 🎁
- ✅ Mise à jour immédiate IndexedDB via `updatePoints` / `consumeReward`

**Mode Client**
- ✅ `client_id` dans IndexedDB `config` store via `useClient()`
- ✅ QR code stable, pas de bouton reset sur `/me`

**IndexedDB / Composables**
- ✅ `updateCard()` implémenté dans `useDB.ts`
- ✅ `createClient()` implémenté (+ création implicite dans `updatePoints`)
- ✅ `getConfig()` / `setConfig()` pour le store `config`

**PWA**
- ✅ Offline-first via workbox (`pnpm build && pnpm preview`)
- ⏳ Icônes réelles — placeholders verts encore en place (`public/pwa-*.png`)

---

## Étape 6 — Rapport de vérification

Produire un rapport structuré :

```markdown
## Résultat specs-checker

### ✅ Conforme
- [liste des règles respectées]

### ⚠️ Divergences existantes (connues)
- client_id en localStorage au lieu d'IndexedDB
- Validation sans Zod (inline dans merchant.vue)
- updateCard() non implémenté
- CardForm.vue non créé

### ❌ Nouvelles violations détectées
- [si applicable]

### 🚫 Hors-scope détecté
- [si applicable]

### 📋 Actions recommandées
- [liste priorisée des corrections à apporter]
```

---

## État de conformité (mis à jour 2026-03-21)

Toutes les divergences historiques ont été résolues. Le seul point en attente est cosmétique :

| Spec PLANING.MD | Code actuel | État |
|---|---|---|
| `client_id` dans IndexedDB | `useClient()` → `config` store | ✅ Conforme |
| Mode mémorisé dans localStorage | `localStorage.setItem('fidely_mode')` | ✅ Conforme |
| Validation Zod dans `utils/validators.ts` | `cardSchema` + `CardForm.vue` | ✅ Conforme |
| `CardForm.vue` composant séparé | `app/components/CardForm.vue` | ✅ Conforme |
| `updateCard()` dans `useDB.ts` | Implémenté + testé | ✅ Conforme |
| `createClient()` explicite | `createClient()` + implicite dans `updatePoints` | ✅ Conforme |
| Icônes PWA réelles | Placeholders PNG verts | ⏳ En attente |

---

## Confirmation en fin de vérification

> ✅ **specs-checker passé**
> - Règles métier 1-11 : [conformes / violation détectée sur règle X]
> - Hors-scope : [aucun élément hors-scope introduit]
> - Décisions techniques : [respectées]
> - Checklist MVP : [conforme / point en attente : X]

