#!/usr/bin/env bash # ============================================================================ # guard_constraints.sh · OTO Enterprise OS DTP # ---------------------------------------------------------------------------- # Enforce les contraintes NON-NÉGOCIABLES de CLAUDE.md dans la CI. # Objectif : empêcher qu'un commit introduise un outil/plateforme interdit # ou une pratique proscrite. Gate qualité DevOps (roadmap Sprint 1). # # Principe de robustesse (zéro faux positif sur le texte de politique) : # - On détecte l'USAGE d'un terme interdit, PAS sa simple mention. # - Une ligne qui contient un MARQUEUR DE PROHIBITION (jamais, ❌, only, # pas de, interdit, SEUL...) est un rappel de la règle → on l'ignore. # - Escape hatch explicite : une ligne contenant « ci-allow » est ignorée. # # Sortie : exit 0 si conforme, exit 1 sinon (liste des violations). # Dépendances : bash, git, grep. Aucun réseau requis. # ============================================================================ set -uo pipefail # shellcheck source=ci/lib.sh source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" || exit 3 cd_repo_root # racine du dépôt, ou ROUGE honnête si hors arbre git (cf. lib.sh) # Marqueur de prohibition : si présent sur la ligne, c'est un rappel de règle. PROHIBITION='jamais|JAMAIS|Jamais|❌|SEUL|Seul|only|Only|ONLY|pas de|pas d|\(pas |NON-|non-|[Ii]nterdit|INTERDIT|forbidden|proscrit|éliminer' # ci-allow : échappatoire manuel documenté. ALLOW='ci-allow' FAIL=0 report() { printf ' \033[31m✗\033[0m %s\n' "$1"; FAIL=1; } ok() { printf ' \033[32m✓\033[0m %s\n' "$1"; } # Fichiers suivis. Exclusions = documents qui contiennent NÉCESSAIREMENT les # termes interdits en tant que TEXTE DE POLITIQUE (mention), jamais en usage : # - ce script lui-même : il énumère tous les termes interdits ; # - les workflows CI : ils référencent le garde ; # - les MANDATS SIGNÉS de Michel à la racine (AUTORISATIONS_*.md, # DIRECTIVE_*.md) : prose de gouvernance énumérant règles ET autorisations # (ex. « Écriture dans /var/www/html/static/ » parmi 40 permissions FS). # Ce sont des mentions dans la loi, pas un usage introduit par un agent ; # l'usage réel vivrait dans un .sh/.py/.yml — TOUJOURS scannés — donc aucune # détection vraie-positive n'est perdue. CLAUDE.md (la constitution) RESTE # scanné : sa prose d'interdits passe via les marqueurs de prohibition. # NB · AUTORISATIONS_*.md l.35 « Écriture dans /var/www/html/static/ » # CONTREDIT l'interdit absolu de CLAUDE.md (le chemin correct est le SYMLINK # source /opt/oto/sites/static/). Contradiction inter-mandats signalée à # Michel (activity log 2026-08-03) — à trancher par lui, pas par le garde. tracked_files() { git ls-files -- . \ ':(exclude)ci/guard_constraints.sh' \ ':(exclude).gitea/workflows/*.yml' \ ':(exclude)AUTORISATIONS_*.md' \ ':(exclude)DIRECTIVE_*.md' } # scan_forbidden