KB-2480

Fix R2-3 — P6 Digest Includes Harness Rows (Atomic)

4 min read Revision 1
c1stagingcodex-r2-fixp6digestharness2026-06-23

05 — FIX R2-3: P6 DIGEST SPANS HARNESS ROWS, ATOMIC

File: sql/p6-evidence-readback.sql (sha256 212ebc0e23c6f8996d76411f4f1e09a78b901dae1eb5bf1fd8f6c3da977c4118).

Requirement

Digest must include verified canonical_operation rows AND the P5 bad-input harness rows; gate + ledger + digest in one transaction (or under locks); no digest/P6_DONE on failure.

Code — digest spans BOTH tables

CREATE OR REPLACE FUNCTION c1_digest() RETURNS jsonb LANGUAGE plpgsql AS $f$
DECLARE vops text; vharness text; BEGIN
  SELECT string_agg(operation_code||'|'||operation_title||'|'||operation_group||'|'||required_inputs::text||'|'||expected_outputs::text||'|'||allowed_modes::text||'|'||status, E'\n' ORDER BY operation_code)
    INTO vops FROM canonical_operation;
  SELECT string_agg(case_no::text||'|'||COALESCE(expect_code,'')||'|'||COALESCE(expect_state,'')||'|'||outcome||'|'||COALESCE(reject_code,'')||'|'||COALESCE(sqlstate,'')||'|'||pass::text, E'\n' ORDER BY case_no)
    INTO vharness FROM c1_test_results WHERE phase='bad';
  RETURN jsonb_build_object(
    'vocab_row_count',(SELECT count(*) FROM canonical_operation),
    'vocab_md5',md5(COALESCE(vops,'')),
    'harness_row_count',(SELECT count(*) FROM c1_test_results WHERE phase='bad'),
    'harness_md5',md5(COALESCE(vharness,'')),
    'combined_md5',md5(COALESCE(vops,'')||E'\n##C1_HARNESS##\n'||COALESCE(vharness,'')),
    'generated_at',now()); END;$f$;

Harness fields hashed: case_no, expect_code, expect_state, outcome, reject_code, sqlstate, pass — exactly the nine case expectations/outcomes/reject signals.

Code — gate + ledger + digest in ONE SHARE-locked txn (no TOCTOU); digest persisted in-txn

BEGIN;
LOCK TABLE canonical_operation, c1_test_results IN SHARE MODE;
DO $g$ ... (P3/P4/P5 evidence; 3 validated ops; 9/9 bad pass/0 fail/0 accepted;
            case-8 42P01 isolation proof; 0 orphan) -- RAISES on any failure ... $g$;
INSERT INTO sbx_meta.dot_manage_ledger(sandbox_id,op,actor,detail)
  VALUES (:'sbx','c1_evidence_readback',:'operator',
          jsonb_build_object('gate','C1_STAGING_FAST_DRY_RUN_PASS','digest',c1_digest()));
COMMIT;
-- readback the PERSISTED digest (authenticated inside the gated txn; NOT recomputed post-hoc)
SELECT jsonb_pretty(detail->'digest') FROM sbx_meta.dot_manage_ledger
  WHERE op='c1_evidence_readback' AND sandbox_id=:'sbx' ORDER BY seq DESC LIMIT 1;

Why the proofs hold

  • Digest cannot be emitted before upstream checks: the digest is computed inside the same txn, AFTER the DO gate, and only the persisted value is read back. If the gate RAISEs, the txn aborts; with ON_ERROR_STOP=1 psql exits at the DO statement, the INSERT/COMMIT never run, nothing commits, and the readback statements are never reached.
  • Digest spans harness rows: the gate guarantees exactly 9 harness rows and 3 validated ops are present and frozen (SHARE locks) when c1_digest() runs, so combined_md5/harness_md5 authenticate that exact snapshot.
  • P6_DONE cannot appear without the digest: the bin wrapper prints P6_DONE only on psql exit 0, which requires the gated txn (digest persisted) + readback to succeed.

Validation (static, no execution)

Dollar-quote tags balanced ($f$=2, $g$=2, $d$=0); BEGIN/COMMIT 2/2; LOCK TABLE … IN SHARE MODE present; digest references c1_test_results; combined_md5+harness_md5 present; persisted-digest INSERT present. Harness column names match the P5 c1_test_results schema. SQL was NOT executed against any DB (no sandbox created; official runtime read-only).

Back to Knowledge Hub knowledge/dev/laws-new/reports/c1-staging-codex-r2-fixes-ready-for-r3/05-fix-p6-digest-includes-harness.md