# `minio_app` — déclarer ses buckets depuis SON dépôt Chacun son périmètre : les buckets d'une application appartiennent au dépôt de cette application. Ce module **standardise** la déclaration, il ne la détient pas — sans lui, chaque bucket de chaque app deviendrait une PR sur `tools`. ## Usage Dans l'`iac/` de l'app : ```hcl # Le provisionneur MinIO : des droits d'administration MINIMAUX (créer un # bucket, un compte de service, une politique), jamais le root — qui, lui, ne # sort pas du pipeline `minio`. data "vault_kv_secret_v2" "minio_provisioner" { mount = "kvv2" name = "minio/provisioner" } provider "minio" { minio_server = "s3.arcodange.fr" minio_user = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_ACCESS_KEY"] minio_password = data.vault_kv_secret_v2.minio_provisioner.data["MINIO_SECRET_KEY"] minio_ssl = true } module "stockage" { source = "git::ssh://git@192.168.1.202:2222/arcodange-org/tools.git//minio/iac/modules/minio_app?depth=1&ref=main" app = "mon-app" # = le nom de son rôle Vault buckets = ["mon-app-fichiers"] providers = { minio = minio } } ``` Puis, côté chart : une `VaultStaticSecret` sur `kvv2/minio/` et l'injection des variables dans le Deployment. ## Ce que le module garantit - les buckets sont **privés** — l'accès passe par des URL présignées ; - les **téléversements abandonnés** sont ramassés au bout d'un jour (voir plus bas : c'est de l'hygiène de protocole, pas un choix de l'app) ; - le compte de service ne peut **rien** toucher d'autre que ces buckets-là ; - ses clés vont dans `kvv2/minio/`, que le module Vault central autorise déjà l'app à lire (règle **inconditionnelle** : le chemin porte le nom de l'app, donc il ne peut exposer que ses propres clés). ## Plusieurs buckets C'est le cas courant : deux contenus aux **cycles de vie différents** méritent deux buckets. Il suffit de les lister — le compte de service existant gagne l'accès, **sans nouvelle clé**. ## Ce que le module ne fait PAS Il ne pose ni quota, ni **expiration de contenu**, ni versioning : ces choix appartiennent à l'app et varient d'un bucket à l'autre. « Ces vidéos se purgent à 90 jours » est une décision de produit, elle se prend dans le dépôt du produit. ### ⚠ L'exception, et la ligne qu'elle trace Ce module pose **une seule** règle de cycle de vie : `AbortIncompleteMultipartUpload` à 1 jour, sur chaque bucket qu'il crée. Elle a l'air de contredire le paragraphe ci-dessus. Elle ne le contredit pas — elle en précise la frontière, et c'est la question « à QUOI cette connaissance appartient-elle ? » qui tranche : - une **expiration de contenu** porte sur des objets que l'app a voulus, qu'elle montre, et dont elle seule sait combien de temps ils valent. Elle varie d'une app à l'autre : elle est chez l'app ; - un **téléversement en plusieurs parts jamais refermé** n'est le contenu de personne. Ce sont des morceaux qu'aucune API ne montre — ni `mc ls`, ni la console — laissés par un navigateur qui a fermé l'onglet. **Aucune app ne veut les garder**, et aucune ne peut les voir depuis son propre code. C'est un déchet de PROTOCOLE, produit par le mécanisme même du bucket : il est chez celui qui crée les buckets. Le test pratique : si la réponse à « combien de temps ? » demande de connaître le produit, c'est chez l'app. Ici, la réponse ne demande que de connaître S3 — passé l'expiration des URL signées, un téléversement en cours ne peut plus rien recevoir, il occupe seulement. ⚠ Le délai n'est **pas** paramétrable, et c'est voulu (YAGNI) : un seul cas existe. Le jour où une app signe des parts pour plus de 24 h, ce sera le déclencheur pour en faire une variable — pas avant. ### Plancher de version ⚠ Ce module exige **`aminueza/minio >= 3.10.0`** : `abort_incomplete_multipart_upload` y est apparu (mesuré en interrogeant le schéma du provider version par version — 3.9.0 ne l'a pas). Un appelant resté plus bas se verra dire, dès `tofu init` : ``` no available releases match the given constraints 3.3.0, >= 3.10.0 ``` … ce qui NOMME la version à atteindre, au lieu d'un « unsupported block type » au plan, qui ne l'aurait pas dite.