J'ai construit un pipeline de qualité complet qui couvre l'ensemble du cycle de vie du code : de l'analyse statique locale jusqu'au monitoring en production. Chaque outil de la chaîne a un rôle précis, et tous s'enchaînent pour garantir que rien ne passe entre les mailles du filet.

1. Vue d'ensemble du pipeline

Mon pipeline qualité suit le code depuis l'éditeur jusqu'à la production. Chaque étape ajoute un signal de confiance supplémentaire :

1

Code

Édition locale

IDE
2

SAST / Lint

Analyse statique

local
3

Tests

Unitaires + E2E

local
4

Quality Gates

5 gates séquentiels

local
5

CI/CD

Pipeline complet

GitLab
6

Runtime Audit

Crawl applicatif

Marble
7

Observabilité

Logs, métriques, RUM

Grafana / Loki

2. Analyse statique (local)

La première ligne de défense est locale. Avant même qu'un commit ne soit créé, j'applique une analyse statique stricte sur chaque projet :

cargo clippy

Rust

Linter Rust avec politique zéro warning. Chaque warning est traité comme une erreur grâce au flag -D warnings.

cargo clippy -- -D warnings

ESLint + Biome

TypeScript

Double linting en mode strict. ESLint pour les règles sémantiques, Biome pour le formatting et les diagnostics rapides.

npx eslint . --max-warnings 0

cargo fmt

Rust

Formatage automatique du code Rust. J'utilise --check en CI pour vérifier sans modifier.

cargo fmt --check

Prettier

TypeScript

Formatage uniforme du code TypeScript, Vue, CSS. Configuration partagée entre tous les projets du lab.

npx prettier --check .

3. Quality Gates (granit-golem)

J'ai défini 5 gates séquentiels dans scripts/testing/quality-gates.ts. Chaque gate doit passer avant que le suivant ne s'exécute. Si un gate échoue, le pipeline s'arrête immédiatement :

1

Compilation + Clippy

0 warnings

Le code doit compiler sans erreur ET passer clippy sans aucun warning. C'est le filtre le plus basique mais aussi le plus important.

2

Unit Tests

100% pass

Tous les tests unitaires doivent passer. Aucune exception, aucun skip toléré, sauf les #[ignore] documentés.

3

Security Scanning

cargo-audit + npm audit

Scan des dépendances pour les vulnérabilités connues. Les CVE critiques et hautes sont bloquantes.

4

Coverage Check

baseline -5%

La couverture ne doit pas baisser de plus de 5% par rapport à la baseline. Cela empêche les régressions progressives sans imposer un seuil absolu irréaliste.

5

TypeScript + ESLint

strict mode

Le frontend passe le typecheck et le linting en mode strict. Pas de any non justifié, pas de warning ignoré.

scripts/testing/quality-gates.ts
// quality-gates.ts - 5 gates séquentiels
const gates = [
  { name: 'Compilation + Clippy', cmd: 'cargo build && cargo clippy -- -D warnings' },
  { name: 'Unit Tests', cmd: 'cargo test' },
  { name: 'Security', cmd: 'cargo audit && npm audit' },
  { name: 'Coverage', cmd: 'cargo tarpaulin --threshold 35' },
  { name: 'Frontend', cmd: 'npm run typecheck && npm run lint' },
];

for (const gate of gates) {
  console.log(`\n--- Gate: ${gate.name} ---`);
  const result = execSync(gate.cmd, { stdio: 'pipe' });
  if (result.status !== 0) {
    console.error(`FAILED: ${gate.name}`);
    process.exit(1);
  }
  console.log(`PASSED: ${gate.name}`);
}

4. Security scanning (SAST)

La sécurité n'est pas une option, c'est une couche du pipeline. J'ai configuré un scanning SAST adapté à chaque projet :

granit-golem

Rust + Node
  • cargo-audit v0.22.1 - Vulnérabilités des crates Rust
  • cargo-deny v0.19.0 - Licences, advisories, sources
  • npm audit - Dépendances frontend, Nuxt

marble-minotaur

Node.js
  • npm audit - Niveau high, bloquant
  • gitleaks - Scan de secrets, bloquant

iolite-ifrit

Cloud OS
  • trivy - Images conteneurs, HIGH/CRITICAL
  • gitleaks - Scan de secrets, bloquant

Tests OWASP Top 10

Au-delà du scan de dépendances, j'ai implémenté des tests actifs OWASP dans security-owasp-tests.ts :

security-owasp-tests.ts
// security-owasp-tests.ts - Tests OWASP Top 10
const owaspChecks = [
  { name: 'HTTPS Enforcement', test: () => checkRedirectToHttps(url) },
  { name: 'Rate Limiting', test: () => floodEndpoint(url, 100) },
  { name: 'Security Headers', test: () => validateHeaders(url, [
    'Strict-Transport-Security',
    'Content-Security-Policy',
    'X-Frame-Options',
    'X-Content-Type-Options',
    'Referrer-Policy',
  ])},
  { name: 'SQL Injection', test: () => testSqlInjection(url, payloads) },
  { name: 'XSS Sanitization', test: () => testXssPayloads(url, xssVectors) },
  { name: 'CSRF Protection', test: () => testCsrfToken(url) },
];

HTTPS Enforcement

Vérification de la redirection HTTP vers HTTPS sur tous les endpoints publics.

Rate Limiting

Test de flood sur les endpoints critiques : 100 requêtes en rafale, vérification du 429.

Security Headers

HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy.

Injection / XSS / CSRF

Payloads d'injection SQL, vecteurs XSS et vérification des tokens CSRF.

5. Mutation Testing

La couverture de code est un indicateur trompeur : 80% de couverture ne signifie pas que les tests sont bons. Pour mesurer la vraie qualité de mes tests, j'utilise le mutation testing avec cargo-mutants :

1

Mutation

L'outil modifie le code source : remplace un + par un -, un > par un <, supprime une condition...

2

Exécution

Les tests sont relancés sur le code muté. Si un test échoue, le mutant est "tué", c'est le bon scénario.

3

Analyse

Si le mutant survit, aucun test n'échoue, c'est un trou dans la couverture réelle. Il faut ajouter un test.

Kill rate cible
≥ 70%

Sur granit-golem, j'atteins un kill rate de 70%+ sur les crates domaine. Chaque mutant survivant est analysé et donne lieu à un test supplémentaire.

scripts/testing/mutation-test.ts
// mutation-test.ts - cargo-mutants pour Rust
import { execSync } from 'child_process';

const KILL_RATE_TARGET = 70;

// Lancer les mutations sur les crates critiques
const result = execSync('cargo mutants --package monitoring-domain', {
  encoding: 'utf-8',
});

// Parser le résultat
const match = result.match(/killed: (\d+).*total: (\d+)/);
const killRate = (parseInt(match[1]) / parseInt(match[2])) * 100;

if (killRate < KILL_RATE_TARGET) {
  console.error(`Kill rate ${killRate}% < target ${KILL_RATE_TARGET}%`);
  process.exit(1);
}
console.log(`Mutation kill rate: ${killRate}% (target: ${KILL_RATE_TARGET}%)`);

6. Marble Minotaur - Runtime Web Auditor

Marble Minotaur est mon auditeur web runtime. Il parcourt les applications en production via un crawl BFS (Breadth-First Search) et applique 7 auditeurs pluggables sur chaque page découverte :

1

SEO

Title, meta description, h1 unique, canonical URL, og:tags pour le partage social.

2

Accessibility

axe-core WCAG 2.1 AA complet, vérification ARIA, contraste couleurs, navigation clavier.

3

Performance

Core Web Vitals : LCP, CLS, TTFB. Mesure réelle via Playwright, pas synthétique.

4

Security Headers

HSTS, CSP, X-Frame-Options, Referrer-Policy. Vérification stricte sur chaque page.

5

Forms

Validation des champs, attributs autocomplete, sécurité de soumission, labels associés.

6

i18n

Détection des clés de traduction manquantes, attribut lang, cohérence linguistique.

7

Images

Sources cassées, alt text manquant, dimensions explicites, formats optimisés.

Scoring et quality gate

Chaque audit produit un score sur 100. Les déductions sont pondérées selon la gravité :

Problème détecté Déduction Limite
Pages 404 -35 par page
Blank renders -25 par page
Erreurs JS -8 max -25 total
Security headers manquants variable pénalité pondérée
Marble Minotaur - Mode CI
# Lancer un audit Marble Minotaur en mode CI
npx tsx src/cli.ts https://mon-app.com \
  --ci \
  --ci-threshold 70 \
  --output json

# Résultat :
# {
#   "score": 82,
#   "pages_crawled": 14,
#   "auditors": {
#     "seo": { "score": 95, "issues": 1 },
#     "accessibility": { "score": 78, "issues": 4 },
#     "performance": { "score": 88, "issues": 2 },
#     "security_headers": { "score": 72, "issues": 3 },
#     "forms": { "score": 90, "issues": 0 },
#     "i18n": { "score": 85, "issues": 1 },
#     "images": { "score": 92, "issues": 1 }
#   }
# }

7. Basalt Beholder - Phase d'audit industrialisation

Avant de coder, j'audite. Chaque nouveau projet passe par une phase d'audit industrialisation avec Basalt Beholder : j'évalue la maturité du projet sur 17 volets, j'identifie les lacunes, et je priorise les chantiers. Cette phase est partiellement automatisée via 12 skills Claude Code et une base de connaissances de 187 questions.

12 Skills d'audit
17 Volets d'évaluation
187 Questions
CMMI 0-4 Échelle de maturité

Orchestration des audits

Le skill /audit-industrialisation orchestre les 8 audits domaine et produit un rapport consolidé avec scoring par volet :

Architecture

ADRs, API design, coupling, scalability

Security

TLS, auth, secrets, incident response

Testing

Strategy, coverage, flaky tests

Quality

Code quality, dependencies, data validation

Observability

Logging, metrics, tracing, alerting

CI/CD

Pipelines, métriques DORA, déploiement

Compliance

GDPR, data governance, FinOps

Performance Frontend

Rendering, JSC, DOM, memory

Modèle de maturité CMMI

0

Unmanaged

Aucun processus défini, résultats imprévisibles.

1

Initial

Processus ad hoc, succès dépendant des individus.

2

Managed

Processus documentés et reproductibles.

3

Defined

Standards organisationnels, processus mesurés.

4

Optimized

Amélioration continue basée sur les métriques.

Basalt Beholder - Skills d'audit
# Lancer un audit complet via Claude Code skill
/audit-industrialisation

# Audits individuels
/audit-architecture    # ADRs, API design, coupling, scalability
/audit-security        # TLS, auth, secrets, incident response
/audit-testing         # Strategy, coverage, flaky tests
/audit-quality         # Code quality, dependencies, data validation
/audit-observability   # Logging, metrics, tracing, alerting
/audit-ci-cd           # Pipelines, métriques DORA, déploiement
/audit-compliance      # GDPR, data governance, FinOps
/audit-performance-frontend  # Rendering, JSC, DOM, memory

8. Crock - Code Quality Analyzer

Crock est mon analyseur de qualité de code. Il couvre 6 volets d'analyse, chacun note sur une échelle de maturité 0-4 :

AST Analysis

Complexité cyclomatique, index de maintenabilité, couverture de typage. Analyse l'arbre syntaxique abstrait pour détecter les fonctions trop complexes.

Git Forensics

Conventional commits, fichiers hotspot, modifiés fréquemment, concentration des connaissances, bus factor. Analyse l'historique git pour détecter les risques.

Debt Markers

Tracking des TODO, FIXME, HACK dans le code. Chaque marqueur est indexé avec son ancienneté et sa localisation pour prioriser le remboursement de dette.

Lint Integration

Agrégation des résultats ESLint, Clippy, Biome. Vue unifiée de tous les diagnostics statiques du projet.

Dependency Health

Âge des dépendances, vulnérabilités connues, dépendances non utilisées. Détection des risques de supply chain.

Test Quality

Ratio tests/code, couverture par module, temps d'exécution. Identification des zones sous-testées et des tests fragiles.

9. CI/CD Pipeline Integration

Mon pipeline GitLab CI est structuré en 4 stages. Les stages check et security tournent en parallèle quand c'est possible, et chaque stage est bloquant pour le suivant :

check

cargo test
clippy
typecheck
lint
parallel

security

cargo-audit
cargo-deny
npm audit
gitleaks
trivy

build

cargo build --release
Docker image

déploiement

smoke tests
health checks
.gitlab-ci.yml
# .gitlab-ci.yml - Stages du pipeline
stages:
  - check
  - security
  - build
  - deploy

check:
  stage: check
  parallel:
    matrix:
      - JOB: [cargo-test, clippy, typecheck, lint]
  script:
    - case $JOB in
        cargo-test) cargo test --workspace ;;
        clippy) cargo clippy -- -D warnings ;;
        typecheck) cd frontend && npm run typecheck ;;
        lint) cd frontend && npm run lint ;;
      esac

security:
  stage: security
  script:
    - cargo audit
    - cargo deny check advisories
    - cd frontend && npm audit --audit-level=high
    - gitleaks detect --source . --verbose
    - trivy image $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

build:
  stage: build
  script:
    - cargo build --release
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

deploy:
  stage: deploy
  script:
    - docker compose up -d
    - ./scripts/smoke-test.sh
    - curl -f https://app.example.com/health

10. Chaîne de signaux complète

Voici comment tous les outils s'enchaînent dans mon workflow quotidien, du premier keystroke jusqu'au monitoring en production :

Local (pre-commit)

👨‍💻 Developer
validate.sh
🛡 quality-gates.ts
📤 git push

CI/CD (GitLab)

check
🔒 security
📦 build + déploiement

Production

🧿 Marble Minotaur
📊 Granit Golem

11. Résultats observés

Voici les résultats concrets de ce pipeline sur l'ensemble de mon lab :

0 Rollbacks sur les projets avec pipeline complet
≥ 70% Mutation kill rate granit-golem, crates domaine
> 95% Quality gate pass rate sur l'ensemble du lab
BLOCKING gitleaks aucun secret jamais commité

Zéro rollback : pourquoi ?

Les 5 quality gates filtrent les problèmes avant le commit. La CI ajoute une couche de vérification en environnement propre. Et le monitoring Marble Minotaur détecte les régressions après déploiement. Chaque couche attrape ce que la précédente a manqué.

gitleaks en mode bloquant

J'ai configuré gitleaks pour bloquer le pipeline si un secret, API key, token, password, est détecté dans le code ou l'historique git. Résultat : aucun secret n'a jamais été commité sur les projets configurés avec cet outil.

Synthèse

Mon pipeline qualité n'est pas un idéal théorique, c'est le résultat de plusieurs mois d'itération sur des projets réels. Chaque outil a été ajouté en réponse à un problème concret, et chaque gate a prouvé sa valeur en attrapant des bugs qui seraient autrement arrivés en production.

Bloquant par défaut

Chaque signal est bloquant. Si quelque chose échoue, le code ne passe pas. Pas de "on verra plus tard".

Local d'abord

Le maximum de vérifications se fait en local, avant le push. La CI est un filet de sécurité, pas le premier barrage.

Mesurer la vraie qualité

La couverture est un proxy. Le mutation testing, le scoring Marble et les audits Beholder mesurent la qualité réelle.

Sécurité intégrée

La sécurité n'est pas un audit ponctuel, c'est une couche du pipeline. gitleaks, cargo-audit, trivy, OWASP, tout est automatisé.