KB-3F9F

GPT Review — 23-P3A Gateway Allow-list Prompt rev2

8 min read Revision 1
gpt-reviewpack-23p3agateway-allow-listrev3-requiredruntime-hardening

GPT Review — 23-P3A Gateway Allow-list Prompt rev2

Date: 2026-05-06
Reviewer: GPT-5.5 Thinking / Incomex Hội đồng AI
Reviewed: knowledge/dev/laws/dieu44-trien-khai/prompts/23-p3a-iu-gateway-allow-list-patch-prompt.md rev2

Verdict

Rev2 is much better but still NOT ready to dispatch. Rev3 required.

Opus correctly applied the 12 fixes from the previous review. The prompt is close, but a few runtime issues remain that could cause failure, false PASS, or broken reporting.

Accepted improvements in rev2

  • pg_get_functiondef() backup is now used for restore.
  • Allow-list parsing syntax is fixed.
  • SAVEPOINT inside DO blocks was removed.
  • Future marker fn_iu_apply_edit_draft is tested in a rollback transaction.
  • fn_iu_create is tested with a real pilot, not dry-run.
  • Function lookup is schema-qualified.
  • dot_config uniqueness is checked.
  • Error message guidance is tested.
  • Metadata and privileges are captured.
  • dot_config rollback is deterministic.
  • Pilot address/counts are reported.

Required rev3 fixes

P1 — Fix variable typo: PSQL_NOSTOP vs PSQL_NONSTOP

The prompt defines:

PSQL_NOSTOP="docker exec -i $CONTAINER psql -U $USER -d $DB"

But tests use:

$PSQL_NONSTOP

This will fail at runtime.

Patch to one consistent name. Prefer:

PSQL_NOSTOP=(docker exec -i "$CONTAINER" psql -U "$USER" -d "$DB")
PSQL=(docker exec -i "$CONTAINER" psql -U "$USER" -d "$DB" -v ON_ERROR_STOP=1)

and call arrays as:

"${PSQL[@]}"
"${PSQL_NOSTOP[@]}"

If not converting to arrays, at minimum rename all PSQL_NONSTOP to PSQL_NOSTOP.

P2 — Verify fn_iu_create signature dynamically before Test 3

Rev2 calls:

fn_iu_create(address, title, body, actor)

But previous Pack 22 prompts used a wider signature, and exact runtime signature must not be assumed.

Patch Test 3 to discover signature first:

SELECT oid::regprocedure::text AS sig,
       pg_get_function_arguments(oid) AS args
FROM pg_proc p
JOIN pg_namespace n ON n.oid=p.pronamespace
WHERE n.nspname='public' AND p.proname='fn_iu_create';

Then call the exact supported signature. If the prompt cannot safely branch by signature, use the signature reported by P3-P2/23-P2 runtime evidence and include it explicitly.

Do not assume the 4-arg form.

P3 — Fix Test 3 JSON parsing / status extraction

Current Test 3 contains a fragile nested shell/psql parse:

T3_STATUS=$(echo "$T3_RESULT" | $PSQL_NOSTOP -t -A -c "SELECT (\$\$${T3_RESULT}\$\$::jsonb)->>'status';")

This is unsafe and may break on quotes/newlines. Instead, have SQL return the status directly:

WITH r AS (
  SELECT public.fn_iu_create(...) AS j
)
SELECT j->>'status' AS status,
       j AS full_result
FROM r;

Or run two SQL columns with field separator and parse safely.

P4 — Initialize all verdict variables

The final report references variables that may never be set:

  • PATCH_STATUS
  • TEST_FAIL
  • T3_STATUS
  • T4
  • T6
  • T7
  • SOURCE_HASH_AFTER
  • T2
  • PILOT_ADDR

Initialize at top:

PREFLIGHT_STATUS=""
PATCH_STATUS="NOT_RUN"
TEST_FAIL=""
PHASE_STATUS=""
P3B_READINESS="BLOCKED"
ROLLBACK_STATUS="N/A"
SOURCE_HASH_AFTER=""
T2=""
T3_STATUS="NOT_RUN"
T4="NOT_RUN"
T5="NOT_RUN"
T6="NOT_RUN"
T7="NOT_RUN"
PILOT_ADDR=""

When each test runs, set a machine-readable variable, not only echo text.

P5 — Preflight fail should exit patch/test path cleanly

Rev2 says “jump to §5” in comments, but a shell script will not jump. Although later sections are conditionally guarded, final variables can still be inconsistent.

Add a clear control flow:

if [ "$PREFLIGHT_STATUS" != "PASS" ]; then
  PATCH_STATUS="NOT_RUN"
  TEST_FAIL="NOT_RUN"
  PHASE_STATUS="FAIL"
  P3B_READINESS="BLOCKED"
  # write report and exit 0 after upload/report generation
fi

Do not rely on comments.

P6 — Test 4/7 direct IU inserts may leave aborted transactions or uncommitted behavior unclear

Use separate psql calls with no explicit transaction for direct-block tests, because gateway exception aborts only that statement/session and no row is inserted.

For marker-accepted tests that may insert, use explicit BEGIN ... ROLLBACK and set +e capture.

This is mostly present, but make the distinction explicit to avoid later “cleanup” attempts.

P7 — Test 5 should not treat FK-first as full gateway proof

It is acceptable as “direct UV write did not succeed,” but it does not prove the UV gateway trigger still blocks direct UV writes.

Rev3 should report it honestly:

  • T5_DIRECT_UV_WRITE_PREVENTED=PASS
  • T5_GATEWAY_PROVEN=PASS/NOT_PROVEN_FK_FIRST

Do not label FK-first as equivalent to gateway block. It is safe for this phase but should not overclaim.

P8 — Add direct UV UPDATE test on an existing pilot UV

P3A patches a guard for INSERT OR UPDATE on UV. Test 5 only tries INSERT and may be blocked by FK first.

Add a rollback transaction test:

  1. Select an existing UV id from a pilot IU.
  2. Begin transaction.
  3. Attempt direct UPDATE unit_version SET body = body || 'x' WHERE id = <uv_id> without marker.
  4. Expect IU Gateway blocked.
  5. Rollback.

This proves UV UPDATE guard still works.

P9 — Test 6 marker acceptance should avoid birth/business-gate false interpretation if possible

The marker-accepted IU INSERT may fail on birth/business gates. That is acceptable, but the test should classify:

  • IU Gateway blocked → FAIL;
  • non-gateway error → PASS_GATEWAY_ACCEPTED_BUT_OTHER_ERROR;
  • insert success → PASS_GATEWAY_ACCEPTED_INSERT_ROLLED_BACK.

Rev2 mostly does this. Make the report variable explicit:

T6="PASS_GATEWAY_ACCEPTED_BUT_OTHER_ERROR"

or equivalent.

P10 — Grants comparison should not treat intentional REVOKE PUBLIC as unexpected ACL change

The patch re-applies:

REVOKE ALL ... FROM PUBLIC

If PUBLIC was previously present, ACL may change in a stricter direction. That is acceptable. Rev3 should compare “not broadened,” not exact equality.

Add a clear rule:

  • fail if PUBLIC gains EXECUTE;
  • fail if intended role loses required execute only if it had it before and is expected to keep it;
  • otherwise ACL change to stricter is OK.

P11 — dot_config uniqueness check should verify uniqueness on key, not any unique constraint

Rev2 fallback checks any UNIQUE/PK constraint on dot_config, which could be unrelated to key.

Use catalog join with attributes. Example:

SELECT count(*)
FROM pg_index i
JOIN pg_class t ON t.oid=i.indrelid
JOIN pg_namespace n ON n.oid=t.relnamespace
WHERE n.nspname='public'
  AND t.relname='dot_config'
  AND i.indisunique
  AND (
    SELECT array_agg(a.attname ORDER BY a.attnum)
    FROM unnest(i.indkey) k(attnum)
    JOIN pg_attribute a ON a.attrelid=t.oid AND a.attnum=k.attnum
  ) = ARRAY['key'];

Expected exactly 1.

P12 — Report upload instruction should be executable

The prompt ends with “UPLOAD REPORT NOW” but does not specify the Agent Data create/update command. Add explicit instruction:

  • create/update KB doc at knowledge/dev/laws/dieu44-trien-khai/reports/23-p3a-iu-gateway-allow-list-patch-report.md;
  • include full log content or a summarized report plus log path;
  • upload even on preflight failure.

Directive to Opus

Patch P3A prompt to rev3 with P1–P12.

Path:

knowledge/dev/laws/dieu44-trien-khai/prompts/23-p3a-iu-gateway-allow-list-patch-prompt.md

Do not dispatch after patch. Return for GPT/User review.

Hard boundaries remain

  • No P3B schema DDL.
  • No edit draft/comment tables.
  • No edit functions.
  • No vector mutation.
  • No cleanup.
  • No Pack 2C.

Summary

Rev2 fixes the big SQL hazards from rev1, but still has runtime issues: a variable typo, likely wrong fn_iu_create signature assumption, fragile JSON parsing, incomplete verdict variables, and UV gateway coverage that may overclaim when FK fires first. Rev3 should correct these before dispatch.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-review-23-p3a-gateway-allow-list-prompt-rev2-2026-05-06.md