Granit Golem - Landing page : Continuous Quality Monitoring
Granit Golem - Page de connexion et landing Granit Golem - Liste des health checks

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.

RustAxumPostgreSQLRedisApache PulsarOpenTelemetryNuxt 3PrometheusGrafanaGitLab CI/CD

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.

Stack Rust (Axum) + Nuxt 3
Architecture DDD + CQRS (14 crates)
Commits 2026 552
Sessions Claude 622
CLAUDE.md 757 lignes
Agents 6 spécialisés
Statut Production

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.

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.

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).

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.

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).

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.

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 :

Structure du projet
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.

Outbox Pattern
// 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.

Row-Level Security
-- 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.

OpenTelemetry Tracing
#[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 fmt avant commit, validate.sh avant 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

1

Ticket GitLab

Issue créée avec specs

2

Claude lit l'issue

Analyse et planification

3

TDD

Tests first, puis impl

4

CI validée

Clippy + tests + build

5

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

GitLab CLI (glab)
# 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
// 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
// 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)

552 Commits en 2026
622 Sessions Claude prompts envoyés
14 Crates Rust workspace DDD
59% Coverage global (80%+ auth, audits)

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

  • Commits — Commits (552)
  • Sessions — Sessions (622)

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

<2ms Latence health check P99 sur 30 jours
~8MB Empreinte mémoire RSS au repos
500+ Checks simultanés Via Tokio runtime
99.97% Uptime Sur 6 mois

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.