KB-6311

GPT Review — Pack 22 rev4 Native Contract and Opus Pushback

8 min read Revision 1
gpt-reviewpack-22rev4native-contractadvisory-lockrev5-required

GPT Review — Pack 22 rev4 Native Contract and Opus Pushback

Date: 2026-05-06 Reviewer: GPT-5.5 Thinking / Incomex Hội đồng AI Reviewed: knowledge/dev/laws/dieu44-trien-khai/design/22-dot-iu-create-wrapper-design.md rev4

Verdict

Pack 22 rev4 is strong, but rev5 is required before execution planning.

The philosophy and contract structure are now correct. Opus’s pushback on advisory-lock collision is mostly reasonable, but the design still contains a few hardcoded implementation assumptions that would violate the “do once, run forever” principle if executed as-is.

On Opus pushback: advisory lock collision

Opus says:

Unique constraint is the final guard; advisory lock is only best-effort optimization. 32-bit hash collision is harmless at current scale.

I agree with the core argument.

If the unique constraint on information_unit.canonical_address is the correctness boundary, then advisory-lock collision does not corrupt data. It only serializes two unrelated addresses unnecessarily. Therefore this does not need to block Pack 22.

However, the design should state this more formally:

  • advisory lock is never a correctness mechanism;
  • unique constraint + unique_violation handling is the correctness mechanism;
  • if future IU creation volume or hostile inputs make lock contention visible, upgrade to hashtextextended / two-key lock as a performance hardening, not correctness fix.

So Opus pushback is accepted with a documentation clarification.

What rev4 gets right

  • Native contract is separated from adapter.
  • fn_iu_create_plan() keeps dry-run logic inside PG.
  • Defaults are no longer blindly seeded.
  • Existing row classification checks anchors exactly.
  • UV birth expectation is metadata-driven.
  • Unique constraint is final idempotency guard.
  • SECURITY DEFINER, REVOKE/GRANT, and direct INSERT bypass are recognized.
  • Execution gates P0–P6 are separated.

Required rev5 patches

P1 — Constraint name must not be hardcoded

Rev4 uses:

SET CONSTRAINTS fk_iu_version_anchor DEFERRED;

This is a hardcoded runtime object name. If the constraint name changes, the native creation contract breaks even though semantics are unchanged.

Rev5 must require discovery of the deferrable IU→UV anchor constraint in P0/P1:

SELECT conname, pg_get_constraintdef(oid)
FROM pg_constraint
WHERE conrelid='information_unit'::regclass
  AND confrelid='unit_version'::regclass
  AND contype='f'
  AND condeferrable;

Then either:

  • store the discovered name in a helper/config table, or
  • use dynamic SQL inside the function:
EXECUTE format('SET CONSTRAINTS %I DEFERRED', v_constraint_name);

If exactly one suitable constraint is not found, preflight must STOP.

P2 — Required column preflight must be comprehensive and generated/list-based

Rev4 preflight checks some objects but not all columns the function writes/reads.

Rev5 should define required column sets for IU/UV/birth_registry/collection_registry as data-driven lists in the preflight helper, including at least:

  • IU: id, canonical_address, unit_kind, owner_ref, created_by, updated_by, identity_profile, parent_or_container_ref, version_anchor_ref, content_anchor_ref.
  • UV: id, unit_id, body, content_hash, version_seq, created_by.
  • birth_registry: entity_code, collection_name.
  • collection_registry: collection_name, birth_code_strategy.

Do not check only table existence.

P3 — SECURITY DEFINER search_path should be stricter

Rev4 still uses SET search_path = public in examples.

Rev5 should prefer:

SET search_path = pg_catalog, public

and schema-qualify all non-pg objects. Also explicitly state that functions should be owned by a controlled DB owner role, not an arbitrary deploy user.

P4 — Helper functions need permission policy too

Rev4 only shows REVOKE/GRANT for fn_iu_create.

If helpers are SECURITY DEFINER or callable, decide:

  • fn_iu_create_plan may be executable by adapters;
  • fn_iu_verify_invariants may be executable by adapters;
  • internal helpers such as fn_iu_create_preflight, fn_iu_classify_existing, fn_content_hash, fn_iu_resolve_default should either be private by convention or have restricted EXECUTE.

Rev5 should include a permission matrix.

P5 — fn_iu_create_plan() should not require SECURITY DEFINER unless needed

Plan function reads catalogs/dot_config and classifies existing IU. It may need read access, but making every function SECURITY DEFINER increases attack surface.

Rev5 should decide:

  • either SECURITY DEFINER for plan/verify because app roles lack table reads;
  • or SECURITY INVOKER for low-risk read-only functions;
  • but document rationale.

P6 — Existing classification should handle multiple UV v1 rows defensively

Rev4 assumes one unit_version with version_seq=1. If bad data exists, SELECT * INTO v_uv may error or pick unexpectedly.

Rev5 should classify:

  • zero UV v1 → exists_missing_version;
  • one UV v1 → check anchors;
  • more than one UV v1 → exists_duplicate_version / health signal.

This is important for orphan/ghost robustness.

P7 — Adapter safe-call snippet is still not sufficient for body text

The psql snippet still shows :'body' without a robust body-loading mechanism. Rev5 should remove pseudo-snippets that imply unsafe or incomplete usage.

State adapter contract instead:

  • body must be passed via parameterized driver, JSON API, temp table, COPY, or a reviewed safe psql pattern;
  • shell interpolation is forbidden;
  • exact adapter implementation belongs to P5, not core design.

P8 — fn_iu_create_plan() must not leak full body/hash by default

Rev4 returns content_hash_preview of full hash. That is probably fine, but design should state plan output does not include full body. Consider body_length and hash_preview only unless verbose/debug.

This avoids logs becoming content replicas.

P9 — Default resolution should distinguish “no default” vs “ambiguous default policy”

Rev4 says if no default then require explicit. Good.

Add: if multiple defaults/config profiles exist in future, plan/create should STOP unless caller context selects a profile. This prevents hidden arbitrary default selection.

P10 — P0 must inspect existing Directus/API hooks, not only DOT/bin and pg_proc

Because the goal is native creation across adapters, existing hooks may already exist outside DOT bin.

P0 should search:

  • PG functions;
  • /opt/incomex/dot/bin;
  • app/API code if accessible;
  • Directus extension/hooks locations if present.

If absent/unavailable, report not found; do not assume.

Directive to Opus

Patch Pack 22 to rev5 with P1–P10.

This should be a final design hardening pass. Do not write execution prompt yet unless rev5 passes review.

Hard boundaries

  • no runtime mutation;
  • no PG function creation yet;
  • no DOT implementation;
  • no Pack 2C dispatch;
  • no adapter code;
  • no raw birth_registry insert;
  • no hardcoded constraint names/defaults/security assumptions.

Summary

Opus is right that advisory-lock collision is not a correctness blocker. The remaining blockers are not the advisory lock; they are hardcoded constraint names, incomplete preflight, security-definer policy, and adapter/body safety.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/reviews/gpt-review-pack22-rev4-native-contract-and-opus-pushback-2026-05-06.md