Preuve complète (16/16) + détail P16 lisible #2

Merged
danallaire merged 1 commit from preuve-p16-complete into main 2026-07-20 20:49:17 -04:00
2 changed files with 20 additions and 4 deletions

View file

@ -7,7 +7,7 @@
> [`docs/audit/affirmations.md`](affirmations.md).
- **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml`
- **Verdict** : ✅ CONFORME (15 OK · 0 echec · 1 saute)
- **Verdict** : ✅ CONFORME (16 OK · 0 echec · 0 saute)
## Preuves
@ -28,7 +28,7 @@
| P13 | Invariants structurels/doctrinaux | AFF-015, AFF-022, AFF-037, AFF-038, AFF-062 | ✅ OK | LICENSE, socle dossier, pas de couches paralleles, SSH clef-only, nftables off : OK. |
| P14 | Pas de chemin lab/ code en dur | AFF-097 | ✅ OK | Aucun chemin instance/inventories/lab/group_vars code en dur. |
| P15 | Modele public socle valide | AFF-022, AFF-099 | ✅ OK | Modele public socle : domaines/serveurs/applications/bases valides. |
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ⚪ SAUTE | Voute chiffree sans ANSIBLE_VAULT_PASSWORD_FILE (prerequis AFF-026). |
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ✅ OK | 14 hotes, 29 groupes (inventaire dechiffre et parse). |
## Couverture des affirmations ✅ du registre

View file

@ -20,6 +20,7 @@ Usage :
from __future__ import annotations
import datetime as _dt
import json
import os
import subprocess
import sys
@ -178,6 +179,22 @@ def preuve_pas_lab_code_en_dur() -> tuple[bool, str]:
return True, "Aucun chemin instance/inventories/lab/group_vars code en dur."
def preuve_inventaire_ansible() -> tuple[bool, str]:
"""`ansible-inventory --list` : l'inventaire (voute dechiffree) se parse (AFF-030)."""
r = subprocess.run(["ansible-inventory", "-i", INV, "--list"],
cwd=RACINE, capture_output=True, text=True, timeout=600)
if r.returncode != 0:
sortie = (r.stdout + r.stderr).strip().splitlines()
return False, f"rc={r.returncode} : {sortie[-1] if sortie else ''}"
try:
data = json.loads(r.stdout)
except ValueError:
return True, "inventaire liste (JSON non parse)."
n_hotes = len((data.get("_meta") or {}).get("hostvars") or {})
n_groupes = len([k for k in data if k not in ("_meta", "all")])
return True, f"{n_hotes} hotes, {n_groupes} groupes (inventaire dechiffre et parse)."
# --- Registre des preuves : (id, titre, refs AFF, executeur) -----------------------
#
# executeur = liste de commandes argv (toutes doivent renvoyer 0), ou callable -> (ok, detail).
@ -264,8 +281,7 @@ def main() -> int:
# Preuve conditionnelle : inventaire Ansible complet (necessite la voute).
preuve_inv = {"id": "P16", "titre": "Inventaire Ansible complet (--list)",
"refs": ["AFF-030"],
"cmds": [["ansible-inventory", "-i", INV, "--list"]]}
"refs": ["AFF-030"], "func": preuve_inventaire_ansible}
liste = list(PREUVES)
if _vault_requis_absent():
resultats.append((preuve_inv, "SAUTE",