; docker/php-fpm/zz-custom.conf — pool FPM (montado em /usr/local/etc/php-fpm.d/zz-custom.conf)
; ADR-005: ignora php.ini/.user.ini do docroot; logs em stderr (ADR-024).
;
; NOTA: o container roda NON-ROOT via Compose (`user:`); não definimos `user`/`group` no pool
; o UID/GID efetivo vem do Compose via `user:`).

; --- Global (antes do `[www]`) -------------------------------------------------
; A seção `[global]` precisa ser **explícita**: o `include` do `php-fpm.conf` não herda a
; seção do arquivo que o inclui, e sem ela o FPM recusa a configuração inteira (exit 78).
;
; `process_control_timeout`: tempo que o master espera os filhos reagirem ao sinal no
; shutdown. Com `request_terminate_timeout = 360s` (abaixo), ela dá um teto ao shutdown.
; `emergency_restart_threshold`/`_interval`: reinício de emergência — o master pode
; reiniciar até 10 vezes em 1 min; passar disso, o FPM se recusa a reiniciar (protege
; contra crash-loop que consome o host).
[global]
process_control_timeout = 10s
emergency_restart_threshold = 10
emergency_restart_interval = 1m

[www]
listen = 9000
; Sem `listen.allowed_clients`: o `web` (Caddy) conecta por TCP na rede `internal` (nenhuma
; porta de FPM e publicada). Restringir a 127.0.0.1 quebraria o proxy do container `web`.

pm = dynamic
pm.max_children = 10
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 500

; ===== Janela de request (D0) =====
; O worker pode ficar preso por 330 s (max_input_time 300 + max_execution_time 30).
; `request_terminate_timeout` fica ACIMA disso (360 s) — é o teto: um request que
; estourou não vira worker eterno, morre e o FPM reabastece a partir do master.
; O `read_timeout` do Caddy (360 s) espera o mesmo tempo, para o app responder (500)
; antes de o edge desistir (504).
request_terminate_timeout = 360s

; Healthcheck real do FPM: sem ele, o Compose pode dizer "healthy" com o FPM travado
; (o healthcheck default do FPM só responde em /status ou /ping se o status path existir).
; MEDIDO (PHP 8.4.26): o master responde ao path com os headers CGI e **corpo vazio** — o
; valor de `ping.response` não é aplicado nesta versão. A prova de vida é, portanto, "o
; master respondeu ao path", não "o corpo é pong". Prová-lo exige `cgi-fcgi` (libfcgi-bin),
; que não está na imagem (ficou para a onda da imagem).
ping.path = /ping
ping.response = pong
; Fila de conexões aceitas: o edge retém o cliente enquanto o FPM não aceita.
listen.backlog = 511

; Logs em stderr; sem arquivos dentro do docroot
catch_workers_output = yes
decorate_workers_output = no
clear_env = no
access.log = /proc/self/fd/2

; Slowlog para diagnóstico (não grava nada no docroot)
request_slowlog_timeout = 5s
slowlog = /proc/self/fd/2

; ===== Ignorar arquivos do cPanel (ADR-005) =====
php_admin_value[user_ini.filename] =
php_admin_value[user_ini.cache_ttl] = 0
php_admin_flag[log_errors] = on
php_admin_value[error_log] = /proc/self/fd/2

; Tmp fora do docroot
php_admin_value[upload_tmp_dir] = /tmp
php_admin_value[sys_temp_dir] = /tmp

; ===== CVE-2026-109619 (php2shell) =====
; O `php_admin_flag` vence `ini_set()`/`.user.ini`: o upload progress não pode
; ser religado pela aplicação nem por configuração de diretório. Defesa em
; profundidade — a correção completa é a base 8.4.27+ (Dockerfile).
php_admin_flag[session.upload_progress.enabled] = off
; Trava os limites da cadeia de upload no valor do php.ini; nenhum ini_set
; da aplicação eleva o teto por request.
php_admin_value[upload_max_filesize] = 110M
php_admin_value[post_max_size] = 114M
; Trava o teto de memória no valor do php.ini (256M). Não usar `-1`: a
; mitigação de OOM do CVE-2026-109618 é a base corrigida; sem limite, um
; request grande vira DoS do host em vez de erro controlado.
php_admin_value[memory_limit] = 256M
