GPT Review — Trigger Guard DROP Bug Investigation Results
GPT Review — Trigger Guard DROP Bug Investigation Results
Date: 2026-04-28
Verdict
Investigation PASS. Agent report is complete and sufficient for a repair gate.
Report reviewed:
knowledge/dev/laws/dieu38-trien-khai/reports/p9-trigger-guard-drop-bug-investigation-2026-04-28.md
Confirmed root cause
fn_evt_trigger_guard_drop() uses nullable r.object_name from pg_event_trigger_dropped_objects() during DROP TRIGGER. For trigger drops, object_name can be NULL. The function then inserts NULL into public.trigger_guard_alerts.trigger_name, which is NOT NULL, causing rollback/DROP TRIGGER to fail.
Secondary defects are also confirmed:
- unqualified
INSERT INTO trigger_guard_alerts; - no locked function-level
search_path; - DROP guard was not updated when DDL guard was repaired;
- same defective source exists in both
directusandincomex_metadata.
Important correction to Opus recommendation
Opus/agent recommend Option A: minimal parity while preserving current security mode.
GPT recommends Option A+, not plain Option A:
- Use Option A's minimal body change:
object_identityfallback;COALESCEfor non-null values;public.trigger_guard_alerts;- locked
search_path = pg_catalog, public.
- But security mode should match the already-repaired DDL guard per DB:
directus: keepSECURITY INVOKER.incomex_metadata: useSECURITY DEFINERif current DDL guard is SECURITY DEFINER, unless a pre-check proves invoker can insert intopublic.trigger_guard_alertsduring the smoke test.
Reason: the prior trigger-guard repair already found incomex_metadata needed SECURITY DEFINER for the DDL guard. Preserving current DROP guard INVOKER there may leave the DROP guard broken or untestable under the executor role.
Decision
Proceed to draft a Trigger Guard DROP Repair Gate — Option A+.
Repair gate requirements
- Executor: Claude Code via SSH
contabo. - Effort: medium (ALTER FUNCTION on two DBs + smoke test).
- Scope: patch only
public.fn_evt_trigger_guard_drop()ondirectusandincomex_metadata. - No Gate B/C.
- No production TAC data changes.
- Pre-check both DBs:
- function owner/security/proconfig;
- DDL guard security mode for parity;
- alert table schema;
- event triggers enabled;
- snapshot old source and metadata.
- Mutation:
- replace function body with minimal Option A pattern;
- lock search_path;
- schema-qualify insert;
- set security mode per DB parity decision.
- Smoke test:
- create temp table/function/trigger;
- DROP temp trigger;
- verify audit row has non-null
trigger_name,actual_enabled=false; - cleanup temp function/table;
- run on both DBs, adapting permissions safely.
- Rollback:
- restore old source only if new repair fails;
- do not leave temp artifacts.
- Action log to KB, no overwrite.
- STOP after report.
Law / governance notes
- ALTER FUNCTION is DDL, so it requires explicit gate and User authorization.
- This is a guard-infrastructure repair under Đ26/Đ31 and must preserve the guard, not bypass or disable it.
- Do not relax
trigger_guard_alertsNOT NULL constraints as primary fix; that would fix the symptom rather than the root cause.
Next direction
Opus should draft the repair execution prompt for Option A+ and submit for review. Do not execute until User GO.