Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions argocd/root/templates/trakrf-backend.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,19 @@
{{- end }}
{{- $values := printf "%s%s" $base $ingress }}
{{- /*
JWT_SECRET is a real, externally-set value (kubectl-managed in-cluster, not in
git — no ESO/sealed-secret ceremony today). The chart's secret.yaml renders the
placeholder default "change-me"; without this carve-out ArgoCD selfHeal reverts
the real secret → the backend's TRA-860/#428 fail-fast guard refuses to boot.
ignoreDifferences (diff) + RespectIgnoreDifferences (sync) make the operator-set
JWT_SECRET stick across syncs. Applies per-env, so prod inherits the carve-out
at cutover (its real secret must be set the same way — see TRA-375).
JWT_SECRET and RESEND_API_KEY are real, externally-set values (kubectl-managed
in-cluster, not in git — no ESO/sealed-secret ceremony today). The chart's
secret.yaml omits each when empty/placeholder; without this carve-out ArgoCD
selfHeal reverts the operator-set values on sync. For JWT that trips the
backend's TRA-860/#428 fail-fast boot guard; for RESEND it silently empties the
key so email send fails with Resend "API key is invalid" (the Railway→GKE
migration miss). ignoreDifferences (diff) + RespectIgnoreDifferences (sync) make
both stick across syncs. Applies per-env, so prod inherits the carve-out at
cutover (its real secrets must be set the same way — see TRA-375).
TODO durable: replace the manual secret source with External Secrets + GCP
Secret Manager (TRA-375 follow-up); the carve-out stays correct either way.
*/ -}}
{{- $ignore := printf "- group: \"\"\n kind: Secret\n name: trakrf-backend\n namespace: trakrf-%s\n jsonPointers:\n - /data/JWT_SECRET\n" $env }}
{{- $ignore := printf "- group: \"\"\n kind: Secret\n name: trakrf-backend\n namespace: trakrf-%s\n jsonPointers:\n - /data/JWT_SECRET\n - /data/RESEND_API_KEY\n" $env }}
---
{{- include "trakrf.application" (dict
"name" (printf "trakrf-backend-%s" $env)
Expand Down
14 changes: 14 additions & 0 deletions helm/trakrf-backend/templates/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,19 @@ stringData:
{{- if and .Values.secrets.jwtSecret (ne .Values.secrets.jwtSecret "change-me") }}
JWT_SECRET: {{ .Values.secrets.jwtSecret | quote }}
{{- end }}
{{- /*
RESEND_API_KEY follows the same omit-when-empty rule as JWT_SECRET. The real
key is set out-of-band (operator kubectl today; ESO + GCP Secret Manager
later — TRA-375). If the chart rendered "", ArgoCD would own
/data/RESEND_API_KEY and revert any operator-set value to empty on every sync
— which is exactly what silently broke preview + prod email after the
Railway→GKE migration (empty key → Resend "API key is invalid", logged as a
non-fatal warning so the UI still showed success). Omitting the key when empty
leaves ArgoCD unaware of it, so the out-of-band value persists. A matching
ignoreDifferences carve-out on /data/RESEND_API_KEY (see
argocd/root/templates/trakrf-backend.yaml) is belt-and-suspenders.
*/}}
{{- if .Values.secrets.resendApiKey }}
RESEND_API_KEY: {{ .Values.secrets.resendApiKey | quote }}
{{- end }}
SENTRY_DSN: {{ .Values.secrets.sentryDsn | quote }}
Loading