110000x · 04 — Điều 31 Integrity Contract + Refusal Tests
110000x · 04 — Điều 31 System Integrity Contract + Refusal Tests
Law: knowledge/dev/architecture/dieu31-review-request.md — contract-driven integrity: every alias must REFUSE every invalid path it could be misused for. The refusals must be deterministic and audit-logged.
Nine integrity invariants (each backed by a refusal test)
| # | Invariant | Refusal mechanism | Test |
|---|---|---|---|
| I1 | Cannot CUT unapproved manifest | G3 not_approved from fn_iu_cut_from_manifest |
R1 |
| I2 | Cannot CUT if manifest_digest changed |
G5 covered by digest stored at MARK time; alias re-derives from staging payload | R2 |
| I3 | Cannot CUT if source_hash changed |
G6 source_changed from fn_iu_cut_from_manifest (alias reads stored hash; if operator-provided text differs, MARK gets a new digest and old digest is no longer in staging) |
R3 |
| I4 | Cannot skip VERIFY-MARK | G3 not_approved (lifecycle stays pending_review until verify-mark applies approval) |
R4 |
| I5 | Cannot upload pending MARK payload to KB | Out-of-band rule: documented in START-HERE; agent-side discipline. Audit by inspecting any knowledge/.../mark_*pending* documents — must be zero. |
R5 |
| I6 | Cannot vectorize staging payload | Structural: iu_staging_record.vector_excluded=true CHECK + no FK from iu_vector_sync_point to staging. |
R6 |
| I7 | Cannot delete official IU pieces during cleanup | fn_iu_staging_cleanup operates only on iu_core.iu_staging_record rows; alias fn_iu_op_cleanup_dry_run calls with p_apply=false. |
R7 |
| I8 | Cannot use wrong destination outside approved corpus/staging rules | fn_iu_op_mark_file writes only to iu_core.iu_staging_*; fn_iu_op_cut writes only via fn_iu_create → public.information_unit. Alias bodies prove this by code inspection. |
R8 |
| I9 | Cannot mutate production_documents |
Table absent in directus DB; alias bodies reference zero such table. |
R9 |
R1 — Refuse CUT on unapproved manifest
BEGIN;
SELECT public.fn_iu_op_mark_file(
p_source_text:='r1 unapproved', p_source_ref:='R1', p_actor:='d31-r1',
p_pieces:='[{"local_piece_id":"p1","unit_kind":"design_doc_section","content_text":"r1","section_type":"paragraph","canonical_address":"R1#k1","piece_role":"body","source_position":1,"sort_order":1}]'::jsonb,
p_source_kind:='system'
) -> 'staging_record_id' \gset sid_
-- Skip approve. Try cut directly.
UPDATE dot_config SET value='true' WHERE key='iu_core.composer_enabled';
SELECT public.fn_iu_op_cut(:'sid_?column?'::uuid, true, 'd31-r1') -> 'refusal_code' AS code;
-- Expect: 'not_approved'
ROLLBACK;
Pass: code = "not_approved".
R2 — Refuse CUT on manifest_digest mismatch (structural)
Alias resolves source_hash from the staged manifest. If staged manifest's digest is tampered with after MARK (e.g., direct UPDATE to staging_payload), the digest verification inside fn_iu_cut_from_manifest (G5) rejects. Demonstration:
BEGIN;
SELECT public.fn_iu_op_mark_file(
p_source_text:='r2', p_source_ref:='R2', p_actor:='d31-r2',
p_pieces:='[{"local_piece_id":"p1","unit_kind":"design_doc_section","content_text":"r2","section_type":"paragraph","canonical_address":"R2#k1","piece_role":"body","source_position":1,"sort_order":1}]'::jsonb,
p_source_kind:='system'
) -> 'staging_record_id' \gset sid_
SELECT public.fn_iu_op_verify_mark(:'sid_?column?'::uuid, true,
'knowledge/.../approval-r2.md','d31-r2','d31-r2');
-- Tamper with stored manifest_digest:
UPDATE iu_core.iu_staging_payload
SET payload_json = jsonb_set(payload_json, '{manifest_digest}', '"00000000000000000000000000000000"')
WHERE staging_record_id = :'sid_?column?'::uuid AND part_name='cut_manifest';
UPDATE dot_config SET value='true' WHERE key='iu_core.composer_enabled';
SELECT public.fn_iu_op_cut(:'sid_?column?'::uuid, true, 'd31-r2') -> 'refusal_code' AS code;
-- Expect: 'digest_changed' (G5)
ROLLBACK;
Pass: code = "digest_changed".
R3 — Refuse CUT on source_hash mismatch
BEGIN;
SELECT public.fn_iu_op_mark_file(
p_source_text:='r3 original', p_source_ref:='R3', p_actor:='d31-r3',
p_pieces:='[{"local_piece_id":"p1","unit_kind":"design_doc_section","content_text":"r3 original","section_type":"paragraph","canonical_address":"R3#k1","piece_role":"body","source_position":1,"sort_order":1}]'::jsonb,
p_source_kind:='system'
) -> 'staging_record_id' \gset sid_
SELECT public.fn_iu_op_verify_mark(:'sid_?column?'::uuid, true,
'knowledge/.../approval-r3.md','d31-r3','d31-r3');
UPDATE dot_config SET value='true' WHERE key='iu_core.composer_enabled';
-- Direct call with WRONG source_hash (alias resolves from staging; can't be tricked).
-- But operator could bypass the alias and call core fn with wrong hash:
SELECT public.fn_iu_cut_from_manifest(:'sid_?column?'::uuid, true, 'WRONG_HASH', 'd31-r3') -> 'refusal_code' AS code;
-- Expect: 'source_changed' (G6)
ROLLBACK;
Pass: code = "source_changed".
R4 — Refuse CUT when VERIFY-MARK skipped
Same as R1 (no approval → not_approved). The alias contract does not auto-approve; operator must invoke fn_iu_op_verify_mark(sid, true, …). There is no --skip-verify flag in any alias.
R5 — Pending MARK payload MUST NOT land in KB
Static rule, agent-side. Verification:
# Run from operator workstation
$ <KB search> "mark pending payload" → expect zero hits in knowledge/.../110000x-* or earlier
KB search verification (programmatic):
mcp__claude_ai_Incomex_KB__list_documents(
path="knowledge/dev/laws/dieu44-trien-khai/v0.6-iu-core-110000x-operator-alias-surface-d30-d31-protection/"
) → 12 reports + 0 mark_*pending* documents
START-HERE explicitly forbids uploading pending MARK files. Audited at agent-prompt level.
R6 — Vectorization of staging payload is structurally impossible
-- 1. CHECK constraint
SELECT pg_get_constraintdef(oid) FROM pg_constraint
WHERE conrelid='iu_core.iu_staging_record'::regclass
AND conname='iu_staging_record_vector_excluded_chk';
-- Expect: CHECK ((vector_excluded = true))
-- 2. iu_vector_sync_point has no FK or column referencing iu_staging_*
SELECT column_name FROM information_schema.columns
WHERE table_name='iu_vector_sync_point'
AND column_name ~ 'staging';
-- Expect: 0 rows
-- 3. Sidecar absent (Q5 confirmed): collection_registry_vector_policy not present
SELECT to_regclass('iu_core.collection_registry_vector_policy') IS NULL AS absent;
-- Expect: true (or present but no link to staging — both safe)
-- 4. Alias bodies: no Qdrant / dblink / http_post call
SELECT proname FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace
WHERE n.nspname='public' AND p.proname LIKE 'fn_iu_op_%'
AND prosrc ~* '(qdrant|dblink|http_post|pg_net)';
-- Expect: 0 rows
R7 — Cleanup cannot delete official IU pieces
-- fn_iu_staging_cleanup operates ONLY on iu_core.iu_staging_record
SELECT prosrc FROM pg_proc WHERE proname='fn_iu_staging_cleanup';
-- Inspect: zero references to public.information_unit / iu_vector_sync_point write paths
SELECT public.fn_iu_op_cleanup_dry_run(15, 'd31-r7') -> 'apply' AS apply_mode;
-- Expect: false (alias never calls fn_iu_staging_cleanup with p_apply=true)
R8 — Wrong destination refused
Alias bodies are explicit:
fn_iu_op_mark_filecalls onlyfn_iu_mark_create_manifest→ only writesiu_core.iu_staging_record+iu_core.iu_staging_payload.fn_iu_op_cutcalls onlyfn_iu_cut_from_manifest→ which usesfn_iu_create+fn_iu_collection_add_piece→ only writespublic.information_unit+public.iu_piece_membership+public.iu_piece_collection+ audit.
Static verification:
SELECT proname, prosrc FROM pg_proc
WHERE proname LIKE 'fn_iu_op_%'
AND prosrc ~* '(information_unit|iu_vector_sync_point|production_documents)'
ORDER BY proname;
-- Expect: zero matches for production_documents; iu_op_* never names these tables directly.
R9 — production_documents mutation impossible
SELECT to_regclass('public.production_documents') IS NULL AS absent;
-- Expect: true (table absent in directus DB; alias cannot write to non-existent table)
SELECT proname FROM pg_proc p JOIN pg_namespace n ON n.oid=p.pronamespace
WHERE n.nspname='public' AND p.proname LIKE 'fn_iu_op_%'
AND prosrc ILIKE '%production_documents%';
-- Expect: 0 rows
Refusal audit trail
Every refusal returned by fn_iu_cut_from_manifest is recorded in dot_iu_command_run with run_status='refused' + evidence JSONB containing the refusal_code. Post-suite tally:
SELECT run_status, count(*) FROM dot_iu_command_run
WHERE created_at > now() - interval '1 hour'
GROUP BY 1;
-- Expect: each refusal test contributes 1 row with run_status='refused'
Verdict template (post-apply)
IU_CORE_110000X_DIEU31_INTEGRITY_PASS
- R1 not_approved: PASS
- R2 digest_changed: PASS
- R3 source_changed: PASS
- R4 skip-verify-blocked: PASS (subset of R1)
- R5 no-pending-MARK-in-KB: PASS (KB list audit)
- R6 vectorization-impossible: PASS (4-layer structural)
- R7 cleanup-staging-only: PASS (code + apply=false)
- R8 destination-bounded: PASS (static)
- R9 production_documents-safe: PASS (table absent + bodies clean)