Phase 3 — Hard Gate 0 write-channel proofs (PASS)
Phase 3 — Hard Gate 0 (write channel) proofs
All 9 prerequisites passed before any pilot mutation.
1. Real shell + SSH + Docker
$ ssh contabo 'uname -a'
Linux vmi3080463 6.8.0-90-generic #91-Ubuntu SMP PREEMPT_DYNAMIC … x86_64 GNU/Linux
$ ssh contabo 'docker ps --format "{{.Names}}\t{{.Image}}\t{{.Status}}" | grep -i postgres'
pg-restore-test-20260520T031054Z postgres:16 Up 6 days
postgres postgres:16 Up 5 weeks (healthy)
2. psql -U workflow_admin -d directus is write-capable
SELECT current_user, current_database(), pg_has_role(current_user,'workflow_admin','MEMBER');
-- workflow_admin | directus | t
(Contrast: the prior attempt used MCP query_pg, which binds context_pack_readonly — explicit non-member of workflow_admin — and failed Hard Gate 0 by design.)
3. BEGIN/ROLLBACK DDL+DML probe
BEGIN
CREATE TABLE -- CREATE TEMP TABLE __probe_x(id int);
INSERT 0 1 -- INSERT INTO __probe_x VALUES (1);
probe_count = 1
ROLLBACK
?column? = 'rollback_ok'
4. pg_dump -Fc works from inside the container
$ docker exec postgres pg_dump -U workflow_admin -d directus -Fc --schema-only -f /tmp/__probe_dump.fc
-rw-r--r-- 1 root root 1828541 May 26 14:18 /tmp/__probe_dump.fc
Full-data baseline (later) 83,207,353 B; post-pilot 83,224,464 B (+17,111 B).
5. job_queue / job_dead_letter / queue_heartbeat exist
SELECT to_regclass('public.job_queue'),
to_regclass('public.job_dead_letter'),
to_regclass('public.queue_heartbeat');
-- job_queue | job_dead_letter | queue_heartbeat
6. MARK / CUT aliases all 5 present
fn_iu_op_cleanup_dry_run(p_older_than_days integer, p_actor text)
fn_iu_op_cut(p_staging_record_id uuid, p_apply boolean, p_actor text, p_open_composer boolean)
fn_iu_op_mark_file(p_source_text text, p_source_ref text, p_pieces jsonb, p_actor text,
p_source_kind text, p_idempotency_key text, p_mark_report_md text, p_workflow_ref text)
fn_iu_op_verify_cut(p_run_id uuid, p_actor text)
fn_iu_op_verify_mark(p_staging_record_id uuid, p_approve boolean,
p_approval_doc_id text, p_approver text, p_actor text)
All signatures are also re-checked in 06-d30-regression-results.md to prove no in-pilot mutation of alias surface.
7. Queue fns present
fn_job_enqueue / fn_job_claim / fn_job_ack / fn_job_fail_or_retry / fn_job_move_to_dead_letter
fn_job_reap_stale_leases_dry_run / fn_job_reap_stale_leases_apply
fn_job_dead_letter_requeue_dry_run / fn_job_dead_letter_triage_update
fn_queue_heartbeat_tick / fn_queue_heartbeat_register_passive / fn_queue_stale_check
8. Điều 37 source available
Source was fetched via mcp__claude_ai_Incomex_KB__get_document_for_rewrite on
knowledge/dev/laws/dieu37-governance-organization-law.md (revision 5, 20,482 chars). Written to
/tmp/dieu37_source.txt (23,387 UTF-8 bytes) and scp'd into the container.
9. Gate state at entry (recorded before any mutation)
queue.dlq.replay_enabled | false
queue.heartbeat.enabled | true
queue.heartbeat.stale_threshold_seconds | 300
queue.job_substrate.enabled | false <-- inert; we flip it ON for the pilot, then back
queue.lease.duration_sec | 300
queue.lease.reaper_dry_run_only | true
queue.lease.reaper_enabled | false
queue.notify.enabled | false
queue.retry.backoff_base_sec | 10
queue.retry.max_attempts_default | 5
queue.runtime.phase | phase2_governance
queue.worker.enabled | false
iu_core.composer_enabled | false <-- flipped ON during cut by alias, closed after
Gates at exit are identical to entry (see 00-summary.md §1 and 06-d30-regression-results.md T6).
Verdict
HARD_GATE_0_WRITE_CHANNEL_PASS — pilot was authorized to proceed.