arcodange/vault-pdb-remount
111
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5ac60c54fa |
fix(vault) — un PDB pour les évictions volontaires, OnRootMismatch pour les remounts
Ce Vault tourne en standalone (Shamir, un seul réplica, pas d'auto-unseal) : toute interruption de pod exige un unseal humain ensuite. Le PDB du sous-chart vendored ne se rend qu'en mode HA (server.ha.disruptionBudget, gardé par `eq .mode "ha"`), donc jamais ici — il en fallait un écrit à la main. Par ailleurs chaque remount du volume déclenchait un chown -R complet du fsGroup, mesuré à ~9 min sur ce PVC (event kubelet VolumePermissionChangeInProgress, suggestion du kubelet lui-même). Avec OnRootMismatch, un remount dont le propriétaire racine est déjà correct saute ce chown. Le PDB ne protège que des évictions volontaires (drain, descheduler) — pas d'une panne de nœud ni d'une suppression manuelle. |
||
|
|
d2202414c0 |
Merge pull request 'fix(redis) — il mourait toutes les 90 s, et c'est le .fr qui tombait' (#28) from arcodange/redis-sonde into main
Reviewed-on: #28 |
||
|
|
f9adc2ec23 |
Merge pull request 'fix(pgbouncer,vault) — ce qu'un client laisse sur une connexion, le suivant n'en hérite plus' (#25) from arcodange/fuite-set-role into main
Reviewed-on: #25 |
||
|
|
49763852d8 |
Merge pull request 'doc(réseau) — le confort LAN ne se règle pas dans Traefik : la mesure, les deux pièges, la voie retenue' (#24) from arcodange/confort-lan into main
Reviewed-on: #24 |
||
|
|
f53c3adb7d |
fix(redis) — il mourait toutes les 90 s, et c'est le .fr qui tombait
Symptôme observé : `kadans.arcodange.fr` et `gitea.arcodange.fr` en 403, corps vide, depuis n'importe quel client extérieur — pendant que `arcodange.fr` et `www` répondaient 200. Ça ressemble à un bannissement d'IP. Ça n'en était pas un. La chaîne, remontée de bout en bout : 1. Le sous-chart fige ses sondes à `timeoutSeconds: 1` sur `redis-cli ping` et n'expose aucune valeur pour les surcharger. 2. Sans réservation de ressources, le conteneur est en QoS `BestEffort` : sur un Raspberry Pi chargé, lancer `redis-cli` dépasse la seconde. 3. « Liveness probe failed: command timed out after 1s » 836 fois en 23 jours, 135 redémarrages, SIGTERM après ~90 s de vie à chaque tour. 4. Le plugin crowdsec de Traefik utilise ce Redis comme cache de décisions. Cache injoignable ⇒ `isCrowdsecStreamHealthy:false` ⇒ refus par défaut de tout client absent de `clientTrustedIPs` ⇒ le 403. D'où le motif trompeur : seuls les hôtes portant le middleware crowdsec tombaient, et depuis le LAN (IP de confiance) tout paraissait sain — l'origine répondait 401, son défi d'authentification normal. Trois fausses pistes en sont sorties : Cloudflare, un bannissement crowdsec, une règle de pare-feu. Aucune n'était la bonne, et `cscli decisions list` disait `isBanned:false` du début à la fin. La réservation fait passer le conteneur en `Burstable` et lui garantit sa part. Les limites restent larges : Redis n'est pas ce qui sature ce nœud. ⚠ Ce commit ne corrige PAS la sonde elle-même — elle reste à 1 s, et elle reste inatteignable depuis les valeurs. Si le clignotement revient malgré la réservation, il faudra un patch Kustomize au niveau de l'Application ArgoCD, ou abandonner ce sous-chart. Une vérification en production a été appliquée à chaud (`timeoutSeconds: 5`, `failureThreshold: 6`) pour rétablir l'accès immédiatement, mais `selfHeal: true` la ré-écrasera : elle n'est pas la correction, ce commit l'est. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK |
||
|
|
7d13a8d764 |
doc(pgbouncer) — la version mesurée n'était pas la déployée, et DISCARD ALL a un prix
Trois corrections au raisonnement, toutes issues d'une contre-vérification qui a refait les mesures au lieu de les relire. 1. La mesure invoquait pgbouncer 1.25.2 « la version en prod ». Le pod tourne 1.23.1 (ghcr.io/icoretech/pgbouncer-docker:1.23.1-fixed, chart 2.3.1, up 133 j). Tout a été rejoué sur 1.23.1 avec la ConfigMap extraite du cluster : les conclusions tiennent, mais la preuve invoquée portait sur autre chose. 2. La portée de la fuite était laissée en suspens, donc lue au pire. Les pools sont partitionnés par (base, utilisateur) — 210 pools, aucun mélange. Le seul héritier possible du SET ROLE de kadans-api est kadans-api. Défaut d'hygiène, pas brèche inter-applications. Le dire baisse la gravité, et c'est plus utile qu'une alarme vague. 3. ⚠ Le point manquant, et c'est l'inverse de ce qu'on croyait : DISCARD ALL rend la protection de db.go STRICTEMENT PLUS FRAGILE. Aujourd'hui (DEALLOCATE ALL) elle survivrait à un passage en transaction pooling ; après, non — le SET ROLE d'AfterConnect est effacé entre deux transactions, et poserRoleProprietaire ne peut pas le voir puisqu'il relit current_role à l'ouverture. Sans danger tant que pool_mode reste `session` (le défaut, non déclaré) — mais c'est précisément le genre de trappe qui se referme des mois plus tard sur quelqu'un qui optimise. Les quatre combinaisons sont mesurées et écrites au-dessus de la ligne. La ceinture Vault couvre ce cas (un défaut de rôle survit à DISCARD ALL), mais seulement au renouvellement des baux. D'où l'avertissement explicite. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK |
||
|
|
1dd905dc5f |
fix(pgbouncer,vault) — ce qu'un client laisse sur une connexion, le suivant n'en hérite plus
Un pgbouncer partagé n'a qu'UNE barrière entre deux clients d'un même pool : le
`server_reset_query`. La nôtre ne nettoyait que les requêtes préparées. Tout le
reste de l'état de session — variables, LISTEN, tables TEMP, et le rôle
courant — traversait la déconnexion et tombait dans les mains du client suivant.
CE QUI A ÉTÉ MESURÉ, PAS SUPPOSÉ
pgbouncer 1.25.2 (la version qui tourne), monté avec NOTRE configuration :
`pool_mode = session`, `server_reset_query = DEALLOCATE ALL`,
`server_reset_query_always = 1`, `default_pool_size = 1`. Le client 1 pose son
état puis se déconnecte ; le client 2, qui n'a rien demandé, arrive.
DEALLOCATE ALL (l'existant) client 2 hérite : work_mem=17MB, 1 LISTEN,
la table TEMP du client 1, et son SET ROLE —
au point de créer des tables appartenant à un
rôle qui n'est pas le sien.
DISCARD ALL (ce commit) client 2 obtient work_mem=4MB, 0 LISTEN, pas
de table TEMP, et son PROPRE rôle.
POURQUOI `DISCARD ALL` NE PEUT RIEN CASSER
C'est le défaut de pgbouncer, et un sur-ensemble STRICT des deux valeurs qui
l'ont précédé ici : il contient `DEALLOCATE ALL` — donc le correctif crowdsec de
|
||
|
|
2cb19809c6 |
doc(reseau) — le confort LAN ne se règle pas dans Traefik : mesure, pièges, voie retenue
Demande : « ne pas avoir le basic auth Traefik quand on est sur le Wi-Fi partagé avec le homelab ». La réponse intuitive — une règle `ClientIP(192.168.1.0/24)` — ne peut pas marcher, et la variante « je regarde CF-Connecting-IP » est un contournement d'authentification. Ce commit écrit la mesure pour qu'on ne re-découvre ni l'une ni l'autre. Mesuré (2026-07-28, homelab) : - `kadans.arcodange.fr` résout vers Cloudflare MÊME depuis le LAN, et redescend par le tunnel cloudflared. L'adresse de socket vue par Traefik est donc toujours celle d'un pod, en 10.42.x.x. - Traefik SAIT qui est le vrai client (journal d'accès : l'IPv6 de la maison, `2a01:cb04:dff:cf00::/64` — pas l'IPv4 qu'`ipify` injecte dans `localIp`), car l'entrypoint `web` fait confiance aux en-têtes venant de 10.42.0.0/16. - Mais le matcher de routeur `ClientIP()`, lui, juge la SOCKET. Prouvé par trois routeurs temporaires vers un Service sans endpoint (503 = règle matchée, 401 = repli sur le routeur normal) : témoin 503, `ClientIP(<IPv6 maison>)` 401, `ClientIP(10.42.0.0/16)` 503. Sondes retirées après mesure. D'où deux pièges, écrits là où on les rencontrerait : - `localIp@file` sur un routeur `.fr` laisserait entrer Internet entier, parce que `10.42.0.0/16` est dans son `sourceRange` et qu'`ipAllowList` juge lui aussi la socket. Vérifié : aucun routeur `.fr` ne le porte aujourd'hui — le piège est latent, et les cinq endroits d'où on pourrait le recopier (2 gabarits `.fr`, 3 values `.lab`) portent désormais l'avertissement. - Un en-tête posé par le client ne peut pas piloter une exemption d'auth : Cloudflare ne retire pas les en-têtes inconnus, et Traefik reste joignable en direct sur 192.168.1.201. Voie retenue, et pourquoi celle-là : la décision « suis-je à la maison ? » doit être prise là où la vraie IP est native et non falsifiable, donc au bord, chez Cloudflare. Une règle de transformation y pré-remplit l'en-tête `Authorization` pour les IP du foyer. Traefik ne bouge pas, aucun certificat public à produire, aucun changement DNS. Surface d'attaque ajoutée : AUCUNE — `kadans:kkadans` est déjà en clair dans le chart de kadans, Cloudflare ne fait que le taper à notre place. Et quand l'IP du foyer dérive, la règle cesse de matcher : le navigateur redemande le mot de passe. Dégradation douce, pas de panne. Le doc écrit l'action Cloudflare mot pour mot (expression, en-tête, valeur, et l'équivalent Terraform pour `cms/cloudflare`) plutôt que de la supposer faite, avec les deux commandes qui la vérifient — et nomme le repli si Cloudflare refuse de modifier `Authorization` : Cloudflare Access avec une politique de bypass, PAS un en-tête secret. Enfin, un contre-exemple utile : le bouncer CrowdSec, lui, juge la VRAIE IP (journal à l'appui). Son `clientTrustedIPs` contient `10.42.0.0/16` sans que ce soit un trou — noté pour que personne ne « corrige » cette ligne en croyant y reproduire le piège. ⚠ Aucun des réglages en cause ne vit dans ce dépôt : les valeurs Helm de Traefik, `dynamic.yaml`/`localIp` et le Middleware crowdsec sont dans `factory` (ansible), le tunnel et le DNS dans `cms`. Ce dépôt reçoit la mesure et les garde-fous parce que c'est lui qui héberge les gabarits `.fr` et les consommateurs de `localIp@file`. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01GdUCA5Uz8QyMwa2P4Pg2hK |
||
|
|
9de9a9663b | Merge pull request 'ci — arrêter les runs qui ne peuvent pas aboutir, et le doublon push+PR' (#23) from arcodange/moins-de-runs-inutiles into main | ||
|
|
2bdc486ae6 |
ci — arrêter les runs qui ne peuvent pas aboutir, et le doublon push+PR
Quatre runs d'une branche déjà mergée ont bloqué, ce matin, l'apply qu'on attendait. Deux causes, indépendantes : 1. Les workflows tofu (minio, vault, crowdsec, plausible) s'authentifient à Vault par un flux OIDC dont un HUMAIN doit ouvrir le lien. Déclenchés tout seuls, ils ne peuvent qu'occuper un runner jusqu'au timeout. Ils font en plus `apply` en `auto_approve` CONTRE LA PROD : partir sur le push d'une branche, c'est appliquer du code que personne n'a relu. → `workflow_dispatch` seul, ce qui écrit enfin ce qu'ils faisaient déjà. (crowdsec et plausible passaient de toute façon par une ancre YAML, donc leurs triggers étaient INERTES — issues 113 → 117 de kadans.) 2. `push` sur toutes les branches + `pull_request` = DEUX runs par commit dès qu'une branche a une PR. Vérifié : runs 258/259 et 260/261 portent le même SHA. helmcharts, qui travaille seul et mérite de rester automatique, prend la forme éprouvée de la CI de kadans : push sur `main`, PR pour la branche. Chaque clé de trigger porte un corps explicite : un `pull_request:` nu n'est pas une forme éprouvée ici, et son mode d'échec est le silencieux. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
901aa9a9dc |
Merge pull request 'fix(minio) — le provisionneur ne pouvait pas créer de bucket : s3:ListBucket manquait' (#22) from arcodange/provisioner-listbucket into main
Helm Charts / Detect changed charts (push) Successful in 1m0s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
MinIO / Auth with gitea for vault (push) Successful in 23s
MinIO / Tofu - minio IAC (push) Successful in 49s
|
||
|
|
e8ab19962b |
fix(minio) — le provisionneur ne pouvait pas créer de bucket : s3:ListBucket manquait
Helm Charts / Detect changed charts (push) Successful in 15s
Helm Charts / Detect changed charts (pull_request) Successful in 16s
Helm Charts / Library charts tool (push) Has been skipped
MinIO / Auth with gitea for vault (push) Failing after 8m31s
MinIO / Tofu - minio IAC (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Le premier apply réel (kadans) a créé la politique, le compte de service,
l'attachement et le secret Vault — puis a échoué sur le bucket lui-même :
Error: [FATAL] unable to check bucket (kadans-videos): Access Denied.
Le provider teste l'existence du bucket AVANT de le créer (HeadBucket), et
MinIO exige `s3:ListBucket` pour ça. C'est le seul point que l'ADR annonçait
comme non éprouvé ; il l'est maintenant.
`s3:ListBucket` donne la vue des CLÉS d'un bucket, pas leur contenu :
GetObject / PutObject restent absents, donc le provisionneur — partagé entre
les rôles CI — ne peut toujours pas lire les vidéos d'une autre application.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
|
||
|
|
5c7dce96e1 |
Merge pull request 'feat(minio) — un compte de service par app consommatrice, borné à son bucket' (#21) from arcodange/minio-comptes-de-service into main
Helm Charts / Detect changed charts (push) Successful in 19s
Hashicorp Vault / Auth with gitea for vault (push) Successful in 2m58s
MinIO / Auth with gitea for vault (push) Successful in 5m52s
Helm Charts / Library charts tool (push) Has been skipped
Hashicorp Vault / Tofu - Vault IAC (push) Successful in 53s
MinIO / Tofu - minio IAC (push) Successful in 33s
Helm Charts / Application charts pgcat (push) Has been skipped
|
||
|
|
7074a94d7e |
docs(minio) — le raisonnement part dans l'ADR, le code garde ce qui protège
Helm Charts / Detect changed charts (push) Successful in 22s
Helm Charts / Detect changed charts (pull_request) Successful in 16s
MinIO / Auth with gitea for vault (push) Failing after 8m33s
MinIO / Tofu - minio IAC (push) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m31s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Les décisions de conception (qui déclare, qui détient, pourquoi les octets ne passent pas par l'API) vivent désormais dans `factory/doc/adr/20260726-stockage-objet-minio.md`. Le code ne garde que ce qu'un relecteur ne peut pas deviner et qui l'empêcherait de casser quelque chose : l'absence VOLONTAIRE de s3:GetObject/PutObject dans la politique du provisionneur, l'absence VOLONTAIRE de basic-auth sur l'ingress S3, le caractère inconditionnel de la règle Vault, et l'avertissement sur les noms d'actions MinIO non éprouvés. Chaque fichier pointe l'ADR. 283 → 230 lignes sur minio/iac. tofu fmt propre, tofu validate réussi sur les deux racines. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
ec71571b98 |
refactor(minio) — chacun son périmètre : les buckets se déclarent depuis le dépôt de l'app
Helm Charts / Detect changed charts (push) Successful in 16s
Helm Charts / Detect changed charts (pull_request) Successful in 16s
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
MinIO / Auth with gitea for vault (push) Failing after 8m31s
MinIO / Tofu - minio IAC (push) Has been skipped
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
Hashicorp Vault / Auth with gitea for vault (push) Has been cancelled
Hashicorp Vault / Tofu - Vault IAC (push) Has been cancelled
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Les buckets sont à déclarer dans le repo de kadans-api. On ne va pas modifier le repo tools à chaque changement d'application. Chacun son périmètre. Tools peut proposer un module pour standardiser la déclaration de buckets à la limite, mais c'est tout. » (fondateur, 26/07) C'est une erreur de fond de ma part : j'avais fait de `tools` le PROPRIÉTAIRE de déclarations qui appartiennent aux applications. À ce rythme, chaque nouveau bucket de n'importe quelle app devenait une PR sur l'infra partagée. CE QUI CHANGE. `consumers.tf` disparaît, et la liste de buckets du chart se vide. À la place, un module réutilisable `iac/modules/minio_app` : une app lui donne son nom et ses buckets, et reçoit des buckets privés, un compte de service qui ne peut rien toucher d'autre, et ses clés dans `kvv2/minio/<app>`. L'OBSTACLE, ET SA RÉPONSE. Déclarer ses buckets depuis son propre dépôt suppose des droits d'ADMINISTRATION sur MinIO. Confier le root serait absurde : il lit et écrit tous les objets de toutes les apps. `tools` fournit donc un compte PROVISIONNEUR aux droits minimaux — créer un bucket, une politique, un compte de service — et AUCUN droit sur les objets. Une app compromise pourrait créer des buckets (une nuisance), pas lire les vidéos d'une autre. Le root, lui, ne sort toujours pas de ce pipeline. Le rôle CI de chaque app gagne la lecture de `kvv2/data/minio/provisioner` dans `app_policy` — générique, et c'est exactement le genre de standardisation qui appartient au dépôt commun. ⚠ CE QUE JE N'AI PAS PU PROUVER : les noms d'actions d'administration MinIO de la politique du provisionneur viennent de la documentation, pas d'un essai — je n'ai pas d'identifiants admin en main. Le premier `apply` les confirmera ou les corrigera. C'est le seul point non vérifié de cette PR, et il est signalé dans le code à l'endroit exact. tofu fmt propre · tofu validate réussi sur minio/iac ET hashicorp-vault/iac. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
0e1b6e1062 |
refactor(minio) — lever la restriction « un seul bucket par app »
Helm Charts / Detect changed charts (pull_request) Successful in 17s
Helm Charts / Detect changed charts (push) Successful in 16s
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been cancelled
Helm Charts / Library charts tool (push) Has been cancelled
MinIO / Tofu - minio IAC (push) Has been cancelled
MinIO / Auth with gitea for vault (push) Has started running
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Pourquoi sommes-nous restreints sur les buckets ? » (fondateur, 26/07) — parce
que JE l'avais décidé, pour rendre tout dérivable d'un seul nom. Rien ne
l'imposait, et la restriction aurait mordu au pas suivant : l'ADR-018 de Kadans
prévoit DEUX paliers de transfert (aperçu 240p régénérable, travail 360p à
garder), donc deux cycles de vie, donc potentiellement deux buckets aux
politiques de purge différentes.
Chaque bucket déclare désormais son app (`app: kadans`). C'est toujours la SEULE
déclaration, au même endroit — mais le nom du bucket redevient libre, et
`kadans-videos` retrouve un nom qui dit ce qu'il contient.
Le compte de service devient par APP et non par bucket : une seule clé, autorisée
sur tous ses buckets et eux seuls. Ajouter un bucket à une app existante ne crée
donc aucune nouvelle clé — le compte existant gagne l'accès. Le secret porte
`MINIO_BUCKETS` (tous) en plus de `MINIO_BUCKET` (le premier), pour que l'app
n'ait pas à les redéclarer de son côté.
Un bucket sans `app:` est ignoré plutôt que de faire échouer le plan : il n'aura
simplement pas de compte de service, ce qui se voit immédiatement et ne casse
rien d'existant.
Vérifié sur le VRAI fichier, pas en théorie : le groupement rend bien
{"kadans" = ["kadans-videos"]}, et avec un second bucket de la même app,
{"kadans" = ["kadans-videos", "kadans-apercus"]} — le cas ADR-018 exact.
tofu fmt propre, tofu validate réussi.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
|
||
|
|
287e3dcf1e |
refactor(minio) — le BUCKET est la seule déclaration : plus de liste à tenir
Helm Charts / Detect changed charts (push) Successful in 14s
Helm Charts / Detect changed charts (pull_request) Successful in 14s
Helm Charts / Application charts pgcat (push) Has been cancelled
Helm Charts / Library charts tool (push) Has been cancelled
MinIO / Tofu - minio IAC (push) Has been cancelled
MinIO / Auth with gitea for vault (push) Has been cancelled
MinIO / Auth with gitea for vault (pull_request) Failing after 8m31s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« Je ne vois pas le mal à donner la permission de lire sur un chemin qui n'existe pas. Je préfère ne pas m'embêter avec consumers ou autre. » (fondateur, 26/07) `var.consumers` disparaît. Le plan LIT `values.yaml` du chart — le même fichier qu'Helm consomme — et provisionne un compte de service par bucket. Créer un bucket EST la déclaration : il devient impossible d'avoir un bucket sans son compte, ou un compte sans son bucket. Une liste de plus aurait été une liste à tenir synchronisée, donc une liste à oublier. La convention qui rend ça possible : UN BUCKET PAR APP, NOMMÉ COMME ELLE. Le bucket passe donc de `kadans-videos` à `kadans`. Il est VIDE aujourd'hui — le renommer maintenant ne coûte rien ; dans un mois ce serait une migration. Tout en découle sans être écrit ailleurs : le compte `<app>-app` borné à ce seul bucket, le secret `kvv2/minio/<app>`, et la lecture que `app_policy` accorde déjà à toute app sur `kvv2/data/minio/<son nom>`. Vérifié plutôt que supposé : `yamldecode` lit bien ce values.yaml, ancres YAML comprises (testé en isolation avant d'écrire le plan). tofu fmt propre, tofu validate réussi. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
91a0f09b49 |
refactor(vault) — lire ses identifiants MinIO devient une propriété de la plateforme
Helm Charts / Detect changed charts (pull_request) Successful in 15s
Helm Charts / Detect changed charts (push) Successful in 15s
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m35s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m36s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Retour fondateur : « je pensais que tools#21 contribuerait à app_policy pour une policy kvv2/minio/<app name> ». Il a raison, et mon choix initial était le plus faible des deux. Mon objection — ne donner le droit qu'aux apps qui en ont besoin — ne tient pas à l'examen : la règle porte le NOM de l'app, donc elle ne peut jamais exposer que ses propres clés. Il n'y a aucun privilège à préserver. Une app qui ne stocke rien lit un chemin qui n'existe pas : une règle inerte, pas un droit. Son argument, lui, porte : savoir lire ses propres identifiants de stockage est une propriété de la PLATEFORME, pas une exception par application. Et `kv_read_paths` est documenté comme la trappe pour un secret appartenant à une AUTRE app (les creds GCS de Longhorn pour l'ERP) — y ranger un motif standard l'aurait rendu invisible et aurait obligé à le redéclarer à chaque app. La règle passe donc dans `app_policy`, en prod ET pour chaque instance non-prod (symétrie stricte), sur deux chemins : le document `kvv2/data/minio/<app>` et ses descendants. Un cran plus loin que la demande : la règle est INCONDITIONNELLE, sans drapeau. Conséquence — déclarer un consommateur MinIO se fait désormais à UN SEUL endroit, `var.consumers` du pipeline minio. Aucune synchronisation à tenir entre deux fichiers, donc rien à oublier. Le `kv_read_paths` que j'avais ajouté à kadans est retiré : il faisait double emploi. tofu fmt propre · tofu validate réussi sur hashicorp-vault/iac. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
4ca4a05370 |
feat(minio) — un compte de service par app consommatrice, borné à son bucket
Helm Charts / Detect changed charts (push) Successful in 57s
MinIO / Auth with gitea for vault (push) Failing after 8m34s
MinIO / Tofu - minio IAC (push) Has been skipped
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m33s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 1m1s
Helm Charts / Library charts tool (push) Has been cancelled
Helm Charts / Application charts pgcat (push) Has been cancelled
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
MinIO / Tofu - minio IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m32s
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
« On peut adopter ce pattern à toutes les apps qui pourraient avoir besoin de MinIO, et ainsi modifier les app roles / app policy générique. » (fondateur, 26/07) Bonne nouvelle : les modules centraux n'ont PAS eu à changer. `kv_read_paths` existe déjà dans `app_policy` et fait exactement ça — l'ERP s'en sert pour lire les creds GCS de Longhorn. Le motif générique était donc à moitié construit ; il manquait la moitié MinIO. CE QUI EST AJOUTÉ : `minio/iac/consumers.tf` provisionne, pour chaque app déclarée dans `var.consumers`, une politique MinIO bornée à SON bucket (GetObject/PutObject/DeleteObject sur les objets, ListBucket sur le bucket seul — ni les autres buckets, ni l'administration), un compte de service, et écrit ses clés dans `kvv2/minio/<app>`. POURQUOI LES CLÉS VIVENT CHEZ MINIO ET PAS CHEZ L'APP : seul ce pipeline possède les identifiants ROOT. Si chaque app créait son propre compte de service, il faudrait donner ce root à chaque rôle CI — c'est-à-dire à tout le monde. Ici il ne sort jamais d'ici, et l'app ne reçoit qu'une clé qui ne peut rien lire d'autre que son bucket. Un compte de service qui fuite ne donne accès qu'aux objets qu'il gérait déjà. Ajouter une app = trois lignes déclaratives, documentées au README : son bucket dans values.yaml, son entrée dans `var.consumers`, son `kv_read_paths` au tfvars central. Aucun module à toucher. Le provider parle à `s3.arcodange.fr` — l'endpoint PUBLIC, parce que le runner CI n'est pas dans le LAN et que `.lab` ne s'y résout pas. C'est l'exposition HTTPS mergée ce matin qui rend ce plan applicable. ⚠ Erreur attrapée par le validateur, et corrigée : je relisais `kvv2/minio/config` alors que `local.config` de main.tf porte déjà les identifiants root — une lecture qui aurait créé une dépendance circulaire avec l'écriture faite par ce même plan. Vérifié : `tofu fmt` propre, `tofu validate` réussi (avec TERRAFORM_VAULT_AUTH_JWT posé — sans lui, le provider Vault échoue déjà sur main, ce n'est pas mon fait). Je n'ai lancé AUCUN apply : c'est le workflow qui le fera, et la revue t'appartient. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
f49a79e393 |
Merge pull request 'feat(minio) — exposer l'API S3 en HTTPS public (s3.arcodange.fr) + CORS de la PWA' (#20) from arcodange/minio-public-fr into main
Reviewed-on: #20 |
||
|
|
1490f4c514 |
feat(minio) — exposer l'API S3 en HTTPS public (s3.arcodange.fr) + CORS de la PWA
Helm Charts / Detect changed charts (push) Successful in 1m6s
Helm Charts / Detect changed charts (pull_request) Successful in 1m5s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Sans ça, la synchronisation des vidéos ne peut pas marcher, et ce sont des faits du navigateur : une page servie en https ne peut pas émettre de requête vers http:// (contenu mixte), et `.lab` n'est pas résolvable hors du LAN. L'ingress existant est en entrypoint `web` sans TLS, sur un domaine interne — donc inutilisable depuis kadans.arcodange.fr, en déplacement COMME à la maison. Même motif que grafana/templates/ingress-public.yaml : entrypoint `web`, TLS terminé par le tunnel Cloudflare (wildcard *.arcodange.fr), middleware crowdsec. Le `.lab` interne reste inchangé. PAS de basic-auth, contrairement à kadans-public : une requête S3 porte sa propre signature (SigV4), et un défi HTTP Basic casserait le PUT présigné auquel le navigateur ne peut pas répondre. L'autorisation vient de l'URL signée et de sa durée de vie courte. CORS déclaré sur les origines EXACTES de la PWA (.fr et .lab), jamais « * » : une URL présignée qui fuiterait serait sinon rejouable depuis n'importe quel site. Sans cette liste, le préflight OPTIONS échoue et le PUT ne part même pas. ⚠ Signalé, NON mesuré : le tunnel Cloudflare plafonne probablement le corps d'une requête (~100 Mo sur les offres gratuites). À éprouver avec un vrai téléversement. Contexte utile : sur le corpus réel du fondateur (707 vidéos, ~2 ans), la durée MOYENNE est de 53 s et deux vidéos seulement dépassent 5 min — au palier « travail » de l'ADR-018, 100 Mo valent ~29 min de cours. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
dce19141a8 |
Merge pull request 'fix(minio) — déclarer minio dans la liste centrale des applications Vault' (#19) from claude/minio-role into main
Helm Charts / Detect changed charts (push) Successful in 29s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Hashicorp Vault / Auth with gitea for vault (push) Successful in 1m28s
Hashicorp Vault / Tofu - Vault IAC (push) Successful in 1m19s
Reviewed-on: #19 |
||
|
|
d146affbcd |
fix(minio) — déclarer minio dans la liste centrale des applications Vault
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Detect changed charts (push) Successful in 1m6s
Helm Charts / Detect changed charts (pull_request) Successful in 24s
Hashicorp Vault / Auth with gitea for vault (push) Failing after 8m38s
Hashicorp Vault / Tofu - Vault IAC (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Library charts tool (push) Has been skipped
Hashicorp Vault / Tofu - Vault IAC (pull_request) Has been skipped
Hashicorp Vault / Auth with gitea for vault (pull_request) Failing after 8m40s
Helm Charts / Application charts pgcat (push) Has been skipped
CI en échec sur le workflow MinIO : role "gitea_cicd_minio" could not be found. Diagnostic : les rôles CI gitea_cicd_<app> ne naissent PAS dans l'IaC de l'application — ils viennent du module app_policy, appliqué centralement par hashicorp-vault/iac pour chaque entrée de terraform.tfvars. J'avais posé minio/iac (qui s'authentifie AVEC ce rôle) sans alimenter la liste : le run tentait donc de s'authentifier avec un rôle que personne n'avait créé. Amorçage circulaire, entièrement de mon fait. - hashicorp-vault/iac/terraform.tfvars : minio ajouté aux applications, avec service_account_namespaces = ["tools"] comme crowdsec et plausible ; - .gitea/workflows/vault.yaml : les triggers couvrent désormais *.tfvars en plus de *.tf. C'est là que vit la liste des applications : sans ça, ajouter une app ne déclenchait jamais la création de son rôle — le piège qui vient de mordre. Les ancres YAML des triggers sont retirées au passage (une ancre dans un trigger Gitea Actions fait taire push ET pull_request en silence, vécu sur arcodange/kadans, issues 113→117 ; c'est probablement pourquoi ce workflow ne partait qu'à la main) ; - minio/README.md : l'ordre de mise en service dit maintenant les DEUX étapes et nomme l'erreur exacte à laquelle on s'expose en les inversant. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
2202e7bbfe |
Merge pull request 'feat(minio) — stockage objet S3 du homelab (brique partagée de tools)' (#18) from claude/minio into main
MinIO / Auth with gitea for vault (push) Successful in 43s
MinIO / Tofu - minio IAC (push) Failing after 13s
Helm Charts / Detect changed charts (push) Successful in 1m3s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Reviewed-on: #18 |
||
|
|
84edfc8640 |
feat(minio) — stockage objet S3 du homelab (brique partagée de tools)
Helm Charts / Detect changed charts (push) Successful in 16s
Helm Charts / Detect changed charts (pull_request) Successful in 15s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
MinIO / Tofu - minio IAC (pull_request) Has been skipped
MinIO / Auth with gitea for vault (pull_request) Failing after 8m32s
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Le fondateur : « on déploie MinIO dans le repo tools du homelab non ? » — oui, c'est bien le pattern : le dossier tools/ porte les briques PARTAGÉES (pgbouncer, clickhouse, grafana…) et le namespace tools les fait tourner ; les charts applicatifs vivent dans le repo de leur app. Décidé de longue date côté produit, jamais déployé : ADR-012 « MinIO local d'abord » (bascule R2 à 100+ utilisateurs / 10 To par mois), ADR-013 (le gratuit reste local-first, MinIO sert les paliers payants). Vérifié avant d'écrire : aucun pod ni service MinIO dans le cluster. Le chart suit la recette du repo (dépendance à la library "tool" + chart amont en SubChart, deux gardes dans templates/) : - mode STANDALONE, 1 réplique : ce qui transite est DÉRIVÉ (le master d'une vidéo reste sur l'appareil de son propriétaire, ADR-018) et Longhorn réplique déjà le volume — l'erasure coding distribué coûterait de la RAM que des Pi 5 n'ont pas à dépenser pour ça ; - 50 Gi sur longhorn ≈ 250 h de cours au palier « travail » (360p, 3,4 Mo/min) ; ⚠ Longhorn réplique : compter ×3 sur la capacité avant d'augmenter ; - ressources bornées (512 Mi / 2 Gi) : la limite protège les voisins de tools ; - API s3.arcodange.lab + console minio.arcodange.lab (Traefik) ; - bucket kadans-videos PRIVÉ — l'accès passera par des URL signées (ADR-0002) ; - identifiants JAMAIS au dépôt : iac/ les génère dans Vault (kvv2/minio/config), le Vault Secrets Operator les matérialise, le chart les lit via existingSecret. Le SA du pod est nommé "minio" (pas le "minio-sa" amont) car le module app_roles borne l'authentification au SA portant le nom de l'app. ⚠ Le workflow minio.yaml écrit ses triggers EN TOUTES LETTRES : une ancre YAML dans un trigger Gitea Actions fait taire push ET pull_request en silence (vécu sur arcodange/kadans, issues 113→117). Les workflows plausible/crowdsec/vault de ce repo en utilisent encore — à vérifier séparément, c'est probablement pourquoi ils ne partent qu'à la main. Vérifié : helm dependency update + helm template (11 ressources rendues, SA et VaultAuth cohérents) + helm lint ✓. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA |
||
|
|
342c4ab346 |
Merge pull request 'feat(grafana): exposer grafana.arcodange.fr via le tunnel Cloudflare (pattern kadans)' (#16) from arcodange/grafana-fr into main
Reviewed-on: #16 |
||
|
|
5fbc7f6ff8 |
feat(grafana): exposition publique grafana.arcodange.fr via le tunnel (pattern kadans)
Helm Charts / Detect changed charts (push) Successful in 17s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 23s
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Second Ingress (grafana-public) en PLUS du .lab, comme kadans : - entrypoint `web` — TLS terminé en amont par le tunnel Cloudflare (wildcard *.arcodange.fr → traefik:80, rien à changer côté cms/cloudflare) ; - middleware crowdsec (convention .fr) ; - pas de basic-auth : Grafana a sa propre authentification (aucun accès anonyme dans grafana.ini), contrairement à kadans qui est ouvert. Le .lab garde son localIp@file ; rendu par le wrapper SubChart et appliqué par ArgoCD (précédent : prometheus/templates/vault-telegram.yaml). Co-Authored-By: Claude Fable 5 <[email protected]> |
||
|
|
bbf6653464 | Merge pull request 'feat(observabilité) — jobs d'analyse Kadans : scrape du worker laptop + dashboard Grafana' (#15) from arcodange/observabilite-kadans into main | ||
|
|
347ebee1b0 |
feat(observabilité) — jobs d'analyse Kadans : scrape du worker LAPTOP + dashboard Grafana
Helm Charts / Detect changed charts (push) Successful in 1m10s
Helm Charts / Detect changed charts (pull_request) Successful in 1m1s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
- prometheus : cible statique kadans-worker-mac (192.168.1.103:9105, tier laptop). Un scrape raté n'est PAS un incident : le Mac dort, up==0 raconte la latence — ne pas alerter dessus. ⚠ réserver l'IP au routeur (DHCP). - grafana : provider + dashboard « Kadans — jobs d'analyse » (uid kadans-jobs-analyse) : worker en écoute / dernier poll / file pending + âge du plus ancien (seuils 1 h / 24 h = le SLO), file par statut et publications par issue (couleurs de STATUT sémantiques), lanes exécutées et durée moyenne par lane. La façade, elle, arrive par les annotations de son pod (kadans-jobs#3) — zéro config ici. Co-Authored-By: Claude Fable 5 <[email protected]> |
||
|
|
53710d9fde |
Merge pull request 'feat(alerting): 5e règle homelab — CertificatNonRenouvele, le mode de panne du 24/07 au matin' (#14) from arcodange/homelab-alerts-cert into main
Reviewed-on: #14 |
||
|
|
6f398f4ddc |
feat(alerting): 5e règle homelab — CertificatNonRenouvele (<4 h restantes)
Helm Charts / Detect changed charts (pull_request) Successful in 22s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Detect changed charts (push) Successful in 1m8s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Les 4 premières règles n'auraient rien vu le matin du 2026-07-24 : nœuds up, traefik up… mais wildcard 24 h expiré (renouvellement en échec silencieux depuis des heures). certmanager_certificate_expiration_timestamp_seconds est déjà scrapée (vérifié live : 2 séries). Cert-manager renouvelle à ~16 h d'âge ; <4 h restantes = plusieurs cycles ratés → critical, 15 min de grâce. Co-Authored-By: Claude Fable 5 <[email protected]> |
||
|
|
ffce6990a3 |
Merge pull request 'feat(alerting): groupe homelab — être prévenu sur Telegram quand (ou juste avant que) le lab tombe' (#13) from arcodange/homelab-alerts into main
Reviewed-on: #13 |
||
|
|
b9626d878b |
feat(alerting): groupe homelab — alerté quand (ou juste avant que) le lab tombe
Helm Charts / Detect changed charts (pull_request) Successful in 2m2s
Helm Charts / Detect changed charts (push) Successful in 10m9s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Incident 2026-07-23 : un build CI sans limites a épuisé la RAM de pi1 (0 swap), load15 >100, traefik + apiserver affamés → tout *.arcodange.lab injoignable, Gitea compris (pourtant sain sur pi2). Personne n'est prévenu : on subit. Quatre règles, livrées par la chaîne Telegram déjà en place (testée live) : - NoeudInjoignable (critical) : node-exporter muet 3 min — nœud down ou noyé. - IngressLabIndisponible (critical) : 0 replica traefik dispo, ou métrique absente (kube-state-metrics vit sur pi1) — *.arcodange.lab est HS. - NoeudPressionMemoire (warning) : <500 Mo dispo 5 min — le précurseur exact de l'incident, déclenche avant le thrash. - NoeudEnSurcharge (warning) : load15 >8 pendant 10 min. Exprs validées contre le Prometheus live (parse + match) : pendant la rédaction, IngressLabIndisponible et NoeudEnSurcharge matchaient l'incident en cours. Prometheus (pi3) et Alertmanager (pi2) survivent à la perte de pi1. Co-Authored-By: Claude Fable 5 <[email protected]> |
||
|
|
bc62304bc3 | Merge pull request 'fix(alerting): alerte fiable sur l'échec de la vidéo quotidienne du brief' (#12) from arcodange/alert-brief-video into main | ||
|
|
8e236230d3 |
fix(alerting): alerte fiable sur l'échec de la vidéo quotidienne du brief
Helm Charts / Detect changed charts (push) Successful in 2m50s
Helm Charts / Detect changed charts (pull_request) Successful in 18s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
ProspectionBriefNotSent (pushed==0, severity info) ne couvrait que la
livraison et déclenchait à tort quand l'étape brief était volontairement
sautée (metrics.py émet brief_rendered=0 aussi sur skip — seul
step_status{step="brief"} distingue skip(2) d'erreur(0)).
Remplacé par deux règles warning, gardées contre le skip :
- ProspectionBriefFailed : rendered==0 AND step_status{brief}!=2 → la
PRODUCTION de la vidéo a échoué (TTS/ffmpeg/PIL ou erreur amont) ;
- ProspectionBriefNotSent : pushed==0 AND rendered==1 → vidéo produite
mais PAS livrée sur Telegram (token/chat_id/API).
Expressions validées en live sur Prometheus (match on(job) prouvé par
requête témoin, les deux exprs vides sur l'état sain du jour). En-tête du
groupe mis à jour : la livraison AM→Telegram est câblée et testée.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
||
|
|
65ff6fcc34 | feat: ajouter kadans à vault | ||
|
|
ef9e6c62c2 | Merge pull request 'feat(grafana): complète le dashboard de monitoring du pipeline prospection' (#11) from arcodange/prospection-grafana-dashboard into main | ||
|
|
4133396720 |
feat(grafana): complète le dashboard de monitoring du pipeline prospection
Helm Charts / Detect changed charts (push) Successful in 1m0s
Helm Charts / Detect changed charts (pull_request) Successful in 44s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Aligne le dashboard « Prospection — pipeline BI missions » sur le cahier
des charges de supervision :
- jauge 0–100 pour le meilleur score d'opportunité (au lieu d'une stat)
- nouvelle stat « Offres du brief » (prospection_brief_offres)
- bar charts « Durée par étape » et « Items par étape » sur le dernier run
(prospection_step_duration_seconds / prospection_step_items)
- cadence quotidienne : refresh 30m et plage par défaut now-7d
Provisionné via le provider Grafana « prospection » (JSON inline dans
grafana/values.yaml), datasource Prometheus (${DS_PROMETHEUS}).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
||
|
|
5fae1f31db | Merge pull request 'fix(alerting): VaultAuth Telegram exige vaultConnectionRef dans le ns tools' (#10) from arcodange/am-telegram-fix into main | ||
|
|
4005d89c0c |
fix(alerting): VaultAuth Telegram exige vaultConnectionRef dans le ns tools
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Detect changed charts (push) Successful in 16s
Helm Charts / Detect changed charts (pull_request) Successful in 15s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
VSO refuse un VaultAuth sans vaultConnectionRef dans le ns tools (« vaultConnectionRef must be set on resources in the "tools" namespace »), contrairement au ns prospection qui hérite d'une connexion par défaut. On référence la VaultConnection `default` déjà présente dans tools. Sans ça, le Secret alertmanager-telegram n'est jamais synchronisé et le pod Alertmanager reste bloqué sur le montage manquant. Co-Authored-By: Claude Opus 4.8 <[email protected]> |
||
|
|
7a8c8537a5 | Merge pull request 'feat(alerting): livraison Telegram des alertes via Alertmanager' (#9) from arcodange/am-telegram into main | ||
|
|
714e2bc2ab |
feat(alerting): livraison Telegram des alertes via Alertmanager
Helm Charts / Detect changed charts (push) Successful in 14s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 14s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Les règles d'alerte `prospection` s'évaluaient déjà dans Prometheus mais ne notifiaient nulle part. On câble Alertmanager pour livrer les alertes sur le bot Telegram de prospection, via `telegram_configs` natif d'Alertmanager. - iac Vault : policy read-only `alertmanager-telegram` sur kvv2/data/prospection/telegram + rôle k8s `alertmanager` (SA prometheus-alertmanager, ns tools). - VSO : VaultAuth + VaultStaticSecret resynchronisent kvv2/prospection/telegram vers un Secret `alertmanager-telegram` dans le ns tools (le Secret prospection est namespace-scoped, non réutilisable). rolloutRestartTargets sur le StatefulSet Alertmanager. - prometheus values : lien server -> Alertmanager (prometheus-alertmanager:9093), route + receiver `telegram` (bot_token_file monté, chat_id inline, parse_mode HTML, send_resolved), et montage du Secret via extraSecretMounts. Additif : ni grafana ni les règles d'alerte existantes ne sont touchés. Co-Authored-By: Claude Opus 4.8 <[email protected]> |
||
|
|
1eabae6936 | Merge pull request 'fix(grafana): startupProbe pour les migrations SQLite (CrashLoop au rollout)' (#8) from arcodange/grafana-startupprobe into main | ||
|
|
e419cb6307 |
fix(grafana): startupProbe + liveness grace pour les migrations SQLite
Helm Charts / Detect changed charts (push) Successful in 24s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 17s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Grafana tourne en SQLite sur emptyDir → migration complète du schéma à chaque démarrage de pod, > 160 s sur Raspberry Pi. La liveson (initialDelay 60 + 10×10s) tuait Grafana en pleine migration → CrashLoop du nouveau pod à chaque rollout (révélé par le rollout du dashboard prospection). Ajoute une startupProbe (~10 min) et relève failureThreshold de la liveness (filet si le chart n'expose pas startupProbe). Co-Authored-By: Claude Opus 4.8 <[email protected]> |
||
|
|
e9998e3b48 | Merge pull request 'feat(monitoring): dashboard Grafana + alertes prospection' (#7) from arcodange/prospection-monitoring into main | ||
|
|
e6fca752a2 |
feat(monitoring): dashboard Grafana + règles d'alerte prospection
Helm Charts / Detect changed charts (push) Successful in 22s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 21s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Consomme les métriques poussées par le pipeline prospection au Pushgateway (job=prospection, déjà scrapé). Additif — n'affecte aucun dashboard existant. - grafana : provider + dashboard « Prospection — pipeline BI missions » inliné (grafana.dashboards.prospection, json) — vue d'ensemble (fraîcheur/statut/durée/ erreurs/missions/score), collecte par étape (table + historique), modèle de données (opportunités A/B, offres/entités), livraison (brief/Telegram) + panneau Alertes actives. Inline plutôt que ConfigMap externe : grafana est déployé via un HelmChart CRD (tool lib), l'inline évite toute hypothèse de namespace. - prometheus : groupe d'alertes `prospection` (serverFiles.alerting_rules.yml) — RunStale (>25h), RunFailed, StepError, NoOffers, BriefNotSent. NB : la livraison des alertes (Alertmanager → Telegram) n'est pas câblée dans le cluster (server.alertmanagers vide, aucun receiver) ; les règles restent visibles dans Prometheus /alerts + le dashboard. Câblage delivery = décision séparée. Co-Authored-By: Claude Opus 4.8 <[email protected]> |
||
|
|
b4f945c310 | Merge pull request 'feat(vault): onboard prospection (gitea_cicd role + ops policy)' (#6) from arcodange/onboard-prospection into main | ||
|
|
31a66884d6 |
feat(vault): onboard prospection (gitea_cicd role + ops policy)
Helm Charts / Detect changed charts (push) Successful in 5m32s
Helm Charts / Detect changed charts (pull_request) Successful in 1m2s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Ajoute prospection à la liste app_policies → crée le rôle JWT gitea_cicd_prospection et la policy prospection-ops, requis par le workflow vault.yaml du repo prospection (qui provisionne le rôle k8s-auth + la policy de lecture kvv2/prospection/*). Co-Authored-By: Claude Opus 4.8 <[email protected]> |
||
|
|
5b24738dcf | Merge pull request 'feat(vault): erp prod runtime may read the shared GCS backup creds (kv_read_paths)' (#5) from claude/erp-backup-vault-read into main | ||
|
|
2953ec3202 |
feat(vault): erp prod runtime may read the shared GCS backup creds (kv_read_paths)
Helm Charts / Detect changed charts (push) Successful in 21s
Helm Charts / Library charts tool (push) Has been skipped
Helm Charts / Application charts pgcat (push) Has been skipped
Helm Charts / Detect changed charts (pull_request) Successful in 14s
Helm Charts / Library charts tool (pull_request) Has been skipped
Helm Charts / Application charts pgcat (pull_request) Has been skipped
Adds an optional kv_read_paths list to the app_policy module (default []) so an app's env=prod runtime policy can read extra kvv2 data paths — e.g. a shared backup-creds path owned by another app. Plumbed through the root applications schema + module call (dynamic rule, read+list). Set for erp: kv_read_paths = ["kvv2/data/longhorn/gcs-backup"], so the dedicated Dolibarr backup CronJob (erp chart, gated) can read the existing GCS HMAC creds via its own VaultStaticSecret instead of borrowing the Longhorn secret cross-namespace or duplicating credentials. No-op for every other app (default []). Only the `erp` runtime policy gains one read+list rule. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]> |