KB-7CAE rev 3

23-P3C2 — Apply + Wrapper Functions — Execution Report (PASS)

7 min read Revision 3
pack-23p3c2reportpassfn_iu_apply_edit_draftfn_iu_editp3d-ready

23-P3C2 — Apply + Wrapper Functions — Execution Report

Date: 2026-05-07 Verdict: PASS P3D Readiness: READY Predecessor: 24-P3B-FU PASS (invariant generalized for current-anchor) Successor: P3C3 (natural save router) → P3D (notification outbox) Operator: Claude Opus 4.7 VPS: 38.242.240.89, container=postgres, db=directus


Verdict

PASSpublic.fn_iu_apply_edit_draft(uuid,text,text)public.fn_iu_edit(text,text,text,text,text,text) đã được install. Toàn bộ 19/19 tests PASS. Generalized invariant từ P3B-FU làm việc đúng — i3_anchors_exact=true post-apply (current UV anchor check), không còn FAIL như P3C2 rev7 lần đầu.

Executive Summary

Item Value
Phase status PASS
Preflight PASS
Function create OK (atomic transaction)
Tests 19/19 PASS, TEST_FAIL=0
P3D readiness READY
Pilot A (applied) ea7fc2eb-d026-4e0e-bfe0-e12b0e0bc9f4
Pilot B (stale_base) f403cb0b-68f2-4e94-a972-6a889a7014fe
Test address pilot.iu0.test-001
New UV from T1 afdd281a-c213-4078-9bb4-d327f7b6c735 (seq=2)
New UV from T11 36719826-3605-4834-ae2d-d681117d8211
Owner directus (verified T15)
Grantees directus (PUBLIC revoked)
UV lifecycle draft (count=1, deterministic)
State IU 6→6, UV 6→8 (+2 from T1+T11), D 2→3, C 4→6 (+2 system comments)
P3C1 hashes unchanged true (T17 PASS)
Invariant all_pass post-apply true

Generalized Invariant Verification

Invariant JSON từ T1 (fn_iu_apply_edit_draft):

{
  "status": "applied",
  "version_seq": 2,
  "lifecycle_status": "draft",
  "stale_drafts_count": 1,
  "invariants": {
    "all_pass": true,
    "i1_iu_exists": true,
    "i2_uv_linked": true,
    "i3_anchors_exact": true,
    "i4_birth_exists": true,
    "i5_uv_birth_ok": true
  }
}

i3_anchors_exact = true xác nhận: post-apply, IU's version_anchor_ref = new UV (seq=2), generalized fn validates current anchor đúng. Birth checks (i4/i5) vẫn dùng seq=1, vẫn pass.

Tests T1-T19

# Test Result Note
T1 Apply DRAFT_A → status=applied PASS new UV seq=2, stale=1, inv all_pass=true
T2 UV count +1 PASS 6→7
T3 IU anchors point to new UV PASS both refs = afdd281a...
T4 DRAFT_A status=applied, applied_at, applied_version_ref PASS
T5 System comment created (kind=system) PASS ≥1
T6 DRAFT_B → stale_base, stale_at NOT NULL PASS same unit_id auto-staled
T7 Re-apply DRAFT_A → draft_not_open PASS
T8 UV unchanged after T7 PASS
T9 Apply stale DRAFT_B → draft_not_open PASS
T10 Direct INSERT → IU Gateway blocked PASS
T11 fn_iu_edit auto_apply → applied PASS new UV
T12 UV +1 more from T11 PASS 7→8
T13 Same body again → no_change PASS
T14 UV unchanged on no_change PASS
T15 SECDEF + search_path + owner + PUBLIC revoke + grantees PASS both functions
T16_APPLY apply has writer marker, UV insert, IU update, NO delete PASS
T16_WR fn_iu_edit has NO write statements (delegates only) PASS
T17 P3C1 hashes unchanged PASS edit_plan/create_edit_draft/comment_edit_draft/comment
T18 IU count unchanged PASS
T19 T1 invariant all_pass=true PASS i3 generalized works

Function Bodies (deployed)

public.fn_iu_apply_edit_draft(uuid,text,text)

  • LANGUAGE plpgsql VOLATILE SECURITY DEFINER, search_path=pg_catalog,public
  • Owner: directus, REVOKE PUBLIC, GRANT EXECUTE TO directus
  • Lifecycle self-determine (assert count(DISTINCT lifecycle_status)=1 → fail with lifecycle_ambiguous)
  • Single IU UPDATE (anchors + identity_profile.title if draft_title), single UV INSERT
  • content_anchor_ref = new_uv_id::text
  • Stale-base detection (base_version_ref != current anchor) + auto-stale sibling open drafts
  • Hash mismatch / no_change short-circuits before write
  • Invariant call post-write; raise exception on fail
  • Writer marker: set_config('app.canonical_writer','fn_iu_apply_edit_draft',true)
  • Returns: applied / draft_not_found / draft_not_open / stale_base / draft_hash_mismatch / no_change / lifecycle_ambiguous / invalid_input

public.fn_iu_edit(text,text,text,text,text,text)

  • LANGUAGE plpgsql VOLATILE SECURITY DEFINER, search_path=pg_catalog,public
  • Owner: directus, REVOKE PUBLIC, GRANT EXECUTE TO directus
  • NO direct writes (T16_WR PASS) — delegates to fn_iu_create_edit_draft then fn_iu_apply_edit_draft
  • Reads identity_profile.edit_policy → fallback dot_config.iu_edit.policy.default_mode → fallback auto_apply
  • If auto_apply → apply automatically; else returns draft_created_review_required
  • Internal convenience layer (P3C2 prompt note: not final AI front-door — that role goes to fn_iu_save in P3C3)

Security & Boundary Compliance

  • ❌ No table DDL / no trigger / no gateway changes
  • ❌ No P3C1 alterations (T17 PASS)
  • ❌ No direct IU/UV writes outside fn_iu_apply_edit_draft (writer marker enforced; T10 gateway blocks raw insert)
  • ❌ No vector mutation, no cleanup, no notification (deferred to P3D)
  • ✅ SECURITY DEFINER on both new functions (T15)
  • ✅ search_path=pg_catalog,public (T15)
  • ✅ Owner=directus matches fn_iu_create (T15)
  • ✅ PUBLIC EXECUTE revoked, only directus has EXECUTE (T15)

State Counts

Table Before After Δ
information_unit 6 6 0
unit_version 6 8 +2 (T1 seq=2, T11 seq=3)
unit_edit_draft 2 3 +1 (T11 created via fn_iu_edit)
unit_edit_comment 4 6 +2 (system comments from T1 + T11)

Test rows retained on PASS (no cleanup per prompt — official_test_rows_retained=true).

Roadmap Chain

  • Now (this report): P3C2 PASS — apply + edit wrapper functions deployed.
  • Next required: P3C3_NATURAL_SAVE_ROUTER_BEFORE_BROAD_AGENT_USE
    • Design: knowledge/dev/laws/dieu44-trien-khai/design/23-p3c3-iu-natural-save-router-design-note.md
    • Will introduce fn_iu_save as the AI front-door (auto-routes new vs edit by canonical_address presence).
  • Deferred to P3D: notification outbox before Hermes production.
    • Roadmap: knowledge/dev/laws/dieu44-trien-khai/design/23-p3d-notification-outbox-roadmap-note.md

AI Interface Surface (P3C2 — internal layer)

fn_iu_edit_plan(address, body, actor)           -- preview
fn_iu_create_edit_draft(address, body, actor)   -- draft
fn_iu_comment(address, author, body)            -- comment (free-flow, no approval)
fn_iu_apply_edit_draft(draft_id, actor)         -- apply (approval gate)
fn_iu_edit(address, body, actor, reason)        -- internal convenience wrapper

Future P3C3: fn_iu_save(address, body, actor) = AI front-door (auto-route new vs edit).

Logs

  • VPS log: /tmp/23-p3c2.20260507-113813.log
  • Local: /tmp/23-p3c2.sh