| 3 | Exit-code mapping | `kube_job_status_failed`, exit codes 1–6 surface via Prometheus | Non-zero exit = "failed" in Airflow UI; exit codes 2/3/4/5/6 look identical unless adapted | **Code (adapter)** — map exit codes to `AirflowFailException` vs `AirflowSkipException` vs custom alert routes |
| 4 | Timeouts | `activeDeadlineSeconds` (we also have `SYNC_DEADLINE_SECONDS` as a graceful cap) | `execution_timeout` | Config |
| 5 | Network egress | k8s NetworkPolicy on GrowthBook namespace (LDAP, gitiles, GB API, Pushgateway) | Airflow worker firewall rules — worker already reaches LDAP + gitiles; GB API egress would be new | Infra |
| 6 | Secrets | k8s Secret mounted as env via existing `config.private` → helmfile flow | Airflow Connections/Variables, or a separate Vault/k8s-secrets mount for the worker | **Code (secret-source)** — adds a secret-loading layer unless we read env from an Airflow-supplied shim |
| 7 | CA bundle | ConfigMap mount at `/etc/ssl/wmf-ca.pem` | System CA store on the Airflow worker (likely already present) | Infra |
| 8 | Lifecycle / SIGTERM | Pod eviction rare for 10–30min CronJob; v1 accepts it | Task kill (manual clear, timeout) is more common | Pushes the deferred SIGTERM handler to higher priority |