efarmz-slackbot-data 1.0.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/.clever.json +12 -0
- package/.dockerignore +13 -0
- package/.env.example +28 -0
- package/.github/workflows/deploy-production.yaml +34 -0
- package/.prettierrc +6 -0
- package/.tasks/F1-bootstrap.md +110 -0
- package/.tasks/F2-domain-layer.md +173 -0
- package/.tasks/F3-application-layer.md +166 -0
- package/.tasks/F4-infrastructure-layer.md +229 -0
- package/.tasks/F5-config-main.md +160 -0
- package/.tasks/F6-schemas-deployment.md +129 -0
- package/CLAUDE.md +163 -0
- package/Dockerfile +15 -0
- package/PRD.md +119 -0
- package/docs/schemas/.gitkeep +0 -0
- package/docs/schemas/_guidelines.md +89 -0
- package/docs/schemas/efarmz_db.md +759 -0
- package/docs/schemas/example.md +16 -0
- package/eslint.config.mjs +18 -0
- package/package.json +54 -0
- package/releaserc.json +15 -0
- package/src/.gitkeep +0 -0
- package/src/application/agent/.gitkeep +0 -0
- package/src/application/agent/AgentContext.test.ts +263 -0
- package/src/application/agent/AgentContext.ts +93 -0
- package/src/application/agent/AgentLoop.test.ts +275 -0
- package/src/application/agent/AgentLoop.ts +101 -0
- package/src/application/agent/AgentRunResult.ts +11 -0
- package/src/application/agent/LLMMessage.ts +16 -0
- package/src/application/agent/tools/RunSqlTool.ts +23 -0
- package/src/application/formatting/.gitkeep +0 -0
- package/src/application/formatting/CsvRenderer.test.ts +162 -0
- package/src/application/formatting/CsvRenderer.ts +34 -0
- package/src/application/formatting/MonospaceTableRenderer.test.ts +129 -0
- package/src/application/formatting/MonospaceTableRenderer.ts +58 -0
- package/src/application/formatting/RenderedResponse.ts +7 -0
- package/src/application/formatting/ResponseRenderer.test.ts +159 -0
- package/src/application/formatting/ResponseRenderer.ts +39 -0
- package/src/application/formatting/ScalarRenderer.test.ts +36 -0
- package/src/application/formatting/ScalarRenderer.ts +12 -0
- package/src/application/usecases/.gitkeep +0 -0
- package/src/application/usecases/AnswerQuestion.test.ts +362 -0
- package/src/application/usecases/AnswerQuestion.ts +69 -0
- package/src/application/usecases/ParseQuestion.test.ts +39 -0
- package/src/application/usecases/ParseQuestion.ts +9 -0
- package/src/config/.gitkeep +0 -0
- package/src/config/Container.test.ts +35 -0
- package/src/config/Container.ts +74 -0
- package/src/config/constants.ts +9 -0
- package/src/config/env.test.ts +103 -0
- package/src/config/env.ts +41 -0
- package/src/domain/entities/.gitkeep +0 -0
- package/src/domain/entities/Conversation.test.ts +69 -0
- package/src/domain/entities/Conversation.ts +26 -0
- package/src/domain/entities/ConversationMessage.test.ts +49 -0
- package/src/domain/entities/ConversationMessage.ts +18 -0
- package/src/domain/entities/index.ts +2 -0
- package/src/domain/errors/.gitkeep +0 -0
- package/src/domain/errors/AgentLoopExceededError.ts +12 -0
- package/src/domain/errors/DomainError.test.ts +106 -0
- package/src/domain/errors/DomainError.ts +11 -0
- package/src/domain/errors/InvalidSqlError.ts +15 -0
- package/src/domain/errors/LLMError.ts +15 -0
- package/src/domain/errors/SchemaLoadError.ts +15 -0
- package/src/domain/errors/SqlExecutionError.ts +15 -0
- package/src/domain/errors/index.ts +15 -0
- package/src/domain/ports/.gitkeep +0 -0
- package/src/domain/ports/AdminLogger.ts +16 -0
- package/src/domain/ports/ConversationRepository.ts +10 -0
- package/src/domain/ports/LLMProvider.ts +33 -0
- package/src/domain/ports/Logger.ts +8 -0
- package/src/domain/ports/SchemaCatalog.ts +5 -0
- package/src/domain/ports/SlackMessenger.ts +8 -0
- package/src/domain/ports/SqlExecutor.ts +8 -0
- package/src/domain/ports/SqlValidator.ts +5 -0
- package/src/domain/ports/index.ts +17 -0
- package/src/domain/value-objects/.gitkeep +0 -0
- package/src/domain/value-objects/LLMProviderName.ts +6 -0
- package/src/domain/value-objects/QueryResult.test.ts +51 -0
- package/src/domain/value-objects/QueryResult.ts +18 -0
- package/src/domain/value-objects/Question.test.ts +59 -0
- package/src/domain/value-objects/Question.ts +22 -0
- package/src/domain/value-objects/QuestionFlags.test.ts +59 -0
- package/src/domain/value-objects/QuestionFlags.ts +18 -0
- package/src/domain/value-objects/ResponseRendering.ts +7 -0
- package/src/domain/value-objects/SqlQuery.test.ts +40 -0
- package/src/domain/value-objects/SqlQuery.ts +12 -0
- package/src/domain/value-objects/ThreadId.test.ts +68 -0
- package/src/domain/value-objects/ThreadId.ts +27 -0
- package/src/domain/value-objects/index.ts +13 -0
- package/src/infrastructure/llm/.gitkeep +0 -0
- package/src/infrastructure/llm/AnthropicLLMProvider.test.ts +229 -0
- package/src/infrastructure/llm/AnthropicLLMProvider.ts +45 -0
- package/src/infrastructure/llm/index.ts +4 -0
- package/src/infrastructure/llm/mappers/AnthropicMessageMapper.test.ts +173 -0
- package/src/infrastructure/llm/mappers/AnthropicMessageMapper.ts +34 -0
- package/src/infrastructure/llm/prompts/SystemPromptBuilder.test.ts +41 -0
- package/src/infrastructure/llm/prompts/SystemPromptBuilder.ts +31 -0
- package/src/infrastructure/llm/prompts/ToolDefinitions.ts +7 -0
- package/src/infrastructure/logging/.gitkeep +0 -0
- package/src/infrastructure/logging/PinoLogger.test.ts +59 -0
- package/src/infrastructure/logging/PinoLogger.ts +28 -0
- package/src/infrastructure/logging/index.ts +1 -0
- package/src/infrastructure/persistence/.gitkeep +0 -0
- package/src/infrastructure/persistence/InMemoryConversationRepository.test.ts +325 -0
- package/src/infrastructure/persistence/InMemoryConversationRepository.ts +69 -0
- package/src/infrastructure/persistence/PostgresPoolFactory.ts +11 -0
- package/src/infrastructure/persistence/PostgresSqlExecutor.test.ts +130 -0
- package/src/infrastructure/persistence/PostgresSqlExecutor.ts +34 -0
- package/src/infrastructure/persistence/index.ts +3 -0
- package/src/infrastructure/schemas/.gitkeep +0 -0
- package/src/infrastructure/schemas/FileSystemSchemaCatalog.test.ts +163 -0
- package/src/infrastructure/schemas/FileSystemSchemaCatalog.ts +35 -0
- package/src/infrastructure/schemas/index.ts +4 -0
- package/src/infrastructure/slack/.gitkeep +0 -0
- package/src/infrastructure/slack/BoltSlackMessenger.test.ts +59 -0
- package/src/infrastructure/slack/BoltSlackMessenger.ts +36 -0
- package/src/infrastructure/slack/SlackAdminLogger.test.ts +54 -0
- package/src/infrastructure/slack/SlackAdminLogger.ts +27 -0
- package/src/infrastructure/slack/SlackApp.ts +9 -0
- package/src/infrastructure/slack/handlers/AppMentionHandler.ts +52 -0
- package/src/infrastructure/slack/handlers/DirectMessageHandler.ts +65 -0
- package/src/infrastructure/slack/index.ts +5 -0
- package/src/infrastructure/sql/.gitkeep +0 -0
- package/src/infrastructure/sql/RegexSqlValidator.test.ts +242 -0
- package/src/infrastructure/sql/RegexSqlValidator.ts +53 -0
- package/src/infrastructure/sql/index.ts +1 -0
- package/src/main.ts +19 -0
- package/tsconfig.json +23 -0
- package/vitest.config.ts +15 -0
- package/vitest.setup.ts +23 -0
package/Dockerfile
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM node:22-slim AS builder
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY package.json yarn.lock ./
|
|
4
|
+
RUN yarn install --frozen-lockfile
|
|
5
|
+
COPY . .
|
|
6
|
+
RUN yarn build
|
|
7
|
+
|
|
8
|
+
FROM node:22-slim AS runtime
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
COPY --from=builder /app/dist ./dist
|
|
11
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
12
|
+
COPY --from=builder /app/docs ./docs
|
|
13
|
+
COPY --from=builder /app/package.json ./
|
|
14
|
+
ENV NODE_ENV=production
|
|
15
|
+
CMD ["node", "dist/main.js"]
|
package/PRD.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "[PRD] Bot Slack NL→SQL — efarmz-slackbot-data"
|
|
3
|
+
type: prd
|
|
4
|
+
status: approved
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# PRD: Bot Slack — Interrogation en langage naturel sur les bases analytiques efarmz
|
|
8
|
+
|
|
9
|
+
## Executive Summary
|
|
10
|
+
|
|
11
|
+
Service Node.js/TypeScript standalone qui écoute les mentions et DM Slack, traduit les questions en langage naturel vers des requêtes SQL via un LLM (Claude Haiku 4.5) avec boucle agentique, exécute les requêtes en read-only sur les bases PostgreSQL analytiques efarmz, et renvoie les résultats formatés (texte / table monospace / CSV) en threading Slack. Architecture DDD hexagonale, sécurité SQL en 4 couches, déployé sur Clever Cloud via Docker.
|
|
12
|
+
|
|
13
|
+
## Problem Statement
|
|
14
|
+
|
|
15
|
+
L'équipe efarmz a besoin d'interroger ses bases analytiques PostgreSQL (commandes, clients, produits, Intercom…) sans écrire de SQL manuellement. Aujourd'hui, obtenir une statistique ad hoc nécessite de solliciter un développeur ou d'accéder directement à la base, ce qui est lent, bloquant et risqué. Un bot Slack permettrait à n'importe quel membre de l'équipe de poser une question en français et d'obtenir un résultat immédiat, sans exposition directe aux données ni risque de mutation accidentelle.
|
|
16
|
+
|
|
17
|
+
## User Stories
|
|
18
|
+
|
|
19
|
+
### Primary User Story
|
|
20
|
+
|
|
21
|
+
En tant que membre de l'équipe efarmz, je veux poser une question en langage naturel dans Slack (mention ou DM) et recevoir la réponse tirée de la base de données en quelques secondes, sans écrire de SQL.
|
|
22
|
+
|
|
23
|
+
### Additional User Stories
|
|
24
|
+
|
|
25
|
+
- En tant qu'analyste, je veux recevoir un tableau monospace ou un fichier CSV pour les résultats larges, afin de pouvoir les exploiter directement.
|
|
26
|
+
- En tant que développeur, je veux ajouter `--sql` à ma question pour voir la requête SQL générée et vérifier sa pertinence.
|
|
27
|
+
- En tant que développeur, je veux ajouter `--debug` pour obtenir le plan d'exécution EXPLAIN et diagnostiquer les performances.
|
|
28
|
+
- En tant qu'utilisateur, je veux que le bot se souvienne du contexte du thread pour poser des questions de suivi sans répéter le contexte.
|
|
29
|
+
- En tant qu'administrateur, je veux recevoir des logs de chaque requête (question, SQL, durée, coût token) dans un channel admin dédié.
|
|
30
|
+
|
|
31
|
+
## Functional Requirements
|
|
32
|
+
|
|
33
|
+
- Le bot répond aux `app_mention` et aux DM (`message.im`)
|
|
34
|
+
- Le message est parsé : strip de la mention `<@U…>`, extraction des flags `--sql`, `--debug`, `--no-context`
|
|
35
|
+
- La boucle agentique traduit la question en SQL via Claude Haiku 4.5, exécute via `run_sql` tool, corrige automatiquement sur erreur SQL (max 5 tours)
|
|
36
|
+
- Le SQL est validé avant exécution : SELECT/WITH uniquement, keywords mutables refusés, LIMIT forcé à 100 lignes max
|
|
37
|
+
- Le format de réponse est déterministe : scalaire (1×1), table monospace (≤15 lignes), table tronquée + CSV uploadé (>15 lignes)
|
|
38
|
+
- L'historique de conversation est maintenu par thread (LRU mémoire, TTL 1h, max 200 threads, max 8 messages)
|
|
39
|
+
- Le flag `--no-context` ignore l'historique du thread courant
|
|
40
|
+
- Le flag `--debug` ajoute le SQL + résultat EXPLAIN au message
|
|
41
|
+
- Le bot log chaque requête dans le channel admin (question, sqls[], rowsCount, durationMs, tokens)
|
|
42
|
+
- Le boot échoue si une variable d'environnement requise est manquante (fail-fast via zod)
|
|
43
|
+
- La doc des schémas PostgreSQL est chargée depuis `docs/schemas/*.md` au démarrage
|
|
44
|
+
|
|
45
|
+
## Non-Functional Requirements
|
|
46
|
+
|
|
47
|
+
- **Performance** : ack Slack < 3s (200 OK immédiat, traitement async) ; timeout SQL = 30s ; réponse totale < 60s
|
|
48
|
+
- **Sécurité** : utilisateur PostgreSQL read-only dédié + RegexSqlValidator + statement_timeout + SqlQuery VO (constructeur privé) — 4 couches indépendantes
|
|
49
|
+
- **Fiabilité** : idempotence par `event_id` (cache 5 min) pour absorber les retries Slack
|
|
50
|
+
- **Coûts** : prompt caching (`cache_control: ephemeral`) sur la doc schémas — économie ~80% tokens sur rafales ; modèle Haiku = quelques centimes/question
|
|
51
|
+
- **Maintenabilité** : architecture DDD hexagonale stricte, dependency rule non-négociable, ports fins (ISP), tests unitaires sur domain + validators + formatters
|
|
52
|
+
- **Extensibilité** : interface `LLMProvider` découplée — ajouter OpenAI = 1 fichier, 0 modif ailleurs
|
|
53
|
+
- **Déploiement** : Dockerisé, déployable sur Clever Cloud sans friction
|
|
54
|
+
|
|
55
|
+
## Success Metrics
|
|
56
|
+
|
|
57
|
+
### Primary Metrics
|
|
58
|
+
|
|
59
|
+
- Taux de réponse correcte (SQL valide + résultat pertinent) : > 85% des questions
|
|
60
|
+
- Temps de réponse médian (de la question à la réponse Slack) : < 15s
|
|
61
|
+
- Zéro mutation de données en production (garantie structurelle, pas de monitoring)
|
|
62
|
+
|
|
63
|
+
### Secondary Metrics
|
|
64
|
+
|
|
65
|
+
- Coût moyen par question : < 0,05€ (Haiku 4.5 + caching)
|
|
66
|
+
- Taux de correction automatique SQL (boucle agentique) : mesuré via logs admin
|
|
67
|
+
- Adoption : > 5 utilisateurs actifs dans les 2 premières semaines
|
|
68
|
+
|
|
69
|
+
## Technical Considerations
|
|
70
|
+
|
|
71
|
+
Architecture hexagonale en 3 couches strictes (`domain` ← `application` ← `infrastructure` ← `main`) avec DI manuelle via `Container`. La règle de dépendance est non-négociable : `domain` n'importe aucun SDK tiers. La boucle agentique (`AgentLoop`) est indépendante du provider LLM et du tool concret. Le prompt caching Anthropic (`cache_control: ephemeral`, TTL 5 min) est appliqué sur le bloc system contenant la doc schémas.
|
|
72
|
+
|
|
73
|
+
Voir `.plans/efarmz-slackbot-data-712fe7.md` pour l'architecture complète, la structure des fichiers, les variables d'environnement et le SQL d'init du rôle read-only.
|
|
74
|
+
|
|
75
|
+
## Implementation Phases
|
|
76
|
+
|
|
77
|
+
### Phase 1 — Bootstrap & Domain (F1 + F2)
|
|
78
|
+
|
|
79
|
+
Setup du projet (tooling, config, Docker) et implémentation de la couche domain pure : entités, value objects, erreurs typées, ports (interfaces). Tests unitaires domain.
|
|
80
|
+
|
|
81
|
+
### Phase 2 — Application & Infrastructure (F3 + F4)
|
|
82
|
+
|
|
83
|
+
Use cases (`ParseQuestion`, `AnswerQuestion`), boucle agentique (`AgentLoop`), formatters de réponse. Puis adapters infra : `RegexSqlValidator`, `PostgresSqlExecutor`, `InMemoryConversationRepository`, `AnthropicLLMProvider`, handlers Slack, `PinoLogger`.
|
|
84
|
+
|
|
85
|
+
### Phase 3 — Config, Déploiement & Documentation (F5 + F6)
|
|
86
|
+
|
|
87
|
+
Composition root (`Container`), entry point (`main.ts`), doc des schémas PostgreSQL efarmz, `Dockerfile`, déploiement Clever Cloud, README.
|
|
88
|
+
|
|
89
|
+
## Risk Assessment
|
|
90
|
+
|
|
91
|
+
### Technical Risks
|
|
92
|
+
|
|
93
|
+
- **Qualité SQL générée** : Haiku peut générer des JOINs incorrects sur des schémas complexes → mitigation : doc schémas détaillée + boucle de correction automatique (max 5 tours)
|
|
94
|
+
- **Timeout LLM** : API Anthropic down → message Slack "Service IA temporairement indisponible" + log admin
|
|
95
|
+
- **Retries Slack** : event redelivery peut déclencher des doublons → mitigation : déduplication par `event_id` (cache 5 min)
|
|
96
|
+
- **Explosion tokens** : historique de conversation trop long → mitigation : résumé condensé (pas les `tool_result` bruts), cap à 8 messages, TTL 1h
|
|
97
|
+
|
|
98
|
+
### Business Risks
|
|
99
|
+
|
|
100
|
+
- **PII dans les résultats** : les tables peuvent contenir emails/noms → mitigation : workspace Slack privé uniquement, accepté
|
|
101
|
+
- **Questions hors-scope** : le LLM peut tenter des requêtes sur des tables sans documentation → mitigation : doc schémas complète obligatoire avant déploiement
|
|
102
|
+
|
|
103
|
+
## Dependencies
|
|
104
|
+
|
|
105
|
+
### Internal Dependencies
|
|
106
|
+
|
|
107
|
+
- Doc schémas PostgreSQL efarmz (`docs/schemas/efarmz_db.md`, etc.) — fournie par l'utilisateur
|
|
108
|
+
- Credentials PostgreSQL (rôle `slackbot_readonly` à créer manuellement)
|
|
109
|
+
- Slack App configurée avec les bons scopes et l'URL de webhook
|
|
110
|
+
|
|
111
|
+
### External Dependencies
|
|
112
|
+
|
|
113
|
+
- `@slack/bolt` — HTTP receiver
|
|
114
|
+
- `@anthropic-ai/sdk` — Claude Haiku 4.5, tool_use, prompt caching
|
|
115
|
+
- `pg` — PostgreSQL pool
|
|
116
|
+
- `zod` — validation env vars + schemas
|
|
117
|
+
- `pino` — structured logging
|
|
118
|
+
- `vitest` — tests unitaires
|
|
119
|
+
- Clever Cloud — hébergement Docker
|
|
File without changes
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Guidelines — Mise à jour des docs schémas
|
|
2
|
+
|
|
3
|
+
Directives pour créer le skill `update-schema-doc` qui modernise les fiches schéma PostgreSQL.
|
|
4
|
+
|
|
5
|
+
## Entrées attendues
|
|
6
|
+
|
|
7
|
+
L'utilisateur fournit en langage libre un des cas suivants :
|
|
8
|
+
|
|
9
|
+
| Cas | Exemple | Cible dans le doc |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| Nouvelle table | "Ajoute la table `efarmz_db.coupons` avec colonnes id, code, discount, expires_at" | `## Tables / ### {domaine}` |
|
|
12
|
+
| Nouvelles colonnes | "Sur `art`, ajoute `weight_kg numeric` et `origin_country varchar`" | Lignes dans le tableau de la table |
|
|
13
|
+
| Suppression colonne | "Retire `psecotax` de `art`, on ne l'utilise plus" | Tableau de la table |
|
|
14
|
+
| Nouvelle règle métier | "Une commande est *cadeau* si `eorderd.artid = 'GIFT'` et `totalpaid = 0`" | `## Règles métier / ### {thème}` |
|
|
15
|
+
| Nouveau pattern SQL | "Voici le pattern pour calculer le délai entre commande et livraison : …" | `## Patterns SQL` (avec ancre) |
|
|
16
|
+
| Nouvelle gotcha PG | "Si tu fais `SUM(qty)` sur `eorderd` sans `GROUP BY w_orderid`, ça double-compte les meals" | `## Conventions globales` |
|
|
17
|
+
| Mise à jour règle existante | "Le seuil panier picking passe de 40 à 50" | Bloc existant + bump `last_updated` |
|
|
18
|
+
| Nouvel alias | "On utilise aussi `cuid` pour `c_uuid` dans certains exports" | `## Glossaire` |
|
|
19
|
+
|
|
20
|
+
## Algorithme
|
|
21
|
+
|
|
22
|
+
1. **Lire** `docs/schemas/{schema}.md` en entier.
|
|
23
|
+
2. **Classifier** l'input → un (ou plusieurs) des cas du tableau ci-dessus. Si ambigu, demander.
|
|
24
|
+
3. **Détecter doublon** :
|
|
25
|
+
- Pour une règle / pattern : grep sur le nom et sur le SQL canonique avant d'ajouter. Si existe → proposer un *update* au lieu d'un *ajout*.
|
|
26
|
+
- Pour une colonne : si déjà présente, demander si on remplace la description ou non.
|
|
27
|
+
4. **Choisir l'emplacement** :
|
|
28
|
+
- Table → mapper au domaine (Commandes / Catalogue / Abonnements / Clients / Référentiel). Si aucun ne colle, demander avant de créer une nouvelle sous-section.
|
|
29
|
+
- Règle métier → mapper à un thème existant (Filtres / Validité / Calculs / Frais). Sinon créer un thème.
|
|
30
|
+
- Pattern → bas de la section, avec ancre `#pattern-{slug}` cohérente.
|
|
31
|
+
5. **Appliquer l'édition** via `Edit` (string replace ciblé). Jamais `Write` complet — préserve le cache Anthropic et minimise le diff.
|
|
32
|
+
6. **Bumper le frontmatter** : `last_updated: {today}`.
|
|
33
|
+
7. **Vérifier l'invariant de format** :
|
|
34
|
+
- Backticks autour de tout nom SQL.
|
|
35
|
+
- Tableaux avec exactement les colonnes `| Colonne | Type | Rôle | Description |`.
|
|
36
|
+
- `⚠️` pour pièges, pas d'autres emojis.
|
|
37
|
+
- Pas de numérotation `## 1`, `## 2` — titres seuls.
|
|
38
|
+
8. **Retourner** un résumé : section touchée, lignes ajoutées/modifiées, alertes éventuelles (doublon détecté, ambiguïté résolue).
|
|
39
|
+
|
|
40
|
+
## Règles d'or (non-négociables)
|
|
41
|
+
|
|
42
|
+
- **DRY** : une règle métier vit à **un** seul endroit. Si un pattern SQL la matérialise, il **référence** la règle (`-- voir Règles métier / Validité abonnement`), il ne la duplique pas.
|
|
43
|
+
- **Pas de renumérotation** : titres sans numéros. Réorganiser ne casse pas les ancres.
|
|
44
|
+
- **Insertion en fin de sous-section** par défaut — préserve le cache Anthropic.
|
|
45
|
+
- **Refuser le contournement de sécurité** : si l'utilisateur demande d'ajouter une règle qui implique une mutation SQL (`UPDATE`, `DELETE`…), c'est hors-scope du bot read-only. Refuser et expliquer.
|
|
46
|
+
- **Demander avant de créer une nouvelle sous-section de domaine** ou un nouveau thème de règle métier — la taxonomie doit rester stable.
|
|
47
|
+
- **Ne jamais éditer le schéma sans validation** : si l'utilisateur dit "ajoute la colonne X" sans préciser le type, demander le type (et idéalement, vérifier en DB, ou demander à l'utilisateur de la fournir).
|
|
48
|
+
|
|
49
|
+
## Convention de tableau de colonnes
|
|
50
|
+
|
|
51
|
+
```markdown
|
|
52
|
+
| Colonne | Type | Rôle | Description |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| `id` | `uuid` | PK | — |
|
|
55
|
+
| `user_id` | `uuid` | FK → `users.id` | — |
|
|
56
|
+
| `status` | `int` | — | `1` = actif, `2` = pausé |
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- **Rôle** : `PK`, `FK → table.col`, `unique`, ou `—`.
|
|
60
|
+
- **Description** : sémantique métier seule. Pas de "FK vers X" dans description (c'est dans Rôle).
|
|
61
|
+
- **Type** : type SQL réel (`varchar(255)`, `numeric(10,2)`, `timestamp`, `int`, etc.).
|
|
62
|
+
|
|
63
|
+
## Convention de pattern SQL
|
|
64
|
+
|
|
65
|
+
````markdown
|
|
66
|
+
### {Nom court} {#pattern-{slug}}
|
|
67
|
+
**Quand** : {1 phrase, cas d'usage}
|
|
68
|
+
**Dépend de** : {refs aux règles métier ou autres patterns, optionnel}
|
|
69
|
+
|
|
70
|
+
```sql
|
|
71
|
+
-- code
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
⚠️ {piège éventuel, optionnel}
|
|
75
|
+
````
|
|
76
|
+
|
|
77
|
+
## Frontmatter du schéma
|
|
78
|
+
|
|
79
|
+
Chaque fichier `docs/schemas/{schema}.md` doit commencer par :
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
---
|
|
83
|
+
schema: {nom du schéma}
|
|
84
|
+
sgbd: postgresql
|
|
85
|
+
last_updated: YYYY-MM-DD
|
|
86
|
+
---
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Le `last_updated` est bumé à chaque édition via le skill.
|