Files
universe/deploy

deploy — the fleet, declared

Every service in this cluster is one values file:

deploy/<namespace>/<name>.yaml

That is the whole inventory. Adding a service is adding a file; there is no second list to keep in step with it.

Each file is values for one shared chart, pulled by version:

oci://oci.hanzo.ai/charts/app:0.1.0

The chart is referenced, never copied. A copy per repository is how two fleets end up with two definitions of the same thing and neither one is wrong.

helm template <name> oci://oci.hanzo.ai/charts/app --version 0.1.0 \
  -n <namespace> -f deploy/<namespace>/<name>.yaml

These files were generated from what is RUNNING

Not from the checked-in manifests. Those were applied by hand over a long period and their currency is unknown — some are ahead of the cluster, some behind, some describe things that were deleted. The running fleet is the only statement of what is true, so it is what was read.

That makes the older manifests and deploy/ disagree on purpose. The disagreement is a drift audit waiting to be done, not a bug to paper over.

Verifying, before changing anything

# regenerate from live
python3 <universe>/charts/app/hack/live2values.py --context <ctx> --out deploy

# render every file and diff it against the live object
python3 <universe>/charts/app/hack/diff-live.py --context <ctx> --values deploy

The gate grades what it finds:

  • BREAKING — the apiserver would refuse the apply. Only a workload's spec.selector qualifies; it is immutable.
  • DRIFT — live differs from the file. Someone changed one of them.
  • BENIGN — an intended consequence of moving to the chart.

Current state for this cluster: BREAKING = 0. Every workload here can be adopted in place.

selectorLabels — why most files have one

spec.selector cannot be changed after a workload is created. Most services here select on app: <name>, not the chart's app.kubernetes.io/name + instance, so each file records the selector its workload already carries. Without that the chart would emit its own, and the apply would be refused.

It is the selector only — the full label set on metadata is still the chart's, so an adopted workload gains the standard labels for everything that reads them without selecting on them.

What is NOT here

Anything that is not a service. Custom resources have their own controllers and stay where they are.

Secrets are not here and never will be. The chart has no way to carry a secret value: kmsSecrets names a path in KMS and the operator syncs it. That is what makes a values file safe to commit and safe to publish.

Deploying

There is no CD in this repository yet, which is why the manifests drifted in the first place. applicationset.yaml here is ready to apply once this cluster runs one. It deliberately has no automated block: the chart adds labels to the pod template, and a pod template change is a rollout, so switching it on would restart the whole fleet at once. Services move over one at a time.