# CLAUDE.md: Kubernetes + Helm

## Commands (read-only by default)
- Render: `helm template ./charts/app -f values/dev.yaml` · Lint: `helm lint ./charts/app`
- Validate: `kubeconform -strict -summary` on rendered output.
- Diff before changes: `helm diff upgrade app ./charts/app -f values/<env>.yaml` (if the plugin is installed).
- **Never run `kubectl apply/delete`, `helm upgrade/uninstall`, or anything against a cluster without explicit approval.** Assume the current context could be production.

## Manifest rules
- Every container sets `resources.requests` (and memory `limits`), `readinessProbe`, `livenessProbe` (and `startupProbe` for slow starters).
- `securityContext`: `runAsNonRoot: true`, `allowPrivilegeEscalation: false`, `readOnlyRootFilesystem: true`, drop `ALL` capabilities.
- Images pinned by tag or digest, never `latest`.
- Config in ConfigMaps, secrets via the cluster's secret tool (External Secrets, Sealed Secrets, SOPS). Never commit plain `Secret` values.
- Deployments: `RollingUpdate` with `maxUnavailable: 0` for user-facing services, a `PodDisruptionBudget`, and topology spread or anti-affinity for >1 replica.
- Labels follow `app.kubernetes.io/*` conventions.
- NetworkPolicies default-deny for new namespaces.

## Helm
- Put defaults in `values.yaml` and document each key; env differences only in `values/<env>.yaml`.
- Use `_helpers.tpl` for names/labels; quote strings with `| quote`; bump `Chart.yaml` `version` for chart changes.
