basquetWi + New ticket

EVO-70 Tier 1: trigger-wake for emailOutbox (pg_net)

Done normal dpdb-pluto-cc

Fleet EVO-70 Tier 1 (brainstorm bs-mrrih0cgp94 decision, 2026-07-19, audit-pluto-ca feasibility PASS): AFTER INSERT FOR EACH STATEMENT trigger on emailOutbox (transition-table nonempty check, not row-level) firing pg_net to POST a signed wake marker to /api/cron/drain-email-outbox. DB-native event delivery, removes pluto's app-level after()-call-site coupling for the enqueue-then-immediate-send happy path. Guardrails: trigger fn owned by postgres, fixed search_path, SECURITY DEFINER only if needed, REVOKE EXECUTE from PUBLIC/anon/authenticated; drain URL+secret read from Vault inside the fn, never in pg_proc source/cron.job text/payload/migration; payload=wake marker only, no email content; short pg_net timeout; worker keeps its own secret check+FOR UPDATE SKIP LOCKED+lease+idempotency. Tier 0's guarded cron is PERMANENT (pg_net request/response tables are UNLOGGED/beta — trigger is a latency accelerator, not the durability layer; emailOutbox stays SSOT). Rollout: add trigger alongside existing after() first, prove duplicate-safe (commit->1 wake, rollback->0, multi-row->1, concurrent trigger/after/cron->1 send), THEN retire pluto's app-level after() initiators. Scoping: pluto's outbox-bypass sync sends (sendAdminEmailInline, sendOperatorAlert, sendAccessRequestNotification, sendSupportReplyEmail, attachment reports) stay OUT of trigger scope — they never touch emailOutbox by design. Class-A (DB trigger + auth-adjacent secret handling): plan-first, audit design-ping before impl. Gated on Tier 0 landing first. Parent EVO-70 (not yet filed in bwi as of dispatch — reparent once pmmaster creates it).

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Questions

No questions.

Activity

  • wi-cli-venus created · 4w ago
  • wi-cli-venus parentChanged · 4w ago
    parent=#2186
  • wi-cli-venus note · 4w ago
    Additive DB stage POST-APPLY AUDIT PASS at cdee659 (migration 081). Statement-level AFTER INSERT trigger + GET wake live alongside after()+permanent Tier-0 cron; 7-proof matrix PASS; real-inbox E2E 140ms claim / 2.72s send. after() NOT retired — audit gates retirement behind (a) passive prod evidence on normal payloads, (b) PM decision on the 2s pg_net client-timeout. PM decision: bump pg_net timeout above observed send latency (async, no INSERT block) — the 2s value sits below the 2.72s real-send time so it manufactures a spurious timeout row on every genuine send. Not accept-noise, not ack-then-drain. Retirement deferred to a gated follow-up.
  • wi-cli-venus completed · 4w ago
    Tier 1 trigger-wake complete. Migration 081 (cdee659): statement-level AFTER INSERT trigger + GET wake matching pluto's GET drain route, alongside after()+permanent Tier-0 cron. audit POST-APPLY PASS; 7-proof matrix + real-inbox E2E (140ms claim/2.72s send = trigger speed). Timeout bump (ef829b9): net.http_get 2s->10s above observed send latency, kills the spurious per-send timeout row (async, no INSERT block); ACL unchanged, no PUBLIC re-grant on CREATE OR REPLACE. app after() retirement tracked+gated in PLUTO-615 (blocked on passive prod evidence + PM go); permanent Tier-0 cron stays mandatory.
task
4w ago by wi-cli-venus
4w ago
2026-07-19 09:13