#87 FTX-87: blank policy_name will 422 ~8% of HITL notifications under mail-api strict rendering
Description
EditEARS SPEC:
Context: mail-api deployed strict rendering for TRANSACTIONAL template sends on
2026-07-26 (their thr-f60cc7a11b7d489e8727). Any variable that is not supplied is
now a hard 422 template_render_error instead of rendering as an empty string.
They measured our live traffic: 10 of 129 `[Action needed]` notifications in the
last 7 days went out with a blank Policy field, so ~8% of our HITL notifications
will now fail to send. For an approval gate a 422 we do not handle is worse than a
blank field: the reviewer is never told and the decision silently waits.
Root cause on our side: app/workers/mail_drain.py passes
`policy_name=ctx.get("policy_name", "")`, and several notification producers never
put policy_name in the outbox context at all — app/workers/runflow_reconcile.py,
app/domain/escalation.py, app/domain/actions.py (reminder path). Every decision
already carries its policy name in the immutable snapshot
(`decision.policy_snapshot["_policy_name"]`), so the value was available and simply
not threaded through.
- MA-1: The Futex mail client SHALL supply a non-empty value for every template
variable in a transactional send, substituting an explicit placeholder where no
real value exists, so that no notification can be rejected for a missing variable.
- MA-2: When a notification is enqueued for a decision, the Futex system SHALL
populate `policy_name` from that decision's immutable policy snapshot.
- MA-3: If mail-api rejects a notification send, THEN the Futex system SHALL NOT
mark the notification sent, and SHALL retry it and dead-letter it after the
configured maximum attempts so the failure is visible rather than silent.
Comments
Loading comments...
Context
Loading context...
Audit History
View AllLoading audit history...