Status: working doctrine for catalog admission and variant routing.
Principle
Every catalog-supported chart presents a small, predictable customization surface:
- One honest
defaultbase - concrete values, zero placeholders where possible, installs to Ready with no required input. Where a zero-placeholder default cannot honestly work (secret-needing charts over GitOps - F3), the default declares its minimum required fills and refuses-with-reason rather than delivering silently-broken. - A parameterized base (where it works) - identical in shape to
default, but with the author-exposed, non-shape-changing fields exposed as placeholders instead of concrete values. This is the explicit "make it yours" surface - the placeholders are the form fields. Can have, not must have: some charts have few safe-to-parameterize fields. - Up to ~4 standard forks - additional base variants from a shared catalog vocabulary (
existing-secret,ingress-tls,ha,no-crds, …), applied per chart only where they apply (don't pad fake forks). Same name = same meaning across the catalog. - Fills layer on top - placeholder values / fact bindings are filled on a derived ConfigHub variant, without changing object shape. The long tail is many derived variants (env / region / customer) over a few bases.
recipe ─┬─ default base (concrete, zero placeholders, works OOTB)
├─ parameterized base (same shape; fill-safe fields → placeholders) ──fill──▶ derived variants
└─ standard forks (0–4) (existing-secret | ingress-tls | ha | no-crds…) ──fill──▶ derived variants
each a real, rendered, Helm-equivalent, pinned shape
The generated master matrix uses this same flow:
| Layer | Role |
|---|---|
F1 | upstream chart/version source |
F2a | honest default rendered base |
F2b | rendered standard fork |
F2c | candidate useful or parameterized base |
F3 | target prerequisite or fill candidate |
F4a | derived ConfigHub clone |
F4b | target-bound derived variant |
F2c and F3 candidate rows are planning rows. They show useful paths and custom-discussion cases without claiming that render parity or live evidence already exists.
Outcome Bar
The outcome is not "we generated chart files." The outcome is:
Every catalog-supported chart default and declared main choice is
reproducible, Helm-equivalent, live-cluster verified, and tied to receipts.
The default base and every declared fork count separately. If a chart advertises existing-secret, ingress-tls, ha, no-crds, server-only, or another main choice, that choice needs its own reproducibility and live-lane evidence. Default-only proof does not cover a non-default fork.
Derived ConfigHub variants count as supported only when the uploaded base-plus-derived-variant path is receipted: clone, allowed mutation, checks, gates or target facts where applicable, and live observation when the variant is presented as deployable.
Load-bearing invariants
- Honest default: reaches Ready, OR declares required fills and refuses a silently broken install through a required-secret gate.
- Fork = shape change; fill = slot binding. A value change that alters the rendered object set is a base fork (re-render, Helm-equivalent, digest-pinned). A value bound into an already-rendered field is a fill (derived variant, no re-render). Never blur this - it is what preserves Helm-equivalence + digest-pinning.
- Shared fork vocabulary - catalog-wide names, not per-chart ad-hoc. Current catalog evidence: the existing-secret fork is named 5 different ways today -
reuse-existing-secret(redis) ·existing-secret(postgresql/mysql/rabbitmq) ·existing-secret-replicaset(mongodb) ·existing-secret-ingress(grafana) ·default-control-plane(consul). A user cannot predict that; the vocabulary fixes it. - Every base is pinned (F2) and Helm-equivalent. Equivalence is verified per base.
- Parameterized reproducibility:
parameterized base + default fills ≡ default base ≡ helm template.
Admission check (what makes a chart "catalog-supported")
installer.yamldeclares exactly onedefault: truebase.- The default installs to Ready (live e2e) or trips a required-input/secret gate (no silent green).
- Each declared fork renders coherently (single-namespace), is Helm-equivalent, pins images, and has lane-tracked live evidence or an explicit
missingbacklog before any broader support claim. - Fork names come from the shared vocabulary.
- Where a parameterized base exists:
parameterized + default fills ≡ default.
Charts not meeting this are catalog-candidates (analysis tier), not catalog-supported.
Why this serves the three goals
- more charts → it's the admission bar (a chart joins when it has an honest default + applicable forks).
- obvious steps → the customization flow starts with "pick a named fork"; the parameterized base is the fill form.
- tested & verified → the admission check is the matrix:
charts × {default + parameterized + forks} × dimensions, same harness/receipts/adversarial-verify.
Open questions (honest)
- Zero-placeholder honest default is impossible for secret charts over GitOps without a required-secret gate or a GitOps secret-delivery mechanism.
- "Fill-safe" fields (placeholder-able without shape change) need a per-chart determination - likely the author-exposed inputs minus structural ones.
- The shared fork vocabulary needs defining + a migration of the current inconsistent fork names.
Sources
helm-expt docs/reference/customization-algorithm.md, docs/user/change-routing-before-oci.md, docs/reference/customization-decision-tree.md, and the generated proof/status data under data/.