100000x · 02 — Re-author + apply 040R (CUT from approved manifest)
100000x · 02 — Re-author + apply 040R
Phase: B · Status: APPLIED · Migration: 040R
Apply
ssh contabo 'docker exec -i postgres psql -U workflow_admin -d directus -v ON_ERROR_STOP=1' < /tmp/iu100000x/040R-cut-from-manifest.sql
Result: BEGIN / CREATE FUNCTION / INSERT 0 1 / COMMIT. One TX, atomic.
Smoke test (immediate, no separate proof TX)
G1 | {ok:false, refusal_code:not_found, run_id:<uuid>}
G2 | {ok:false, refusal_code:wrong_kind, staging_kind:sql_snapshot, run_id:<uuid>}
CAT | dot_iu_cut_from_manifest registered (1 row)
Substrate validates. plpgsql function body successfully resolves all SQL statement column references at runtime ([[feedback-plpgsql-check-function-bodies-defers-sql-stmt-resolution]] guard).
Contract (preserved from 90000x report 05)
| Input | Type | Default |
|---|---|---|
p_staging_record_id |
uuid | (required) |
p_apply |
boolean | false |
p_source_hash |
text | NULL |
p_actor |
text | 'fn_iu_cut_from_manifest' |
Returns jsonb:
- Refusal:
{ok:false, refusal_code:<code>, ...context, run_id:<uuid>} - Dry-run:
{ok:true, dry_run:true, pieces_planned:<n>, guards_passed:[G1..G7], run_id} - Apply:
{ok:true, applied:true, run_id, staging_record_id, pieces_created_count:<n>, pieces_created:[uuid,...]}
G1-G7 guards (live signatures honored)
| Guard | Check | Refusal code |
|---|---|---|
| G1 | SELECT FOR UPDATE of staging row finds it |
not_found |
| G2 | staging_kind = 'mark_manifest' |
wrong_kind |
| G3 | lifecycle_status = 'approved' (consumed/pending/etc all refuse) |
not_approved |
| G4 | approved_at AND approved_by AND approval_doc_id all NOT NULL |
incomplete_approval |
| G5 | manifest.manifest_digest ~ ^[0-9a-f]{32}$ |
digest_changed |
| G6 | p_source_hash matches manifest.source_hash (if both provided) |
source_changed |
| G7 | fn_iu_composer_enabled() returns true |
composer_gate_closed |
SELECT FOR UPDATE provides concurrency safety: parallel cut attempts on the same staging row serialize; the second caller observes lifecycle_status='consumed' and refuses via G3.
Drift patches vs 90000x mig 040 (mechanical, contract preserved)
| Original (90000x) | Live | 040R fix |
|---|---|---|
v_unit_id := fn_iu_create(unit_kind, content_text, section_type, piece_role, canonical_address, source_position) returning uuid |
fn_iu_create(p_canonical_address, p_title, p_body, p_actor, p_unit_kind, p_section_type, p_owner_ref, p_publication_type, p_parent_ref) returning jsonb |
Call with named params; extract via (result->>'iu_id')::uuid |
| (none) | fn_iu_create writes section_type to identity_profile only |
Follow with UPDATE information_unit SET sort_order, section_type, doc_code, section_code WHERE id=v_unit_id |
fn_iu_collection_add_piece(parent_uuid, child_uuid, piece_role, source_position) |
Not appropriate for parent-child IU edges (it's for piece↔collection edges) | Use p_parent_ref on fn_iu_create directly; no membership write in 040R |
INSERT INTO dot_iu_command_run (command_name, payload_json, actor, status) VALUES (..., 'running') |
Live columns: category, run_mode, run_status, evidence. No payload_json / status / running |
One INSERT per call with run_mode ∈ {plan,apply}, run_status ∈ {refused,planned,applied}, evidence jsonb |
DOT catalog category='cut' |
Vocab is {collection, piece, lifecycle, read, health} |
category='piece' |
Algorithm
SELECT FOR UPDATEstaging row. G1 fail → audit refused + return.- G2 / G3 / G4 sequential checks, each emits a refusal audit on miss.
- Load
cut_manifestpayload_json. G5 digest 32-hex check. - G6 source_hash compare (if both sides present).
- G7 composer gate.
- If
p_apply=false→ auditplanned+ return dry-run shape. - Loop pieces ordered
(parent_local_id NULL FIRST, source_position ASC):- Resolve
v_parent_uuidfrom local map. - Call
fn_iu_createwith all named params (title = first line of body, fallback to canonical_address; truncated to 200 chars). - Assert
result->>'status' = 'created'; RAISE otherwise (whole TX rolls back). UPDATE information_unit SET sort_order, section_type, doc_code, section_code WHERE id = v_unit_id.- Append
(local_id, unit_id)tov_local_to_unit, appendv_unit_idtov_pieces_created.
- Resolve
- Audit row
run_status='applied'withevidencecarryingrun_id, staging_record_id, manifest_digest, pieces_created, pieces_created_count. - UPDATE staging row →
lifecycle_status='consumed',consumed_at=now(),consumed_by_run_id=v_run_id,referenced_iu_ids=v_pieces_created, appendcut_pieces_created/cut_run_id/cut_attometadata. - Return
{ok:true, applied:true, run_id, staging_record_id, pieces_created_count, pieces_created}.
Any RAISE in steps 7-9 triggers TX rollback; staging row stays approved, no IU pieces persist.
Rollback
BEGIN;
DELETE FROM public.dot_iu_command_catalog WHERE command_name='dot_iu_cut_from_manifest';
DROP FUNCTION IF EXISTS public.fn_iu_cut_from_manifest(uuid, boolean, text, text);
COMMIT;
Refuse to rollback if any staging row currently has lifecycle_status='consumed' with consumed_by_run_id populated (would orphan audit linkage). 100000x leaves no such rows (proof rolled back).
Cross-links
- [[feedback-fn-iu-create-returns-jsonb-not-uuid]] (refresh: key is
iu_id) - [[feedback-information-unit-no-piece-role-column]]
- 90000x report 05 (original author intent).