Étude de cas : granit-golem
Granit Golem
Continuous Quality Monitoring en Rust
Plateforme SaaS de monitoring d'infrastructure en temps réel. Définition des checks as code, alerting instantané, quality audits automatisés et dashboard de supervision multi-tenant. Backend Rust haute performance (Axum + Tokio), frontend Nuxt 3, base PostgreSQL avec RLS. Développé intégralement avec Claude Code en architecture DDD + Clean Architecture.
granit-golem est une plateforme SaaS de continuous quality monitoring développée en Rust avec 14 crates DDD, représentant le projet le plus actif de mon lab avec 552 commits et 622 sessions Claude Code en 2026.
1. Contexte et objectifs
Problématique métier
granit-golem répond à un besoin critique de surveillance de santé d'une infrastructure distribuée :
- Monitoring multi-services (API, bases de données, services tiers)
- Alerting en temps réel avec escalade configurable
- Dashboard de visualisation de l'état de santé
- Historique et métriques pour analyse de tendances
Pourquoi Rust ?
Performance
Faible empreinte mémoire, latence minimale pour les health checks fréquents.
Fiabilité
Garanties de sécurité mémoire, pas de panics non gérées en production.
Typage strict
Détection d'erreurs à la compilation, moins de bugs en runtime.
Async natif
Tokio runtime pour gérer des centaines de checks simultanés.
2. Parcours utilisateur illustré
Granit Golem propose une expérience complète de monitoring, de l'inscription à la supervision avancée. Voici le parcours type d'un utilisateur.
Landing page et inscription
La landing page présente les fonctionnalités clés : Health Checks, Quality Audits et Drift Detection. Le système supporte 15+ types de sondes, une latence d'alerte inférieure à 1 seconde, et un monitoring 24/7. L'inscription est gratuite, sans carte bancaire, avec une mise en route en 5 minutes.
Landing page : Health Checks, Quality Audits, Drift Detection
Page complète avec témoignages, pricing et CTA
Authentification
L'authentification utilise JWT avec support "Remember me". L'interface est split-screen : formulaire à gauche, branding et statistiques à droite. Support du "Forgot password" avec envoi d'email via Mailjet.
Page de connexion :design split-screen dark theme
Connexion avec email, mot de passe et "Remember me"
Dashboard de supervision
Le dashboard offre une vue globale de la santé de l'infrastructure avec un indicateur de santé en temps réel (100% Health), le nombre de checks actifs et leur statut (passing/warning/failing). Les Projects SLI donnent une vision par projet avec le Service Level Indicator. Le graphique Execution Trend (24h) affiche les temps de réponse moyens et la distribution par type de check (HTTP, Web Accessibility, DNS).
Dashboard :santé globale, SLI par projet et trend d'exécution
Vue complète :graphiques de tendance et distribution par type de check
Gestion des Health Checks
La page Health Checks affiche les 9 checks configurés avec leur statut en temps réel. Chaque check montre le nom, le projet associé, l'URL cible, le temps de réponse et le rating (Excellent/Rapide). Les checks couvrent Security Headers, WCAG Accessibility, Web Performance et HTTP/DNS. Le filtrage est possible par projet et par statut.
Health Checks - 9 checks actifs, tous Excellent, filtrage par projet/statut
Auto-Discovery :entrez une URL ou connexion DB pour créer les checks automatiquement
Quality Audits
Les Quality Audits combinent plusieurs health checks en une évaluation pondérée globale. Chaque audit affiche un score (Excellent 90-100, Good 70-89, Needs Work 50-69, Poor 0-49) et peut être déclenché manuellement ou planifié. L'audit "Frontend Audit - siliceum.com FR" regroupe 3 checks (Security Headers, WCAG Accessibility, Web Performance).
Audits :score pondéré, grille Excellent/Good/Poor, déclenchement manuel
Alerting :alertes par projet, règles, channels de notification
Projets, incidents et administration
La gestion par projets permet d'organiser les checks par environnement (Production, Staging). La page Incidents affiche l'état opérationnel global. Les settings couvrent la configuration de l'organisation (Team, Billing, Integrations), le compte personnel (Profil, Sécurité, Notifications) et les clés API.
Projets :organisation par environnement, barre de santé par projet
Incidents :état opérationnel, compteurs Critical/Warning
Settings - Organisation, compte personnel, API Keys
Fonctionnalités transverses
Multi-tenant
Isolation complète par organisation via RLS PostgreSQL. Chaque tenant ne voit que ses données. Plans Enterprise, Team et Free avec quotas différenciés.
Alerting configurable
Règles d'alerte avec conditions, seuils et escalade. Notifications par email (Mailjet), webhook et Slack. Historique complet des alertes avec timeline.
Projets multiples
Organisation des checks et audits par projet (production, staging, development). Chaque projet a sa propre configuration et ses propres seuils.
API REST complète
API documentée pour intégration CI/CD. Création de checks programmatique, déclenchement d'audits à la demande, export de métriques vers Prometheus.
3. Architecture technique
Domain-Driven Design
Le projet applique rigoureusement les principes DDD :
granit-golem/
├── backend/ # Rust workspace (14 crates DDD)
│ └── crates/
│ ├── shared-kernel/ # Types communs, identifiants, events
│ ├── monitoring-domain/ # Check aggregate, Target, Thresholds
│ ├── monitoring-application/ # CQRS commands/queries, DTOs
│ ├── monitoring-infrastructure/ # Probes, repositories
│ ├── audit-domain/ # Audit aggregate, scores, drift
│ ├── audit-application/ # CQRS audit commands/queries
│ ├── audit-infrastructure/ # Lighthouse, security scanners
│ ├── discovery/ # Service discovery
│ ├── api-types/ # Type definitions for API
│ ├── api-core/ # Shared API middleware
│ ├── api-server/ # Axum REST API, auth, PostgreSQL
│ └── cli/ # CLI interface (Clap)
├── frontend/ # Nuxt 3 SPA (Vue 3, Tailwind, Pinia)
│ ├── e2e/ # Playwright E2E (page objects)
│ └── i18n/ # Multi-langue FR/EN
├── specifications/ # Gherkin BDD specs (59% coverage)
├── scripts/ # CI/CD, testing, quality gates
│ ├── testing/validate.sh # Full validation (before push)
│ └── ci/gitlab-cli.ts # GitLab CLI integration
└── .claude/
├── CLAUDE.md # ~757 lignes d'instructions
└── agents/ # 6 agents spécialisés Patterns architecturaux clés
Outbox Pattern
Garantie de livraison des événements avec table outbox et worker asynchrone. Évite la perte d'alertes en cas de crash.
// Insertion atomique avec la transaction métier
pub async fn execute_check(&self, check: Check) -> Result<CheckResult> {
let mut tx = self.pool.begin().await?;
let result = self.check_service.execute(&check).await?;
self.check_repo.save_result(&mut tx, &result).await?;
// Outbox dans la même transaction
self.outbox.publish(&mut tx, CheckCompletedEvent::from(&result)).await?;
tx.commit().await?;
Ok(result)
} Row-Level Security (RLS)
Isolation multi-tenant au niveau PostgreSQL. Chaque organisation ne voit que ses propres données.
-- Politique RLS
CREATE POLICY tenant_isolation ON checks
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- Application dans le code Rust
sqlx::query("SET LOCAL app.tenant_id = $1")
.bind(&tenant_id)
.execute(&mut *tx)
.await?; Observabilité (OpenTelemetry)
Tracing distribué avec corrélation des spans, métriques Prometheus, logs structurés.
#[tracing::instrument(skip(self), fields(check_id = %check.id))]
pub async fn execute(&self, check: &Check) -> Result<CheckResult> {
let span = tracing::info_span!("http_check", url = %check.url);
let response = self.http_client
.get(&check.url)
.send()
.instrument(span)
.await?;
// Métriques Prometheus
CHECK_DURATION_HISTOGRAM
.with_label_values(&[&check.name])
.observe(response.elapsed().as_secs_f64());
// ...
} 4. Utilisation de Claude Code
Configuration CLAUDE.md
Le fichier CLAUDE.md de granit-golem est le plus complet du lab avec 757 lignes et 6 agents spécialisés :
Sections clés du CLAUDE.md
- Mode autonome : /autopilot activé pour maintenance et refactoring
- Règles obligatoires :
cargo fmtavant commit,validate.shavant push - TDD obligatoire : Chaque feature/fix nécessite des tests E2E
- Scripts TypeScript only : Pas de JavaScript dans le tooling
- Pièges connus : Mocks E2E pour sous-routes, DATABASE_URL depuis .env
- Workflow GitLab : Issues, épiques, kanban avec labels (P0-P3), quality gates
6 agents Claude spécialisés
- senior-rust-dev (375 lignes) : expertise Rust, DDD, performance
- senior-sre-architect : infrastructure, déploiement, monitoring
- qa-tester : tests E2E, Playwright, couverture
- sre-product-owner : priorisation, roadmap, specs
- pipeline-monitor : CI/CD, quality gates, pipelines
- project-maestro : orchestration globale du projet
Extrait du CLAUDE.md
CLAUDE.md 757 lignes ## Rust-specific rules
### Compilation check
- ALWAYS run `cargo clippy -- -D warnings` before considering code done
- NEVER suppress clippy lints without explicit justification
- Run `cargo fmt --check` to validate formatting
### Async patterns (MANDATORY)
Every async function MUST follow this template:
```rust
#[tracing::instrument(skip(self), fields(entity_id = %id))]
pub async fn my_function(&self, id: Uuid) -> Result<MyType> {
let span = tracing::info_span!("operation_name");
// ... implementation ...
.instrument(span)
.await?
}
```
### Error handling
- Use `thiserror` for domain errors, `anyhow` for infra
- NEVER use `.unwrap()` in production code
- Pattern: `map_err(|e| DomainError::from(e))?`
### Testing
- Unit tests in same file: `#[cfg(test)] mod tests`
- Integration tests in `/tests` directory
- ALWAYS mock external services (DB, HTTP, MQ)
- Target: 85%+ coverage on domain layer
### Database migrations
BEFORE creating any migration:
1. Check existing data impact
2. Provide rollback migration
3. Use `IF NOT EXISTS` / `IF EXISTS` guards
4. Test migration on copy of prod data Workflow typique
Ticket GitLab
Issue créée avec specs
Claude lit l'issue
Analyse et planification
TDD
Tests first, puis impl
CI validée
Clippy + tests + build
MR créée
Review et merge
Scripts d'automation GitLab
Le projet utilise des scripts TypeScript pour automatiser les interactions GitLab, combinant la librairie @gitbeaker/node et le GitLab CLI (glab) :
GitLab CLI (glab) - Commandes fréquentes
# Créer une MR depuis la branche courante
glab mr create --title "feat: add health check endpoint" \
--description "Implements HC for Redis cluster" \
--label "claude-code,auto-generated" \
--assignee @lead-dev \
--remove-source-branch
# Lister les issues assignées
glab issue list --assignee=@me --label="claude-code"
# Voir le pipeline CI en cours
glab ci status
# Consulter les logs d'un job CI
glab ci view --job-id 12345
# Créer une issue depuis Claude Code
glab issue create --title "fix: RLS policy missing on alerts table" \
--label "bug,security" \
--description "Discovered during integration test run"
# Checker le statut d'une MR
glab mr view 42 --comments Automatisation via @gitbeaker
// scripts/create-mr.ts
import { Gitlab } from '@gitbeaker/node';
async function createMergeRequest(branchName: string, title: string) {
const api = new Gitlab({ token: process.env.GITLAB_TOKEN });
await api.MergeRequests.create(PROJECT_ID, branchName, 'main', title, {
labels: ['claude-code', 'auto-generated'],
assignee_id: LEAD_DEV_ID,
remove_source_branch: true,
});
} Workflow automatisé complet
// scripts/auto-workflow.ts - Exécuté par Claude Code en /autopilot
import { Gitlab } from '@gitbeaker/node';
import { execSync } from 'child_process';
async function fullWorkflow(issueId: number) {
const api = new Gitlab({ token: process.env.GITLAB_TOKEN });
// 1. Lire l'issue
const issue = await api.Issues.show(PROJECT_ID, issueId);
// 2. Créer la branche
const branch = `feat/${issueId}-${slugify(issue.title)}`;
execSync(`git checkout -b ${branch}`);
// 3. [Claude Code implémente ici]
// 4. Push + MR
execSync(`git push -u origin ${branch}`);
const mr = await api.MergeRequests.create(
PROJECT_ID, branch, 'main', issue.title, {
labels: ['claude-code'],
assignee_id: LEAD_DEV_ID,
remove_source_branch: true,
description: `Closes #${issueId}\n\nGenerated by Claude Code`,
}
);
// 5. Attendre la CI
console.log(`MR !${mr.iid} created, waiting for CI...`);
} 5. Métriques et résultats
Vue d'ensemble (2026)
Types de fixes observés
| Catégorie | Nombre | Exemples |
|---|---|---|
| Sécurité | 3 | RLS policies, input validation, rate limiting |
| Migrations | 2 | Corrections de schéma, index manquants |
| Accessibilité | 2 | ARIA labels, contraste couleurs |
| CI/CD | 2 | Pipeline fixes, cache optimization |
| Autres | 1 | Typos, formatting |
Ratio sessions/commits : 1.13
Interprétation : Un ratio de 1.13 sessions par commit est très efficace : presque chaque session Claude produit un commit. Cela reflète un CLAUDE.md mature (757 lignes) et des agents bien calibrés qui minimisent les itérations inutiles.
Performance en production
6. Problèmes rencontrés et solutions
Lifetimes Rust complexes
Problème : Claude générait parfois du code avec des lifetimes incorrects, causant des erreurs de compilation cryptiques.
Solution : Ajout d'exemples de patterns corrects dans CLAUDE.md + instruction de toujours compiler avant de considérer le code terminé.
Async/await patterns
Problème : Confusion entre `.await` et `.await?`, oubli de `.instrument()` pour le tracing.
Solution : Template de fonction async dans CLAUDE.md avec tous les patterns requis.
Migrations SQL
Problème : Migrations générées sans considération pour les données existantes (ALTER TABLE destructifs).
Solution : Checklist obligatoire dans CLAUDE.md : vérifier l'impact sur les données, prévoir les rollbacks.
Contexte projet volumineux
Problème : Avec 552+ commits et 14 crates, le contexte devient énorme et coûteux en tokens (308 MB de données sessions).
Solution : 6 agents spécialisés par domaine (Rust, SRE, QA), `/compact` systématique, fichier session.md pour persistance inter-sessions, mémoire projet (13 fichiers).
7. Enseignements clés
TDD non négociable
Chaque feature commence par un test. Claude comprend bien ce workflow et le respecte quand c'est explicitement demandé.
CLAUDE.md détaillé = moins de fixes
Plus les instructions sont précises, moins il y a de corrections à faire. L'investissement initial est largement rentabilisé.
Rust + Claude = bonne combo
Le typage strict de Rust compense les potentielles erreurs de Claude. Le compilateur attrape ce que Claude rate.
Automation GitLab payante
Les scripts d'automation réduisent les frictions et permettent un workflow fluide PR-centric.