Trois questions indépendantes, tranchées lors du branchement de Kadans sur
MinIO (2026-07-26) : qui déclare les buckets d'une app, qui détient les
identifiants capables de les créer, et comment l'app lit les siens.
La décision de fond est du fondateur : CHACUN SON PÉRIMÈTRE. Une application
déclare ses buckets depuis son propre dépôt ; `tools` fournit le serveur, un
module de standardisation et un compte de provisionnement — pas la liste. Une
première version faisait tout porter par l'infra partagée : à ce rythme, chaque
bucket de chaque app devenait une PR sur le dépôt commun.
L'ADR consigne aussi les trois identités et leurs portées (root / provisionneur
/ compte de service), pourquoi la lecture des identifiants est une propriété
inconditionnelle de la plateforme plutôt qu'une déclaration par app, et pourquoi
les octets ne transitent pas par l'API — avec les conséquences que ça impose
(endpoint public, CORS aux origines exactes, pas de basic-auth sur l'ingress S3).
Les alternatives écartées sont listées avec leur motif, dont deux que j'avais
moi-même proposées et qui étaient plus faibles.
Deux limites assumées y figurent : le provisionneur est un secret PARTAGÉ entre
rôles CI (sa compromission permet de créer des buckets, pas de lire des objets),
et les noms d'actions d'administration MinIO n'ont pas été éprouvés contre le
serveur au moment d'écrire.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01CoafGWmRVESaWX819USUUA
Activates the sandbox environment for the ERP on the Postgres side
(ADR-0002 Phase D). `erp` gains `envs = ["prod", "sandbox"]`, so the
elision flatten now materialises a second instance `erp-sandbox`:
- database `erp-sandbox`
- owner role `erp_sandbox_role` (snake-case per the convention)
- pgbouncer user_lookup function + grants for the new DB
The prod `erp` instance is unchanged (db `erp`, role `erp_role`) — the
apply is purely additive (~6 resources for erp-sandbox, 0 changed,
0 destroyed on everything else). Verified the flatten output with a
standalone tofu apply before pushing.
This is D1 of the Phase D activation. D2 (tools Vault policies),
D3 (erp iac creds + KV), D4 (ArgoCD Application) follow in order.
Refs ADR-0002 (factory#15), Phase B (factory#16).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
ADR-0002 Phase B. Makes postgres/iac, argocd, and the conventions docs
multi-environment-capable WITHOUT activating any sandbox yet — every app
stays prod-only, so this change is behaviour-neutral:
- postgres/iac `tofu plan` is a no-op (proven: the elision flatten keys
are bare app names, db=<app>, role=<app>_role — identical addresses)
- the argocd apps.yaml render is byte-identical (181→181 lines, diff
empty) since no app declares `envs`
postgres/iac:
- variables.tf: `applications` becomes set(object({name, envs=optional(["prod"])}))
- main.tf: a `local.app_instances` flatten of applications × envs keyed by the
elided instance id (env=prod → "<app>"); per-app resources iterate it and
reference each.key / each.value.{database,role}. For prod-only apps every
resource address + attribute is unchanged. (main.tf also got a full
`tofu fmt` pass — the pgbouncer function block reindents 4→2 spaces, which
is cosmetic; the correctness gate is the CI tofu plan, not the text diff.)
- terraform.tfvars: string entries → { name = "..." } objects.
argocd/templates/apps.yaml:
- after the prod Application, a `range $app_attr.envs` loop renders one extra
Application per non-prod env: name/namespace `<app>-<env>`, shared repoURL,
helm.valueFiles [values.yaml, values-<env>.yaml], per-env syncPolicy override.
Renders nothing while no app sets `envs` → prod render unchanged.
docs:
- doc/runbooks/new-web-app/conventions.md (FR, authoritative): new section
"Plusieurs environnements pour une même app" — elision rule, suffix rule,
snake-case owner-role exception, erp/erp-sandbox table, ADR-0002 link.
- vibe/guidebooks/lab-ecosystem/naming-conventions.md (EN mirror): the env
coordinate section + a "Two sandbox models" section reconciling the
separate-cluster (ADR-0001, names repeat) vs in-cluster sibling (ADR-0002,
<env> suffix) strategies; Last Updated bumped; ADR-0002 cross-links.
Activation (erp gets envs=["prod","sandbox"] in postgres tfvars + argocd
values + erp/iac) is Phase D, gated by its own plan review.
Refs ADR-0002 (factory#15). Phase A = tools#2 (merged). Phase C = erp#11 (merged).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>