Status: working proposal. The third piece of the catalog model: catalog-doctrine.md (the principle) → fork-vocabulary.md (the shared names + current state) → this doc (the recommended recipe per chart) → customization-decision-tree.md (the user flow). Grounded by current catalog roles, the generated data under data/, and the current package bases.
What this is
For each TOP20 chart, the recommended recipe: one honest default, a parameterized base where fill-safe fields exist, and the 1–4 standard forks (from the shared vocabulary) that genuinely apply to that chart's role. This is the target surface and the build backlog - today every chart ships only 2 bases (fork-vocabulary.md). A recommended base becomes real only after it passes the doctrine's admission check: renders single-namespace, Helm-equivalent, images pinned.
Method - recommend a fork only where the role makes it real (no padding)
| dimension | recommended when the chart… |
|---|---|
existing-secret | generates/needs a secret (the F3 fix-path) |
ha | has a real replicated/clustered mode |
ingress-tls | has a web UI / external HTTP surface |
no-crds | ships CRDs a controller/GitOps should own |
minimal | has optional components worth dropping |
tls | consumes BYO TLS/CA material |
Forks compose (existing-secret + ingress-tls); a composed fork is one base, named by its dimensions. Fork = shape change; fill = slot binding (doctrine invariant) - replica count, image tag, resource requests, persistence size, retention are fills on the parameterized base, never forks.
Recommended recipe per chart
Legend: default always present · P = parameterized base recommended · forks named from the shared vocabulary (a+b = composed single base) · n = standard fork count (target 1–4).
| # | chart | role | default base | P | recommended standard forks | n | notes |
|---|---|---|---|---|---|---|---|
| 1 | nginx | stateless web | default (http-clusterip) | ✓ | ingress-tls · ingress-tls+existing-secret (BYO cert) | 2 | TLS cert arrives as existing-secret |
| 2 | metrics-server | cluster metrics addon | default | ✓ | tls (serving CA) · ha (2× + PDB) | 2 | lean addon |
| 3 | ingress-nginx | ingress controller | default | ✓ | minimal (admission-disabled) · ha (replicas+PDB) | 2 | |
| 4 | cert-manager | CRD operator | no-crds (flip) | ✓ | crds (bundled) · ha | 2 | default flips to no-crds - GitOps owns CRDs |
| 5 | external-secrets | CRD operator | default | ✓ | no-crds · ha | 2 | |
| 6 | secrets-store-csi-driver | secret CSI addon | default | ✓ | rotation (sync-secret) | 1 | rotation is a chart-feature fork |
| 7 | argo-cd | GitOps platform | default | ✓ | no-crds · ha · ingress-tls (UI) · existing-secret (admin) | 4 | rich platform chart |
| 8 | loki | log store (stateful) | default (single-binary) | ✓ | ha (scalable+object store) · ha+existing-secret (store creds) | 2 | default is the lean mode |
| 9 | prometheus | monitoring | default | ✓ | minimal (server-only-ephemeral) · ha (replicas+persistent) · ingress-tls (UI) | 3 | |
| 10 | tempo | tracing (stateful) | default (local-persistent) | ✓ | ha (S3 scalable) · ha+existing-secret (S3 creds) | 2 | |
| 11 | redis | cache + secret | default | ✓ | existing-secret · ha (sentinel/cluster) | 2 | F3: default must declare required secret |
| 12 | postgresql | secret DB | default | ✓ | existing-secret · ha (replication) | 2 | F3 |
| 13 | mysql | secret DB | default | ✓ | existing-secret · ha (replication) | 2 | F3 |
| 14 | mongodb | secret DB | default | ✓ | existing-secret · ha (replicaset) · existing-secret+ha | 3 | current fork = the composed base |
| 15 | rabbitmq | queue + secret | default | ✓ | existing-secret · ha (cluster) | 2 | F3 |
| 16 | grafana | dashboards + secret | default | ✓ | existing-secret · ingress-tls (UI) · existing-secret+ingress-tls | 3 | current fork = the composed base |
| 17 | longhorn | block storage | default | ✓ | ingress-tls (UI) · no-crds · ha (replica count) | 3 | ships CRDs |
| 18 | vault | HA secret store | default | ✓ | ha (raft) · ingress-tls (UI) · tls (BYO TLS) | 3 | |
| 19 | consul | service mesh | default (control-plane) | ✓ | ha (servers) · existing-secret (gossip/mesh) · ingress-tls (UI) | 3 | |
| 20 | kube-prometheus-stack | monitoring suite | default | ✓ | no-crds · minimal (drop exporters) · ingress-tls (UI) · existing-secret (grafana admin) | 4 | umbrella chart |
Catalog rollup
- Today: 40 bases (20
default+ 20 ad-hoc forks), 0parameterized(fork-vocabulary.md). - Target: ~20
default+ ~18parameterized+ ~47 standard forks ≈ ~85 bases - roughly double, but predictable: the same fork name means the same thing on every chart. - Highest-leverage dimensions - build these first:
ha(~16 charts) andexisting-secret(~12) are the broadest,ingress-tls(~8) next.tls,crds,rotationare niche (1–2 charts each). - Average 2.35 forks/chart - inside the 1–4 band; only the platform/umbrella charts (argo-cd, kube-prometheus-stack) hit 4. No chart needs a padded fork to look complete.
Typical fill-safe fields (the parameterized placeholders, not forks)
Image tag · replica count (within a mode) · resource requests/limits · persistence size · service annotations · chart-specific tunables (retention, log level, storage class). These bind on a derived variant with no re-render. Anything that changes the rendered object set (enable ingress, switch to cluster mode, add/drop CRDs) is a fork, not a fill - that is what preserves Helm-equivalence and digest-pinning.
How a user reaches these (decision-tree START)
- Pick the chart → see its
default(installs to Ready, or declares its required secret fill - F3). - Need a change? Pick a named fork from this chart's row - the menu is the same vocabulary everywhere.
- Want to make it yours? Use the
parameterizedbase and fill the placeholder fields (the form). - The long tail (env / region / customer) is derived variants layered on the chosen base - fills only.
Open decisions (carried from the doctrine + vocabulary)
- cert-manager default flips to
no-crds(GitOps owns CRDs);crdsbecomes the fork. (fork-vocabulary.mdrec 4) - Secret-chart defaults (F3): redis/postgresql/mysql/mongodb/rabbitmq/grafana
defaultmust either declare the required secret fill and refuse a silently broken install through a required-secret gate or shipexisting-secretas the recommended base - never deliver silently broken over GitOps. - Per-chart fill-set: the exact "fill-safe (non-shape) fields" list per chart needs author confirmation; the typical set above is the proposed starting point.
Sources
catalog-doctrine.md, fork-vocabulary.md, generated status/outcome data, and current package bases.