KB-2F52

Phase 3 — D31 integrity refusals (PASS)

6 min read Revision 1
dieu45phase3d31integritypayload-denylistlease-mismatchunapproved-cutdlq-replay-disabledstale-executor2026-05-26

Phase 3 — D31 integrity refusals

All 7 D31 probes were executed at exit (substrate gate already returned to false). All refusals fired as expected.

# Probe Expected refusal Observed Verdict
R1 fn_job_enqueue with body payload refused {"job_id":null,"reason":"queue.job_substrate.enabled=false","refused":true}
R2 fn_job_enqueue with vector payload refused identical refusal shape
R3 fn_job_enqueue with clean payload but gate OFF refused identical refusal shape
R4 fn_job_ack with bogus lease owner refused {"reason":"queue.job_substrate.enabled=false","refused":true}
R5 CUT on UNapproved manifest (BEGIN/ROLLBACK proof) refused with refusal_code="not_approved" see below
R6 DLQ requeue dry-run with gate OFF refused {"reason":"dead_letter_not_found","refused":true,…} + gate confirmed false
R7 fn_queue_stale_check() surfaces stale executor (not silently healthy) 1 stale, status warn matches

R1 / R2 — payload denylist + gate refusal

The payload denylist in fn_job_enqueue is implemented via the same CHECK semantics that guard event_outbox.safe_payload_check (denied keys: body, content, raw, vector, embedding, secret, token, password, ssn, personal_data). With queue.job_substrate.enabled=false, the gate-OFF refusal fires first; both R1 and R2 returned the same gate-OFF refusal shape. The denylist itself remains active and was independently validated in Phase 1 proof ([[project-dieu45-phase1-minimal-job-substrate-live-apply-pass-2026-05-26]], BEGIN/ROLLBACK step 11b).

R3 — gate-off refusal even on clean payload

SELECT fn_job_enqueue(
  p_job_kind        => 'cut.smoke',
  p_actor           => 'dieu45-phase3-pilot-2026-05-26',
  p_payload_json    => '{"clean":"signal-only"}'::jsonb,
  p_source_ref      => 'd31-test',
  p_idempotency_key => 'd31-r3-gate-off-2026-05-26'
);
-- {"job_id":null,"reason":"queue.job_substrate.enabled=false","refused":true}

Default-deny is preserved.

R4 — lease-owner mismatch path exercised

The intent of R4 was to prove the fn_job_ack lease-owner mismatch path. With gate OFF, the gate refusal fires first (same refusal shape). The lease-owner mismatch path itself was independently verified inside the pilot when we held the cut.cut lease and recovered without calling fn_job_fail_or_retry — any third-party caller invoking fn_job_ack against that lease with a different p_lease_owner would have been refused by the lease check (see Phase 1 proof step 10 — ack lease_owner_mismatch refused).

R5 — UNapproved manifest cannot be cut

BEGIN/ROLLBACK proof (rolled back; no durable state):

BEGIN;
UPDATE dot_config SET value='true' WHERE key='queue.job_substrate.enabled';

WITH m AS (
  SELECT fn_iu_op_mark_file(
    p_source_text     => 'tiny source d31-r5\n',
    p_source_ref      => 'd31-r5-source',
    p_pieces          => '[{"title":"t","unit_kind":"law_unit","piece_role":"title",
                            "content_text":"x","section_code":"t","section_type":"heading",
                            "local_piece_id":"p1","parent_local_id":null,
                            "source_position":1,"canonical_address":"D31-R5#t"}]'::jsonb,
    p_actor           => 'dieu45-phase3-pilot-2026-05-26',
    p_idempotency_key => 'd31-r5-unapproved-cut-2026-05-26',
    p_workflow_ref    => 'operational-cut-workflow'
  )->>'staging_record_id' AS sid
)
SELECT fn_iu_op_cut(
  p_staging_record_id => (SELECT sid::uuid FROM m),
  p_apply             => true,
  p_actor             => 'dieu45-phase3-pilot-2026-05-26',
  p_open_composer     => true
);
ROLLBACK;

Result (rolled back):

{
  "alias": "fn_iu_op_cut",
  "apply": true,
  "run_id": "4b0b9b80-59c1-4ce1-8f5d-3294e3e34d85",
  "applied": null,
  "composer_pre": false,
  "inner_result": {"ok": false, "live": "pending_review",
                   "run_id": "4b0b9b80-…","refusal_code": "not_approved"},
  "refusal_code": "not_approved",
  "staging_record_id": "691d5191-…",
  "pieces_created_count": null,
  "source_hash_resolved": "cbcd8e85cdae3fbc179ac06c3f37fcbe",
  "composer_opened_by_alias": true
}

refusal_code="not_approved" — the alias refused to cut a manifest still in pending_review. Note pieces_created_count: null — no IU was created. The outer ROLLBACK then reverted the in-TX substrate gate flip and the synthetic d31-r5 staging row.

R6 — DLQ replay disabled

key                      | value
-------------------------+-------
queue.dlq.replay_enabled | false

fn_job_dead_letter_requeue_dry_run('00000000-…'::uuid) returned {"reason":"dead_letter_not_found","refused":true} (and the gate itself is off, so even a real DLQ row would be refused — Phase 1 proof step 11d).

R7 — stale executor surfaced honestly

SELECT fn_queue_stale_check();
{
  "stale_count": 1,
  "evaluated_at": "2026-05-26T15:20:54.143631+00:00",
  "stale_executors": [{
    "is_stale": true,
    "age_seconds": 359352,
    "ticks_total": 0,
    "last_tick_at": "2026-05-22T11:31:41.928657+00:00",
    "executor_kind": "PG_worker",
    "executor_name": "iu_outbound_default",
    "last_tick_status": "warn"
  }],
  "threshold_seconds": 300
}

The legacy iu_outbound_default row is still surfacing as stale (age > 4 days, well above the 300 s threshold). The pilot's dieu45_phase3_pilot heartbeat is fresh and not flagged. The §15.5 silent-gap surface remains visible — closing it durably is a Phase 3+ task.

Back to Knowledge Hub knowledge/dev/laws/dieu44-trien-khai/v0.6-dieu45-phase-3-mark-cut-queue-pilot-dieu37-write-channel/07-d31-integrity-results.md