GPT Review — 22-P3-P1 PASS and P3-P2 Directive
GPT Review — 22-P3-P1 PASS and P3-P2 Directive
Date: 2026-05-06
Reviewer: GPT-5.5 Thinking / Incomex Hội đồng AI
Reviewed:
knowledge/dev/laws/dieu44-trien-khai/reports/22-p3-p1-iu-gateway-policy-and-canonical-marker-report.mdknowledge/dev/laws/dieu44-trien-khai/reviews/opus-review-22-p3-p1-execution-pass-2026-05-06.md
Verdict
22-P3-P1 PASS. P3-P1 COMPLETE.
Opus review is accurate. Agent executed P3-P1 rev6 correctly. No additional P3-P1 Agent action is needed.
Accepted facts
patch_state=UNPATCHED,function_replace=EXECUTED.fn_iu_createsource hash changed from5db9f7542c2e62e0cfefa01df43eb294to3017892a5ac605a6daeaa5348e2a6cdf.MARKER_PRESENTafter patch.app.canonical_writer='fn_iu_create'is set inside canonical writer path.- Leak test after commit returns
(not set). - 9/9 gateway policy keys exist in
dot_config. - P3-P1 pilot
pilot.p3.p1.20260506-070623.cbb29036created and verifiesall_pass=true. - Idempotent re-call returned
exists_complete. - Trigger counts unchanged: IU=4, UV=0.
- PUBLIC EXECUTE absent;
directusEXECUTE present; SECDEF/VOLATILE preserved. - No trigger guard, no GRANT/REVOKE, no Directus change, no cleanup.
Correction to Opus P3-P2 proposal
Opus direction is right but two details must be adjusted before prompt writing:
1. Guard must cover INSERT and UPDATE, not only INSERT
The user’s gateway problem is not just birth-time creation. Direct table UPDATE can also mutate IU/UV into inconsistent state after canonical creation.
P3-P2 should design guards for:
information_unitBEFORE INSERT OR UPDATE;unit_versionBEFORE INSERT OR UPDATE.
If UPDATE guard proves too risky in prompt review, it can be staged, but the default design should include UPDATE.
2. Trigger names should be discovered / non-conflicting, not chosen by aesthetic order
Opus suggested trg_iu_a_canonical_guard for alphabetical ordering before L1. This may be okay, but do not rely on a handpicked name without inspecting existing triggers.
P3-P2 prompt should:
- inspect existing trigger names first;
- choose non-conflicting names;
- state that exact order relative to current L1 is not the main correctness boundary because this guard only checks session marker and does not mutate row content;
- avoid hardcoding order as correctness requirement.
Next step: P3-P2 prompt, not dispatch yet
Opus should create a compact but safe P3-P2 execution prompt:
knowledge/dev/laws/dieu44-trien-khai/prompts/22-p3-p2-iu-gateway-trigger-guard-prompt.md
Report path:
knowledge/dev/laws/dieu44-trien-khai/reports/22-p3-p2-iu-gateway-trigger-guard-report.md
Do not dispatch after creating. Return for GPT/User review.
P3-P2 objective
Deploy the wrong-door blocker / trigger guard for IU and UV writes.
P3-P2 must enforce:
Direct writes to
information_unitandunit_versionare blocked unless the current transaction/session has the canonical marker set byfn_iu_create.
This is still a speed bump, not a security boundary. Role separation and detectors remain future layers.
Required P3-P2 scope
§1. Preflight
Read/verify:
- P3-P1 marker exists in
fn_iu_createsource. - 9 required gateway keys exist in
dot_config. iu_create.gateway.marker_keyandiu_create.gateway.marker_valuevalues are present.iu_create.gateway.readme_pathexists as a value; README file may be planned/not yet created.- Current trigger names/counts on IU and UV.
- No existing guard trigger/function with target names.
- Current counts IU/UV/birth before.
§2. Guard function design
Create one reusable function, preferred:
public.fn_iu_gateway_write_guard()
Behavior:
- Reads marker key/value and readme path/canonical function from
dot_config. - Does not hardcode the README/canonical function in error message except as fallback if policy keys are missing.
- If
current_setting(marker_key, true) = marker_value, allow write. - Else
RAISE EXCEPTIONwith message instructing caller to read README and usefn_iu_create/fn_iu_create_plan. - Should include table name and operation in error detail/hint where possible using
TG_TABLE_NAME,TG_OP. - SECURITY DEFINER or INVOKER: prefer INVOKER unless policy-key reads require definer. If DEFINER, justify and set search_path.
§3. Trigger deployment
Create triggers:
- on
public.information_unit: BEFORE INSERT OR UPDATE; - on
public.unit_version: BEFORE INSERT OR UPDATE.
Trigger names:
- use a clear prefix, e.g.
trg_iu_gateway_write_guardandtrg_uv_gateway_write_guard, unless preflight finds conflicts; - no raw assumption about alphabetical order as a correctness condition.
Use CREATE TRIGGER, not CREATE OR REPLACE TRIGGER.
If trigger/function already exists, STOP or verify-idempotent; do not silently replace.
§4. Tests
Run inside controlled flow:
-
Canonical create via
fn_iu_createstill succeeds.- New dynamic pilot:
pilot.p3.p2.<timestamp>.<hex>. - Verify IU=1, UV=1, birth=1, invariants all_pass=true.
- Idempotent re-call returns
exists_complete.
- New dynamic pilot:
-
Direct IU insert is blocked.
- Attempt inside SAVEPOINT or transaction block and catch exception.
- Must not leave row behind.
- Error should mention README/canonical function.
-
Direct UV insert is blocked.
- Attempt with dummy/new UUID values if possible without relying on FK success; guard should fire before constraint issues.
- Catch exception.
- Must not leave row behind.
-
Direct IU update is blocked.
- Use a pilot row in SAVEPOINT/exception block.
- Attempt harmless field update, catch exception, verify original row unchanged.
-
Direct UV update is blocked.
- Use pilot UV row, attempt harmless field update, catch exception, verify original row unchanged.
-
No marker leak.
- After transaction/session,
current_setting(marker_key,true)not set.
- After transaction/session,
§5. Verification
After commit:
- Trigger counts increased exactly as expected:
- IU +1 guard trigger;
- UV +1 guard trigger.
- Existing IU invariants still pass for all current IU if count small; if count large, sample safely.
- Direct write blocked tests passed.
- Canonical create still works through guards.
- No unexpected trigger/function replacements.
- PUBLIC function execute state checked if guard is SECURITY DEFINER.
§6. Failure handling
If any test fails:
- Roll back if inside transaction.
- If triggers were created and a post-test fails after commit, report exact state and do not improvise cleanup unless prompt explicitly includes rollback path.
Preferred safer approach:
- Do everything in one transaction:
- create guard function/triggers;
- run canonical and direct-block tests;
- if all pass, COMMIT;
- if fail, ROLLBACK leaves no guard.
Post-COMMIT verify then confirms deployment.
§7. Hard boundaries
No:
- GRANT/REVOKE;
- Directus permission changes;
- role separation;
- detector implementation;
- DOT registration;
- adapter implementation;
- cleanup pilots;
- Pack 2C.
Additional prompt-hardening requirements
Keep P3-P2 prompt compact, but include these guardrails from prior lessons:
- Environment defaults:
PG_CONTAINER,PG_USER,PG_DB. set -uo pipefail, no globalset -eif final report must always print.- Validate pilot address.
- Final verdict machine fields:
sql_exitpost_exitcanonical_statusiu_direct_block_statusuv_direct_block_statusiu_update_block_statusuv_update_block_statustrigger_count_statusphase_statusp3p3_readiness
- Always upload report.
Expected Opus response
Opus should now create the P3-P2 prompt at the path above and stop. Do not dispatch.
Summary
P3-P1 prepared the gateway. P3-P2 should install the wrong-door blocker. The key design point: block both INSERT and UPDATE for IU/UV, while preserving the canonical fn_iu_create path. This remains a speed bump plus guidance layer, not the final permission/security boundary.