This commit is contained in:
Daniel Allaire 2026-03-15 14:43:50 -04:00
parent 54f7c8c300
commit 3247d98fb3
44 changed files with 2871 additions and 973 deletions

View file

@ -61,6 +61,8 @@ validate-generated: $(ICINGA_FILES) bpm/Life-NOC.conf
@grep -R 'check_life_noc_mock' icinga/templates icinga/commands icinga/services >/dev/null @grep -R 'check_life_noc_mock' icinga/templates icinga/commands icinga/services >/dev/null
@$(PYTHON) -c 'import pathlib; p = pathlib.Path("bpm/Life-NOC.conf"); text = p.read_text(encoding="utf-8"); lines = [l.strip() for l in text.splitlines() if l.strip()]; assert any(l == "### Business Process Config File ###" for l in lines), "bpm/Life-NOC.conf invalide: en-tête BPM absent"; assert any(l.startswith("display 1;") for l in lines), "bpm/Life-NOC.conf invalide: aucun display absent"; print("Artefacts générés valides")' @$(PYTHON) -c 'import pathlib; p = pathlib.Path("bpm/Life-NOC.conf"); text = p.read_text(encoding="utf-8"); lines = [l.strip() for l in text.splitlines() if l.strip()]; assert any(l == "### Business Process Config File ###" for l in lines), "bpm/Life-NOC.conf invalide: en-tête BPM absent"; assert any(l.startswith("display 1;") for l in lines), "bpm/Life-NOC.conf invalide: aucun display absent"; print("Artefacts générés valides")'
check: generate validate
mock-ok: mock-ok:
@bash checks/check_life_noc_mock.sh --state OK --message "Sous contrôle" --item-name "demo" --date "2026-03-13" @bash checks/check_life_noc_mock.sh --state OK --message "Sous contrôle" --item-name "demo" --date "2026-03-13"

View file

@ -7,7 +7,7 @@ Type=simple
User=root User=root
Group=root Group=root
WorkingDirectory={{ life_noc_project_root }} WorkingDirectory={{ life_noc_project_root }}
ExecStart=/usr/bin/python3 -m uvicorn scripts.life_noc_input_api:app --host 127.0.0.1 --port 8787 ExecStart=/usr/bin/python3 -m uvicorn scripts.life_noc_input_api:app --host 0.0.0.0 --port 8787
Restart=on-failure Restart=on-failure
RestartSec=3 RestartSec=3

View file

@ -1,121 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${1:-.}"
need_file() {
local f="$1"
if [[ ! -f "$ROOT/$f" ]]; then
echo "Fichier introuvable: $f" >&2
exit 1
fi
}
echo "==> Vérification"
need_file "domains.yaml"
need_file "icinga/commands/check_life_noc_probe.conf"
need_file "scripts/generate_services.py"
need_file "Makefile"
echo "==> Sauvegarde minimale"
mkdir -p "$ROOT/.backup-days-until-due-pilot"
cp -a "$ROOT/domains.yaml" "$ROOT/.backup-days-until-due-pilot/domains.yaml.bak"
echo "==> Création du store d'intrants"
mkdir -p "$ROOT/data/inputs"
cat > "$ROOT/data/inputs/obligations-legales-personnelles.yaml" <<'EOF'
renouvellement-permis-conduire:
value: "2026-09-20"
captured_at: "2026-03-14T23:30:00Z"
origin: manual
EOF
echo "==> Mise à jour de domains.yaml"
python3 - "$ROOT/domains.yaml" <<'PY'
from pathlib import Path
import sys
import yaml
path = Path(sys.argv[1])
data = yaml.safe_load(path.read_text(encoding="utf-8"))
domains = data.get("domains")
if not isinstance(domains, dict):
raise SystemExit("domains.yaml invalide: clé racine 'domains' absente ou invalide")
domain_name = "obligations-legales-personnelles"
items = domains.get(domain_name)
if not isinstance(items, list):
raise SystemExit(f"Domaine introuvable ou invalide: {domain_name}")
target = None
for item in items:
if isinstance(item, dict) and item.get("name") == "renouvellement-permis-conduire":
target = item
break
if target is None:
raise SystemExit("Item 'renouvellement-permis-conduire' introuvable dans domains.yaml")
target["date"] = "2026-09-20"
target["notes"] = "Vérifier la proximité de léchéance du permis"
target["probe"] = {
"type": "days_until_due",
"source": {
"type": "manual_date",
"inputs_file": "/opt/life-noc/data/inputs/obligations-legales-personnelles.yaml",
"item_key": "renouvellement-permis-conduire",
},
"metric": {
"unit": "days",
},
"thresholds": {
"critical_lt": 7,
"warning_lt": 30,
"ok_lt": 90,
"unknown_gte": 90,
},
"policy": {
"on_error": "critical",
},
}
path.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding="utf-8")
print("domains.yaml mis à jour")
PY
echo "==> Vérification rapide de la commande Icinga"
for needle in \
'--unknown-gte' \
'--ok-lt' \
'--warning-lt' \
'--critical-lt'
do
if ! grep -q -- "$needle" "$ROOT/icinga/commands/check_life_noc_probe.conf"; then
echo "ERREUR: argument manquant dans icinga/commands/check_life_noc_probe.conf : $needle" >&2
exit 1
fi
done
echo "==> Génération"
(
cd "$ROOT"
python3 scripts/generate_services.py
)
echo "==> Validation"
(
cd "$ROOT"
make check
)
echo "==> Déploiement"
(
cd "$ROOT"
make deploy-with-bpm
)
echo
echo "Terminé."
echo "Test utile ensuite :"
echo " python3 scripts/life_noc_input.py set obligations-legales-personnelles renouvellement-permis-conduire 2026-03-20"

View file

@ -0,0 +1,295 @@
# Architecture et fonctionnement de Life-NOC
## 1. Présentation générale
### 1.1 Définition
**Life-NOC** est un système de pilotage personnel qui applique à la vie réelle la logique dun **NOC** (Network Operations Center / centre dopérations).
Son but nest pas dautomatiser la vie à la place de la personne. Son but est de :
- rendre visibles les suivis importants ;
- transformer la charge mentale en état observable ;
- soutenir la mémoire prospective ;
- orienter lattention vers ce qui mérite réellement dêtre vu ;
- réduire la friction entre la prise de conscience et laction.
Life-NOC peut être résumé ainsi :
> **Voir clair, prioriser juste, agir au bon endroit.**
### 1.2 Finalité
Life-NOC sert à superviser des éléments de la vie personnelle, domestique, administrative, technique ou communautaire comme sil sagissait de services critiques dans une salle de contrôle.
Il permet par exemple de suivre :
- des revues périodiques ;
- des échéances ;
- des stocks ;
- des vérifications techniques ;
- des obligations administratives ;
- des contrôles de maintenance ;
- des routines de résilience ;
- des points dattention dans lenvironnement physique.
### 1.3 Positionnement
Life-NOC nest pas :
- un simple gestionnaire de tâches ;
- un agenda ;
- un ERP ;
- un moteur dautomatisation généraliste ;
- un outil dinventaire pur.
Life-NOC est :
- un **système de supervision attentionnelle** ;
- un **cadre dévaluation de suivis** ;
- un **point de convergence** entre intrants, règles, états et actions ;
- une **interface de réduction de charge mentale**.
## 2. Principes de fonctionnement
### 2.1 Séparation des couches
Life-NOC repose sur quatre couches distinctes :
1. **définition** ;
2. **ingestion** ;
3. **persistance** ;
4. **évaluation**.
**Définition**
Contient les items à superviser, les méthodes, les seuils, les notes et les liens utiles.
**Ingestion**
Contient les mécanismes par lesquels une donnée entre dans le système :
- saisie manuelle ;
- API ;
- page HTML ;
- QR code ;
- plus tard MQTT, GUI avancée, etc.
**Persistance**
Contient les intrants vivants à jour.
**Évaluation**
Contient la logique qui transforme un intrant en état Life-NOC.
### 2.2 Philosophie générale
Le système suit cette logique :
- le **domaine** organise ;
- la **méthode** évalue ;
- l**item** fait le lien entre les deux ;
- l**intrant** fournit la valeur vivante ;
- la **page item** réduit la friction daction ;
- **Icinga** rend les états visibles dans un cadre de supervision.
## 3. États Life-NOC
### 3.1 États
- **UNKNOWN** : pas encore dû, pas encore à faire ;
- **OK** : actionnable maintenant ;
- **WARNING** : il faut se presser ;
- **CRITICAL** : en retard, anormal, ou impossible à évaluer.
### 3.2 Politique derreur
Par défaut, si le système ne peut pas conclure techniquement, il retourne **CRITICAL**.
Exemples :
- fichier introuvable ;
- donnée absente ;
- format invalide ;
- parsing impossible ;
- seuil incohérent ;
- type de sonde non pris en charge.
## 4. Organisation métier par domaines
Les domaines servent à organiser les suivis.
Exemples :
- revue ;
- focus ;
- finances-personnelles ;
- obligations-legales-personnelles ;
- maison ;
- energie ;
- voiture ;
- projets ;
- documentation ;
- animaux.
Le domaine est une unité dorganisation métier, pas nécessairement une unité de calcul.
## 5. Taxonomie des méthodes de sonde
### 5.1 `elapsed_time`
Mesure le temps écoulé depuis une dernière exécution.
### 5.2 `days_until_due`
Mesure le temps restant avant une échéance fixe.
### 5.3 `elapsed_distance`
Mesure une distance écoulée depuis une action passée.
### 5.4 `current_value`
Évalue une valeur instantanée contre des seuils.
### 5.5 `remaining_quantity`
Évalue ce quil reste dun stock ou dune réserve.
## 6. Portée actuellement validée
Au stade actuel, les méthodes réellement validées sont :
- `elapsed_time` ;
- `days_until_due`.
## 7. Définition des items
Les items sont définis dans :
```text
domains.yaml
```
Un item peut contenir :
- `name`
- `date`
- `notes`
- `notes_url`
- `instructions_url`
- `action_url`
- `probe`
### 7.1 Rôle des champs descriptifs
- `notes` : résumé court ;
- `notes_url` : contexte / référence ;
- `instructions_url` : procédure ;
- `action_url` : outil ou page daction.
## 8. Store des intrants
Les intrants vivants sont stockés sous :
```text
data/inputs/<domaine>.yaml
```
Exemple :
```yaml
revue-hebdomadaire-priorites:
value: "2026-03-14"
captured_at: "2026-03-14T23:16:41Z"
origin: manual
```
## 9. CLI des intrants
Commandes principales :
- `list`
- `get`
- `set`
- `complete`
Exemples :
```bash
life-noc-input list revue
life-noc-input get revue revue-hebdomadaire-priorites
life-noc-input set revue revue-hebdomadaire-priorites 2026-03-14
life-noc-input complete revue revue-hebdomadaire-priorites
```
## 10. API locale des intrants
API locale sur :
```text
http://127.0.0.1:8787
```
Endpoints JSON :
- `GET /health`
- `GET /inputs/{domain}`
- `GET /inputs/{domain}/{item_key}`
- `POST /inputs/{domain}/{item_key}`
- `POST /inputs/{domain}/{item_key}/complete`
Dépendances importantes :
- `python3-fastapi`
- `python3-uvicorn`
- `python3-multipart`
## 11. Pages HTML Life-NOC
Route :
```text
/life-noc/item/<domaine>/<item_key>
```
La page affiche :
- titre humain ;
- état actuel ;
- type de sonde ;
- dernier intrant ;
- domaine ;
- item key ;
- notes ;
- liens utiles ;
- bouton `Compléter`.
Le bouton utilise :
```text
POST /life-noc/item/<domaine>/<item_key>/complete
```
## 12. Intégration Icinga
Life-NOC sappuie sur Icinga pour :
- la visualisation des états ;
- le `Check Now` ;
- les BPM natifs ;
- les servicegroups ;
- laffichage des variables utiles.
## 13. Flux complet
1. définition dans `domains.yaml` ;
2. intrant dans `data/inputs/<domaine>.yaml` ;
3. mise à jour par CLI, API ou page HTML ;
4. lecture par la sonde ;
5. calcul de létat ;
6. affichage dans Icinga ;
7. action de lusager ;
8. mise à jour de lintrant.
## 14. Déploiement
Commandes usuelles :
```bash
make check
make deploy-with-bpm
```
Le dépôt doit rester reproductible sans correctifs manuels cachés.

View file

@ -0,0 +1,83 @@
# Exploitation et dépannage Life-NOC
## 1. Vérifications utiles
### Vérifier lAPI
```bash
curl http://127.0.0.1:8787/health
```
### Vérifier un intrant
```bash
curl http://127.0.0.1:8787/inputs/revue/revue-hebdomadaire-priorites
```
### Vérifier une page item
```bash
curl http://127.0.0.1:8787/life-noc/item/revue/revue-hebdomadaire-priorites
```
## 2. Cas fréquent : lintrant change mais pas létat dans Icinga
Cela signifie souvent quIcinga na pas encore refait le check.
Il faut alors :
- lancer un `Check Now` ;
- ou attendre le prochain check ;
- ou tester directement le plugin à la main.
## 3. Cas fréquent : route HTML absente après déploiement
Vérifier :
- que le service API tourne ;
- que le fichier déployé contient bien les routes HTML ;
- que les dépendances FastAPI sont installées, notamment `python3-multipart`.
## 4. Vérifier le service API
```bash
sudo systemctl status life-noc-input-api --no-pager
sudo journalctl -u life-noc-input-api -n 80 --no-pager
```
## 5. Vérifier directement un plugin
Exemple pour `elapsed_time` :
```bash
/usr/lib/nagios/plugins/check_life_noc_probe.py --probe-type elapsed_time --source-type manual_date --inputs-file /opt/life-noc/data/inputs/revue.yaml --item-key revue-hebdomadaire-priorites --unit days --unknown-lt 5 --ok-gte 5 --warning-gte 7 --critical-gte 10 --on-error critical --label revue-hebdomadaire-priorites
```
## 6. Déploiement
```bash
make check
make deploy-with-bpm
```
## 7. Dépendances API importantes
Le service API nécessite :
- `python3-fastapi`
- `python3-uvicorn`
- `python3-multipart`
## 8. État actuel validé
Éléments validés en pratique :
- Icinga Web 2 ;
- BPM natif ;
- servicegroups ;
- `Check Now` ;
- store dintrants ;
- CLI ;
- API locale ;
- pages HTML ditem ;
- méthodes `elapsed_time` et `days_until_due`.

View file

@ -0,0 +1,79 @@
# Guide usager Life-NOC
## 1. À quoi sert Life-NOC
Life-NOC aide une personne à voir rapidement ce qui mérite son attention, sans tout garder dans sa tête.
Il sert à suivre par exemple :
- des revues régulières ;
- des dates importantes ;
- des entretiens ;
- des vérifications ;
- des obligations.
## 2. Ce que signifient les états
- **UNKNOWN** : pas encore le temps dagir ;
- **OK** : cest le bon moment pour sen occuper ;
- **WARNING** : il faut accélérer ;
- **CRITICAL** : cest urgent ou il y a un problème.
## 3. Comment consulter un item
Un item peut être consulté :
- dans Icinga ;
- via une page Life-NOC ;
- plus tard via un QR code.
La page Life-NOC affiche :
- le nom du suivi ;
- son état ;
- la dernière valeur enregistrée ;
- les notes ;
- les instructions ;
- un bouton pour marquer laction comme faite.
## 4. Comment marquer une action comme faite
Quand litem le permet, il suffit de cliquer sur **Compléter**.
Cela met à jour la valeur de lintrant avec la date du jour.
## 5. À quoi servent les liens utiles
- **Notes** : pour comprendre le contexte ;
- **Instructions** : pour savoir quoi faire ;
- **Action** : pour aller directement au bon outil ou à la bonne page.
## 6. Ce que lusager na pas besoin de savoir
Lusager na normalement pas besoin de comprendre :
- les fichiers YAML ;
- le moteur de sonde ;
- larchitecture technique ;
- le fonctionnement interne dIcinga.
Il lui suffit de :
- voir létat ;
- consulter les instructions ;
- marquer laction effectuée.
## 7. QR codes — direction prévue
Life-NOC est conçu pour permettre lusage de QR codes pointant vers :
```text
/life-noc/item/<domaine>/<item_key>
```
Le scan permettra :
- douvrir directement litem ;
- de lire les instructions ;
- de confirmer laction ;
- de mettre à jour le système facilement.

View file

@ -0,0 +1,734 @@
# Life-NOC — Documentation complète
## 1. Présentation générale
### 1.1 Définition
**Life-NOC** est un système de pilotage personnel qui applique à la vie réelle la logique dun **NOC** (Network Operations Center / centre dopérations).
Son but nest pas dautomatiser la vie à la place de la personne.
Son but est de :
- rendre visibles les suivis importants ;
- transformer la charge mentale en état observable ;
- soutenir la mémoire prospective ;
- orienter lattention vers ce qui mérite réellement dêtre vu ;
- réduire la friction entre la prise de conscience et laction.
Life-NOC peut être résumé ainsi :
> **Voir clair, prioriser juste, agir au bon endroit.**
---
### 1.2 Finalité
Life-NOC sert à superviser des éléments de la vie personnelle, domestique, administrative, technique ou communautaire comme sil sagissait de services critiques dans une salle de contrôle.
Il permet par exemple de suivre :
- des revues périodiques ;
- des échéances ;
- des stocks ;
- des vérifications techniques ;
- des obligations administratives ;
- des contrôles de maintenance ;
- des routines de résilience ;
- des points dattention dans lenvironnement physique.
---
### 1.3 Positionnement
Life-NOC nest pas :
- un simple gestionnaire de tâches ;
- un agenda ;
- un ERP ;
- un moteur dautomatisation généraliste ;
- un outil dinventaire pur.
Life-NOC est :
- un **système de supervision attentionnelle** ;
- un **cadre dévaluation de suivis** ;
- un **point de convergence** entre intrants, règles, états et actions ;
- une **interface de réduction de charge mentale**.
---
## 2. Principes de fonctionnement
### 2.1 Séparation des couches
Life-NOC repose sur quatre couches distinctes :
1. **définition** ;
2. **ingestion** ;
3. **persistance** ;
4. **évaluation**.
#### Définition
Contient les items à superviser, les méthodes, les seuils, les notes et les liens utiles.
#### Ingestion
Contient les mécanismes par lesquels une donnée entre dans le système :
- saisie manuelle ;
- API ;
- page HTML ;
- QR code ;
- plus tard MQTT, GUI avancée, etc.
#### Persistance
Contient les intrants vivants à jour.
#### Évaluation
Contient la logique qui transforme un intrant en état Life-NOC.
---
### 2.2 Philosophie générale
Le système suit cette logique :
- le **domaine** organise ;
- la **méthode** évalue ;
- l**item** fait le lien entre les deux ;
- l**intrant** fournit la valeur vivante ;
- la **page item** réduit la friction daction ;
- **Icinga** rend les états visibles dans un cadre de supervision.
---
## 3. États Life-NOC
Life-NOC utilise une sémantique propre des états.
### 3.1 États
- **UNKNOWN** : pas encore dû, pas encore à faire ;
- **OK** : actionnable maintenant ;
- **WARNING** : il faut se presser ;
- **CRITICAL** : en retard, anormal, ou impossible à évaluer.
### 3.2 Différence avec lusage classique de Nagios/Icinga
Dans Life-NOC :
- le vert ne signifie pas seulement « tout va bien » ;
- le vert signifie souvent « cest le bon moment pour agir » ;
- le gris signifie que litem nest pas encore entré dans sa fenêtre daction.
### 3.3 Politique derreur
Par défaut, si le système ne peut pas conclure techniquement, il retourne **CRITICAL**.
Exemples :
- fichier introuvable ;
- donnée absente ;
- format invalide ;
- parsing impossible ;
- seuil incohérent ;
- type de sonde non pris en charge.
Cette politique force la correction des faux positifs techniques plutôt que leur invisibilisation.
---
## 4. Organisation métier par domaines
Life-NOC regroupe les items dans des **domaines**.
Exemples de domaines :
- revue ;
- focus ;
- finances-personnelles ;
- fiscalite-personnelle ;
- obligations-legales-personnelles ;
- maison ;
- garage-et-rangement ;
- energie ;
- resilience ;
- stock-alimentaire ;
- sante ;
- voiture ;
- jardin ;
- informatique-personnelle ;
- infrastructure-chezlepro ;
- reseau-chezlepro ;
- securite-chezlepro ;
- exploitation-chezlepro ;
- projets ;
- communaute ;
- documentation ;
- animaux.
Le domaine est une unité dorganisation métier, pas nécessairement une unité de calcul.
Un même domaine peut contenir plusieurs méthodes de sonde.
---
## 5. Taxonomie des méthodes de sonde
Le modèle conceptuel v1 de Life-NOC prévoit cinq méthodes principales.
### 5.1 elapsed_time
Mesure le temps écoulé depuis un événement ou une exécution précédente.
Exemples :
- revue hebdomadaire ;
- inspection trimestrielle ;
- test périodique.
Intrant attendu :
- date de dernière exécution.
Unité typique :
- jours.
---
### 5.2 days_until_due
Mesure le temps restant avant une échéance fixe.
Exemples :
- renouvellement du permis ;
- passeport ;
- assurance ;
- obligation légale.
Intrant attendu :
- date déchéance.
Unité typique :
- jours.
---
### 5.3 elapsed_distance
Mesure la distance écoulée depuis une action passée.
Exemples :
- vidange ;
- entretien pneus ;
- entretien freins.
Intrants attendus :
- compteur courant ;
- compteur au dernier entretien.
Unité typique :
- kilomètres.
---
### 5.4 current_value
Évalue une valeur instantanée contre des seuils.
Exemples :
- tension batterie ;
- température ;
- humidité ;
- espace libre.
Intrant attendu :
- valeur actuelle.
Unité typique :
- variable selon le cas.
---
### 5.5 remaining_quantity
Évalue ce quil reste dun stock ou dune réserve.
Exemples :
- nourriture chats ;
- réserve deau ;
- carburant ;
- consommables.
Intrant attendu :
- quantité restante.
Unité typique :
- jours, litres, unités, pourcentage, etc.
---
## 6. Portée actuellement validée
Au stade actuel, les méthodes réellement validées dans le système sont :
- `elapsed_time` ;
- `days_until_due`.
Les autres méthodes sont conceptuellement définies, mais pas encore consolidées de la même manière dans le dépôt.
---
## 7. Définition des items
Les items supervisés sont définis dans :
```text
domains.yaml
```
Chaque item peut contenir :
- `name` ;
- `date` ;
- `notes` ;
- `notes_url` ;
- `instructions_url` ;
- `action_url` ;
- `probe` ;
- `thresholds` ;
- `policy`.
### 7.1 Rôle des champs descriptifs
- `notes` : résumé humain court ;
- `notes_url` : contexte / référence ;
- `instructions_url` : quoi faire / procédure ;
- `action_url` : où agir concrètement.
### 7.2 Champ probe
Le champ `probe` décrit :
- la méthode ;
- la source ;
- lunité ;
- les seuils ;
- la politique derreur.
Exemple :
```yaml
probe:
type: elapsed_time
source:
type: manual_date
inputs_file: "/opt/life-noc/data/inputs/revue.yaml"
item_key: "revue-hebdomadaire-priorites"
metric:
unit: days
thresholds:
unknown_lt: 5
ok_gte: 5
warning_gte: 7
critical_gte: 10
policy:
on_error: critical
```
---
## 8. Store des intrants
### 8.1 Principe
Les intrants vivants ne sont pas mélangés à la définition des items.
Ils sont stockés sous :
```text
data/inputs/<domaine>.yaml
```
Exemples :
- `data/inputs/revue.yaml`
- `data/inputs/obligations-legales-personnelles.yaml`
### 8.2 Contenu minimal dun intrant
Un intrant contient en général :
- `value` ;
- `captured_at` ;
- `origin`.
Exemple :
```yaml
revue-hebdomadaire-priorites:
value: "2026-03-14"
captured_at: "2026-03-14T23:16:41Z"
origin: manual
```
### 8.3 Rôle du store
Le store dintrants permet :
- de changer une valeur sans toucher à `domains.yaml` ;
- dalimenter les sondes avec des valeurs vivantes ;
- de préparer les futures interfaces GUI, API, QR et autres.
---
## 9. CLI de gestion des intrants
Life-NOC dispose dune CLI de gestion des intrants.
### 9.1 Commandes principales
- `list`
- `get`
- `set`
- `complete`
### 9.2 Exemples
```bash
life-noc-input list revue
life-noc-input get revue revue-hebdomadaire-priorites
life-noc-input set revue revue-hebdomadaire-priorites 2026-03-14
life-noc-input complete revue revue-hebdomadaire-priorites
```
### 9.3 Rôle de complete
`complete` est particulièrement utile pour les items de type `elapsed_time/manual_date`.
Il inscrit automatiquement :
- `value = date du jour`
- `captured_at = maintenant`
- `origin = manual`
---
## 10. API locale des intrants
Life-NOC expose une API locale sur :
```text
http://127.0.0.1:8787
```
### 10.1 Endpoints JSON
- `GET /health`
- `GET /inputs/{domain}`
- `GET /inputs/{domain}/{item_key}`
- `POST /inputs/{domain}/{item_key}`
- `POST /inputs/{domain}/{item_key}/complete`
### 10.2 Exemple
```bash
curl http://127.0.0.1:8787/health
curl http://127.0.0.1:8787/inputs/revue
curl http://127.0.0.1:8787/inputs/revue/revue-hebdomadaire-priorites
curl -X POST http://127.0.0.1:8787/inputs/revue/revue-hebdomadaire-priorites \
-H 'Content-Type: application/json' \
-d '{"value":"2026-03-14","origin":"manual"}'
```
### 10.3 Dépendances importantes
Le service FastAPI nécessite notamment :
- `python3-fastapi`
- `python3-uvicorn`
- `python3-multipart`
---
## 11. Pages HTML Life-NOC
Le serveur Life-NOC sert aussi des pages HTML simples destinées à laction humaine.
### 11.1 URL ditem
Format :
```text
/life-noc/item/<domaine>/<item_key>
```
Exemple :
```text
/life-noc/item/revue/revue-hebdomadaire-priorites
```
### 11.2 Contenu de la page
La page affiche :
- titre humain ;
- état actuel ;
- type de sonde ;
- dernier intrant ;
- domaine ;
- item key ;
- notes ;
- lien `notes_url` ;
- lien `instructions_url` ;
- lien `action_url` ;
- bouton `Compléter`.
### 11.3 Route daction HTML
Le bouton `Compléter` utilise :
```text
POST /life-noc/item/<domaine>/<item_key>/complete
```
Puis redirige vers la page de litem.
---
## 12. Intégration Icinga
Life-NOC sappuie sur Icinga 2 / Icinga Web 2 pour la visualisation des états supervisés.
### 12.1 Ce que le système sait faire
- déployer les définitions de services ;
- exposer les custom variables ;
- rendre les états lisibles dans Icinga ;
- supporter `Check Now` ;
- intégrer les BPM natifs ;
- générer des servicegroups cohérents.
### 12.2 Informations visibles dans Icinga
Selon litem, on peut voir notamment :
- létat calculé ;
- les variables de seuil ;
- les variables de source ;
- les liens utiles ;
- `instructions_url` en variable personnalisée.
---
## 13. BPM et servicegroups
Life-NOC génère :
- des services Icinga ;
- des groupes de services ;
- une configuration BPM native.
Lobjectif est de rendre visibles à la fois :
- les items unitaires ;
- les regroupements par domaine ;
- la vision densemble hiérarchisée.
---
## 14. Flux de fonctionnement complet
Le fonctionnement complet suit le chemin suivant :
1. litem est défini dans `domains.yaml` ;
2. lintrant vivant est stocké dans `data/inputs/<domaine>.yaml` ;
3. la CLI, lAPI ou la page HTML modifient cet intrant ;
4. la sonde lit le store ;
5. la sonde calcule létat ;
6. Icinga laffiche ;
7. lusager agit ;
8. lintrant est mis à jour ;
9. le cycle recommence.
---
## 15. Déploiement et reproductibilité
Le dépôt doit permettre de reproduire le système sans correctifs manuels cachés.
### 15.1 Principes
- les correctifs doivent vivre dans le dépôt ;
- les dépendances nécessaires doivent être installées automatiquement ;
- les scripts de chantier temporaires doivent être supprimés une fois les changements intégrés proprement.
### 15.2 Déploiement habituel
```bash
make check
make deploy-with-bpm
```
---
## 16. Documentation pour les usagers
# Guide usager Life-NOC
## 16.1 À quoi sert Life-NOC pour lusager
Life-NOC aide une personne à voir rapidement ce qui mérite son attention, sans tout garder dans sa tête.
Il sert à suivre des choses comme :
- des revues régulières ;
- des dates importantes ;
- des entretiens ;
- des vérifications ;
- des obligations.
## 16.2 Ce que signifient les états
- **UNKNOWN** : pas encore le temps dagir ;
- **OK** : cest le bon moment pour sen occuper ;
- **WARNING** : il faut accélérer ;
- **CRITICAL** : cest urgent ou il y a un problème.
## 16.3 Comment consulter un item
Un item peut être consulté :
- dans Icinga ;
- via une page Life-NOC ;
- plus tard via QR code.
La page Life-NOC affiche :
- le nom du suivi ;
- son état ;
- la dernière valeur enregistrée ;
- les notes ;
- les instructions ;
- un bouton pour marquer laction comme faite.
## 16.4 Comment marquer une action comme faite
Quand litem le permet, il suffit de cliquer sur **Compléter**.
Cela met à jour la valeur de lintrant avec la date du jour.
## 16.5 Quand utiliser les liens utiles
- **Notes** : pour comprendre le contexte ;
- **Instructions** : pour savoir quoi faire ;
- **Action** : pour aller directement au bon outil ou à la bonne page.
## 16.6 Ce que lusager na pas besoin de faire
Lusager na normalement pas besoin de comprendre :
- le moteur de sonde ;
- les fichiers YAML ;
- la structure technique ;
- larchitecture Icinga.
Il lui suffit de :
- voir létat ;
- consulter les instructions ;
- marquer laction effectuée.
---
## 17. Documentation dexploitation
### 17.1 Vérifications utiles
#### Vérifier lAPI
```bash
curl http://127.0.0.1:8787/health
```
#### Vérifier un intrant
```bash
curl http://127.0.0.1:8787/inputs/revue/revue-hebdomadaire-priorites
```
#### Vérifier une page item
```bash
curl http://127.0.0.1:8787/life-noc/item/revue/revue-hebdomadaire-priorites
```
### 17.2 Cas fréquent : lintrant change mais pas létat dans Icinga
Cela signifie souvent quIcinga na pas encore refait le check.
Il faut alors :
- lancer un `Check Now` ;
- ou attendre le prochain check ;
- ou tester directement le plugin à la main.
### 17.3 Cas fréquent : route HTML absente après déploiement
Vérifier :
- que le service API tourne ;
- que le fichier déployé contient bien les routes HTML ;
- que les dépendances FastAPI sont installées, notamment `python3-multipart`.
---
## 18. QR codes — direction prévue
Life-NOC est conçu pour pouvoir pointer des QR codes vers des pages item.
Format visé :
```text
/life-noc/item/<domaine>/<item_key>
```
Le scan permettrait :
- douvrir litem ;
- de lire les instructions ;
- de confirmer laction ;
- de mettre à jour le système facilement.
---
## 19. État actuel du projet
Le système a déjà validé en pratique :
- Icinga Web 2 fonctionnel ;
- BPM natif fonctionnel ;
- servicegroups fonctionnels ;
- `Check Now` fonctionnel ;
- store dintrants séparé ;
- CLI des intrants ;
- API locale ;
- pages HTML ditem ;
- méthodes réelles `elapsed_time` et `days_until_due`.
---
## 20. Conclusion
Life-NOC dispose désormais dun noyau opératoire réel.
Il ne sagit plus seulement dun concept ou dune maquette.
Le système sait déjà :
- définir des suivis ;
- stocker des intrants ;
- évaluer des états ;
- exposer ces états ;
- fournir des instructions ;
- permettre laction ;
- réintégrer cette action dans la supervision.
Cest la base dun véritable système de pilotage personnel orienté action.

View file

@ -0,0 +1,657 @@
# Plan de démockage Life-NOC
## 1. Objet
Ce document sert de plan directeur pour faire évoluer Life-NOC dune preuve de concept partiellement mockée vers un système où **chaque item** :
- possède une **méthode réelle** ;
- possède une **source dintrants réelle** ;
- possède une **page web canonique** ;
- possède une **URL stable** ;
- peut être **consulté**, **compris** et **renseigné** de manière interactive.
Lobjectif final est :
> **1 item = 1 URL = 1 page = 1 logique = 1 source de vérité**
---
## 2. Principes retenus
### 2.1 Tout item doit être démocké
À terme, aucun item ne devrait dépendre dun état mocké durablement.
Le mock a servi à :
- prouver larchitecture ;
- faire exister la structure BPM et Icinga ;
- valider les flux de déploiement ;
- permettre une mise en place progressive.
Mais la cible est désormais :
- **zéro item purement mocké**.
### 2.2 Chaque item doit avoir sa page web
Chaque item doit avoir une URL canonique de la forme :
```text
/life-noc/item/<domaine>/<item_key>
```
Cette page doit devenir :
- la page dinformation ;
- la page dinstructions ;
- la page daction ;
- la page de saisie des intrants.
### 2.3 La page web dun item est linstruction par défaut
Pour tout item :
- si `instructions_url` est défini, il surcharge ;
- sinon, la page canonique de litem est la page dinstructions implicite.
Règle :
```text
instructions_url implicite = /life-noc/item/<domaine>/<item_key>
```
### 2.4 Les domaines organisent, les méthodes évaluent
- le **domaine** organise les items par sens métier ;
- la **méthode** exprime la logique de calcul ;
- l**item** relie domaine, méthode, intrant, UI et action.
Donc :
- plusieurs items dun même domaine peuvent utiliser des méthodes différentes ;
- plusieurs domaines peuvent réutiliser la même méthode.
---
## 3. Méthodes de sonde cibles
### 3.1 Méthodes déjà validées
#### `elapsed_time`
Mesure le temps écoulé depuis une dernière exécution.
#### `days_until_due`
Mesure le temps restant avant une échéance fixe.
### 3.2 Méthodes encore à industrialiser
#### `elapsed_distance`
Mesure une distance écoulée depuis une action passée.
#### `current_value`
Évalue une valeur instantanée contre des seuils.
#### `remaining_quantity`
Évalue une quantité restante contre des seuils.
---
## 4. Types dintrants cibles
Les intrants vivants continueront dêtre stockés dans :
```text
data/inputs/<domaine>.yaml
```
Les types principaux dintrants à supporter sont :
- `manual_date`
- `manual_counter`
- `manual_value`
À terme, dautres sources pourront exister, mais le démockage initial se concentre sur les intrants simples et robustes.
---
## 5. Formulaires web cibles
Chaque item doit pouvoir afficher un formulaire adapté à son type réel.
### 5.1 `complete_date`
Pour les items de type `elapsed_time` avec saisie de date de dernière exécution.
Exemples :
- revue périodique ;
- inspection ;
- test ;
- vérification périodique.
Fonctions attendues :
- bouton `Compléter`
- saisie manuelle dune date
- bouton `Aujourdhui`
### 5.2 `due_date`
Pour les items de type `days_until_due`.
Exemples :
- permis ;
- assurance ;
- passeport ;
- échéance administrative.
Fonctions attendues :
- saisie dune date déchéance
- bouton `Enregistrer`
### 5.3 `counter_pair`
Pour les items de type `elapsed_distance`.
Exemples :
- huile moteur ;
- pneus ;
- freins ;
- timing belt.
Fonctions attendues :
- compteur courant
- compteur au dernier entretien
- bouton `Enregistrer`
### 5.4 `numeric_value`
Pour les items de type `current_value`.
Exemples :
- tension batterie
- capacité libre
- température
- mesure technique
Fonctions attendues :
- saisie numérique
- unité affichée
- bouton `Enregistrer`
### 5.5 `remaining_quantity`
Pour les items de type `remaining_quantity`.
Exemples :
- réserve deau
- stock nourriture chats
- stock consommables
- carburant
Fonctions attendues :
- quantité restante
- unité
- bouton `Enregistrer`
---
## 6. Modèle cible dun item réel
Le modèle canonique minimal dun item réel devrait converger vers ceci :
```yaml
- name: remplacement-filtre-fournaise
title: "Remplacement du filtre de la fournaise"
summary: "Suivi périodique du filtre principal."
notes: "À faire selon la fréquence dusage et la saison."
notes_url: ""
instructions: |
1. Couper le système si nécessaire.
2. Retirer le filtre usagé.
3. Vérifier le sens du flux dair.
4. Installer le nouveau filtre.
5. Confirmer la date dans Life-NOC.
instructions_url: ""
action_url: ""
probe:
type: elapsed_time
source:
type: manual_date
inputs_file: "/opt/life-noc/data/inputs/maison.yaml"
item_key: "remplacement-filtre-fournaise"
metric:
unit: days
thresholds:
unknown_lt: 30
ok_gte: 30
warning_gte: 60
critical_gte: 90
policy:
on_error: critical
ui:
form_mode: complete_date
allow_complete: true
allow_manual_edit: true
```
Tous les champs ne seront pas obligatoires immédiatement, mais cette structure donne la direction.
---
## 7. Tableau de migration
## 7.1 REVUE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revue-quotidienne-life-noc | elapsed_time | manual_date | complete_date | réel |
| revue-hebdomadaire-priorites | elapsed_time | manual_date | complete_date | réel |
| revue-mensuelle-systeme-vie | elapsed_time | manual_date | complete_date | à migrer |
| revue-trimestrielle-orientation | elapsed_time | manual_date | complete_date | à migrer |
## 7.2 FOCUS
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| entretien-processus-focus | elapsed_time | manual_date | complete_date | à migrer |
| nettoyage-inbox-mentale | elapsed_time | manual_date | complete_date | à migrer |
| revue-limitation-engagements | elapsed_time | manual_date | complete_date | à migrer |
## 7.3 FINANCES-PERSONNELLES
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revision-comptes-bancaires | elapsed_time | manual_date | complete_date | à migrer |
| verification-cartes-credit | elapsed_time | manual_date | complete_date | à migrer |
| paiement-cartes-credit | elapsed_time | manual_date | complete_date | à migrer |
| revision-budget-personnel | elapsed_time | manual_date | complete_date | à migrer |
| verification-prelevements-automatiques | elapsed_time | manual_date | complete_date | à migrer |
| verification-placements | elapsed_time | manual_date | complete_date | à migrer |
| verification-cotisations-reer | elapsed_time | manual_date | complete_date | à migrer |
| verification-celi | elapsed_time | manual_date | complete_date | à migrer |
| preparation-dossier-financier-annuel | elapsed_time | manual_date | complete_date | à migrer |
## 7.4 FISCALITE-PERSONNELLE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| preparation-documents-impots | elapsed_time | manual_date | complete_date | à migrer |
| production-impots-federal | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| production-impots-quebec | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| paiement-solde-impots | days_until_due | manual_date | due_date | à migrer |
| verification-avis-cotisation | elapsed_time | manual_date | complete_date | à migrer |
| archivage-documents-fiscaux | elapsed_time | manual_date | complete_date | à migrer |
| verification-acomptes-provisionnels | days_until_due | manual_date | due_date | à migrer |
## 7.5 OBLIGATIONS-LEGALES-PERSONNELLES
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-testament | elapsed_time | manual_date | complete_date | à migrer |
| verification-mandat-inaptitude | elapsed_time | manual_date | complete_date | à migrer |
| verification-directives-medicales | elapsed_time | manual_date | complete_date | à migrer |
| verification-papiers-identite | elapsed_time | manual_date | complete_date | à migrer |
| renouvellement-permis-conduire | days_until_due | manual_date | due_date | réel |
| verification-carte-assurance-maladie | days_until_due | manual_date | due_date | à migrer |
| verification-passeport | days_until_due | manual_date | due_date | à migrer |
## 7.6 MAISON
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| remplacement-filtre-fournaise | elapsed_time | manual_date | complete_date | à migrer |
| inspection-fournaise | elapsed_time | manual_date | complete_date | à migrer |
| inspection-thermopompe | elapsed_time | manual_date | complete_date | à migrer |
| nettoyage-unites-exterieures | elapsed_time | manual_date | complete_date | à migrer |
| inspection-toiture | elapsed_time | manual_date | complete_date | à migrer |
| inspection-gouttieres | elapsed_time | manual_date | complete_date | à migrer |
| inspection-fondation | elapsed_time | manual_date | complete_date | à migrer |
| verification-drainage-terrain | elapsed_time | manual_date | complete_date | à migrer |
| test-detecteurs-fumee | elapsed_time | manual_date | complete_date | à migrer |
| test-detecteurs-co | elapsed_time | manual_date | complete_date | à migrer |
| remplacement-piles-detecteurs | elapsed_time | manual_date | complete_date | à migrer |
| verification-plomberie-visible | elapsed_time | manual_date | complete_date | à migrer |
| inspection-sump-pump | elapsed_time | manual_date | complete_date | à migrer |
| verification-calfetrage | elapsed_time | manual_date | complete_date | à migrer |
| inspection-portes-garage | elapsed_time | manual_date | complete_date | à migrer |
| verification-extincteurs | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
## 7.7 GARAGE-ET-RANGEMENT
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| inspection-rangement-plafond | elapsed_time | manual_date | complete_date | à migrer |
| revue-inventaire-garage | elapsed_time | manual_date | complete_date | à migrer |
| verification-rouille-outillage | elapsed_time | manual_date | complete_date | à migrer |
| inspection-securite-garage | elapsed_time | manual_date | complete_date | à migrer |
| rotation-stockage-bacs | elapsed_time | manual_date | complete_date | à migrer |
## 7.8 ENERGIE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| inspection-batteries-lifepo4 | elapsed_time | manual_date | complete_date | à migrer |
| verification-tension-batteries | current_value | manual_value | numeric_value | à migrer |
| verification-smartshunt | current_value | manual_value | numeric_value | à préciser |
| verification-cerbo-gx | elapsed_time / current_value | manual_date / manual_value | complete_date / numeric_value | à préciser |
| verification-can-rs485 | elapsed_time | manual_date | complete_date | à migrer |
| inspection-cablage-energie | elapsed_time | manual_date | complete_date | à migrer |
| verification-busbars | elapsed_time | manual_date | complete_date | à migrer |
| verification-parametres-charge | elapsed_time | manual_date | complete_date | à migrer |
| test-charge-batteries | elapsed_time | manual_date | complete_date | à migrer |
| test-comportement-onduleur | elapsed_time | manual_date | complete_date | à migrer |
| verification-journal-evenements-victron | elapsed_time | manual_date | complete_date | à migrer |
## 7.9 RESILIENCE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| test-generatrice-propane | elapsed_time | manual_date | complete_date | à migrer |
| verification-carburant-generatrice | remaining_quantity | manual_value | remaining_quantity | à migrer |
| verification-procedure-bascule | elapsed_time | manual_date | complete_date | à migrer |
| verification-stock-lampes-piles | remaining_quantity | manual_value | remaining_quantity | à migrer |
| verification-trousses-urgence | remaining_quantity / elapsed_time | manual_value / manual_date | remaining_quantity / complete_date | à préciser |
| revision-plan-urgence | elapsed_time | manual_date | complete_date | à migrer |
| test-autonomie-base | elapsed_time | manual_date | complete_date | à migrer |
| verification-moyens-cuisson-secours | remaining_quantity / elapsed_time | manual_value / manual_date | remaining_quantity / complete_date | à préciser |
## 7.10 STOCK-ALIMENTAIRE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| rotation-nourriture-seche | elapsed_time | manual_date | complete_date | à migrer |
| verification-reserve-eau | remaining_quantity | manual_value | remaining_quantity | à migrer |
| verification-mylar-absorbeurs | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revue-inventaire-conserves | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revue-inventaire-farine-riz-pates | remaining_quantity | manual_value | remaining_quantity | à migrer |
| verification-bacs-legumes-racines | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revue-supplements-vitamines | remaining_quantity | manual_value | remaining_quantity | à migrer |
## 7.11 SANTE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-trousse-premiers-soins | remaining_quantity / elapsed_time | manual_value / manual_date | remaining_quantity / complete_date | à préciser |
| verification-expiration-medicaments | days_until_due | manual_date | due_date | à migrer |
| revision-rendez-vous-medicaux | days_until_due | manual_date | due_date | à migrer |
| verification-lunettes-prescriptions | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| verification-dossier-sante | elapsed_time | manual_date | complete_date | à migrer |
## 7.12 VOITURE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-huile-moteur | elapsed_distance | manual_counter | counter_pair | à migrer |
| inspection-freins | elapsed_distance | manual_counter | counter_pair | à migrer |
| verification-pneus | elapsed_distance | manual_counter | counter_pair | à migrer |
| ajustement-valves | elapsed_distance / elapsed_time | manual_counter / manual_date | counter_pair / complete_date | à préciser |
| verification-timing-belt | elapsed_distance | manual_counter | counter_pair | à migrer |
| verification-batterie-voiture | current_value | manual_value | numeric_value | à migrer |
| verification-balais-essuie-glace | elapsed_time | manual_date | complete_date | à migrer |
| verification-liquides | current_value / elapsed_time | manual_value / manual_date | numeric_value / complete_date | à préciser |
| verification-eclairage | elapsed_time | manual_date | complete_date | à migrer |
| verification-immatriculation-assurance | days_until_due | manual_date | due_date | à migrer |
## 7.13 JARDIN
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| inspection-vignes | elapsed_time | manual_date | complete_date | à migrer |
| entretien-bleuetiers | elapsed_time | manual_date | complete_date | à migrer |
| entretien-framboisiers | elapsed_time | manual_date | complete_date | à migrer |
| inspection-kiwis-nordiques | elapsed_time | manual_date | complete_date | à migrer |
| entretien-rhubarbe | elapsed_time | manual_date | complete_date | à migrer |
| inspection-groseillier | elapsed_time | manual_date | complete_date | à migrer |
| inspection-muriers | elapsed_time | manual_date | complete_date | à migrer |
| entretien-houblon | elapsed_time | manual_date | complete_date | à migrer |
| revision-pharmacopee-jardin | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revision-armoire-produits-jardin | remaining_quantity | manual_value | remaining_quantity | à migrer |
## 7.14 OUTILS-ET-EQUIPEMENTS
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| entretien-outils-jardin | elapsed_time | manual_date | complete_date | à migrer |
| inspection-outils-electriques | elapsed_time | manual_date | complete_date | à migrer |
| verification-rallonges-et-connecteurs | elapsed_time | manual_date | complete_date | à migrer |
| verification-compresseur-et-accessoires | elapsed_time | manual_date | complete_date | à migrer |
| revision-inventaire-outillage | elapsed_time | manual_date | complete_date | à migrer |
## 7.15 INFORMATIQUE-PERSONNELLE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-sauvegardes-personnelles | elapsed_time | manual_date | complete_date | à migrer |
| nettoyage-stockage-personnel | elapsed_time | manual_date | complete_date | à migrer |
| verification-comptes-importants | elapsed_time | manual_date | complete_date | à migrer |
| revue-mots-de-passe-personnels | elapsed_time | manual_date | complete_date | à migrer |
| verification-documents-cloud-personnels | elapsed_time | manual_date | complete_date | à migrer |
## 7.16 INFRASTRUCTURE-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-proxmox | elapsed_time | manual_date | complete_date | à migrer |
| verification-ceph | elapsed_time / current_value | manual_date / manual_value | complete_date / numeric_value | à préciser |
| test-restauration-backups | elapsed_time | manual_date | complete_date | à migrer |
| verification-pbs-truenas | elapsed_time | manual_date | complete_date | à migrer |
| verification-ups-infrastructure | current_value | manual_value | numeric_value | à migrer |
| verification-capacite-stockage | current_value | manual_value | numeric_value | à migrer |
| verification-apt-cacher-ng | elapsed_time | manual_date | complete_date | à migrer |
| verification-icinga2 | elapsed_time | manual_date | complete_date | à migrer |
| verification-keycloak-openldap | elapsed_time | manual_date | complete_date | à migrer |
| verification-nextcloud | elapsed_time | manual_date | complete_date | à migrer |
| verification-mailcow | elapsed_time | manual_date | complete_date | à migrer |
| verification-openvas | elapsed_time | manual_date | complete_date | à migrer |
| verification-journaux-systemes | elapsed_time | manual_date | complete_date | à migrer |
## 7.17 RESEAU-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-firewalls | elapsed_time | manual_date | complete_date | à migrer |
| verification-vpn-openvpn | elapsed_time | manual_date | complete_date | à migrer |
| verification-crl-certificats | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| verification-switches | elapsed_time | manual_date | complete_date | à migrer |
| verification-vlans-segmentation | elapsed_time | manual_date | complete_date | à migrer |
| verification-dns | elapsed_time | manual_date | complete_date | à migrer |
| verification-dynamic-dns | elapsed_time | manual_date | complete_date | à migrer |
| audit-regles-firewall | elapsed_time | manual_date | complete_date | à migrer |
| verification-geoblocking | elapsed_time | manual_date | complete_date | à migrer |
| verification-certificats-publics | days_until_due | manual_date | due_date | à migrer |
## 7.18 SECURITE-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-mises-a-jour-securite | elapsed_time | manual_date | complete_date | à migrer |
| audit-comptes-acces | elapsed_time | manual_date | complete_date | à migrer |
| verification-ids-snort | elapsed_time | manual_date | complete_date | à migrer |
| revue-pki-privee | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| revue-politiques-securite | elapsed_time | manual_date | complete_date | à migrer |
| verification-sauvegardes-configuration | elapsed_time | manual_date | complete_date | à migrer |
## 7.19 EXPLOITATION-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revision-playbooks-ansible | elapsed_time | manual_date | complete_date | à migrer |
| verification-inventaires-ansible | elapsed_time | manual_date | complete_date | à migrer |
| revision-documentation-technique | elapsed_time | manual_date | complete_date | à migrer |
| verification-procedures-reprise | elapsed_time | manual_date | complete_date | à migrer |
| revue-capacite-ressources | elapsed_time | manual_date | complete_date | à migrer |
| verification-jobs-automatises | elapsed_time | manual_date | complete_date | à migrer |
## 7.20 OBLIGATIONS-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-registraire-entreprise | days_until_due | manual_date | due_date | à migrer |
| verification-declarations-taxes | days_until_due | manual_date | due_date | à migrer |
| verification-dossier-comptable-entreprise | elapsed_time | manual_date | complete_date | à migrer |
| verification-facturation-clients | elapsed_time | manual_date | complete_date | à migrer |
| verification-paiements-fournisseurs | elapsed_time | manual_date | complete_date | à migrer |
| verification-contrats-ententes | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| verification-assurances-entreprise | days_until_due | manual_date | due_date | à migrer |
| archivage-documents-entreprise | elapsed_time | manual_date | complete_date | à migrer |
## 7.21 ACTIFS-CHEZLEPRO
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revision-inventaire-materiel | elapsed_time | manual_date | complete_date | à migrer |
| verification-amortissables | days_until_due / elapsed_time | manual_date | due_date / complete_date | à préciser |
| verification-serveurs-et-composants | elapsed_time | manual_date | complete_date | à migrer |
| verification-reserve-pieces | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revision-actifs-transferts | elapsed_time | manual_date | complete_date | à migrer |
## 7.22 PROJETS
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revision-life-noc | elapsed_time | manual_date | complete_date | à migrer |
| revision-alliance-boreale | elapsed_time | manual_date | complete_date | à migrer |
| revision-erplibre | elapsed_time | manual_date | complete_date | à migrer |
| revision-semence-numerique | elapsed_time | manual_date | complete_date | à migrer |
| revision-ortrux-1 | elapsed_time | manual_date | complete_date | à migrer |
| revision-district16 | elapsed_time | manual_date | complete_date | à migrer |
## 7.23 COMMUNAUTE
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-outils-aa | elapsed_time | manual_date | complete_date | à migrer |
| verification-espace-87-16 | elapsed_time | manual_date | complete_date | à migrer |
| verification-salles-visio-groupes | elapsed_time | manual_date | complete_date | à migrer |
| verification-depots-rapports-rsg | elapsed_time | manual_date | complete_date | à migrer |
| revision-outils-communication-communaute | elapsed_time | manual_date | complete_date | à migrer |
## 7.24 DOCUMENTATION
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| revue-docs-personnelles-importantes | elapsed_time | manual_date | complete_date | à migrer |
| revue-wiki-technique | elapsed_time | manual_date | complete_date | à migrer |
| revue-base-connaissances | elapsed_time | manual_date | complete_date | à migrer |
| verification-sauvegarde-docs-cles | elapsed_time | manual_date | complete_date | à migrer |
## 7.25 ANIMAUX
| item_key | méthode cible | intrant | formulaire | statut |
|---|---|---|---|---|
| verification-stock-nourriture-chats | remaining_quantity | manual_value | remaining_quantity | à migrer |
| verification-friandises-et-litiere | remaining_quantity | manual_value | remaining_quantity | à migrer |
| revision-routine-soins-animaux | elapsed_time | manual_date | complete_date | à migrer |
---
## 8. Priorité de migration
### Vague 1 — tout ce qui est date simple
Objectif :
- finir `elapsed_time`
- finir `days_until_due`
Cest la vague la plus simple, la plus rentable et la moins risquée.
### Vague 2 — voiture
Objectif :
- introduire `elapsed_distance`
### Vague 3 — stocks et réserves
Objectif :
- introduire `remaining_quantity`
### Vague 4 — mesures techniques
Objectif :
- introduire `current_value`
---
## 9. Pages web cibles
Chaque item doit converger vers une page web canonique :
```text
/life-noc/item/<domaine>/<item_key>
```
Cette page doit devenir :
- la fiche de contexte ;
- la fiche dinstructions ;
- la fiche daction ;
- la fiche de saisie des intrants.
### 9.1 Contenu minimal
- titre humain
- état actuel
- dernier intrant
- résumé
- notes
- instructions
- liens utiles
- formulaire adapté
- action disponible
### 9.2 Règle sur `instructions_url`
La page de litem est la page dinstructions par défaut.
Règle :
- si `instructions_url` est explicite, on lutilise ;
- sinon, on considère implicitement :
```text
/life-noc/item/<domaine>/<item_key>
```
---
## 10. Critère de fin de démockage
Le démockage dun item sera considéré terminé quand :
- litem possède un `probe` réel ;
- litem possède un intrant réel ;
- litem possède une page web opérationnelle ;
- litem possède un formulaire web adapté ;
- litem possède une URL canonique stable ;
- létat Icinga est calculé à partir du vrai store.
---
## 11. Stratégie de mise en œuvre
### Phase 1
Finir toutes les migrations `elapsed_time` et `days_until_due`.
### Phase 2
Faire évoluer la page item pour afficher :
- `title`
- `summary`
- `instructions`
- formulaire adapté au type dintrant.
### Phase 3
Ajouter les endpoints HTML de mise à jour interactive des intrants.
### Phase 4
Introduire successivement :
- `elapsed_distance`
- `remaining_quantity`
- `current_value`
### Phase 5
Éliminer complètement les items mockés restants.
---
## 12. Conclusion
La cible Life-NOC retenue est désormais claire :
- **tout item doit être réel**
- **tout item doit avoir sa page**
- **tout item doit avoir son URL**
- **tout item doit être renseignable**
- **tout item doit pouvoir guider laction**
Ce plan sert de carte de migration pour converger progressivement vers ce modèle.

View file

@ -21,6 +21,7 @@ domains:
- name: revue-hebdomadaire-priorites - name: revue-hebdomadaire-priorites
date: '2026-03-10' date: '2026-03-10'
notes: Revoir les priorités de la semaine notes: Revoir les priorités de la semaine
instructions_url: "https://chezlepro.ca/life-noc/test-instructions"
probe: probe:
type: elapsed_time type: elapsed_time
source: source:

View file

@ -11,6 +11,7 @@ apply Service "actifs-chezlepro-revision-inventaire-materiel" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ACTIFS-CHEZLEPRO" ] groups = [ "ACTIFS-CHEZLEPRO" ]
notes = "Revoir l'inventaire du matériel de Chezlepro" notes = "Revoir l'inventaire du matériel de Chezlepro"
vars.instructions_url = "/life-noc/item/actifs-chezlepro/revision-inventaire-materiel"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "actifs-chezlepro-verification-amortissables" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ACTIFS-CHEZLEPRO" ] groups = [ "ACTIFS-CHEZLEPRO" ]
notes = "Vérifier le registre des biens amortissables" notes = "Vérifier le registre des biens amortissables"
vars.instructions_url = "/life-noc/item/actifs-chezlepro/verification-amortissables"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "actifs-chezlepro-verification-serveurs-et-composants" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ACTIFS-CHEZLEPRO" ] groups = [ "ACTIFS-CHEZLEPRO" ]
notes = "Vérifier l'état des serveurs et composants matériels" notes = "Vérifier l'état des serveurs et composants matériels"
vars.instructions_url = "/life-noc/item/actifs-chezlepro/verification-serveurs-et-composants"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "actifs-chezlepro-verification-reserve-pieces" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ACTIFS-CHEZLEPRO" ] groups = [ "ACTIFS-CHEZLEPRO" ]
notes = "Vérifier les pièces de rechange critiques" notes = "Vérifier les pièces de rechange critiques"
vars.instructions_url = "/life-noc/item/actifs-chezlepro/verification-reserve-pieces"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "actifs-chezlepro-revision-actifs-transferts" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ACTIFS-CHEZLEPRO" ] groups = [ "ACTIFS-CHEZLEPRO" ]
notes = "Réviser les actifs transférés ou à transférer à l'entreprise" notes = "Réviser les actifs transférés ou à transférer à l'entreprise"
vars.instructions_url = "/life-noc/item/actifs-chezlepro/revision-actifs-transferts"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "animaux-verification-stock-nourriture-chats" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ANIMAUX" ] groups = [ "ANIMAUX" ]
notes = "Vérification du stock de nourriture pour chats" notes = "Vérification du stock de nourriture pour chats"
vars.instructions_url = "/life-noc/item/animaux/verification-stock-nourriture-chats"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "animaux-verification-friandises-et-litiere" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ANIMAUX" ] groups = [ "ANIMAUX" ]
notes = "Vérification des stocks de friandises et de litière" notes = "Vérification des stocks de friandises et de litière"
vars.instructions_url = "/life-noc/item/animaux/verification-friandises-et-litiere"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,5 +33,6 @@ apply Service "animaux-revision-routine-soins-animaux" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ANIMAUX" ] groups = [ "ANIMAUX" ]
notes = "Revue de la routine de soins et des besoins matériels des chats" notes = "Revue de la routine de soins et des besoins matériels des chats"
vars.instructions_url = "/life-noc/item/animaux/revision-routine-soins-animaux"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "communaute-verification-outils-aa" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "COMMUNAUTE" ] groups = [ "COMMUNAUTE" ]
notes = "Vérifier les outils numériques liés aux activités communautaires" notes = "Vérifier les outils numériques liés aux activités communautaires"
vars.instructions_url = "/life-noc/item/communaute/verification-outils-aa"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "communaute-verification-espace-87-16" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "COMMUNAUTE" ] groups = [ "COMMUNAUTE" ]
notes = "Vérifier l'espace Nextcloud du district" notes = "Vérifier l'espace Nextcloud du district"
vars.instructions_url = "/life-noc/item/communaute/verification-espace-87-16"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "communaute-verification-salles-visio-groupes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "COMMUNAUTE" ] groups = [ "COMMUNAUTE" ]
notes = "Vérifier les salles de visioconférence des groupes" notes = "Vérifier les salles de visioconférence des groupes"
vars.instructions_url = "/life-noc/item/communaute/verification-salles-visio-groupes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "communaute-verification-depots-rapports-rsg" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "COMMUNAUTE" ] groups = [ "COMMUNAUTE" ]
notes = "Vérifier les dépôts de rapports RSG" notes = "Vérifier les dépôts de rapports RSG"
vars.instructions_url = "/life-noc/item/communaute/verification-depots-rapports-rsg"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "communaute-revision-outils-communication-communaute" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "COMMUNAUTE" ] groups = [ "COMMUNAUTE" ]
notes = "Réviser les moyens de communication communautaires" notes = "Réviser les moyens de communication communautaires"
vars.instructions_url = "/life-noc/item/communaute/revision-outils-communication-communaute"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "documentation-revue-docs-personnelles-importantes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "DOCUMENTATION" ] groups = [ "DOCUMENTATION" ]
notes = "Revoir l'organisation des documents personnels importants" notes = "Revoir l'organisation des documents personnels importants"
vars.instructions_url = "/life-noc/item/documentation/revue-docs-personnelles-importantes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "documentation-revue-wiki-technique" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "DOCUMENTATION" ] groups = [ "DOCUMENTATION" ]
notes = "Revoir le wiki technique et sa cohérence" notes = "Revoir le wiki technique et sa cohérence"
vars.instructions_url = "/life-noc/item/documentation/revue-wiki-technique"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "documentation-revue-base-connaissances" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "DOCUMENTATION" ] groups = [ "DOCUMENTATION" ]
notes = "Revoir la base de connaissances globale" notes = "Revoir la base de connaissances globale"
vars.instructions_url = "/life-noc/item/documentation/revue-base-connaissances"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,5 +44,6 @@ apply Service "documentation-verification-sauvegarde-docs-cles" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "DOCUMENTATION" ] groups = [ "DOCUMENTATION" ]
notes = "Vérifier la sauvegarde des documents clés" notes = "Vérifier la sauvegarde des documents clés"
vars.instructions_url = "/life-noc/item/documentation/verification-sauvegarde-docs-cles"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "energie-inspection-batteries-lifepo4" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Inspection physique et logique des batteries LiFePO4" notes = "Inspection physique et logique des batteries LiFePO4"
vars.instructions_url = "/life-noc/item/energie/inspection-batteries-lifepo4"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "energie-verification-tension-batteries" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification des tensions et cohérence des batteries" notes = "Vérification des tensions et cohérence des batteries"
vars.instructions_url = "/life-noc/item/energie/verification-tension-batteries"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "energie-verification-smartshunt" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification SmartShunt et cohérence du monitoring" notes = "Vérification SmartShunt et cohérence du monitoring"
vars.instructions_url = "/life-noc/item/energie/verification-smartshunt"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "energie-verification-cerbo-gx" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification Cerbo GX et remontée des données" notes = "Vérification Cerbo GX et remontée des données"
vars.instructions_url = "/life-noc/item/energie/verification-cerbo-gx"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "energie-verification-can-rs485" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification des communications CAN ou RS485" notes = "Vérification des communications CAN ou RS485"
vars.instructions_url = "/life-noc/item/energie/verification-can-rs485"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "energie-inspection-cablage-energie" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Inspection du câblage et des connexions énergétiques" notes = "Inspection du câblage et des connexions énergétiques"
vars.instructions_url = "/life-noc/item/energie/inspection-cablage-energie"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "energie-verification-busbars" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification du serrage, corrosion et échauffement des busbars" notes = "Vérification du serrage, corrosion et échauffement des busbars"
vars.instructions_url = "/life-noc/item/energie/verification-busbars"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "energie-verification-parametres-charge" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification des paramètres de charge et float" notes = "Vérification des paramètres de charge et float"
vars.instructions_url = "/life-noc/item/energie/verification-parametres-charge"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "energie-test-charge-batteries" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Test de comportement en charge des batteries" notes = "Test de comportement en charge des batteries"
vars.instructions_url = "/life-noc/item/energie/test-charge-batteries"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,6 +110,7 @@ apply Service "energie-test-comportement-onduleur" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérifier le comportement du Multiplus sous charge légère" notes = "Vérifier le comportement du Multiplus sous charge légère"
vars.instructions_url = "/life-noc/item/energie/test-comportement-onduleur"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -111,5 +121,6 @@ apply Service "energie-verification-journal-evenements-victron" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "ENERGIE" ] groups = [ "ENERGIE" ]
notes = "Vérification des événements et anomalies Victron" notes = "Vérification des événements et anomalies Victron"
vars.instructions_url = "/life-noc/item/energie/verification-journal-evenements-victron"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "exploitation-chezlepro-revision-playbooks-ansible" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Revue des playbooks Ansible" notes = "Revue des playbooks Ansible"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/revision-playbooks-ansible"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "exploitation-chezlepro-verification-inventaires-ansible" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Vérification des inventaires Ansible" notes = "Vérification des inventaires Ansible"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/verification-inventaires-ansible"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "exploitation-chezlepro-revision-documentation-technique" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Revue de la documentation technique Chezlepro" notes = "Revue de la documentation technique Chezlepro"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/revision-documentation-technique"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "exploitation-chezlepro-verification-procedures-reprise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Vérifier les procédures de reprise et restauration" notes = "Vérifier les procédures de reprise et restauration"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/verification-procedures-reprise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "exploitation-chezlepro-revue-capacite-ressources" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Revue CPU RAM stockage et charge de l'infrastructure" notes = "Revue CPU RAM stockage et charge de l'infrastructure"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/revue-capacite-ressources"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,5 +66,6 @@ apply Service "exploitation-chezlepro-verification-jobs-automatises" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "EXPLOITATION-CHEZLEPRO" ] groups = [ "EXPLOITATION-CHEZLEPRO" ]
notes = "Vérification des jobs automatisés et scripts périodiques" notes = "Vérification des jobs automatisés et scripts périodiques"
vars.instructions_url = "/life-noc/item/exploitation-chezlepro/verification-jobs-automatises"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "finances-personnelles-revision-comptes-bancaires" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Révision mensuelle des comptes bancaires personnels" notes = "Révision mensuelle des comptes bancaires personnels"
vars.instructions_url = "/life-noc/item/finances-personnelles/revision-comptes-bancaires"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "finances-personnelles-verification-cartes-credit" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Vérification des soldes et transactions des cartes de crédit" notes = "Vérification des soldes et transactions des cartes de crédit"
vars.instructions_url = "/life-noc/item/finances-personnelles/verification-cartes-credit"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "finances-personnelles-paiement-cartes-credit" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Paiement des cartes de crédit personnelles" notes = "Paiement des cartes de crédit personnelles"
vars.instructions_url = "/life-noc/item/finances-personnelles/paiement-cartes-credit"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "finances-personnelles-revision-budget-personnel" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Révision mensuelle du budget personnel" notes = "Révision mensuelle du budget personnel"
vars.instructions_url = "/life-noc/item/finances-personnelles/revision-budget-personnel"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "finances-personnelles-verification-prelevements-automatiques" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Vérification des prélèvements automatiques personnels" notes = "Vérification des prélèvements automatiques personnels"
vars.instructions_url = "/life-noc/item/finances-personnelles/verification-prelevements-automatiques"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "finances-personnelles-verification-placements" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Vérification périodique des placements et comptes enregistrés" notes = "Vérification périodique des placements et comptes enregistrés"
vars.instructions_url = "/life-noc/item/finances-personnelles/verification-placements"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "finances-personnelles-verification-cotisations-reer" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Vérification des cotisations REER" notes = "Vérification des cotisations REER"
vars.instructions_url = "/life-noc/item/finances-personnelles/verification-cotisations-reer"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "finances-personnelles-verification-celi" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Vérification de l'espace CELI et de son utilisation" notes = "Vérification de l'espace CELI et de son utilisation"
vars.instructions_url = "/life-noc/item/finances-personnelles/verification-celi"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,5 +99,6 @@ apply Service "finances-personnelles-preparation-dossier-financier-annuel" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FINANCES-PERSONNELLES" ] groups = [ "FINANCES-PERSONNELLES" ]
notes = "Préparer le dossier financier annuel personnel" notes = "Préparer le dossier financier annuel personnel"
vars.instructions_url = "/life-noc/item/finances-personnelles/preparation-dossier-financier-annuel"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "fiscalite-personnelle-preparation-documents-impots" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Rassembler tous les documents fiscaux personnels" notes = "Rassembler tous les documents fiscaux personnels"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/preparation-documents-impots"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "fiscalite-personnelle-production-impots-federal" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Produire la déclaration de revenus fédérale" notes = "Produire la déclaration de revenus fédérale"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/production-impots-federal"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "fiscalite-personnelle-production-impots-quebec" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Produire la déclaration de revenus Québec" notes = "Produire la déclaration de revenus Québec"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/production-impots-quebec"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "fiscalite-personnelle-paiement-solde-impots" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Payer tout solde d'impôt exigible" notes = "Payer tout solde d'impôt exigible"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/paiement-solde-impots"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "fiscalite-personnelle-verification-avis-cotisation" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Vérifier les avis de cotisation ARC et Revenu Québec" notes = "Vérifier les avis de cotisation ARC et Revenu Québec"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/verification-avis-cotisation"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "fiscalite-personnelle-archivage-documents-fiscaux" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Archiver les documents fiscaux personnels" notes = "Archiver les documents fiscaux personnels"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/archivage-documents-fiscaux"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,5 +77,6 @@ apply Service "fiscalite-personnelle-verification-acomptes-provisionnels" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FISCALITE-PERSONNELLE" ] groups = [ "FISCALITE-PERSONNELLE" ]
notes = "Vérifier si des acomptes provisionnels sont requis" notes = "Vérifier si des acomptes provisionnels sont requis"
vars.instructions_url = "/life-noc/item/fiscalite-personnelle/verification-acomptes-provisionnels"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "focus-entretien-processus-focus" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FOCUS" ] groups = [ "FOCUS" ]
notes = "Vérifier que les cartouches FOCUS sont à jour" notes = "Vérifier que les cartouches FOCUS sont à jour"
vars.instructions_url = "/life-noc/item/focus/entretien-processus-focus"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "focus-nettoyage-inbox-mentale" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FOCUS" ] groups = [ "FOCUS" ]
notes = "Vider et clarifier les éléments capturés hors système" notes = "Vider et clarifier les éléments capturés hors système"
vars.instructions_url = "/life-noc/item/focus/nettoyage-inbox-mentale"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,5 +33,6 @@ apply Service "focus-revue-limitation-engagements" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "FOCUS" ] groups = [ "FOCUS" ]
notes = "Vérifier que les engagements actifs demeurent réalistes" notes = "Vérifier que les engagements actifs demeurent réalistes"
vars.instructions_url = "/life-noc/item/focus/revue-limitation-engagements"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "garage-et-rangement-inspection-rangement-plafond" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "GARAGE-ET-RANGEMENT" ] groups = [ "GARAGE-ET-RANGEMENT" ]
notes = "Vérification des supports suspendus au plafond du garage" notes = "Vérification des supports suspendus au plafond du garage"
vars.instructions_url = "/life-noc/item/garage-et-rangement/inspection-rangement-plafond"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "garage-et-rangement-revue-inventaire-garage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "GARAGE-ET-RANGEMENT" ] groups = [ "GARAGE-ET-RANGEMENT" ]
notes = "Revue de l'inventaire et de l'ordre du garage" notes = "Revue de l'inventaire et de l'ordre du garage"
vars.instructions_url = "/life-noc/item/garage-et-rangement/revue-inventaire-garage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "garage-et-rangement-verification-rouille-outillage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "GARAGE-ET-RANGEMENT" ] groups = [ "GARAGE-ET-RANGEMENT" ]
notes = "Vérification de la corrosion sur les outils et équipements" notes = "Vérification de la corrosion sur les outils et équipements"
vars.instructions_url = "/life-noc/item/garage-et-rangement/verification-rouille-outillage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "garage-et-rangement-inspection-securite-garage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "GARAGE-ET-RANGEMENT" ] groups = [ "GARAGE-ET-RANGEMENT" ]
notes = "Vérification des conditions de sécurité du garage" notes = "Vérification des conditions de sécurité du garage"
vars.instructions_url = "/life-noc/item/garage-et-rangement/inspection-securite-garage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "garage-et-rangement-rotation-stockage-bacs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "GARAGE-ET-RANGEMENT" ] groups = [ "GARAGE-ET-RANGEMENT" ]
notes = "Revue des contenus de bacs de rangement" notes = "Revue des contenus de bacs de rangement"
vars.instructions_url = "/life-noc/item/garage-et-rangement/rotation-stockage-bacs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "informatique-personnelle-verification-sauvegardes-personnelles" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFORMATIQUE-PERSONNELLE" ] groups = [ "INFORMATIQUE-PERSONNELLE" ]
notes = "Vérification des sauvegardes personnelles" notes = "Vérification des sauvegardes personnelles"
vars.instructions_url = "/life-noc/item/informatique-personnelle/verification-sauvegardes-personnelles"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "informatique-personnelle-nettoyage-stockage-personnel" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFORMATIQUE-PERSONNELLE" ] groups = [ "INFORMATIQUE-PERSONNELLE" ]
notes = "Nettoyage du stockage numérique personnel" notes = "Nettoyage du stockage numérique personnel"
vars.instructions_url = "/life-noc/item/informatique-personnelle/nettoyage-stockage-personnel"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "informatique-personnelle-verification-comptes-importants" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFORMATIQUE-PERSONNELLE" ] groups = [ "INFORMATIQUE-PERSONNELLE" ]
notes = "Vérification des comptes numériques personnels importants" notes = "Vérification des comptes numériques personnels importants"
vars.instructions_url = "/life-noc/item/informatique-personnelle/verification-comptes-importants"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "informatique-personnelle-revue-mots-de-passe-personnels" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFORMATIQUE-PERSONNELLE" ] groups = [ "INFORMATIQUE-PERSONNELLE" ]
notes = "Revue des mots de passe personnels critiques" notes = "Revue des mots de passe personnels critiques"
vars.instructions_url = "/life-noc/item/informatique-personnelle/revue-mots-de-passe-personnels"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "informatique-personnelle-verification-documents-cloud-personnels"
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFORMATIQUE-PERSONNELLE" ] groups = [ "INFORMATIQUE-PERSONNELLE" ]
notes = "Vérifier la cohérence des documents personnels sauvegardés" notes = "Vérifier la cohérence des documents personnels sauvegardés"
vars.instructions_url = "/life-noc/item/informatique-personnelle/verification-documents-cloud-personnels"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "infrastructure-chezlepro-verification-proxmox" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification générale de l'environnement Proxmox" notes = "Vérification générale de l'environnement Proxmox"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-proxmox"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "infrastructure-chezlepro-verification-ceph" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification générale de l'état Ceph" notes = "Vérification générale de l'état Ceph"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-ceph"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "infrastructure-chezlepro-test-restauration-backups" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Test de restauration des sauvegardes" notes = "Test de restauration des sauvegardes"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/test-restauration-backups"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "infrastructure-chezlepro-verification-pbs-truenas" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification des solutions de sauvegarde et synchronisation" notes = "Vérification des solutions de sauvegarde et synchronisation"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-pbs-truenas"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "infrastructure-chezlepro-verification-ups-infrastructure" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification des UPS de l'infrastructure" notes = "Vérification des UPS de l'infrastructure"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-ups-infrastructure"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "infrastructure-chezlepro-verification-capacite-stockage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérifier capacité et croissance du stockage" notes = "Vérifier capacité et croissance du stockage"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-capacite-stockage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "infrastructure-chezlepro-verification-apt-cacher-ng" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification du bon fonctionnement d'apt-cacher-ng" notes = "Vérification du bon fonctionnement d'apt-cacher-ng"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-apt-cacher-ng"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "infrastructure-chezlepro-verification-icinga2" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification de la supervision Icinga2" notes = "Vérification de la supervision Icinga2"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-icinga2"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "infrastructure-chezlepro-verification-keycloak-openldap" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification de l'identité et de l'authentification centralisées" notes = "Vérification de l'identité et de l'authentification centralisées"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-keycloak-openldap"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,6 +110,7 @@ apply Service "infrastructure-chezlepro-verification-nextcloud" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification de l'état Nextcloud" notes = "Vérification de l'état Nextcloud"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-nextcloud"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -111,6 +121,7 @@ apply Service "infrastructure-chezlepro-verification-mailcow" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification de l'infrastructure Mailcow" notes = "Vérification de l'infrastructure Mailcow"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-mailcow"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -121,6 +132,7 @@ apply Service "infrastructure-chezlepro-verification-openvas" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Vérification de la plateforme OpenVAS" notes = "Vérification de la plateforme OpenVAS"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-openvas"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -131,5 +143,6 @@ apply Service "infrastructure-chezlepro-verification-journaux-systemes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "INFRASTRUCTURE-CHEZLEPRO" ] groups = [ "INFRASTRUCTURE-CHEZLEPRO" ]
notes = "Revue des journaux systèmes critiques" notes = "Revue des journaux systèmes critiques"
vars.instructions_url = "/life-noc/item/infrastructure-chezlepro/verification-journaux-systemes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "jardin-inspection-vignes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Inspection et entretien des vignes" notes = "Inspection et entretien des vignes"
vars.instructions_url = "/life-noc/item/jardin/inspection-vignes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "jardin-entretien-bleuetiers" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Entretien des bleuetiers" notes = "Entretien des bleuetiers"
vars.instructions_url = "/life-noc/item/jardin/entretien-bleuetiers"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "jardin-entretien-framboisiers" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Entretien des framboisiers" notes = "Entretien des framboisiers"
vars.instructions_url = "/life-noc/item/jardin/entretien-framboisiers"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "jardin-inspection-kiwis-nordiques" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Vérification des kiwis nordiques" notes = "Vérification des kiwis nordiques"
vars.instructions_url = "/life-noc/item/jardin/inspection-kiwis-nordiques"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "jardin-entretien-rhubarbe" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Entretien de la rhubarbe" notes = "Entretien de la rhubarbe"
vars.instructions_url = "/life-noc/item/jardin/entretien-rhubarbe"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "jardin-inspection-groseillier" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Inspection du groseillier" notes = "Inspection du groseillier"
vars.instructions_url = "/life-noc/item/jardin/inspection-groseillier"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "jardin-inspection-muriers" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Inspection des mûriers" notes = "Inspection des mûriers"
vars.instructions_url = "/life-noc/item/jardin/inspection-muriers"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "jardin-entretien-houblon" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Vérification et entretien du houblon" notes = "Vérification et entretien du houblon"
vars.instructions_url = "/life-noc/item/jardin/entretien-houblon"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "jardin-revision-pharmacopée-jardin" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Vérification du stock de soins pour végétaux" notes = "Vérification du stock de soins pour végétaux"
vars.instructions_url = "/life-noc/item/jardin/revision-pharmacopée-jardin"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,5 +110,6 @@ apply Service "jardin-revision-armoire-produits-jardin" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "JARDIN" ] groups = [ "JARDIN" ]
notes = "Vérification et ordre de l'armoire des produits pour végétaux" notes = "Vérification et ordre de l'armoire des produits pour végétaux"
vars.instructions_url = "/life-noc/item/jardin/revision-armoire-produits-jardin"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "maison-remplacement-filtre-fournaise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Remplacer le filtre de la fournaise" notes = "Remplacer le filtre de la fournaise"
vars.instructions_url = "/life-noc/item/maison/remplacement-filtre-fournaise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "maison-inspection-fournaise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Inspection générale de la fournaise avant saison froide" notes = "Inspection générale de la fournaise avant saison froide"
vars.instructions_url = "/life-noc/item/maison/inspection-fournaise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "maison-inspection-thermopompe" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Inspection et entretien de la thermopompe" notes = "Inspection et entretien de la thermopompe"
vars.instructions_url = "/life-noc/item/maison/inspection-thermopompe"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "maison-nettoyage-unites-exterieures" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Nettoyer les unités extérieures et vérifier le dégagement" notes = "Nettoyer les unités extérieures et vérifier le dégagement"
vars.instructions_url = "/life-noc/item/maison/nettoyage-unites-exterieures"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "maison-inspection-toiture" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Inspection annuelle de la toiture" notes = "Inspection annuelle de la toiture"
vars.instructions_url = "/life-noc/item/maison/inspection-toiture"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "maison-inspection-gouttieres" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Inspection et nettoyage des gouttières" notes = "Inspection et nettoyage des gouttières"
vars.instructions_url = "/life-noc/item/maison/inspection-gouttieres"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "maison-inspection-fondation" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Inspection de la fondation et des fissures" notes = "Inspection de la fondation et des fissures"
vars.instructions_url = "/life-noc/item/maison/inspection-fondation"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "maison-verification-drainage-terrain" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification du drainage autour de la maison" notes = "Vérification du drainage autour de la maison"
vars.instructions_url = "/life-noc/item/maison/verification-drainage-terrain"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "maison-test-detecteurs-fumee" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Test des détecteurs de fumée" notes = "Test des détecteurs de fumée"
vars.instructions_url = "/life-noc/item/maison/test-detecteurs-fumee"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,6 +110,7 @@ apply Service "maison-test-detecteurs-co" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Test des détecteurs de monoxyde de carbone" notes = "Test des détecteurs de monoxyde de carbone"
vars.instructions_url = "/life-noc/item/maison/test-detecteurs-co"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -111,6 +121,7 @@ apply Service "maison-remplacement-piles-detecteurs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Remplacement préventif des piles des détecteurs" notes = "Remplacement préventif des piles des détecteurs"
vars.instructions_url = "/life-noc/item/maison/remplacement-piles-detecteurs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -121,6 +132,7 @@ apply Service "maison-verification-plomberie-visible" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification visuelle de la plomberie accessible" notes = "Vérification visuelle de la plomberie accessible"
vars.instructions_url = "/life-noc/item/maison/verification-plomberie-visible"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -131,6 +143,7 @@ apply Service "maison-inspection-sump-pump" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification de la pompe de puisard si applicable" notes = "Vérification de la pompe de puisard si applicable"
vars.instructions_url = "/life-noc/item/maison/inspection-sump-pump"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -141,6 +154,7 @@ apply Service "maison-verification-calfetrage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification du calfeutrage portes et fenêtres" notes = "Vérification du calfeutrage portes et fenêtres"
vars.instructions_url = "/life-noc/item/maison/verification-calfetrage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -151,6 +165,7 @@ apply Service "maison-inspection-portes-garage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification mécanique et sécurité des portes de garage" notes = "Vérification mécanique et sécurité des portes de garage"
vars.instructions_url = "/life-noc/item/maison/inspection-portes-garage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -161,5 +176,6 @@ apply Service "maison-verification-extincteurs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "MAISON" ] groups = [ "MAISON" ]
notes = "Vérification des extincteurs" notes = "Vérification des extincteurs"
vars.instructions_url = "/life-noc/item/maison/verification-extincteurs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "obligations-chezlepro-verification-registraire-entreprise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier les obligations au Registraire des entreprises" notes = "Vérifier les obligations au Registraire des entreprises"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-registraire-entreprise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "obligations-chezlepro-verification-declarations-taxes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier les obligations de taxes de l'entreprise si applicables" notes = "Vérifier les obligations de taxes de l'entreprise si applicables"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-declarations-taxes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "obligations-chezlepro-verification-dossier-comptable-entreprise"
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier l'ordre du dossier comptable Chezlepro" notes = "Vérifier l'ordre du dossier comptable Chezlepro"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-dossier-comptable-entreprise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "obligations-chezlepro-verification-facturation-clients" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier la facturation et son suivi" notes = "Vérifier la facturation et son suivi"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-facturation-clients"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "obligations-chezlepro-verification-paiements-fournisseurs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier les paiements fournisseurs" notes = "Vérifier les paiements fournisseurs"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-paiements-fournisseurs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "obligations-chezlepro-verification-contrats-ententes" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier contrats, ententes et obligations associées" notes = "Vérifier contrats, ententes et obligations associées"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-contrats-ententes"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "obligations-chezlepro-verification-assurances-entreprise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Vérifier les assurances de l'entreprise" notes = "Vérifier les assurances de l'entreprise"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/verification-assurances-entreprise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,5 +88,6 @@ apply Service "obligations-chezlepro-archivage-documents-entreprise" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-CHEZLEPRO" ] groups = [ "OBLIGATIONS-CHEZLEPRO" ]
notes = "Archiver les documents administratifs et financiers de l'entreprise" notes = "Archiver les documents administratifs et financiers de l'entreprise"
vars.instructions_url = "/life-noc/item/obligations-chezlepro/archivage-documents-entreprise"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "obligations-legales-personnelles-verification-testament" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier la pertinence et l'actualité du testament" notes = "Vérifier la pertinence et l'actualité du testament"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-testament"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "obligations-legales-personnelles-verification-mandat-inaptitude"
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier le mandat de protection et documents connexes" notes = "Vérifier le mandat de protection et documents connexes"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-mandat-inaptitude"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "obligations-legales-personnelles-verification-directives-medicale
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier les directives médicales anticipées" notes = "Vérifier les directives médicales anticipées"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-directives-medicales"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "obligations-legales-personnelles-verification-papiers-identite" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier l'expiration des papiers d'identité" notes = "Vérifier l'expiration des papiers d'identité"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-papiers-identite"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -60,6 +64,7 @@ apply Service "obligations-legales-personnelles-renouvellement-permis-conduire"
vars.life_noc_threshold_critical_lt = "7" vars.life_noc_threshold_critical_lt = "7"
vars.life_noc_on_error = "critical" vars.life_noc_on_error = "critical"
notes = "Vérifier la proximité de léchéance du permis" notes = "Vérifier la proximité de léchéance du permis"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/renouvellement-permis-conduire"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -70,6 +75,7 @@ apply Service "obligations-legales-personnelles-verification-carte-assurance-mal
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier l'expiration de la carte d'assurance maladie" notes = "Vérifier l'expiration de la carte d'assurance maladie"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-carte-assurance-maladie"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -80,5 +86,6 @@ apply Service "obligations-legales-personnelles-verification-passeport" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ] groups = [ "OBLIGATIONS-LEGALES-PERSONNELLES" ]
notes = "Vérifier l'expiration du passeport" notes = "Vérifier l'expiration du passeport"
vars.instructions_url = "/life-noc/item/obligations-legales-personnelles/verification-passeport"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "outils-et-equipements-entretien-outils-jardin" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OUTILS-ET-EQUIPEMENTS" ] groups = [ "OUTILS-ET-EQUIPEMENTS" ]
notes = "Nettoyage et entretien des outils de jardin" notes = "Nettoyage et entretien des outils de jardin"
vars.instructions_url = "/life-noc/item/outils-et-equipements/entretien-outils-jardin"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "outils-et-equipements-inspection-outils-electriques" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OUTILS-ET-EQUIPEMENTS" ] groups = [ "OUTILS-ET-EQUIPEMENTS" ]
notes = "Vérification des outils électriques" notes = "Vérification des outils électriques"
vars.instructions_url = "/life-noc/item/outils-et-equipements/inspection-outils-electriques"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "outils-et-equipements-verification-rallonges-et-connecteurs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OUTILS-ET-EQUIPEMENTS" ] groups = [ "OUTILS-ET-EQUIPEMENTS" ]
notes = "Vérification des rallonges et connecteurs" notes = "Vérification des rallonges et connecteurs"
vars.instructions_url = "/life-noc/item/outils-et-equipements/verification-rallonges-et-connecteurs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "outils-et-equipements-verification-compresseur-et-accessoires" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OUTILS-ET-EQUIPEMENTS" ] groups = [ "OUTILS-ET-EQUIPEMENTS" ]
notes = "Vérification du compresseur et accessoires" notes = "Vérification du compresseur et accessoires"
vars.instructions_url = "/life-noc/item/outils-et-equipements/verification-compresseur-et-accessoires"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "outils-et-equipements-revision-inventaire-outillage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "OUTILS-ET-EQUIPEMENTS" ] groups = [ "OUTILS-ET-EQUIPEMENTS" ]
notes = "Revue de l'inventaire d'outillage" notes = "Revue de l'inventaire d'outillage"
vars.instructions_url = "/life-noc/item/outils-et-equipements/revision-inventaire-outillage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "projets-revision-life-noc" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du projet Life-NOC" notes = "Révision du projet Life-NOC"
vars.instructions_url = "/life-noc/item/projets/revision-life-noc"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "projets-revision-alliance-boreale" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du projet Alliance Boréale" notes = "Révision du projet Alliance Boréale"
vars.instructions_url = "/life-noc/item/projets/revision-alliance-boreale"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "projets-revision-erplibre" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du projet ERPLibre" notes = "Révision du projet ERPLibre"
vars.instructions_url = "/life-noc/item/projets/revision-erplibre"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "projets-revision-semence-numerique" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du projet semence numérique" notes = "Révision du projet semence numérique"
vars.instructions_url = "/life-noc/item/projets/revision-semence-numerique"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "projets-revision-ortrux-1" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du système Ortrux-1" notes = "Révision du système Ortrux-1"
vars.instructions_url = "/life-noc/item/projets/revision-ortrux-1"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,5 +66,6 @@ apply Service "projets-revision-district16" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "PROJETS" ] groups = [ "PROJETS" ]
notes = "Révision du projet DISTRICT16" notes = "Révision du projet DISTRICT16"
vars.instructions_url = "/life-noc/item/projets/revision-district16"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "reseau-chezlepro-verification-firewalls" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification des firewalls" notes = "Vérification des firewalls"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-firewalls"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "reseau-chezlepro-verification-vpn-openvpn" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification des tunnels OpenVPN" notes = "Vérification des tunnels OpenVPN"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-vpn-openvpn"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "reseau-chezlepro-verification-crl-certificats" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification de la CRL et des certificats" notes = "Vérification de la CRL et des certificats"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-crl-certificats"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "reseau-chezlepro-verification-switches" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification des switches et uplinks" notes = "Vérification des switches et uplinks"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-switches"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "reseau-chezlepro-verification-vlans-segmentation" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification de la segmentation réseau" notes = "Vérification de la segmentation réseau"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-vlans-segmentation"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "reseau-chezlepro-verification-dns" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification DNS interne et externe" notes = "Vérification DNS interne et externe"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-dns"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "reseau-chezlepro-verification-dynamic-dns" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérification du DNS dynamique si utilisé" notes = "Vérification du DNS dynamique si utilisé"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-dynamic-dns"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "reseau-chezlepro-audit-regles-firewall" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Audit périodique des règles de firewall" notes = "Audit périodique des règles de firewall"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/audit-regles-firewall"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "reseau-chezlepro-verification-geoblocking" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérifier le geoblocking et son effet attendu" notes = "Vérifier le geoblocking et son effet attendu"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-geoblocking"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,5 +110,6 @@ apply Service "reseau-chezlepro-verification-certificats-publics" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESEAU-CHEZLEPRO" ] groups = [ "RESEAU-CHEZLEPRO" ]
notes = "Vérifier les expirations de certificats publics" notes = "Vérifier les expirations de certificats publics"
vars.instructions_url = "/life-noc/item/reseau-chezlepro/verification-certificats-publics"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "resilience-test-generatrice-propane" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Test mensuel de la génératrice au propane" notes = "Test mensuel de la génératrice au propane"
vars.instructions_url = "/life-noc/item/resilience/test-generatrice-propane"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "resilience-verification-carburant-generatrice" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Vérification de l'approvisionnement propane lié à la génératrice" notes = "Vérification de l'approvisionnement propane lié à la génératrice"
vars.instructions_url = "/life-noc/item/resilience/verification-carburant-generatrice"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "resilience-verification-procedure-bascule" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Réviser la procédure de bascule en mode secours" notes = "Réviser la procédure de bascule en mode secours"
vars.instructions_url = "/life-noc/item/resilience/verification-procedure-bascule"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "resilience-verification-stock-lampes-piles" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Vérification des lampes, piles et éclairage d'urgence" notes = "Vérification des lampes, piles et éclairage d'urgence"
vars.instructions_url = "/life-noc/item/resilience/verification-stock-lampes-piles"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "resilience-verification-trousses-urgence" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Vérification des trousses d'urgence" notes = "Vérification des trousses d'urgence"
vars.instructions_url = "/life-noc/item/resilience/verification-trousses-urgence"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "resilience-revision-plan-urgence" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Réviser le plan d'urgence domestique" notes = "Réviser le plan d'urgence domestique"
vars.instructions_url = "/life-noc/item/resilience/revision-plan-urgence"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "resilience-test-autonomie-base" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Vérifier l'autonomie énergétique minimale attendue" notes = "Vérifier l'autonomie énergétique minimale attendue"
vars.instructions_url = "/life-noc/item/resilience/test-autonomie-base"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,5 +88,6 @@ apply Service "resilience-verification-moyens-cuisson-secours" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "RESILIENCE" ] groups = [ "RESILIENCE" ]
notes = "Vérification des moyens de cuisson de secours" notes = "Vérification des moyens de cuisson de secours"
vars.instructions_url = "/life-noc/item/resilience/verification-moyens-cuisson-secours"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -20,6 +20,7 @@ apply Service "revue-revue-quotidienne-life-noc" {
vars.life_noc_threshold_critical_gte = "3" vars.life_noc_threshold_critical_gte = "3"
vars.life_noc_on_error = "critical" vars.life_noc_on_error = "critical"
notes = "Vérifier le tableau de bord Life-NOC" notes = "Vérifier le tableau de bord Life-NOC"
vars.instructions_url = "/life-noc/item/revue/revue-quotidienne-life-noc"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -39,6 +40,7 @@ apply Service "revue-revue-hebdomadaire-priorites" {
vars.life_noc_threshold_critical_gte = "10" vars.life_noc_threshold_critical_gte = "10"
vars.life_noc_on_error = "critical" vars.life_noc_on_error = "critical"
notes = "Revoir les priorités de la semaine" notes = "Revoir les priorités de la semaine"
vars.instructions_url = "https://chezlepro.ca/life-noc/test-instructions"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -49,6 +51,7 @@ apply Service "revue-revue-mensuelle-systeme-vie" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "REVUE" ] groups = [ "REVUE" ]
notes = "Revue mensuelle de l'ensemble du système Life-NOC" notes = "Revue mensuelle de l'ensemble du système Life-NOC"
vars.instructions_url = "/life-noc/item/revue/revue-mensuelle-systeme-vie"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -59,5 +62,6 @@ apply Service "revue-revue-trimestrielle-orientation" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "REVUE" ] groups = [ "REVUE" ]
notes = "Revue trimestrielle des orientations de vie et de Chezlepro" notes = "Revue trimestrielle des orientations de vie et de Chezlepro"
vars.instructions_url = "/life-noc/item/revue/revue-trimestrielle-orientation"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "sante-verification-trousse-premiers-soins" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SANTE" ] groups = [ "SANTE" ]
notes = "Vérification de la trousse de premiers soins" notes = "Vérification de la trousse de premiers soins"
vars.instructions_url = "/life-noc/item/sante/verification-trousse-premiers-soins"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "sante-verification-expiration-medicaments" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SANTE" ] groups = [ "SANTE" ]
notes = "Vérification des dates d'expiration des médicaments" notes = "Vérification des dates d'expiration des médicaments"
vars.instructions_url = "/life-noc/item/sante/verification-expiration-medicaments"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "sante-revision-rendez-vous-medicaux" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SANTE" ] groups = [ "SANTE" ]
notes = "Revoir les rendez-vous médicaux requis" notes = "Revoir les rendez-vous médicaux requis"
vars.instructions_url = "/life-noc/item/sante/revision-rendez-vous-medicaux"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "sante-verification-lunettes-prescriptions" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SANTE" ] groups = [ "SANTE" ]
notes = "Vérifier les prescriptions et besoins de renouvellement" notes = "Vérifier les prescriptions et besoins de renouvellement"
vars.instructions_url = "/life-noc/item/sante/verification-lunettes-prescriptions"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,5 +55,6 @@ apply Service "sante-verification-dossier-sante" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SANTE" ] groups = [ "SANTE" ]
notes = "Vérifier l'ordre et l'accessibilité des documents de santé" notes = "Vérifier l'ordre et l'accessibilité des documents de santé"
vars.instructions_url = "/life-noc/item/sante/verification-dossier-sante"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "securite-chezlepro-verification-mises-a-jour-securite" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Vérification des mises à jour de sécurité" notes = "Vérification des mises à jour de sécurité"
vars.instructions_url = "/life-noc/item/securite-chezlepro/verification-mises-a-jour-securite"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "securite-chezlepro-audit-comptes-acces" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Audit des comptes et accès privilégiés" notes = "Audit des comptes et accès privilégiés"
vars.instructions_url = "/life-noc/item/securite-chezlepro/audit-comptes-acces"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "securite-chezlepro-verification-ids-snort" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Vérification des IDS et de leur état" notes = "Vérification des IDS et de leur état"
vars.instructions_url = "/life-noc/item/securite-chezlepro/verification-ids-snort"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "securite-chezlepro-revue-pki-privee" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Revue de la PKI privée et des autorités intermédiaires" notes = "Revue de la PKI privée et des autorités intermédiaires"
vars.instructions_url = "/life-noc/item/securite-chezlepro/revue-pki-privee"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "securite-chezlepro-revue-politiques-securite" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Revue des politiques et pratiques de sécurité numérique" notes = "Revue des politiques et pratiques de sécurité numérique"
vars.instructions_url = "/life-noc/item/securite-chezlepro/revue-politiques-securite"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,5 +66,6 @@ apply Service "securite-chezlepro-verification-sauvegardes-configuration" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "SECURITE-CHEZLEPRO" ] groups = [ "SECURITE-CHEZLEPRO" ]
notes = "Vérifier les sauvegardes des configurations critiques" notes = "Vérifier les sauvegardes des configurations critiques"
vars.instructions_url = "/life-noc/item/securite-chezlepro/verification-sauvegardes-configuration"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "stock-alimentaire-rotation-nourriture-seche" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Rotation des stocks de nourriture sèche" notes = "Rotation des stocks de nourriture sèche"
vars.instructions_url = "/life-noc/item/stock-alimentaire/rotation-nourriture-seche"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "stock-alimentaire-verification-reserve-eau" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Vérification de la réserve d'eau potable" notes = "Vérification de la réserve d'eau potable"
vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-reserve-eau"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "stock-alimentaire-verification-mylar-absorbeurs" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Vérifier l'intégrité des emballages Mylar et absorbeurs" notes = "Vérifier l'intégrité des emballages Mylar et absorbeurs"
vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-mylar-absorbeurs"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "stock-alimentaire-revue-inventaire-conserves" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Revue des conserves et dates de rotation" notes = "Revue des conserves et dates de rotation"
vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-inventaire-conserves"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "stock-alimentaire-revue-inventaire-farine-riz-pates" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Vérification des gros stocks alimentaires de base" notes = "Vérification des gros stocks alimentaires de base"
vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-inventaire-farine-riz-pates"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "stock-alimentaire-verification-bacs-legumes-racines" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Vérification des bacs de stockage de légumes racines" notes = "Vérification des bacs de stockage de légumes racines"
vars.instructions_url = "/life-noc/item/stock-alimentaire/verification-bacs-legumes-racines"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,5 +77,6 @@ apply Service "stock-alimentaire-revue-supplements-vitamines" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "STOCK-ALIMENTAIRE" ] groups = [ "STOCK-ALIMENTAIRE" ]
notes = "Vérification du stock de suppléments et dates utiles" notes = "Vérification du stock de suppléments et dates utiles"
vars.instructions_url = "/life-noc/item/stock-alimentaire/revue-supplements-vitamines"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -11,6 +11,7 @@ apply Service "voiture-verification-huile-moteur" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification de l'huile moteur" notes = "Vérification de l'huile moteur"
vars.instructions_url = "/life-noc/item/voiture/verification-huile-moteur"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -21,6 +22,7 @@ apply Service "voiture-inspection-freins" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Inspection des freins" notes = "Inspection des freins"
vars.instructions_url = "/life-noc/item/voiture/inspection-freins"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -31,6 +33,7 @@ apply Service "voiture-verification-pneus" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification usure, pression et permutation des pneus" notes = "Vérification usure, pression et permutation des pneus"
vars.instructions_url = "/life-noc/item/voiture/verification-pneus"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -41,6 +44,7 @@ apply Service "voiture-ajustement-valves" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification et ajustement des valves Honda Accord" notes = "Vérification et ajustement des valves Honda Accord"
vars.instructions_url = "/life-noc/item/voiture/ajustement-valves"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -51,6 +55,7 @@ apply Service "voiture-verification-timing-belt" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification de la courroie de distribution et pompe à eau" notes = "Vérification de la courroie de distribution et pompe à eau"
vars.instructions_url = "/life-noc/item/voiture/verification-timing-belt"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -61,6 +66,7 @@ apply Service "voiture-verification-batterie-voiture" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification de l'état de la batterie automobile" notes = "Vérification de l'état de la batterie automobile"
vars.instructions_url = "/life-noc/item/voiture/verification-batterie-voiture"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -71,6 +77,7 @@ apply Service "voiture-verification-balais-essuie-glace" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification des essuie-glaces" notes = "Vérification des essuie-glaces"
vars.instructions_url = "/life-noc/item/voiture/verification-balais-essuie-glace"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -81,6 +88,7 @@ apply Service "voiture-verification-liquides" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification des liquides de la voiture" notes = "Vérification des liquides de la voiture"
vars.instructions_url = "/life-noc/item/voiture/verification-liquides"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -91,6 +99,7 @@ apply Service "voiture-verification-eclairage" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification de l'éclairage et des phares" notes = "Vérification de l'éclairage et des phares"
vars.instructions_url = "/life-noc/item/voiture/verification-eclairage"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }
@ -101,5 +110,6 @@ apply Service "voiture-verification-immatriculation-assurance" {
vars.mock_message = "Sous contrôle" vars.mock_message = "Sous contrôle"
groups = [ "VOITURE" ] groups = [ "VOITURE" ]
notes = "Vérification papiers d'assurance et immatriculation" notes = "Vérification papiers d'assurance et immatriculation"
vars.instructions_url = "/life-noc/item/voiture/verification-immatriculation-assurance"
assign where host.name == "life-noc" assign where host.name == "life-noc"
} }

View file

@ -5,6 +5,7 @@ from pathlib import Path
import yaml import yaml
INPUTS_DIR = Path("data/inputs") INPUTS_DIR = Path("data/inputs")
DOMAINS_FILE = Path("domains.yaml")
def utc_now_iso() -> str: def utc_now_iso() -> str:
@ -68,3 +69,76 @@ def set_item(domain: str, item_key: str, value: str, origin: str = "manual") ->
def complete_item(domain: str, item_key: str, origin: str = "manual") -> dict: def complete_item(domain: str, item_key: str, origin: str = "manual") -> dict:
return set_item(domain, item_key, utc_today_date(), origin=origin) return set_item(domain, item_key, utc_today_date(), origin=origin)
def load_domains_definition() -> dict:
if not DOMAINS_FILE.exists():
raise ValueError(f"Fichier introuvable: {DOMAINS_FILE}")
data = yaml.safe_load(DOMAINS_FILE.read_text(encoding="utf-8"))
if not isinstance(data, dict):
raise ValueError("domains.yaml invalide")
domains = data.get("domains")
if not isinstance(domains, dict):
raise ValueError("domains.yaml invalide: clé 'domains' absente ou invalide")
return domains
def get_defined_service(domain: str, item_key: str) -> dict:
domains = load_domains_definition()
items = domains.get(domain)
if not isinstance(items, list):
raise KeyError(domain)
for item in items:
if isinstance(item, dict) and item.get("name") == item_key:
return item
raise KeyError(item_key)
def compute_state_for_item(domain: str, item_key: str) -> str:
service = get_defined_service(domain, item_key)
probe = service.get("probe")
if not isinstance(probe, dict):
return "MOCK"
probe_type = str(probe.get("type", "")).strip()
source = probe.get("source", {})
thresholds = probe.get("thresholds", {})
metric = probe.get("metric", {})
if str(source.get("type", "")).strip() != "manual_date":
return "CRITICAL"
if str(metric.get("unit", "")).strip() != "days":
return "CRITICAL"
item = get_item(domain, item_key)
value = str(item.get("value", "")).strip()
dt = datetime.strptime(value, "%Y-%m-%d").replace(tzinfo=timezone.utc)
now = datetime.now(timezone.utc)
if probe_type == "elapsed_time":
days = (now - dt).total_seconds() / 86400.0
if "critical_gte" in thresholds and days >= float(thresholds["critical_gte"]):
return "CRITICAL"
if "warning_gte" in thresholds and days >= float(thresholds["warning_gte"]):
return "WARNING"
if "ok_gte" in thresholds and days >= float(thresholds["ok_gte"]):
return "OK"
if "unknown_lt" in thresholds and days < float(thresholds["unknown_lt"]):
return "UNKNOWN"
return "CRITICAL"
if probe_type == "days_until_due":
days = (dt - now).total_seconds() / 86400.0
if "critical_lt" in thresholds and days < float(thresholds["critical_lt"]):
return "CRITICAL"
if "warning_lt" in thresholds and days < float(thresholds["warning_lt"]):
return "WARNING"
if "ok_lt" in thresholds and days < float(thresholds["ok_lt"]):
return "OK"
if "unknown_gte" in thresholds and days >= float(thresholds["unknown_gte"]):
return "UNKNOWN"
return "CRITICAL"
return "CRITICAL"

View file

@ -1,260 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${1:-.}"
need_file() {
local f="$1"
if [[ ! -f "$ROOT/$f" ]]; then
echo "Fichier introuvable: $f" >&2
exit 1
fi
}
echo "==> Vérification du dépôt"
need_file "domains.yaml"
need_file "scripts/generate_bpm.py"
need_file "Makefile"
need_file "ansible/roles/life_noc/defaults/main.yml"
need_file "ansible/roles/life_noc/tasks/main.yml"
echo "==> Sauvegarde minimale"
mkdir -p "$ROOT/.patch-backup"
cp -a "$ROOT/scripts/generate_bpm.py" "$ROOT/.patch-backup/generate_bpm.py.bak"
cp -a "$ROOT/Makefile" "$ROOT/.patch-backup/Makefile.bak"
cp -a "$ROOT/ansible/roles/life_noc/defaults/main.yml" "$ROOT/.patch-backup/life_noc_defaults_main.yml.bak"
cp -a "$ROOT/ansible/roles/life_noc/tasks/main.yml" "$ROOT/.patch-backup/life_noc_tasks_main.yml.bak"
[[ -f "$ROOT/preuve-de-reproductibilite.md" ]] && cp -a "$ROOT/preuve-de-reproductibilite.md" "$ROOT/.patch-backup/preuve-de-reproductibilite.md.bak"
[[ -f "$ROOT/decisions-techniques.md" ]] && cp -a "$ROOT/decisions-techniques.md" "$ROOT/.patch-backup/decisions-techniques.md.bak"
echo "==> Réécriture de scripts/generate_bpm.py"
cat > "$ROOT/scripts/generate_bpm.py" <<'PYEOF'
#!/usr/bin/env python3
from __future__ import annotations
import re
from pathlib import Path
import sys
import yaml
ROOT = Path(__file__).resolve().parents[1]
DOMAINS_YAML = ROOT / "domains.yaml"
OUTPUT_DIR = ROOT / "bpm"
OUTPUT_FILE = OUTPUT_DIR / "Life-NOC.conf"
HOST_NAME = "life-noc"
TITLE = "Life-NOC"
OWNER = "icingadmin"
def slugify(value: str) -> str:
value = value.strip().lower()
replacements = {
"à": "a", "â": "a", "ä": "a",
"ç": "c",
"é": "e", "è": "e", "ê": "e", "ë": "e",
"î": "i", "ï": "i",
"ô": "o", "ö": "o",
"ù": "u", "û": "u", "ü": "u",
"ÿ": "y",
"œ": "oe", "æ": "ae",
"'": "", "": "",
}
for old, new in replacements.items():
value = value.replace(old, new)
value = re.sub(r"[^a-z0-9\-]+", "-", value)
value = re.sub(r"-{2,}", "-", value)
return value.strip("-")
def aliasify(value: str) -> str:
value = value.strip().upper()
replacements = {
"À": "A", "Â": "A", "Ä": "A",
"Ç": "C",
"É": "E", "È": "E", "Ê": "E", "Ë": "E",
"Î": "I", "Ï": "I",
"Ô": "O", "Ö": "O",
"Ù": "U", "Û": "U", "Ü": "U",
"Ÿ": "Y",
"Œ": "OE", "Æ": "AE",
"'": "", "": "",
}
for old, new in replacements.items():
value = value.replace(old, new)
value = re.sub(r"[^A-Z0-9\-]+", "-", value)
value = re.sub(r"-{2,}", "-", value)
return value.strip("-")
def read_domains() -> dict:
data = yaml.safe_load(DOMAINS_YAML.read_text(encoding="utf-8"))
if not isinstance(data, dict) or "domains" not in data:
raise ValueError("domains.yaml doit contenir une clé racine 'domains'")
domains = data["domains"]
if not isinstance(domains, dict):
raise ValueError("domains.yaml: 'domains' doit être un mapping")
return domains
def collect_services(domain_data: dict, domain_name: str) -> list[str]:
items = domain_data.get("items", [])
if not isinstance(items, list):
raise ValueError(f"Domaine '{domain_name}': 'items' doit être une liste")
services: list[str] = []
for item in items:
if not isinstance(item, dict):
raise ValueError(f"Domaine '{domain_name}': item invalide (dict attendu)")
item_name = item.get("name")
if not item_name:
raise ValueError(f"Domaine '{domain_name}': item sans champ 'name'")
service_name = f"{slugify(domain_name)}-{slugify(str(item_name))}"
services.append(f"{HOST_NAME};{service_name}")
if not services:
raise ValueError(f"Domaine '{domain_name}' ne contient aucun item")
return services
def header() -> str:
return f"""### Business Process Config File ###
#
# Title : {TITLE}
# Description :
# Owner : {OWNER}
# AddToMenu : yes
# Backend :
# Statetype : soft
#
###################################
"""
def main() -> int:
domains = read_domains()
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
lines: list[str] = [header()]
aliases: list[tuple[str, str]] = []
for domain_name, domain_data in domains.items():
if not isinstance(domain_data, dict):
raise ValueError(f"Domaine '{domain_name}': structure invalide")
alias = aliasify(domain_name)
label = domain_data.get("label", domain_name)
services = collect_services(domain_data, domain_name)
expr = " & ".join(services)
lines.append(f"{alias} = {expr}\n")
aliases.append((alias, str(label)))
lines.append("\n")
root_expr = " & ".join(alias for alias, _label in aliases)
lines.append(f"LIFE-NOC = {root_expr}\n")
lines.append("display 1;LIFE-NOC;LIFE-NOC\n")
for alias, label in aliases:
lines.append(f"display 1;{alias};{label}\n")
OUTPUT_FILE.write_text("".join(lines), encoding="utf-8")
print(f"BPM généré: {OUTPUT_FILE.relative_to(ROOT)}")
print("Processus générés :")
print(" - LIFE-NOC")
for alias, _label in aliases:
print(f" - {alias}")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except Exception as exc:
print(f"ERREUR: {exc}", file=sys.stderr)
raise
PYEOF
chmod +x "$ROOT/scripts/generate_bpm.py"
echo "==> Ajustements texte ciblés"
python3 - "$ROOT" <<'PYEOF'
from pathlib import Path
import re
import sys
root = Path(sys.argv[1])
def replace_text(path_str, replacements):
path = root / path_str
if not path.exists():
return
text = path.read_text(encoding="utf-8")
original = text
for old, new in replacements:
text = text.replace(old, new)
if text != original:
path.write_text(text, encoding="utf-8")
print(f"Modifié: {path_str}")
def regex_replace(path_str, pattern, repl, must_match=False):
path = root / path_str
if not path.exists():
return
text = path.read_text(encoding="utf-8")
new_text, count = re.subn(pattern, repl, text, flags=re.MULTILINE)
if must_match and count == 0:
raise SystemExit(f"Aucun match dans {path_str} pour: {pattern}")
if new_text != text:
path.write_text(new_text, encoding="utf-8")
print(f"Modifié: {path_str}")
# Makefile
replace_text("Makefile", [
("bpm/life-noc.json", "bpm/Life-NOC.conf"),
])
# defaults main.yml
replace_text("ansible/roles/life_noc/defaults/main.yml", [
("/etc/icingaweb2/modules/businessprocess/processes/life-noc.json",
"/etc/icingaweb2/modules/businessprocess/processes/Life-NOC.conf"),
])
# tasks main.yml
replace_text("ansible/roles/life_noc/tasks/main.yml", [
("bpm/life-noc.json", "bpm/Life-NOC.conf"),
("life-noc.json", "Life-NOC.conf"),
])
# docs
for doc in ["preuve-de-reproductibilite.md", "decisions-techniques.md"]:
replace_text(doc, [
("bpm/life-noc.json", "bpm/Life-NOC.conf"),
("life-noc.json", "Life-NOC.conf"),
("export JSON", "export natif Business Process"),
("artefact JSON", "artefact natif Business Process"),
])
PYEOF
echo "==> Nettoyage de l'ancien artefact si présent"
rm -f "$ROOT/bpm/life-noc.json"
echo "==> Génération du nouveau BPM"
(
cd "$ROOT"
python3 scripts/generate_bpm.py
)
echo "==> Vérification rapide"
if [[ -f "$ROOT/bpm/Life-NOC.conf" ]]; then
echo "OK: bpm/Life-NOC.conf généré"
else
echo "ERREUR: bpm/Life-NOC.conf absent" >&2
exit 1
fi
echo
echo "Patch terminé."
echo "Fichiers sauvegardés dans: $ROOT/.patch-backup"
echo "Prochaine étape recommandée:"
echo " make check"
echo "Puis redéploiement avec BPM activé."

View file

@ -1,283 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${1:-.}"
need_file() {
local f="$1"
if [[ ! -f "$ROOT/$f" ]]; then
echo "Fichier introuvable: $f" >&2
exit 1
fi
}
echo "==> Vérification du dépôt"
need_file "checks/check_life_noc_probe.py"
need_file "icinga/commands/check_life_noc_probe.conf"
need_file "scripts/generate_services.py"
need_file "domains.yaml"
echo "==> Sauvegarde"
mkdir -p "$ROOT/.patch-backup-days-until-due"
cp -a "$ROOT/checks/check_life_noc_probe.py" "$ROOT/.patch-backup-days-until-due/check_life_noc_probe.py.bak"
cp -a "$ROOT/icinga/commands/check_life_noc_probe.conf" "$ROOT/.patch-backup-days-until-due/check_life_noc_probe.conf.bak"
cp -a "$ROOT/scripts/generate_services.py" "$ROOT/.patch-backup-days-until-due/generate_services.py.bak"
cp -a "$ROOT/domains.yaml" "$ROOT/.patch-backup-days-until-due/domains.yaml.bak"
echo "==> Réécriture de checks/check_life_noc_probe.py"
cat > "$ROOT/checks/check_life_noc_probe.py" <<'PYEOF'
#!/usr/bin/env python3
import argparse
from datetime import datetime, timezone
from pathlib import Path
import yaml
def exit_with(code: int, text: str) -> None:
print(text)
raise SystemExit(code)
def parse_date(value: str) -> datetime:
return datetime.strptime(value, "%Y-%m-%d").replace(tzinfo=timezone.utc)
def load_input_value(inputs_file: str, item_key: str) -> str:
path = Path(inputs_file)
if not path.exists():
raise ValueError(f"inputs file introuvable: {inputs_file}")
data = yaml.safe_load(path.read_text(encoding="utf-8"))
if not isinstance(data, dict):
raise ValueError(f"inputs file invalide: {inputs_file}")
if item_key not in data:
raise ValueError(f"item_key introuvable dans le store: {item_key}")
item = data[item_key]
if not isinstance(item, dict):
raise ValueError(f"entrée invalide pour item_key: {item_key}")
if "value" not in item:
raise ValueError(f"champ 'value' absent pour item_key: {item_key}")
return str(item["value"]).strip()
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--probe-type", required=True)
ap.add_argument("--source-type", required=True)
ap.add_argument("--source-value")
ap.add_argument("--inputs-file")
ap.add_argument("--item-key")
ap.add_argument("--unit", required=True)
ap.add_argument("--unknown-lt", type=float)
ap.add_argument("--unknown-gte", type=float)
ap.add_argument("--ok-gte", type=float)
ap.add_argument("--ok-lt", type=float)
ap.add_argument("--warning-gte", type=float)
ap.add_argument("--warning-lt", type=float)
ap.add_argument("--critical-gte", type=float)
ap.add_argument("--critical-lt", type=float)
ap.add_argument("--on-error", default="critical")
ap.add_argument("--label", default="life-noc")
args = ap.parse_args()
try:
if args.source_type != "manual_date":
exit_with(2, f"CRITICAL - source_type non supporté: {args.source_type}")
if args.unit != "days":
exit_with(2, f"CRITICAL - unité non supportée: {args.unit}")
if args.inputs_file and args.item_key:
source_value = load_input_value(args.inputs_file, args.item_key)
elif args.source_value:
source_value = args.source_value
else:
raise ValueError("aucune source fournie: inputs-file/item-key ou source-value requis")
dt = parse_date(source_value)
now = datetime.now(timezone.utc)
if args.probe_type == "elapsed_time":
metric = (now - dt).total_seconds() / 86400.0
if args.critical_gte is not None and metric >= args.critical_gte:
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} jours")
if args.warning_gte is not None and metric >= args.warning_gte:
exit_with(1, f"WARNING - {args.label}: {metric:.1f} jours")
if args.ok_gte is not None and metric >= args.ok_gte:
exit_with(0, f"OK - {args.label}: {metric:.1f} jours")
if args.unknown_lt is not None and metric < args.unknown_lt:
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} jours")
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
elif args.probe_type == "days_until_due":
metric = (dt - now).total_seconds() / 86400.0
if args.critical_lt is not None and metric < args.critical_lt:
exit_with(2, f"CRITICAL - {args.label}: {metric:.1f} jours restants")
if args.warning_lt is not None and metric < args.warning_lt:
exit_with(1, f"WARNING - {args.label}: {metric:.1f} jours restants")
if args.ok_lt is not None and metric < args.ok_lt:
exit_with(0, f"OK - {args.label}: {metric:.1f} jours restants")
if args.unknown_gte is not None and metric >= args.unknown_gte:
exit_with(3, f"UNKNOWN - {args.label}: {metric:.1f} jours restants")
exit_with(2, f"CRITICAL - {args.label}: seuils incohérents")
else:
exit_with(2, f"CRITICAL - probe_type non supporté: {args.probe_type}")
except Exception as exc:
if args.on_error == "critical":
exit_with(2, f"CRITICAL - erreur sonde: {exc}")
exit_with(3, f"UNKNOWN - erreur sonde: {exc}")
if __name__ == "__main__":
raise SystemExit(main())
PYEOF
chmod +x "$ROOT/checks/check_life_noc_probe.py"
echo "==> Réécriture de icinga/commands/check_life_noc_probe.conf"
cat > "$ROOT/icinga/commands/check_life_noc_probe.conf" <<'CONFEOF'
object CheckCommand "check_life_noc_probe" {
command = [ PluginDir + "/check_life_noc_probe.py" ]
arguments = {
"--probe-type" = "$life_noc_probe_type$"
"--source-type" = "$life_noc_source_type$"
"--source-value" = "$life_noc_source_value$"
"--inputs-file" = "$life_noc_inputs_file$"
"--item-key" = "$life_noc_item_key$"
"--unit" = "$life_noc_metric_unit$"
"--unknown-lt" = "$life_noc_threshold_unknown_lt$"
"--unknown-gte" = "$life_noc_threshold_unknown_gte$"
"--ok-gte" = "$life_noc_threshold_ok_gte$"
"--ok-lt" = "$life_noc_threshold_ok_lt$"
"--warning-gte" = "$life_noc_threshold_warning_gte$"
"--warning-lt" = "$life_noc_threshold_warning_lt$"
"--critical-gte" = "$life_noc_threshold_critical_gte$"
"--critical-lt" = "$life_noc_threshold_critical_lt$"
"--on-error" = "$life_noc_on_error$"
"--label" = "$life_noc_label$"
}
}
CONFEOF
echo "==> Patch de scripts/generate_services.py"
python3 - "$ROOT/scripts/generate_services.py" <<'PYEOF'
from pathlib import Path
import sys
path = Path(sys.argv[1])
text = path.read_text(encoding="utf-8")
old = ' if "critical_gte" in thresholds:\n lines.append(f\' vars.life_noc_threshold_critical_gte = "{icinga_escape(str(thresholds["critical_gte"]))}"\')\n'
new = old + ' if "unknown_gte" in thresholds:\n lines.append(f\' vars.life_noc_threshold_unknown_gte = "{icinga_escape(str(thresholds["unknown_gte"]))}"\')\n if "ok_lt" in thresholds:\n lines.append(f\' vars.life_noc_threshold_ok_lt = "{icinga_escape(str(thresholds["ok_lt"]))}"\')\n if "warning_lt" in thresholds:\n lines.append(f\' vars.life_noc_threshold_warning_lt = "{icinga_escape(str(thresholds["warning_lt"]))}"\')\n if "critical_lt" in thresholds:\n lines.append(f\' vars.life_noc_threshold_critical_lt = "{icinga_escape(str(thresholds["critical_lt"]))}"\')\n'
if old not in text:
raise SystemExit("Bloc seuils introuvable dans generate_services.py")
text = text.replace(old, new, 1)
old2 = ' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time"}:\n raise ValueError("seul probe.type=elapsed_time est supporté en v1")\n'
new2 = ' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time", "days_until_due"}:\n raise ValueError("seuls probe.type=elapsed_time et days_until_due sont supportés")\n'
if old2 in text:
text = text.replace(old2, new2, 1)
else:
old3 = ' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time", "days_until_due"}:\n raise ValueError("seuls probe.type=elapsed_time et days_until_due sont supportés")\n'
if old3 not in text:
raise SystemExit("Bloc validate_probe introuvable ou inattendu dans generate_services.py")
path.write_text(text, encoding="utf-8")
print("generate_services.py patché")
PYEOF
echo "==> Création du store data/inputs/obligations-legales-personnelles.yaml"
mkdir -p "$ROOT/data/inputs"
cat > "$ROOT/data/inputs/obligations-legales-personnelles.yaml" <<'YAMLEOF'
renouvellement-permis-conduire:
value: "2026-09-20"
captured_at: "2026-03-14T23:30:00Z"
origin: manual
YAMLEOF
echo "==> Mise à jour de domains.yaml"
python3 - "$ROOT/domains.yaml" <<'PYEOF'
from pathlib import Path
import sys
import yaml
path = Path(sys.argv[1])
data = yaml.safe_load(path.read_text(encoding="utf-8"))
domain = "obligations-legales-personnelles"
items = data.get("domains", {}).get(domain)
if not isinstance(items, list):
raise SystemExit(f"Domaine introuvable ou invalide: {domain}")
target = None
for item in items:
if isinstance(item, dict) and item.get("name") == "renouvellement-permis-conduire":
target = item
break
if target is None:
raise SystemExit("Item 'renouvellement-permis-conduire' introuvable dans domains.yaml")
target["date"] = "2026-09-20"
target["notes"] = "Vérifier la proximité de léchéance du permis"
target["probe"] = {
"type": "days_until_due",
"source": {
"type": "manual_date",
"inputs_file": "/opt/life-noc/data/inputs/obligations-legales-personnelles.yaml",
"item_key": "renouvellement-permis-conduire",
},
"metric": {
"unit": "days",
},
"thresholds": {
"critical_lt": 7,
"warning_lt": 30,
"ok_lt": 90,
"unknown_gte": 90,
},
"policy": {
"on_error": "critical",
},
}
path.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding="utf-8")
print("domains.yaml mis à jour")
PYEOF
echo "==> Régénération"
(
cd "$ROOT"
python3 scripts/generate_services.py
)
echo
echo "Patch terminé."
echo "Étapes suivantes :"
echo " python3 scripts/generate_services.py"
echo " make check"
echo " make deploy-with-bpm"
echo
echo "Test utile ensuite :"
echo " python3 scripts/life_noc_input.py set obligations-legales-personnelles renouvellement-permis-conduire 2026-03-20"

View file

@ -1,145 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${1:-.}"
need_file() {
local f="$1"
if [[ ! -f "$ROOT/$f" ]]; then
echo "Fichier introuvable: $f" >&2
exit 1
fi
}
echo "==> Vérification"
need_file "scripts/generate_services.py"
need_file "domains.yaml"
echo "==> Sauvegarde"
mkdir -p "$ROOT/.patch-backup-days-until-due-v2"
cp -a "$ROOT/scripts/generate_services.py" "$ROOT/.patch-backup-days-until-due-v2/generate_services.py.bak"
cp -a "$ROOT/domains.yaml" "$ROOT/.patch-backup-days-until-due-v2/domains.yaml.bak"
echo "==> Patch de scripts/generate_services.py"
python3 - "$ROOT/scripts/generate_services.py" <<'PYEOF'
from pathlib import Path
import sys
path = Path(sys.argv[1])
text = path.read_text(encoding="utf-8")
# 1) Ajouter les seuils *_lt / unknown_gte si absents
needle = ' if "critical_gte" in thresholds:\n lines.append(f\' vars.life_noc_threshold_critical_gte = "{icinga_escape(str(thresholds["critical_gte"]))}"\')\n'
addition = (
' if "unknown_gte" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_unknown_gte = "{icinga_escape(str(thresholds["unknown_gte"]))}"\')\n'
' if "ok_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_ok_lt = "{icinga_escape(str(thresholds["ok_lt"]))}"\')\n'
' if "warning_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_warning_lt = "{icinga_escape(str(thresholds["warning_lt"]))}"\')\n'
' if "critical_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_critical_lt = "{icinga_escape(str(thresholds["critical_lt"]))}"\')\n'
)
if 'vars.life_noc_threshold_unknown_gte' not in text:
if needle not in text:
raise SystemExit("Impossible de trouver le bloc des seuils dans generate_services.py")
text = text.replace(needle, needle + addition, 1)
# 2) Élargir validate_probe aux deux types
old_variants = [
' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time"}:\n raise ValueError("seul probe.type=elapsed_time est supporté en v1")\n',
' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time"}:\n raise ValueError("seul probe.type=elapsed_time est supporté en v1")\r\n',
]
new_block = ' probe_type = str(probe.get("type", "")).strip()\n if probe_type not in {"elapsed_time", "days_until_due"}:\n raise ValueError("seuls probe.type=elapsed_time et days_until_due sont supportés")\n'
replaced = False
for old in old_variants:
if old in text:
text = text.replace(old, new_block, 1)
replaced = True
break
if not replaced:
# si déjà patché, on accepte
if new_block.strip() not in text:
raise SystemExit("Bloc validate_probe introuvable ou déjà trop différent dans generate_services.py")
path.write_text(text, encoding="utf-8")
print("generate_services.py patché")
PYEOF
echo "==> Création du store data/inputs/obligations-legales-personnelles.yaml"
mkdir -p "$ROOT/data/inputs"
cat > "$ROOT/data/inputs/obligations-legales-personnelles.yaml" <<'YAMLEOF'
renouvellement-permis-conduire:
value: "2026-09-20"
captured_at: "2026-03-14T23:30:00Z"
origin: manual
YAMLEOF
echo "==> Mise à jour de domains.yaml"
python3 - "$ROOT/domains.yaml" <<'PYEOF'
from pathlib import Path
import sys
import yaml
path = Path(sys.argv[1])
data = yaml.safe_load(path.read_text(encoding="utf-8"))
domain = "obligations-legales-personnelles"
items = data.get("domains", {}).get(domain)
if not isinstance(items, list):
raise SystemExit(f"Domaine introuvable ou invalide: {domain}")
target = None
for item in items:
if isinstance(item, dict) and item.get("name") == "renouvellement-permis-conduire":
target = item
break
if target is None:
raise SystemExit("Item 'renouvellement-permis-conduire' introuvable")
target["date"] = "2026-09-20"
target["notes"] = "Vérifier la proximité de léchéance du permis"
target["probe"] = {
"type": "days_until_due",
"source": {
"type": "manual_date",
"inputs_file": "/opt/life-noc/data/inputs/obligations-legales-personnelles.yaml",
"item_key": "renouvellement-permis-conduire",
},
"metric": {
"unit": "days",
},
"thresholds": {
"critical_lt": 7,
"warning_lt": 30,
"ok_lt": 90,
"unknown_gte": 90,
},
"policy": {
"on_error": "critical",
},
}
path.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding="utf-8")
print("domains.yaml mis à jour")
PYEOF
echo "==> Régénération"
(
cd "$ROOT"
python3 scripts/generate_services.py
)
echo
echo "Patch terminé."
echo "Étapes suivantes :"
echo " python3 scripts/generate_services.py"
echo " make check"
echo " make deploy-with-bpm"
echo
echo "Test utile ensuite :"
echo " python3 scripts/life_noc_input.py set obligations-legales-personnelles renouvellement-permis-conduire 2026-03-20"

View file

@ -1,161 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="${1:-.}"
need_file() {
local f="$1"
if [[ ! -f "$ROOT/$f" ]]; then
echo "Fichier introuvable: $f" >&2
exit 1
fi
}
echo "==> Vérification"
need_file "scripts/generate_services.py"
need_file "domains.yaml"
echo "==> Sauvegarde"
mkdir -p "$ROOT/.patch-backup-days-until-due-v3"
cp -a "$ROOT/scripts/generate_services.py" "$ROOT/.patch-backup-days-until-due-v3/generate_services.py.bak"
cp -a "$ROOT/domains.yaml" "$ROOT/.patch-backup-days-until-due-v3/domains.yaml.bak"
echo "==> Patch robuste de scripts/generate_services.py"
python3 - "$ROOT/scripts/generate_services.py" <<'PYEOF'
from pathlib import Path
import re
import sys
path = Path(sys.argv[1])
text = path.read_text(encoding="utf-8")
# 1) Ajouter les seuils lt/gte manquants dans render_probe_service, juste avant on_error
if 'vars.life_noc_threshold_unknown_gte' not in text:
marker = ' on_error = str(policy.get("on_error", "critical")).strip()\n'
inject = (
' if "unknown_gte" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_unknown_gte = "{icinga_escape(str(thresholds["unknown_gte"]))}"\')\n'
' if "ok_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_ok_lt = "{icinga_escape(str(thresholds["ok_lt"]))}"\')\n'
' if "warning_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_warning_lt = "{icinga_escape(str(thresholds["warning_lt"]))}"\')\n'
' if "critical_lt" in thresholds:\n'
' lines.append(f\' vars.life_noc_threshold_critical_lt = "{icinga_escape(str(thresholds["critical_lt"]))}"\')\n'
)
if marker not in text:
raise SystemExit("Impossible de trouver le point d'injection des seuils dans render_probe_service")
text = text.replace(marker, inject + marker, 1)
# 2) Remplacer entièrement validate_probe(...)
new_validate = '''def validate_probe(item: dict) -> None:
probe = item["probe"]
if not isinstance(probe, dict):
raise ValueError("probe doit être un objet")
probe_type = str(probe.get("type", "")).strip()
if probe_type not in {"elapsed_time", "days_until_due"}:
raise ValueError("seuls probe.type=elapsed_time et days_until_due sont supportés")
source = probe.get("source")
if not isinstance(source, dict):
raise ValueError("probe.source doit être un objet")
if str(source.get("type", "")).strip() != "manual_date":
raise ValueError("seul probe.source.type=manual_date est supporté en v1")
has_inline_value = "value" in source
has_store_ref = "inputs_file" in source and "item_key" in source
if not has_inline_value and not has_store_ref:
raise ValueError("probe.source.value ou probe.source.inputs_file + item_key requis")
metric = probe.get("metric")
if not isinstance(metric, dict):
raise ValueError("probe.metric doit être un objet")
if str(metric.get("unit", "")).strip() != "days":
raise ValueError("seul probe.metric.unit=days est supporté en v1")
thresholds = probe.get("thresholds")
if not isinstance(thresholds, dict):
raise ValueError("probe.thresholds doit être un objet")
'''
pattern = r'def validate_probe\(item: dict\) -> None:\n(?: .*\n)+?(?=\ndef render_servicegroup|\ndef main\()'
new_text, count = re.subn(pattern, new_validate + "\n", text, flags=re.MULTILINE)
if count == 0:
raise SystemExit("Impossible de remplacer validate_probe(...) dans generate_services.py")
text = new_text
path.write_text(text, encoding="utf-8")
print("generate_services.py patché")
PYEOF
echo "==> Création du store"
mkdir -p "$ROOT/data/inputs"
cat > "$ROOT/data/inputs/obligations-legales-personnelles.yaml" <<'YAMLEOF'
renouvellement-permis-conduire:
value: "2026-09-20"
captured_at: "2026-03-14T23:30:00Z"
origin: manual
YAMLEOF
echo "==> Mise à jour de domains.yaml"
python3 - "$ROOT/domains.yaml" <<'PYEOF'
from pathlib import Path
import sys
import yaml
path = Path(sys.argv[1])
data = yaml.safe_load(path.read_text(encoding="utf-8"))
domain = "obligations-legales-personnelles"
items = data.get("domains", {}).get(domain)
if not isinstance(items, list):
raise SystemExit(f"Domaine introuvable ou invalide: {domain}")
target = None
for item in items:
if isinstance(item, dict) and item.get("name") == "renouvellement-permis-conduire":
target = item
break
if target is None:
raise SystemExit("Item 'renouvellement-permis-conduire' introuvable")
target["date"] = "2026-09-20"
target["notes"] = "Vérifier la proximité de léchéance du permis"
target["probe"] = {
"type": "days_until_due",
"source": {
"type": "manual_date",
"inputs_file": "/opt/life-noc/data/inputs/obligations-legales-personnelles.yaml",
"item_key": "renouvellement-permis-conduire",
},
"metric": {
"unit": "days",
},
"thresholds": {
"critical_lt": 7,
"warning_lt": 30,
"ok_lt": 90,
"unknown_gte": 90,
},
"policy": {
"on_error": "critical",
},
}
path.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding="utf-8")
print("domains.yaml mis à jour")
PYEOF
echo "==> Régénération"
(
cd "$ROOT"
python3 scripts/generate_services.py
)
echo
echo "Patch terminé."
echo "Étapes suivantes :"
echo " python3 scripts/generate_services.py"
echo " make check"
echo " make deploy-with-bpm"

View file

@ -79,6 +79,9 @@ def render_mock_service(domain: str, group_name: str, item: dict) -> str:
date = str(item["date"]).strip() date = str(item["date"]).strip()
notes = item.get("notes", "").strip() notes = item.get("notes", "").strip()
notes_url = item.get("notes_url", "").strip() notes_url = item.get("notes_url", "").strip()
instructions_url = item.get("instructions_url", "").strip()
if not instructions_url:
instructions_url = f"/life-noc/item/{domain}/{name}"
action_url = item.get("action_url", "").strip() action_url = item.get("action_url", "").strip()
mock_state = normalize_mock_state(item.get("mock_state", DEFAULT_MOCK_STATE)) mock_state = normalize_mock_state(item.get("mock_state", DEFAULT_MOCK_STATE))
mock_message = item.get("mock_message", DEFAULT_MOCK_MESSAGE).strip() or DEFAULT_MOCK_MESSAGE mock_message = item.get("mock_message", DEFAULT_MOCK_MESSAGE).strip() or DEFAULT_MOCK_MESSAGE
@ -98,6 +101,8 @@ def render_mock_service(domain: str, group_name: str, item: dict) -> str:
lines.append(f' notes = "{icinga_escape(notes)}"') lines.append(f' notes = "{icinga_escape(notes)}"')
if notes_url: if notes_url:
lines.append(f' notes_url = "{icinga_escape(notes_url)}"') lines.append(f' notes_url = "{icinga_escape(notes_url)}"')
if instructions_url:
lines.append(f' vars.instructions_url = "{icinga_escape(instructions_url)}"')
if action_url: if action_url:
lines.append(f' action_url = "{icinga_escape(action_url)}"') lines.append(f' action_url = "{icinga_escape(action_url)}"')
@ -112,6 +117,9 @@ def render_probe_service(domain: str, group_name: str, item: dict) -> str:
name = item["name"].strip() name = item["name"].strip()
notes = item.get("notes", "").strip() notes = item.get("notes", "").strip()
notes_url = item.get("notes_url", "").strip() notes_url = item.get("notes_url", "").strip()
instructions_url = item.get("instructions_url", "").strip()
if not instructions_url:
instructions_url = f"/life-noc/item/{domain}/{name}"
action_url = item.get("action_url", "").strip() action_url = item.get("action_url", "").strip()
probe = item["probe"] probe = item["probe"]
@ -160,6 +168,8 @@ def render_probe_service(domain: str, group_name: str, item: dict) -> str:
lines.append(f' notes = "{icinga_escape(notes)}"') lines.append(f' notes = "{icinga_escape(notes)}"')
if notes_url: if notes_url:
lines.append(f' notes_url = "{icinga_escape(notes_url)}"') lines.append(f' notes_url = "{icinga_escape(notes_url)}"')
if instructions_url:
lines.append(f' vars.instructions_url = "{icinga_escape(instructions_url)}"')
if action_url: if action_url:
lines.append(f' action_url = "{icinga_escape(action_url)}"') lines.append(f' action_url = "{icinga_escape(action_url)}"')

View file

@ -0,0 +1,307 @@
#!/usr/bin/env python3
from pathlib import Path
import re
import sys
import yaml
INPUT_FILE = Path("domains.yaml")
OUTPUT_DIR = Path("icinga/services")
SERVICEGROUPS_DIR = Path("icinga/servicegroups")
SERVICEGROUPS_FILE = SERVICEGROUPS_DIR / "life-noc.conf"
HOST_NAME = "life-noc"
SERVICE_TEMPLATE = "service_echeance"
PROBE_TEMPLATE = "service_life_noc_probe"
DEFAULT_MOCK_STATE = "OK"
DEFAULT_MOCK_MESSAGE = "Sous contrôle"
def slugify(value: str) -> str:
value = value.strip().lower()
replacements = {
"à": "a", "â": "a", "ä": "a",
"ç": "c",
"é": "e", "è": "e", "ê": "e", "ë": "e",
"î": "i", "ï": "i",
"ô": "o", "ö": "o",
"ù": "u", "û": "u", "ü": "u",
"ÿ": "y",
"œ": "oe",
"æ": "ae",
"'": "",
"": "",
}
for old, new in replacements.items():
value = value.replace(old, new)
value = re.sub(r"[^a-z0-9\-]+", "-", value)
value = re.sub(r"-{2,}", "-", value)
return value.strip("-")
def aliasify(value: str) -> str:
value = value.strip().upper()
replacements = {
"À": "A", "Â": "A", "Ä": "A",
"Ç": "C",
"É": "E", "È": "E", "Ê": "E", "Ë": "E",
"Î": "I", "Ï": "I",
"Ô": "O", "Ö": "O",
"Ù": "U", "Û": "U", "Ü": "U",
"Ÿ": "Y",
"Œ": "OE",
"Æ": "AE",
"'": "",
"": "",
}
for old, new in replacements.items():
value = value.replace(old, new)
value = re.sub(r"[^A-Z0-9\-]+", "-", value)
value = re.sub(r"-{2,}", "-", value)
return value.strip("-")
def icinga_escape(value: str) -> str:
return value.replace("\\", "\\\\").replace('"', '\\"')
def normalize_mock_state(value: str) -> str:
state = str(value).strip().upper()
allowed = {"OK", "WARNING", "CRITICAL"}
if state not in allowed:
raise ValueError(
f"mock_state invalide: {value}. Valeurs permises: {', '.join(sorted(allowed))}"
)
return state
def render_mock_service(domain: str, group_name: str, item: dict) -> str:
name = item["name"].strip()
date = str(item["date"]).strip()
notes = item.get("notes", "").strip()
notes_url = item.get("notes_url", "").strip()
action_url = item.get("action_url", "").strip()
mock_state = normalize_mock_state(item.get("mock_state", DEFAULT_MOCK_STATE))
mock_message = item.get("mock_message", DEFAULT_MOCK_MESSAGE).strip() or DEFAULT_MOCK_MESSAGE
service_name = f"{domain}-{name}"
lines = [
f'apply Service "{icinga_escape(service_name)}" {{',
f' import "{SERVICE_TEMPLATE}"',
f' vars.date_echeance = "{icinga_escape(date)}"',
f' vars.mock_state = "{icinga_escape(mock_state)}"',
f' vars.mock_message = "{icinga_escape(mock_message)}"',
f' groups = [ "{icinga_escape(group_name)}" ]',
]
if notes:
lines.append(f' notes = "{icinga_escape(notes)}"')
if notes_url:
lines.append(f' notes_url = "{icinga_escape(notes_url)}"')
if action_url:
lines.append(f' action_url = "{icinga_escape(action_url)}"')
lines.append(f' assign where host.name == "{HOST_NAME}"')
lines.append("}")
lines.append("")
return "\n".join(lines)
def render_probe_service(domain: str, group_name: str, item: dict) -> str:
name = item["name"].strip()
notes = item.get("notes", "").strip()
notes_url = item.get("notes_url", "").strip()
action_url = item.get("action_url", "").strip()
probe = item["probe"]
probe_type = str(probe["type"]).strip()
source = probe["source"]
metric = probe["metric"]
thresholds = probe["thresholds"]
policy = probe.get("policy", {})
service_name = f"{domain}-{name}"
lines = [
f'apply Service "{icinga_escape(service_name)}" {{',
f' import "{PROBE_TEMPLATE}"',
f' vars.life_noc_probe_type = "{icinga_escape(probe_type)}"',
f' vars.life_noc_source_type = "{icinga_escape(str(source["type"]).strip())}"',
f' vars.life_noc_source_value = "{icinga_escape(str(source.get("value", "")).strip())}"',
f' vars.life_noc_inputs_file = "{icinga_escape(str(source.get("inputs_file", "")).strip())}"',
f' vars.life_noc_item_key = "{icinga_escape(str(source.get("item_key", name)).strip())}"',
f' vars.life_noc_metric_unit = "{icinga_escape(str(metric["unit"]).strip())}"',
f' vars.life_noc_label = "{icinga_escape(name)}"',
f' groups = [ "{icinga_escape(group_name)}" ]',
]
if "unknown_lt" in thresholds:
lines.append(f' vars.life_noc_threshold_unknown_lt = "{icinga_escape(str(thresholds["unknown_lt"]))}"')
if "ok_gte" in thresholds:
lines.append(f' vars.life_noc_threshold_ok_gte = "{icinga_escape(str(thresholds["ok_gte"]))}"')
if "warning_gte" in thresholds:
lines.append(f' vars.life_noc_threshold_warning_gte = "{icinga_escape(str(thresholds["warning_gte"]))}"')
if "critical_gte" in thresholds:
lines.append(f' vars.life_noc_threshold_critical_gte = "{icinga_escape(str(thresholds["critical_gte"]))}"')
if "unknown_gte" in thresholds:
lines.append(f' vars.life_noc_threshold_unknown_gte = "{icinga_escape(str(thresholds["unknown_gte"]))}"')
if "ok_lt" in thresholds:
lines.append(f' vars.life_noc_threshold_ok_lt = "{icinga_escape(str(thresholds["ok_lt"]))}"')
if "warning_lt" in thresholds:
lines.append(f' vars.life_noc_threshold_warning_lt = "{icinga_escape(str(thresholds["warning_lt"]))}"')
if "critical_lt" in thresholds:
lines.append(f' vars.life_noc_threshold_critical_lt = "{icinga_escape(str(thresholds["critical_lt"]))}"')
on_error = str(policy.get("on_error", "critical")).strip()
lines.append(f' vars.life_noc_on_error = "{icinga_escape(on_error)}"')
if notes:
lines.append(f' notes = "{icinga_escape(notes)}"')
if notes_url:
lines.append(f' notes_url = "{icinga_escape(notes_url)}"')
if action_url:
lines.append(f' action_url = "{icinga_escape(action_url)}"')
lines.append(f' assign where host.name == "{HOST_NAME}"')
lines.append("}")
lines.append("")
return "\n".join(lines)
def validate_probe(item: dict) -> None:
probe = item["probe"]
if not isinstance(probe, dict):
raise ValueError("probe doit être un objet")
probe_type = str(probe.get("type", "")).strip()
if probe_type not in {"elapsed_time", "days_until_due"}:
raise ValueError("seuls probe.type=elapsed_time et days_until_due sont supportés")
source = probe.get("source")
if not isinstance(source, dict):
raise ValueError("probe.source doit être un objet")
if str(source.get("type", "")).strip() != "manual_date":
raise ValueError("seul probe.source.type=manual_date est supporté en v1")
has_inline_value = "value" in source
has_store_ref = "inputs_file" in source and "item_key" in source
if not has_inline_value and not has_store_ref:
raise ValueError("probe.source.value ou probe.source.inputs_file + item_key requis")
metric = probe.get("metric")
if not isinstance(metric, dict):
raise ValueError("probe.metric doit être un objet")
if str(metric.get("unit", "")).strip() != "days":
raise ValueError("seul probe.metric.unit=days est supporté en v1")
thresholds = probe.get("thresholds")
if not isinstance(thresholds, dict):
raise ValueError("probe.thresholds doit être un objet")
def render_servicegroup(group_name: str) -> str:
return "\n".join([
f'object ServiceGroup "{icinga_escape(group_name)}" {{',
f' display_name = "{icinga_escape(group_name)}"',
"}",
"",
])
def main() -> int:
if not INPUT_FILE.exists():
print(f"Erreur: fichier introuvable: {INPUT_FILE}", file=sys.stderr)
return 1
with INPUT_FILE.open("r", encoding="utf-8") as f:
data = yaml.safe_load(f)
if not isinstance(data, dict) or "domains" not in data:
print("Erreur: le YAML doit contenir une clé racine 'domains'.", file=sys.stderr)
return 1
domains = data["domains"]
if not isinstance(domains, dict):
print("Erreur: 'domains' doit être un objet YAML.", file=sys.stderr)
return 1
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
SERVICEGROUPS_DIR.mkdir(parents=True, exist_ok=True)
for existing_conf in OUTPUT_DIR.glob("*.conf"):
existing_conf.unlink()
if SERVICEGROUPS_FILE.exists():
SERVICEGROUPS_FILE.unlink()
generated_files = []
servicegroup_content = [
"/*",
" AUTO-GENERATED FILE - SERVICE GROUPS",
" Ne pas modifier manuellement.",
" Source: domains.yaml",
"*/",
"",
]
for raw_domain, services in domains.items():
domain = slugify(str(raw_domain))
group_name = aliasify(str(raw_domain))
if not isinstance(services, list):
print(f"Erreur: le domaine '{raw_domain}' doit contenir une liste.", file=sys.stderr)
return 1
output_file = OUTPUT_DIR / f"{domain}.conf"
content = [
"/*",
f" AUTO-GENERATED FILE - DOMAIN: {raw_domain}",
" Ne pas modifier manuellement.",
" Source: domains.yaml",
"*/",
"",
]
servicegroup_content.append(render_servicegroup(group_name))
for idx, item in enumerate(services, start=1):
if not isinstance(item, dict):
print(f"Erreur: entrée invalide dans '{raw_domain}' à la position {idx}.", file=sys.stderr)
return 1
missing = [key for key in ("name", "date", "notes") if key not in item]
if missing:
print(
f"Erreur: dans le domaine '{raw_domain}', entrée {idx}, champs manquants: {', '.join(missing)}",
file=sys.stderr,
)
return 1
try:
if "probe" in item:
validate_probe(item)
content.append(render_probe_service(domain, group_name, item))
else:
content.append(render_mock_service(domain, group_name, item))
except ValueError as exc:
print(f"Erreur dans '{raw_domain}', entrée {idx}: {exc}", file=sys.stderr)
return 1
output_file.write_text("\n".join(content).rstrip() + "\n", encoding="utf-8")
generated_files.append(str(output_file))
SERVICEGROUPS_FILE.write_text("\n".join(servicegroup_content).rstrip() + "\n", encoding="utf-8")
generated_files.append(str(SERVICEGROUPS_FILE))
print("Fichiers générés :")
for file_path in generated_files:
print(f" - {file_path}")
return 0
if __name__ == "__main__":
raise SystemExit(main())

View file

@ -5,14 +5,22 @@ from __future__ import annotations
from pathlib import Path from pathlib import Path
import sys import sys
from fastapi import FastAPI, HTTPException from fastapi import FastAPI, HTTPException, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from pydantic import BaseModel from pydantic import BaseModel
ROOT = Path(__file__).resolve().parents[1] ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path: if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT)) sys.path.insert(0, str(ROOT))
from lib.life_noc_inputs import list_items, get_item, set_item, complete_item # noqa: E402 from lib.life_noc_inputs import ( # noqa: E402
list_items,
get_item,
set_item,
complete_item,
get_defined_service,
compute_state_for_item,
)
class SetInputRequest(BaseModel): class SetInputRequest(BaseModel):
@ -27,6 +35,31 @@ class CompleteInputRequest(BaseModel):
app = FastAPI(title="Life-NOC Input API", version="1.0.0") app = FastAPI(title="Life-NOC Input API", version="1.0.0")
def html_escape(value: str) -> str:
return (
str(value)
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace('"', "&quot;")
)
def link_row(label: str, url: str) -> str:
if not url:
return ""
u = html_escape(url)
l = html_escape(label)
return f'<li><a href="{u}" target="_blank" rel="noopener">{l}</a></li>'
def resolve_instructions_url(domain: str, item_key: str, service: dict) -> str:
explicit = str(service.get("instructions_url", "")).strip()
if explicit:
return explicit
return f"/life-noc/item/{domain}/{item_key}"
@app.get("/health") @app.get("/health")
def health() -> dict: def health() -> dict:
return {"status": "ok"} return {"status": "ok"}
@ -59,3 +92,191 @@ def api_complete_input(domain: str, item_key: str, req: CompleteInputRequest | N
origin = "manual" if req is None else req.origin origin = "manual" if req is None else req.origin
item = complete_item(domain, item_key, origin=origin) item = complete_item(domain, item_key, origin=origin)
return {"domain": domain, "item_key": item_key, **item} return {"domain": domain, "item_key": item_key, **item}
@app.get("/life-noc/item/{domain}/{item_key}", response_class=HTMLResponse)
def page_item(domain: str, item_key: str) -> HTMLResponse:
try:
service = get_defined_service(domain, item_key)
current_input = get_item(domain, item_key)
state = compute_state_for_item(domain, item_key)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
title = service.get("title") or service.get("display_name") or item_key.replace("-", " ").capitalize()
summary = service.get("summary", "")
notes = service.get("notes", "")
instructions = service.get("instructions", "")
notes_url = service.get("notes_url", "")
instructions_url = resolve_instructions_url(domain, item_key, service)
action_url = service.get("action_url", "")
probe_type = service.get("probe", {}).get("type", "unknown")
ui = service.get("ui", {}) if isinstance(service.get("ui", {}), dict) else {}
form_mode = ui.get("form_mode", "")
allow_complete = bool(ui.get("allow_complete", probe_type == "elapsed_time"))
allow_manual_edit = bool(ui.get("allow_manual_edit", True))
links_html = ""
for fragment in [
link_row("Notes", notes_url),
link_row("Instructions", instructions_url),
link_row("Action", action_url),
]:
if fragment:
links_html += fragment
summary_html = ""
if summary:
summary_html = f'<p><strong>Résumé :</strong> {html_escape(summary)}</p>'
instructions_html = ""
if instructions:
instructions_html = f"""
<section class="card">
<h2>Instructions</h2>
<pre style="white-space: pre-wrap; font-family: Arial, sans-serif;">{html_escape(instructions)}</pre>
</section>
"""
manual_form_html = ""
if allow_manual_edit and form_mode == "complete_date":
manual_form_html = f"""
<section class="card">
<h2>Mettre à jour la date</h2>
<form method="post" action="/life-noc/item/{html_escape(domain)}/{html_escape(item_key)}/set">
<input type="date" name="value" value="{html_escape(current_input.get("value", ""))}" required>
<input type="hidden" name="origin" value="manual">
<button type="submit">Enregistrer</button>
</form>
</section>
"""
complete_form_html = ""
if allow_complete:
complete_form_html = f"""
<section class="card">
<h2>Action rapide</h2>
<form method="post" action="/life-noc/item/{html_escape(domain)}/{html_escape(item_key)}/complete">
<button type="submit">Compléter</button>
</form>
</section>
"""
html = f"""<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Life-NOC {html_escape(title)}</title>
<style>
body {{
font-family: Arial, sans-serif;
max-width: 760px;
margin: 0 auto;
padding: 1rem;
line-height: 1.45;
}}
.card {{
border: 1px solid #ccc;
border-radius: 10px;
padding: 1rem;
margin-bottom: 1rem;
}}
.state {{
font-size: 1.2rem;
font-weight: bold;
}}
button {{
font-size: 1rem;
padding: 0.9rem 1.2rem;
border-radius: 8px;
border: 1px solid #444;
cursor: pointer;
}}
input[type="date"] {{
font-size: 1rem;
padding: 0.7rem;
border-radius: 8px;
border: 1px solid #666;
margin-right: 0.5rem;
}}
ul {{
padding-left: 1.25rem;
}}
code {{
background: #f3f3f3;
padding: 0.1rem 0.3rem;
border-radius: 4px;
}}
</style>
</head>
<body>
<main>
<section class="card">
<h1>{html_escape(title)}</h1>
<p class="state">État actuel : {html_escape(state)}</p>
<p><strong>Type de sonde :</strong> {html_escape(probe_type)}</p>
{summary_html}
</section>
<section class="card">
<h2>Dernier intrant</h2>
<p><strong>Valeur :</strong> {html_escape(current_input.get("value", ""))}</p>
<p><strong>Capturé le :</strong> {html_escape(current_input.get("captured_at", ""))}</p>
<p><strong>Origine :</strong> {html_escape(current_input.get("origin", ""))}</p>
</section>
<section class="card">
<h2>Contexte</h2>
<p><strong>Domaine :</strong> {html_escape(domain)}</p>
<p><strong>Item key :</strong> <code>{html_escape(item_key)}</code></p>
<p><strong>Notes :</strong> {html_escape(notes)}</p>
</section>
{instructions_html}
<section class="card">
<h2>Liens utiles</h2>
<ul>
{links_html}
</ul>
</section>
{manual_form_html}
{complete_form_html}
</main>
</body>
</html>"""
return HTMLResponse(content=html)
@app.post("/life-noc/item/{domain}/{item_key}/set")
def page_set_item(domain: str, item_key: str, value: str = Form(...), origin: str = Form(default="manual")) -> RedirectResponse:
try:
set_item(domain, item_key, value=value, origin=origin)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return RedirectResponse(
url=f"/life-noc/item/{domain}/{item_key}",
status_code=303,
)
@app.post("/life-noc/item/{domain}/{item_key}/complete")
def page_complete_item(domain: str, item_key: str, origin: str = Form(default="manual")) -> RedirectResponse:
try:
complete_item(domain, item_key, origin=origin)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return RedirectResponse(
url=f"/life-noc/item/{domain}/{item_key}",
status_code=303,
)

View file

@ -0,0 +1,227 @@
#!/usr/bin/env python3
from __future__ import annotations
from pathlib import Path
import sys
from fastapi import FastAPI, HTTPException, Form
from fastapi.responses import HTMLResponse, RedirectResponse
from pydantic import BaseModel
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from lib.life_noc_inputs import ( # noqa: E402
list_items,
get_item,
set_item,
complete_item,
get_defined_service,
compute_state_for_item,
)
class SetInputRequest(BaseModel):
value: str
origin: str = "manual"
class CompleteInputRequest(BaseModel):
origin: str = "manual"
app = FastAPI(title="Life-NOC Input API", version="1.0.0")
def html_escape(value: str) -> str:
return (
str(value)
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace('"', "&quot;")
)
def link_row(label: str, url: str) -> str:
if not url:
return ""
u = html_escape(url)
l = html_escape(label)
return f'<li><a href="{u}" target="_blank" rel="noopener">{l}</a></li>'
def resolve_instructions_url(domain: str, item_key: str, service: dict) -> str:
explicit = str(service.get("instructions_url", "")).strip()
if explicit:
return explicit
return f"/life-noc/item/{domain}/{item_key}"
@app.get("/health")
def health() -> dict:
return {"status": "ok"}
@app.get("/inputs/{domain}")
def api_list_inputs(domain: str) -> dict:
return {"domain": domain, "items": list_items(domain)}
@app.get("/inputs/{domain}/{item_key}")
def api_get_input(domain: str, item_key: str) -> dict:
try:
item = get_item(domain, item_key)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return {"domain": domain, "item_key": item_key, **item}
@app.post("/inputs/{domain}/{item_key}")
def api_set_input(domain: str, item_key: str, req: SetInputRequest) -> dict:
item = set_item(domain, item_key, req.value, origin=req.origin)
return {"domain": domain, "item_key": item_key, **item}
@app.post("/inputs/{domain}/{item_key}/complete")
def api_complete_input(domain: str, item_key: str, req: CompleteInputRequest | None = None) -> dict:
origin = "manual" if req is None else req.origin
item = complete_item(domain, item_key, origin=origin)
return {"domain": domain, "item_key": item_key, **item}
@app.get("/life-noc/item/{domain}/{item_key}", response_class=HTMLResponse)
def page_item(domain: str, item_key: str) -> HTMLResponse:
try:
service = get_defined_service(domain, item_key)
current_input = get_item(domain, item_key)
state = compute_state_for_item(domain, item_key)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
title = service.get("title") or service.get("display_name") or item_key.replace("-", " ").capitalize()
summary = service.get("summary", "")
notes = service.get("notes", "")
instructions = service.get("instructions", "")
notes_url = service.get("notes_url", "")
instructions_url = resolve_instructions_url(domain, item_key, service)
action_url = service.get("action_url", "")
probe_type = service.get("probe", {}).get("type", "unknown")
ui = service.get("ui", {}) if isinstance(service.get("ui", {}), dict) else {}
form_mode = ui.get("form_mode", "")
allow_complete = bool(ui.get("allow_complete", probe_type == "elapsed_time"))
allow_manual_edit = bool(ui.get("allow_manual_edit", True))
html = f"""<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Life-NOC {html_escape(title)}</title>
<style>
body {{
font-family: Arial, sans-serif;
max-width: 760px;
margin: 0 auto;
padding: 1rem;
line-height: 1.45;
}}
.card {{
border: 1px solid #ccc;
border-radius: 10px;
padding: 1rem;
margin-bottom: 1rem;
}}
.state {{
font-size: 1.2rem;
font-weight: bold;
}}
button {{
font-size: 1rem;
padding: 0.9rem 1.2rem;
border-radius: 8px;
border: 1px solid #444;
cursor: pointer;
}}
ul {{
padding-left: 1.25rem;
}}
code {{
background: #f3f3f3;
padding: 0.1rem 0.3rem;
border-radius: 4px;
}}
</style>
</head>
<body>
<main>
<section class="card">
<h1>{html_escape(title)}</h1>
<p class="state">État actuel : {html_escape(state)}</p>
<p><strong>Type de sonde :</strong> {html_escape(probe_type)}</p>
</section>
<section class="card">
<h2>Dernier intrant</h2>
<p><strong>Valeur :</strong> {html_escape(current_input.get("value", ""))}</p>
<p><strong>Capturé le :</strong> {html_escape(current_input.get("captured_at", ""))}</p>
<p><strong>Origine :</strong> {html_escape(current_input.get("origin", ""))}</p>
</section>
<section class="card">
<h2>Contexte</h2>
<p><strong>Domaine :</strong> {html_escape(domain)}</p>
<p><strong>Item key :</strong> <code>{html_escape(item_key)}</code></p>
<p><strong>Notes :</strong> {html_escape(notes)}</p>
</section>
<section class="card">
<h2>Liens utiles</h2>
<ul>
{link_row("Notes", notes_url)}
{link_row("Instructions", instructions_url)}
{link_row("Action", action_url)}
</ul>
</section>
<section class="card">
<h2>Action</h2>
<form method="post" action="/life-noc/item/{html_escape(domain)}/{html_escape(item_key)}/complete">
<button type="submit">Compléter</button>
</form>
</section>
</main>
</body>
</html>"""
return HTMLResponse(content=html)
@app.post("/life-noc/item/{domain}/{item_key}/set")
def page_set_item(domain: str, item_key: str, value: str = Form(...), origin: str = Form(default="manual")) -> RedirectResponse:
try:
set_item(domain, item_key, value=value, origin=origin)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return RedirectResponse(
url=f"/life-noc/item/{domain}/{item_key}",
status_code=303,
)
@app.post("/life-noc/item/{domain}/{item_key}/complete")
def page_complete_item(domain: str, item_key: str, origin: str = Form(default="manual")) -> RedirectResponse:
try:
complete_item(domain, item_key, origin=origin)
except KeyError:
raise HTTPException(status_code=404, detail="item introuvable")
except ValueError as exc:
raise HTTPException(status_code=400, detail=str(exc))
return RedirectResponse(
url=f"/life-noc/item/{domain}/{item_key}",
status_code=303,
)