KB-38DA
23-P3C3 — IU Natural Save Router — Execution Report
7 min read Revision 1
p3c3dieu44fn_iu_savereportPASS
23-P3C3 — IU Natural Save Router — Execution Report
Date: 2026-05-07 Prompt: knowledge/dev/laws/dieu44-trien-khai/prompts/23-p3c3-iu-natural-save-router-prompt.md (rev3) Status: PASS Log:
/tmp/23-p3c3.20260507-121717.log(VPS 38.242.240.89)
Summary
- phase_status=PASS
- T1–T14 all PASS (T4 applied: policy=auto_apply branch)
public.fn_iu_save(text,text,text,text,text,text)created and persisted- All hard boundaries respected — no DDL on tables, triggers, gateway; no IU/UV writes inside fn_iu_save; no canonical_writer marker; no policy switch; protected functions untouched (count=9, hashes identical)
Phase outcome
| Field | Value |
|---|---|
| phase_status | PASS |
| preflight | PASS |
| function_creation | OK |
| test_failures | 0 |
| owner | directus |
| function_security | SECDEF, search_path=pg_catalog,public, PUBLIC revoked |
| p3c_unchanged | true |
| protected_function_count_before | 9 |
| protected_function_count_after | 9 |
| policy_before | auto_apply |
| policy_after | auto_apply (T14 unchanged) |
Counts (T13)
| Table | Before | After | Delta | Expected (auto_apply) |
|---|---|---|---|---|
| information_unit | 8 | 9 | +1 | +1 (T1) |
| unit_version | 12 | 14 | +2 | +2 (T1, T3) |
| unit_edit_draft | 7 | 9 | +2 | +2 (T2 open, T3 applied) |
| unit_edit_comment | 8 | 10 | +2 | +2 (T3 system + T7 user) |
T13=PASS
Test results
| Test | Result | Notes |
|---|---|---|
| T1 — new address → official IU + version 1 | PASS | status=created; iu=1, uv=1, version_seq=1, invariants all_pass=true |
| T2 — existing addr, mode=draft → draft only, no UV | PASS | status=draft_created_review_required; uv unchanged 13→13 |
| T3 — existing addr, mode=auto, policy=auto_apply | PASS | status=applied; uv 13→14 |
| T4 — same body re-save → no_change (T3 applied branch) | PASS | status=no_change |
| T5 — invalid mode rejected | PASS | status=invalid_input |
| T6 — empty address/body/actor rejected | PASS | all three return invalid_input |
| T7 — fn_iu_comment free-flow with explicit draft context | PASS | status=comment_added; comments 9→10 |
| T8 — source check: no direct IU/UV writes, no canonical_writer marker | PASS | has_insert=f, has_update=f, has_delete=f, has_marker=f |
| T9 — security (SECDEF, search_path, owner, PUBLIC revoked) | PASS | prosecdef=t, search_path includes pg_catalog, owner=directus, PUBLIC EXECUTE=0 |
| T10 — grantees can EXECUTE | PASS | directus has_function_privilege=t |
| T11 — wrong-door direct IU INSERT still gateway-blocked | PASS | "IU Gateway blocked" raised |
| T12 — protected function hashes & count unchanged | PASS | count=9 before/after; hashes identical |
| T13 — counts match policy expectations | PASS | see table above |
| T14 — policy unchanged | PASS | iu_edit.policy.default_mode=auto_apply (no switch) |
Pilot artifacts
| Field | Value |
|---|---|
| test_new_addr | test/p3c3/pilot-20260507-121717 |
| t1_status | created |
| t2_draft_id | e79fb157-789e-433c-bb91-025094175e5c |
| t3_status | applied |
| t3_draft_id | 2afaa131-5665-4557-8017-b6af31ab24ad |
| t3_version_id | eae754de-1f58-41c1-80d4-cfbcbad708ab |
| t7_comment_status | comment_added |
(t1_unit_id/t1_version_id empty in returned JSON — fn_iu_create returns these under different keys; downstream count check T1_IU=1, T1_UV=1, T1_SEQ=1, T1_INV=true confirmed correctness.)
fn_iu_save signature
public.fn_iu_save(
p_address text,
p_body text,
p_actor text,
p_title text DEFAULT NULL,
p_reason text DEFAULT NULL,
p_mode text DEFAULT 'auto' -- 'auto' | 'draft'
) RETURNS jsonb
LANGUAGE plpgsql
VOLATILE
SECURITY DEFINER
SET search_path = pg_catalog, public
Routing logic:
- New address →
fn_iu_create(address, title || address, body, actor) - Existing address →
fn_iu_create_edit_draft(address, body, actor, reason, title)- mode='draft' → return
draft_created_review_required - mode='auto' + policy=auto_apply →
fn_iu_apply_edit_draft(draft_id, actor, reason) - mode='auto' + policy=require_review → return
draft_created_review_requiredwith policy field
- mode='draft' → return
Hard boundaries — verified
- ❌ No table DDL — only
CREATE FUNCTION/REVOKE/GRANT - ❌ No trigger/gateway changes
- ❌ No vector mutation
- ❌ No notification implementation
- ❌ No cleanup/pilot deletion (test rows retained on PASS)
- ❌ No alteration of P3C1/P3C2/P3B-FU functions (T12 hash stable, count=9)
- ❌ No P3D implementation
- ❌ No comment approval logic
- ❌ No broad-use policy switch in P3C3 (T14)
- ❌ No direct IU/UV INSERT/UPDATE/DELETE inside fn_iu_save (T8)
- ❌ No
app.canonical_writermarker inside fn_iu_save (T8)
Deviations from prompt rev3 (preflight/test adjustments only — no logic change)
- Preflight signature for
fn_iu_create: prompt expected(text,text,text,text); actual function in DB has 9 args with 5 defaults:(text,text,text,text,text,text,text,text,uuid). Adjusted preflightto_regprocedurelookup to actual signature. fn_iu_save body still callsfn_iu_createwith 4 positional args (remaining args default to NULL). No change to fn_iu_create. - T7 fn_iu_comment kind: prompt used
'note'; actual validation acceptsgeneral/review/change_request/approval/system. Used'general'. - T7 author_type: prompt passed
NULL; column is NOT NULL. Used'agent'.
These are test-harness fixes against the live schema; the protected functions and policy remain untouched (T12=PASS, T14=PASS).
AI front-door surface (after P3C3)
fn_iu_save(address, body, actor) -- create/edit content (front-door)
fn_iu_comment(address, actor, comment) -- free-flow comment (front-door)
fn_iu_apply_edit_draft(draft_id, actor) -- reviewer approval button
Cleanup semantics
| Field | Value |
|---|---|
| cleanup_on_test_fail | drop_fn_iu_save_only |
| test_rows_retained_on_fail | true |
| test_rows_retained_on_pass | true |
P3C3 PASS → fn_iu_save persists; pilot test rows retained per prompt.
Next steps
- next_required_step — switch
iu_edit.policy.default_modetorequire_reviewfor broad use (separate policy-pack phase) - Update Agent context pack / README to point AI at the 2 front-doors + 1 approval button
- deferred — P3D notification outbox before Hermes production cutover
P3C3 PASS | 14 tests | fn_iu_save live | protected_count=9 unchanged | policy=auto_apply preserved