POST /cert/deliver delegates to deliver_cert_internal
What changed (2026-08-05, entirely-api cc591c4, completing 3868129):
The API-key route POST /cert/deliver no longer carries its own copy of the
cert send pipeline. It predated email tracking, so API-initiated sends went
out with no pixel and no tokened link while portal sends were fully
tracked. It is now a thin wrapper over deliver_cert_internal — the single
send path — so every cert send gets identical per-recipient tracking
(PER_RECIPIENT_CERT_TRACKING), preflight gating, idempotency, and
post-send hardening.
Preserved wrapper semantics (pinned by TestDeliverRouteDelegation in
tests/test_cert_pipeline.py): dry_run preview (same response shape, no
preflight/idempotency/tokens/send), to_override/cc_override,
X-Idempotency-Key replay, force bypass, 400 on no-route,
project/account/pdf response keys, initiated_by="api" in sent_log.
deliver_cert_internal gained dry_run + initiated_by params; the
cert_delivered timeline event moved into it (portal sends now log one too).
Test-suite side effects:
pillow_heifinstalled on the host →tests/test_cert_pipeline.py(57 tests) is back in the suite after being--ignore’d since session 71.- Three latent failures the ignore was masking, all fixed: routing e2e tests
now pin per-recipient tracking off (they assert routing, not delivery
mode); scope-closeout
_runusesasyncio.run(get_event_loop dies after pytest-asyncio files on py3.12); idempotency tests patchredis.asyncioas a parent-package attribute too (tb26’s permanent stub bypassed the sys.modules fake). cert_preflight._check_no_active_duplicatenow accepts raw SmartSuite status IDs alongside resolved labels (value-ID convention).
Suite 483 passed; deployed (api + worker + scheduler rebuilt — note:
worker/scheduler have their own image tags, restart alone does NOT pick up
a rebuilt image); live-verified via dry_run on R373 Token Forest Drive.