{{- if and .Values.app.enabled (include "sim.createAppSecrets" .) }} {{/* Secret for app + realtime env. Every key in .Values.app.env and .Values.realtime.env is written here and mounted via envFrom on the respective Deployments. Chart-computed values (DATABASE_URL, SOCKET_SERVER_URL, OLLAMA_URL, PII_URL) are omitted — they're injected as inline env on the container so they reflect chart-time resolution. Treating all env values as secret-grade avoids maintaining a sensitivity classifier and prevents accidental leaks when new provider keys are added. */}} apiVersion: v1 kind: Secret metadata: name: {{ include "sim.fullname" . }}-app-secrets namespace: {{ .Release.Namespace }} labels: {{- include "sim.app.labels" . | nindent 4 }} type: Opaque stringData: {{- $chartComputed := list "DATABASE_URL" "SOCKET_SERVER_URL" "OLLAMA_URL" "PII_URL" }} {{- /* Intent: app.env is authoritative for shared keys (both pods envFrom this Secret, so the app container must not be silently overwritten by a realtime-side value), BUT empty strings must never win. Sprig `merge` treats "" as a real value, so a default-empty app.env entry would shadow a non-empty realtime.env entry. Build the effective dict manually: start from realtime.env, then overlay non-empty app.env values on top — this gives app.env-wins-on-collision without empty-string shadowing. Mirrors the pattern used in deployment-realtime.yaml. */}} {{- $appEnv := .Values.app.env | default dict }} {{- $rtEnv := .Values.realtime.env | default dict }} {{- $effective := dict }} {{- range $key, $value := $rtEnv }} {{- if and (ne (toString $value) "") (ne (toString $value) "") }} {{- $_ := set $effective $key $value }} {{- end }} {{- end }} {{- range $key, $value := $appEnv }} {{- if and (ne (toString $value) "") (ne (toString $value) "") }} {{- $_ := set $effective $key $value }} {{- end }} {{- end }} {{- range $key, $value := $effective }} {{- if not (has $key $chartComputed) }} {{ $key }}: {{ $value | quote }} {{- end }} {{- end }} {{- end }}