Skip to content

feat(document-records): make persistence retries idempotent - #312

Draft
seonghobae wants to merge 70 commits into
feat/document-record-persistencefrom
feat/document-record-idempotent-persistence
Draft

feat(document-records): make persistence retries idempotent#312
seonghobae wants to merge 70 commits into
feat/document-record-persistencefrom
feat/document-record-idempotent-persistence

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Finding

#107 makes document metadata immutable and tenant-scoped, and #312 adds authoritative uncertain-retry receipts. The production persistence boundary is now an execute-only database capability: persist_document_record_once(...) is owned by a deny-default SECURITY DEFINER role, the executor receives function EXECUTE but no direct document/receipt DML, PUBLIC EXECUTE is revoked, and function-local tenant-before-lock, Read Committed, UTC digest, advisory-serialization, FORCE-RLS and replay/conflict controls remain fail closed.

A fresh DDD/data-model audit then found a separate canonical-truth gap tracked by #313: migration 0024 created document_record_persist_receipt, but the canonical Data Model, ERD, and migration-backed object inventory did not all register that relation. The first ERD repair also overstated total cardinality as mandatory one-to-one even though migration 0024 does not backfill pre-existing document_record rows. Both defects are now repaired ordinary-forward.

Current exact authority

Current RED → causal repair

Database-capability lineage: 12b474b5fd4218d6d9d94e5c2869b9c503035b71 added real-PostgreSQL ACL RED; 50c0259a24089cba7e848ab97887cbf0f581746e implemented the deny-default owner/executor SECURITY DEFINER boundary. ADR 0309, traceability, OPERABILITY, SECURITY, THREAT_MODEL, and TEST_STRATEGY describe the same capability boundary.

Canonical-model lineage for #313:

  • 1b714de0050276832e5e656a9065e65b89580b4a: registers document_record and document_record_persist_receipt purpose, tenant/idempotency identity, receipt digest/database time, PII exclusion, replay semantics, and lifecycle boundary in docs/DATA_MODEL.md.
  • 792a9060807cf225eeec4e7a9d90346a978ec64f: adds receipt relationship/cardinality to docs/ERD.md.
  • ce7a5807fcf109fe2588d94f3eeef62f18f995f0: adds document_record_persist_receipt to canonical and migration-backed database object inventories.
  • f8d035c2e65401149612023a18d99bba370ea425: adds a focused regression proving comments/string/dollar-quoted fake CREATE TABLE text cannot satisfy receipt migration identity.
  • 1ba3a15ef3e0c9f60e3b5f36526271382610cc95: reseals the 96-artifact Foundation manifest after the above repair.
  • 0bdf9012d4f46e52b482694e6c0272b38d18d816: corrects the ERD from mandatory one-to-one to dataset-level zero-or-one receipt per document; the idempotent write port still creates exactly one receipt for each first committed command, while historical/pre-port document rows need no synthetic backfill.
  • b996e19090e5cc38ef0a4d41a8b4de6d561b89d8: reseals the corrected ERD bytes in manifest.json.

The existing database function semantics are unchanged by the #313 repair.

Executable acceptance

The owner-neutral PostgreSQL roots remain:

  • tests/test_document_record_idempotency_postgres.sh
  • tests/test_document_record_idempotency_function_acl_postgres.sh
  • tests/test_document_record_idempotency_isolation_postgres.sh
  • tests/test_document_record_idempotency_tenant_context_postgres.sh

tests/document_record_idempotency_postcommit_recovery_companion.sh remains the reviewed companion of the main idempotency root and must not become a filename-specific Foundation switch.

For #313, the deterministic Foundation contract now requires document_record_persist_receipt in both canonical object inventories and requires executable migration DDL after PostgreSQL comments and literal bodies are masked. At 1ba3a15..., exact-tree npm run validate passed all 56 Node tests plus Python/Foundation/OpenAPI/dispatcher validation and the generated manifest candidate matched committed bytes. The later 0bdf901... change only corrects ERD cardinality and b996e190... reseals that exact ERD; protected-base PostgreSQL acceptance remains separately pending.

Evidence boundary and integration

This PR targets #107 while #310/#311 own PostgreSQL Foundation admission on a separate prerequisite stack. Do not create a feature-local workflow, temporarily retarget to develop, synthesize statuses, self-approve, transfer predecessor GREEN, or weaken protected gates.

Keep Draft until #107 and the Foundation prerequisite stack (#258/#259#310/#311 or verified successors) integrate or this branch is ordinary-forward reconciled onto then-current protected truth. After reconciliation, Foundation must discover all four roots plus the reviewed recovery companion from the immutable exact-candidate tree, execute them in isolated PostgreSQL containers, and reacquire exact-head Foundation/SAST/Security/CodeQL/OpenCode/Noema/Strix plus qualifying independent review evidence before normal merge.

Refs #309, #313.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/document-record-idempotent-persistence

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review the current exact head, especially the transaction-scoped idempotency serialization, replay digest binding, tenant-qualified receipt FK/RLS, and the real-concurrency PostgreSQL contract. Do not treat predecessor #107 evidence as current-head acceptance.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== PR metadata and exact head =='
gh pr view 312 --repo ContextualWisdomLab/Orgmetra \
  --json number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,statusCheckRollup}'

echo '== Changed files at the PR head =='
gh pr diff 312 --repo ContextualWisdomLab/Orgmetra --name-only

echo '== Repository head =='
git rev-parse HEAD
git status --short

echo '== Locate relevant artifacts =='
fd -a -i '0024.*document.*record.*idempotent.*persistence.*\.sql|0309.*|test_document_record_idempotency_postgres\.sh' . || true

echo '== SQL migration outline and content =='
sql_file="$(fd -a -i '0024.*document.*record.*idempotent.*persistence.*\.sql' . | head -n1)"
if [ -n "$sql_file" ]; then
  ast-grep outline "$sql_file" --items all || true
  nl -ba "$sql_file"
fi

echo '== PostgreSQL contract content =='
test_file="$(fd -a -i 'test_document_record_idempotency_postgres\.sh' . | head -n1)"
if [ -n "$test_file" ]; then
  nl -ba "$test_file"
fi

echo '== ADR content =='
adr_file="$(fd -a -i '0309.*' . | head -n1)"
if [ -n "$adr_file" ]; then
  nl -ba "$adr_file"
fi

echo '== Related table definitions, policies, and persistence callers =='
rg -n -i -C 4 \
  'document_records?|idempotency|replay.*receipt|persist_document_record_once|row level security|create policy|force row level' \
  --glob '*.sql' --glob '*.sh' --glob '*.md' .

Length of output: 202018


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sql=database/migrations/0024_document_record_idempotent_persistence.sql
test=tests/test_document_record_idempotency_postgres.sh

echo '== Exact PR head and changed files =='
gh pr view 312 --repo ContextualWisdomLab/Orgmetra \
  --json headRefOid,baseRefOid,isDraft,state,mergeStateStatus,statusCheckRollup \
  --jq '{headRefOid,baseRefOid,isDraft,state,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,conclusion,status,workflowName}]}'
gh pr diff 312 --repo ContextualWisdomLab/Orgmetra --name-only

echo '== Exact repository head =='
git rev-parse HEAD

echo '== Migration: complete function and privilege metadata =='
nl -ba "$sql" | sed -n '74,325p'
rg -n -C 3 'GRANT|REVOKE|ALTER FUNCTION|SECURITY DEFINER|persist_document_record_once' \
  database/migrations

echo '== Parent document relation and its RLS policy =='
nl -ba database/migrations/0021_document_record_persistence.sql | sed -n '1,130p;315,345p'

echo '== Test: setup, helper functions, and sequential replay/conflict assertions =='
nl -ba "$test" | sed -n '1,172p'

echo '== Test: concurrency, tenant RLS, and append-only assertions =='
nl -ba "$test" | sed -n '173,280p'

echo '== Test registry state on this head =='
rg -n -C 2 'test_document_record_idempotency_postgres|document-record.*idempot' \
  README.md docs .github tests 2>/dev/null || true

echo '== Migration ordering and application mechanism =='
rg -n -C 3 'migrations/|database/migrations|0024_document_record' \
  tests .github README.md docs 2>/dev/null || true

Length of output: 84875


@seonghobae I reviewed exact head 3ef61434b04c6cc01d15788a62e71fc8036ad926.

I found two issues.

  1. Replay digest depends on the PostgreSQL session TimeZone.
    In database/migrations/0024_document_record_idempotent_persistence.sql, Line 163 passes p_received_at directly to jsonb_build_object. PostgreSQL JSON conversion of timestamptz uses the current session time zone. Two retry sessions can provide the same instant with different TimeZone settings. They then compute different semantic digests. The second request fails as a changed command instead of replaying the original result.

    Normalize p_received_at to a fixed UTC representation before digest construction. Add a regression that performs the same-key replay from a session with a different TimeZone.

  2. The concurrency contract uses a fixed scheduling delay.
    In tests/test_document_record_idempotency_postgres.sh, Line 181 uses sleep 0.25 before it starts the second session. A slow first session can cause the second session to start after the first transaction commits. The test then passes without proving that the second session waited on pg_advisory_xact_lock.

    Replace the delay with an observable database barrier. The first session should signal after it has acquired the advisory lock. The test should then start the second session, confirm that it blocks, and release the first session. This proves real concurrent serialization.

The receipt table has the requested tenant-qualified composite foreign key and FORCE ROW LEVEL SECURITY. However, the current contract only verifies the RLS flags. It does not prove read and write denial through a NOBYPASSRLS role.

No hosted PostgreSQL acceptance is available on this exact head. I did not treat predecessor #107 evidence as current-head acceptance.

⚠️ Action not completed

Head commit changed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is now 00ba4ee03df7ca86bfc3ef2383e04de211532296. Please review the complete current delta from #107, including the timezone-stable semantic/receipt digest repair, VOLATILE + Read Committed replay assumption, advisory-lock scope, tenant-qualified receipt FK/RLS, and real concurrent PostgreSQL acceptance. Prior review state must not be transferred to this head.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/Orgmetra"
expected_head="00ba4ee03df7ca86bfc3ef2383e04de211532296"

echo '== PR metadata =='
gh pr view 312 --repo "$repo" \
  --json number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,status,conclusion,workflowName}]}'

echo '== checked-out commit =='
git rev-parse HEAD
git status --short

echo '== changed files: PR delta =='
gh pr diff 312 --repo "$repo" --name-only

echo '== changed files: exact base-to-head delta =='
base="$(gh pr view 312 --repo "$repo" --json baseRefOid --jq .baseRefOid)"
git diff --name-status "$base" "$expected_head"

echo '== locate primary and related artifacts =='
fd -a -i '002[0-9].*document.*record.*\.sql|0309.*|test_document_record_idempotency_postgres\.sh' . || true

echo '== outlines =='
for f in \
  database/migrations/0021_document_record_persistence.sql \
  database/migrations/0024_document_record_idempotent_persistence.sql \
  tests/test_document_record_idempotency_postgres.sh
do
  if [ -f "$f" ]; then
    echo "-- $f"
    ast-grep outline "$f" --items all || true
  fi
done

echo '== idempotency migration =='
nl -ba database/migrations/0024_document_record_idempotent_persistence.sql

echo '== predecessor document schema and RLS =='
nl -ba database/migrations/0021_document_record_persistence.sql

echo '== PostgreSQL contract =='
nl -ba tests/test_document_record_idempotency_postgres.sh

echo '== ADR 0309 =='
adr="$(fd -a -i '0309.*' . | head -n 1 || true)"
if [ -n "$adr" ]; then nl -ba "$adr"; fi

echo '== all persistence-function references and migration/test execution references =='
rg -n -C 3 \
  'persist_document_record_once\s*\(|document_record_replay_receipts|test_document_record_idempotency_postgres|database/migrations' \
  --glob '*.sql' --glob '*.sh' --glob '*.md' --glob '*.yml' --glob '*.yaml' .

Length of output: 89733


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== exact patch =='
git diff --find-renames --find-copies 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d 00ba4ee03df7ca86bfc3ef2383e04de211532296 -- \
  database/migrations/0024_document_record_idempotent_persistence.sql \
  docs/adr/0309-document-record-idempotent-persistence.md \
  docs/traceability/document-record-idempotent-persistence.md \
  tests/test_document_record_idempotency_postgres.sh

echo '== tenant-context helper, RLS patterns, and relevant grants =='
rg -n -C 8 \
  'CREATE( OR REPLACE)? FUNCTION public\.current_tenant_record_id|current_tenant_record_id\(\)|GRANT .*document_record|REVOKE .*document_record|GRANT .*persist_document_record_once|REVOKE .*persist_document_record_once|ALTER TABLE .* FORCE ROW LEVEL SECURITY' \
  --glob '*.sql' database/migrations

echo '== document migrations 0022 and 0023 =='
nl -ba database/migrations/0022_document_record_evidence_unique_keys.sql
nl -ba database/migrations/0023_document_record_canonical_encoding.sql

echo '== traceability =='
nl -ba docs/traceability/document-record-idempotent-persistence.md

echo '== all PostgreSQL test concurrency synchronization patterns =='
rg -n -C 10 \
  'pg_advisory|pg_stat_activity|pg_sleep|mktemp|application_name|wait "\$\{|sleep [0-9]' \
  --glob 'test_*postgres*.sh' tests

echo '== function volatility/isolation declarations in migrations =='
rg -n -C 5 \
  'LANGUAGE plpgsql|VOLATILE|STABLE|SET TRANSACTION ISOLATION LEVEL|transaction_isolation|pg_advisory_xact_lock' \
  --glob '*.sql' database/migrations

Length of output: 174249


@seonghobae I reviewed exact head 00ba4ee03df7ca86bfc3ef2383e04de211532296 against base 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d.

I found two issues.

  1. The concurrent acceptance does not prove advisory-lock contention.
    In tests/test_document_record_idempotency_postgres.sh, Line 181 uses sleep 0.25 before it starts the second session. If the first session has not reached pg_advisory_xact_lock, the test does not establish the required ordering. If the first session completes before the second invocation, the test still passes without proving waiting behavior.

    Add an observable first-session barrier after the function obtains the lock. Then start the second session. Confirm that the second session is blocked on the advisory lock before the first session commits. Existing tests use pg_stat_activity polling for this type of synchronization.

  2. The RLS acceptance checks metadata, not RLS enforcement.
    In tests/test_document_record_idempotency_postgres.sh, Lines 214-221 only verify relrowsecurity and relforcerowsecurity. The test never uses a NOBYPASSRLS role. It also never sets tenant context before receipt access.

    Add a role-based test that grants only required access, sets orgmetra.tenant_record_id, and verifies that the role can access its own receipt but cannot read or write another tenant’s receipt. This proves the policy and the FORCE RLS setting work at runtime.

The function-local UTC setting correctly covers timestamptz serialization in the semantic digest and receipt digest. The VOLATILE declaration and the ADR’s Read Committed restriction are consistent with the post-lock replay lookup. The advisory-lock key includes tenant identity, owner namespace, and idempotency key. The receipt foreign key is tenant-qualified.

No hosted PostgreSQL execution or protected-base acceptance exists for this exact head. I did not use predecessor #107 evidence as current-head acceptance.

⚠️ Action not completed

Head commit changed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact current head 45a0296f9ad513b3f73dfce24a09d26d629b447a from base #107 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d. Focus on the transaction-scoped advisory-lock replay semantics, function-local UTC digest identity, explicit Read Committed fail-closed guard, tenant-qualified receipt FK/RLS/immutability, and both real PostgreSQL acceptance contracts. Do not transfer findings/approval from predecessor heads.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/Orgmetra"
base="7ce73aa44f47113b2ecd42d51bb5d38a22c0367d"
head="45a0296f9ad513b3f73dfce24a09d26d629b447a"

echo '== Pull request metadata and exact commits =='
gh pr view 312 --repo "$repo" \
  --json number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefName,baseRefOid,headRefName,headRefOid,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,status,conclusion,workflowName}]}'
printf 'checked_out='; git rev-parse HEAD
printf 'expected_base=%s\nexpected_head=%s\n' "$base" "$head"

echo '== Complete base-to-head changed-file list =='
git diff --name-status "$base" "$head"

echo '== Locate relevant files =='
fd -a -i \
  '0021_document_record_persistence\.sql|0024_document_record_idempotent_persistence\.sql|0309.*|document-record-idempotent-persistence.*|test_document_record_idempotency(_isolation)?_postgres\.sh' \
  . | sort

echo '== Migration 0024 complete content =='
nl -ba database/migrations/0024_document_record_idempotent_persistence.sql

echo '== Parent document-record schema, RLS, and ownership definitions =='
nl -ba database/migrations/0021_document_record_persistence.sql

echo '== Both real PostgreSQL acceptance contracts =='
for f in \
  tests/test_document_record_idempotency_postgres.sh \
  tests/test_document_record_idempotency_isolation_postgres.sh
do
  if [ -f "$f" ]; then
    echo "-- $f"
    nl -ba "$f"
  fi
done

echo '== ADR and traceability documents =='
for f in \
  docs/adr/0309-document-record-idempotent-persistence.md \
  docs/traceability/document-record-idempotent-persistence.md
do
  if [ -f "$f" ]; then
    echo "-- $f"
    nl -ba "$f"
  fi
done

echo '== Exact implementation patch =='
git diff --find-renames --find-copies "$base" "$head" -- \
  database/migrations \
  tests/test_document_record_idempotency_postgres.sh \
  tests/test_document_record_idempotency_isolation_postgres.sh \
  docs/adr/0309-document-record-idempotent-persistence.md \
  docs/traceability/document-record-idempotent-persistence.md

echo '== Relevant schema helpers, grants, triggers, policies, and test discovery =='
rg -n -C 5 \
  'persist_document_record_once|document_record_replay_receipts|current_tenant_record_id|pg_advisory_xact_lock|transaction_isolation|set_config|TimeZone|timezone|ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY|GRANT|REVOKE|CREATE TRIGGER|append.only|UPDATE|DELETE|test_document_record_idempotency' \
  --glob '*.sql' --glob '*.sh' --glob '*.md' --glob '*.yml' --glob '*.yaml' \
  database tests docs .github 2>/dev/null || true

Length of output: 203164


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '== Exact head confirmation =='
git rev-parse HEAD
git merge-base --is-ancestor 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d 45a0296f9ad513b3f73dfce24a09d26d629b447a && echo 'base_is_ancestor=yes'

echo '== Migration 0024: table and full function body in focused ranges =='
nl -ba database/migrations/0024_document_record_idempotent_persistence.sql | sed -n '1,340p'

echo '== Idempotency main contract: complete file =='
nl -ba tests/test_document_record_idempotency_postgres.sh

echo '== Isolation contract: complete file =='
nl -ba tests/test_document_record_idempotency_isolation_postgres.sh

echo '== Related 0021 table definition, constraints, triggers, and RLS only =='
rg -n -A10 -B5 \
  'CREATE TABLE.*document_record|ALTER TABLE.*document_record|CREATE (UNIQUE )?INDEX.*document_record|CONSTRAINT.*document_record|FOREIGN KEY|document_record.*tenant|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY|append.only|TRUNCATE' \
  database/migrations/0021_document_record_persistence.sql

echo '== Main contract concurrency and RLS sections with syntax context =='
rg -n -A55 -B12 \
  'PGAPPNAME|application_name|concurr|pg_stat_activity|pg_locks|advisory|NOBYPASSRLS|SET ROLE|document_record_persist_receipt|append-only|TRUNCATE|OTHER_TENANT|other tenant' \
  tests/test_document_record_idempotency_postgres.sh

echo '== SQL references from test: extracted heredocs around function invocation =='
rg -n -A45 -B8 \
  'persist_document_record_once\(' \
  tests/test_document_record_idempotency_postgres.sh

echo '== Test registration / inventory coverage at exact head =='
rg -n -C3 \
  'test_document_record_idempotency_postgres\.sh|test_document_record_idempotency_isolation_postgres\.sh' \
  .github tests docs README.md package.json 2>/dev/null || true

Length of output: 56917


@seonghobae I reviewed exact head 45a0296f9ad513b3f73dfce24a09d26d629b447a from base 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d.

I found two issues.

  1. The concurrent acceptance does not prove advisory-lock contention.
    In tests/test_document_record_idempotency_postgres.sh, Line 181 uses sleep 0.25 before the test starts the second PostgreSQL session. The first session can still be before pg_advisory_xact_lock, or it can have completed before the second session invokes the function. In either case, the test can pass without proving that the retry waited for the transaction-scoped advisory lock.

    Use an observable database barrier after the first invocation has acquired the lock and persisted its receipt. Then start the second session. Confirm that the second session waits on the advisory lock before the first transaction commits.

  2. The receipt RLS test checks catalog metadata but not runtime enforcement.
    In tests/test_document_record_idempotency_postgres.sh, Lines 214-221 check only relrowsecurity and relforcerowsecurity. The test does not use a NOBYPASSRLS role to read or write document_record_persist_receipt.

    Add a role-based acceptance case. Grant only the required receipt privileges. Set orgmetra.tenant_record_id. Verify that the role can access its tenant receipt, cannot access another tenant receipt, and cannot insert a receipt for another tenant. This verifies the policy and FORCE ROW LEVEL SECURITY at runtime.

The function-local SET TimeZone = 'UTC' protects the timestamptz values used in the semantic and receipt digest construction. The same-key retry test covers UTC to Asia/Seoul replay. The VOLATILE declaration and the Read Committed guard are consistent with the post-lock replay lookup. The receipt foreign key is tenant-qualified. The receipt has update/delete and TRUNCATE guards.

No hosted PostgreSQL execution is available for this exact head. I did not use predecessor evidence as current-head acceptance.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is 8ba15958762ed49bc33c4f6d78573b0427bec927. Please review the new tenant-context boundary in persist_document_record_once(...) and tests/test_document_record_idempotency_tenant_context_postgres.sh, including whether tenant mismatch is rejected before advisory-lock acquisition or durable state and whether the existing retry/concurrency tests now supply tenant context consistently.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/Orgmetra"
base="7ce73aa44f47113b2ecd42d51bb5d38a22c0367d"
head="8ba15958762ed49bc33c4f6d78573b0427bec927"

echo '== Exact PR and checkout identity =='
gh pr view 312 --repo "$repo" \
  --json number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,status,conclusion,workflowName}]}'
printf 'checked_out='
git rev-parse HEAD
git merge-base --is-ancestor "$base" "$head" && echo 'base_is_ancestor=yes'

echo '== Complete base-to-head changed files =='
git diff --name-status "$base" "$head"

echo '== Locate review artifacts =='
fd -a -i \
  '002[1-4]_document_record.*\.sql|0309.*|document-record-idempotent-persistence.*|test_document_record_idempotency(_(isolation|tenant_context))?_postgres\.sh' \
  . | sort

echo '== Migration 0024 outline =='
ast-grep outline database/migrations/0024_document_record_idempotent_persistence.sql --items all || true

echo '== Migration 0024 complete content =='
nl -ba database/migrations/0024_document_record_idempotent_persistence.sql

echo '== Tenant helper and document-record RLS/schema definitions =='
rg -n -A18 -B8 \
  'CREATE( OR REPLACE)? FUNCTION public\.current_tenant_record_id|current_tenant_record_id\(\)|CREATE TABLE.*document_record|ALTER TABLE.*document_record|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY|FOREIGN KEY|GRANT|REVOKE' \
  --glob '*.sql' database/migrations

echo '== All three PostgreSQL contracts =='
for f in \
  tests/test_document_record_idempotency_postgres.sh \
  tests/test_document_record_idempotency_isolation_postgres.sh \
  tests/test_document_record_idempotency_tenant_context_postgres.sh
do
  echo "-- $f"
  nl -ba "$f"
done

echo '== Every persistence-function call, tenant context assignment, and concurrency synchronization path =='
rg -n -A18 -B10 \
  "persist_document_record_once\s*\(|orgmetra\.tenant_record_id|set_config\s*\(\s*'orgmetra\.tenant_record_id'|current_tenant_record_id\s*\(|pg_advisory_xact_lock|pg_stat_activity|wait_event|application_name|PGAPPNAME" \
  --glob '*.sql' --glob '*.sh' database tests

echo '== Exact patch for reviewed scope =='
git diff --find-renames --find-copies "$base" "$head" -- \
  database/migrations/0024_document_record_idempotent_persistence.sql \
  tests/test_document_record_idempotency_postgres.sh \
  tests/test_document_record_idempotency_isolation_postgres.sh \
  tests/test_document_record_idempotency_tenant_context_postgres.sh \
  docs/adr/0309-document-record-idempotent-persistence.md \
  docs/traceability/document-record-idempotent-persistence.md

Length of output: 189664


@seonghobae I reviewed exact head 8ba15958762ed49bc33c4f6d78573b0427bec927 from base 7ce73aa44f47113b2ecd42d51bb5d38a22c0367d.

I found one issue.

  1. The concurrent PostgreSQL acceptance still does not prove advisory-lock contention.
    In tests/test_document_record_idempotency_postgres.sh, Line 189 waits for a fixed sleep 0.25 before it starts the second session. The first session can still be before pg_advisory_xact_lock, or it can complete before the second call. The test can then pass without proving that the second call waited on the transaction-scoped advisory lock.

    Use an observable database barrier. First confirm that the first session has persisted its receipt and remains in its transaction. Then start the second session. Confirm that it waits on the advisory lock before the first session commits.

The tenant-context boundary is correctly ordered in persist_document_record_once(...). The function checks current_tenant_record_id() after the required null-field guard and before semantic-digest construction, replay lookup, pg_advisory_xact_lock, and durable writes. A valid tenant-mismatch command therefore fails before it can coordinate on another tenant’s advisory-lock key.

tests/test_document_record_idempotency_tenant_context_postgres.sh supplies valid tenant-beta fields with tenant-alpha session context. It requires the explicit tenant-boundary error and verifies zero tenant-beta document and receipt rows. The static function order establishes that this rejection also occurs before lock acquisition.

The existing retry calls use with_tenant. Both concurrent psql sessions set orgmetra.tenant_record_id. The isolation test intentionally omits tenant context because it verifies that the Read Committed guard fails before command-field validation.

I did not verify hosted PostgreSQL execution for this exact head.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head 8db666f33804058b377b393406b73675bbb01a2e, especially the manifest-only provenance repair: both Foundation required-file inventories already register the #312 owner artifacts, while this commit re-closes manifest coverage and restores child OPERABILITY/TEST_STRATEGY hashes after ordinary-forward parent adoption. Please flag any remaining checked-versus-used or inventory/manifest divergence; do not treat predecessor verdicts as current-head evidence.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/Orgmetra"
previous="3e7866878a628cf6e2503357d8253c984baa721d"
head="8db666f33804058b377b393406b73675bbb01a2e"
supplier="3e021ad104afe4163814ea0d2bfdaabd63ccaa7d"

echo '== Pull request and exact-head identity =='
gh pr view 312 --repo "$repo" \
  --json number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,status,conclusion,workflowName}]}'
printf 'checked_out_head='
git rev-parse HEAD
git cat-file -e "${head}^{commit}"
git merge-base --is-ancestor "$previous" "$head" && echo 'previous_is_ancestor=yes' || echo 'previous_is_ancestor=no'
git merge-base --is-ancestor "$supplier" "$head" && echo 'supplier_is_ancestor=yes' || echo 'supplier_is_ancestor=no'
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"

echo '== Exact manifest-only repair delta =='
git diff --check "$previous" "$head"
git diff --name-status "$previous" "$head"
git diff --unified=100 "$previous" "$head" -- \
  manifest.json \
  tests/validate_repository.py \
  scripts/foundation-contract-core.mjs \
  docs/OPERABILITY.md \
  docs/TEST_STRATEGY.md

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
git archive "$head" | tar -x -C "$tmpdir"
cd "$tmpdir"

echo '== Exact manifest structure and relevant entries =='
python3 - <<'PY'
from pathlib import Path
import json
manifest = json.loads(Path("manifest.json").read_text(encoding="utf-8"))
print(f"package={manifest.get('package')}")
print(f"version={manifest.get('version')}")
print(f"generated_for_branch={manifest.get('generated_for_branch')}")
print(f"manifest_entry_count={len(manifest.get('files', []))}")
for entry in manifest["files"]:
    if (
        "0024_document_record_idempotent_persistence" in entry["path"]
        or "document_record_idempotency" in entry["path"]
        or "0309-document-record-idempotent-persistence" in entry["path"]
        or "document-record-idempotent-persistence" in entry["path"]
        or entry["path"] in {
            "docs/OPERABILITY.md",
            "docs/TEST_STRATEGY.md",
            "scripts/foundation-contract-core.mjs",
            "tests/validate_repository.py",
        }
    ):
        print(json.dumps(entry, sort_keys=True))
PY

echo '== Static exact-tree verification of inventories and manifest =='
python3 - <<'PY'
from pathlib import Path
import ast
import hashlib
import json
import re
import sys

root = Path(".")
py_source = (root / "tests/validate_repository.py").read_text(encoding="utf-8")
js_source = (root / "scripts/foundation-contract-core.mjs").read_text(encoding="utf-8")

py_match = re.search(r"REQUIRED = (\[.*?\])\n\nUNFINISHED_MARKER_LINE_PATTERN", py_source, re.S)
js_match = re.search(r"REQUIRED_FILES = Object\.freeze\(\[(.*?)\]\);", js_source, re.S)
if not py_match or not js_match:
    raise SystemExit("could not parse canonical required inventories")

py_required = set(ast.literal_eval(py_match.group(1)))
js_required = set(re.findall(r"^\s*'([^']+)',?\s*$", js_match.group(1), re.M))
required_nonself = py_required - {"manifest.json"}

manifest = json.loads((root / "manifest.json").read_text(encoding="utf-8"))
entries_list = manifest["files"]
entries = {entry["path"]: entry for entry in entries_list}
entry_paths = set(entries)

missing = sorted(required_nonself - entry_paths)
extra = sorted(entry_paths - required_nonself)
duplicates = sorted(
    path for path in entry_paths
    if sum(1 for entry in entries_list if entry["path"] == path) != 1
)
mismatches = []
for path in sorted(required_nonself & entry_paths):
    data = (root / path).read_bytes()
    actual = {
        "sha256": hashlib.sha256(data).hexdigest(),
        "bytes": len(data),
        "lines": len(data.decode("utf-8").splitlines()),
    }
    changed = {
        key: (entries[path].get(key), value)
        for key, value in actual.items()
        if entries[path].get(key) != value
    }
    if changed:
        mismatches.append((path, changed))

discovered = {
    *(f"database/migrations/{p.name}" for p in (root / "database/migrations").iterdir()
      if re.fullmatch(r"\d{4}_[a-z0-9_]+\.sql", p.name)),
    *(f"tests/{p.name}" for p in (root / "tests").iterdir()
      if re.fullmatch(r"test_[a-z0-9_]+_postgres\.sh", p.name)),
}
expected_owner_artifacts = {
    "database/migrations/0024_document_record_idempotent_persistence.sql",
    "docs/adr/0309-document-record-idempotent-persistence.md",
    "docs/traceability/document-record-idempotent-persistence.md",
    "tests/test_document_record_idempotency_postgres.sh",
    "tests/test_document_record_idempotency_function_acl_postgres.sh",
    "tests/test_document_record_idempotency_isolation_postgres.sh",
    "tests/test_document_record_idempotency_tenant_context_postgres.sh",
    "tests/document_record_idempotency_postcommit_recovery_companion.sh",
    "tests/test_document_record_idempotency_postcommit_recovery_contract.py",
}

print(f"python_required_count={len(py_required)}")
print(f"node_required_count={len(js_required)}")
print(f"only_python={sorted(py_required - js_required)!r}")
print(f"only_node={sorted(js_required - py_required)!r}")
print(f"manifest_entry_count={len(entries_list)}")
print(f"manifest_unique_path_count={len(entry_paths)}")
print(f"manifest_missing_count={len(missing)}")
print(f"manifest_extra_count={len(extra)}")
print(f"manifest_duplicate_count={len(duplicates)}")
print(f"manifest_mismatch_count={len(mismatches)}")
print(f"dispatcher_discovered_count={len(discovered)}")
print(f"dispatcher_missing_python={sorted(discovered - py_required)!r}")
print(f"dispatcher_missing_node={sorted(discovered - js_required)!r}")
print(f"owner_missing_python={sorted(expected_owner_artifacts - py_required)!r}")
print(f"owner_missing_node={sorted(expected_owner_artifacts - js_required)!r}")
print(f"owner_missing_manifest={sorted(expected_owner_artifacts - entry_paths)!r}")
for path in missing:
    print(f"MANIFEST_MISSING {path}")
for path in extra:
    print(f"MANIFEST_EXTRA {path}")
for path in duplicates:
    print(f"MANIFEST_DUPLICATE {path}")
for path, fields in mismatches:
    print(f"MANIFEST_MISMATCH {path} {fields!r}")

canonical = {
    "package": manifest["package"],
    "version": manifest["version"],
    "generated_for_branch": manifest["generated_for_branch"],
    "files": [
        {
            "path": path,
            "sha256": hashlib.sha256((root / path).read_bytes()).hexdigest(),
            "bytes": len((root / path).read_bytes()),
            "lines": len((root / path).read_bytes().decode("utf-8").splitlines()),
        }
        for path in sorted(required_nonself)
    ],
}
canonical_bytes = (json.dumps(canonical, indent=2) + "\n").encode()
actual_bytes = (root / "manifest.json").read_bytes()
print(f"derived_manifest_sha256={hashlib.sha256(canonical_bytes).hexdigest()}")
print(f"actual_manifest_sha256={hashlib.sha256(actual_bytes).hexdigest()}")
print(f"manifest_byte_exact={'yes' if actual_bytes == canonical_bytes else 'no'}")
PY

echo '== Checked-versus-used references for manifest validation =='
rg -n -A20 -B12 \
  'REQUIRED|REQUIRED_FILES|manifest\.json|--print-manifest|sha256|dispatcher|database/migrations|test_\[a-z0-9_\]\+_postgres' \
  tests/validate_repository.py scripts/foundation-contract-core.mjs tests/dispatcher-inventory.test.mjs

echo '== Static text and shell syntax checks only =='
for f in \
  tests/test_document_record_idempotency_postgres.sh \
  tests/test_document_record_idempotency_function_acl_postgres.sh \
  tests/test_document_record_idempotency_isolation_postgres.sh \
  tests/test_document_record_idempotency_tenant_context_postgres.sh \
  tests/document_record_idempotency_postcommit_recovery_companion.sh
do
  bash -n "$f"
done
echo 'shell_syntax=valid'
echo 'Repository executables were not run.'

Length of output: 69266


@seonghobae I reviewed exact head 8db666f33804058b377b393406b73675bbb01a2e.

I found one blocking manifest issue.

manifest.json still diverges from the exact tree in two required entries:

Path Required SHA-256 Required bytes Required lines Checked-in manifest value
CHANGELOG.md 321c43f388dd561b8867684daac74b0c21f3676d66e15f941feed28d5cf02459 17829 78 SHA-256 f2d2e0b488c0440533effa821808f2f17e37d92f8fb586174c2fdb594f760ca5, 17539 bytes, 77 lines
scripts/foundation-contract-core.mjs aa1965c7101551570a64c9e679c2f9042eb449173fa82face5e94e9c72ded8d1 29278 706 705 lines

The CHANGELOG.md entry is stale. The scripts/foundation-contract-core.mjs SHA-256 and byte count are correct, but its line count is one line too low. tests/validate_repository.py checks all three fields. Therefore this head cannot pass manifest validation.

The checked-in manifest has SHA-256:

aa43e3484567e1facb9ddb0042599a25973b2b97c0a32f9080f3d1d29e7cff8a

The statically derived replacement manifest has SHA-256:

c96756e8b76b0141201b03e7acc5692c15c766c61ed713b878a0682944ce7065

The inventories have no remaining divergence:

  • Python REQUIRED: 97 paths.
  • Node REQUIRED_FILES: 97 paths.
  • Manifest entries: 96 unique non-self paths.
  • Missing, extra, and duplicate manifest entries: none.
  • All #312 owner artifacts are present in both inventories and in manifest.json.
  • Dispatcher-discovered migrations and PostgreSQL roots are present in both inventories.

git diff --check passed. Static shell syntax checks passed for the PostgreSQL contracts. I did not execute npm run validate or any PostgreSQL contract on this head.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

Exact-head RED after reseal — 2026-09-12

Direct materialization of 8db666f33804058b377b393406b73675bbb01a2e still fails npm run validate before Node tests:

manifest sha256 mismatch for CHANGELOG.md: expected '321c43f388dd561b8867684daac74b0c21f3676d66e15f941feed28d5cf02459', observed 'f2d2e0b488c0440533effa821808f2f17e37d92f8fb586174c2fdb594f760ca5'

Here expected is the actual exact-tree file digest; observed is the stale manifest seal. The nine newly registered artifacts and other reported replacements are present, but the generated manifest did not include the current CHANGELOG.md replacement.

Please regenerate from this exact tree and rerun full npm run validate plus git diff --check; do not patch the validator or transfer #107 GREEN. Current head remains Draft with zero hosted runs.

Copy link
Copy Markdown
Contributor Author

Exact-head repair evidence for 5fa9b191864b11f6a842c64a84e03e5a532525de / tree 9cdd51dc07c531907f0274bb337b49ea875da8a4.

The prior manifest-only head remained RED: CHANGELOG still carried the parent seal, two newly registered paths were out of deterministic order, and scripts/foundation-contract-core.mjs retained the pre-terminal-LF line count. Ordinary child d79580d2 changes only those exact candidate values; 5fa9b191 restores the manifest terminal LF lost at the contents boundary.

Exact-tree verification:

  • npm run validate: Foundation validator PASS and Node contracts 55/55
  • python3 tests/test_document_record_idempotency_postcommit_recovery_contract.py: PASS
  • git diff --check: PASS
  • manifest: 96 entries, SHA-256 c96756e8b76b0141201b03e7acc5692c15c766c61ed713b878a0682944ce7065, 18,895 bytes / 583 newline-counted lines

This repairs provenance only; PostgreSQL runtime acceptance, hosted exact-head Checks, prerequisite integration, and qualifying independent approval remain required. Draft status is preserved.

Copy link
Copy Markdown
Contributor Author

Fresh exact-head audit on 5fa9b191864b11f6a842c64a84e03e5a532525de found a separate DDD/documentation identity gap and split it as #313 rather than hiding it in this PR body: migration 0024 persists document_record_persist_receipt, but the canonical Data Model/ERD and migration-backed logical-object inventory do not yet name/protect that relation. #313 is the ordinary-forward successor repair on this same document_records owner stack and requires Data Model/ERD + validator regression + final manifest reseal. Keep #312 Draft; do not copy this mutable schema into #307 or claim protected/released truth from the current local validation.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head 8e86c42d5545b9025341dca9afc220666ab56c93, especially migration 0024's fresh owner/executor role preflight and transactional ownership handoff, SECURITY DEFINER/search_path/RLS interactions, the executor's zero-direct-DML guarantee, the behavioral ACL regression, and whether any implicit PostgreSQL privilege or trigger/helper requirement can still bypass or break the intended execute-only persistence capability. Treat predecessor-head review as historical only.

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="ContextualWisdomLab/Orgmetra"
head="8e86c42d5545b9025341dca9afc220666ab56c93"
migration="database/migrations/0024_document_record_idempotent_persistence.sql"
acl_root="tests/test_document_record_idempotency_function_acl_postgres.sh"
main_root="tests/test_document_record_idempotency_postgres.sh"
isolation_root="tests/test_document_record_idempotency_isolation_postgres.sh"
tenant_root="tests/test_document_record_idempotency_tenant_context_postgres.sh"

echo '== Exact PR/head identity =='
gh pr view 312 --repo "$repo" \
  --json number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,statusCheckRollup \
  --jq '{number,state,isDraft,baseRefOid,headRefOid,mergeStateStatus,checks:[.statusCheckRollup[]? | {name,status,conclusion,workflowName}]}'
printf 'checked_out_head='; git rev-parse HEAD
git cat-file -e "${head}^{commit}"
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"

echo '== Complete exact PR delta and whitespace validation =='
base="$(gh pr view 312 --repo "$repo" --json baseRefOid --jq .baseRefOid)"
git diff --check "$base" "$head"
git diff --name-status "$base" "$head"

echo '== Current ownership-handoff delta =='
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
git diff --check "$parent" "$head"
git diff --unified=140 "$parent" "$head" -- \
  "$migration" "$acl_root" \
  docs/adr/0309-document-record-idempotent-persistence.md \
  docs/SECURITY.md docs/THREAT_MODEL.md docs/OPERABILITY.md docs/TEST_STRATEGY.md \
  manifest.json

echo '== Migration outline and complete relevant implementation =='
ast-grep outline "$migration" --items all || true
nl -ba "$migration"

echo '== Parent table, receipt relation, policies, triggers, and helper dependencies =='
rg -n -A100 -B25 \
  'CREATE TABLE.*document_record|CREATE TABLE.*document_record_persist_receipt|CREATE POLICY|FORCE ROW LEVEL SECURITY|ENABLE ROW LEVEL SECURITY|CREATE TRIGGER|CREATE FUNCTION|current_tenant_record_id|audit|outbox|document_record' \
  --glob '*.sql' database/migrations

echo '== All grants/revokes/ownership/security-definer references =='
rg -n -A20 -B12 \
  'orgmetra_document_persistence_(owner|executor)|SECURITY DEFINER|ALTER FUNCTION|ALTER TABLE.*OWNER|GRANT|REVOKE|PUBLIC|search_path|BYPASSRLS|NOBYPASSRLS|CREATE ROLE|DROP ROLE' \
  --glob '*.sql' database/migrations

echo '== Full behavioral ACL root =='
nl -ba "$acl_root"

echo '== ACL root lifecycle, permissions, direct-DML probes, and function invocation =='
rg -n -A75 -B25 \
  'CREATE ROLE|DROP ROLE|DROP OWNED|cleanup|trap|SET ROLE|has_table_privilege|has_function_privilege|information_schema|document_record|document_record_persist_receipt|INSERT|SELECT|UPDATE|DELETE|persist_document_record_once|permission denied|owner|executor|PUBLIC|NOBYPASSRLS' \
  "$acl_root"

echo '== Function caller paths and all direct document/receipt DML sources =='
rg -n -A20 -B12 \
  'persist_document_record_once\s*\(|(?:INSERT INTO|UPDATE|DELETE FROM|SELECT .*FROM)\s+(?:public\.)?(?:document_record|document_record_persist_receipt)\b' \
  --glob '*.sql' --glob '*.sh' --glob '*.py' database tests scripts

echo '== Test root registration and executor-role references =='
rg -n -A12 -B8 \
  'test_document_record_idempotency_function_acl_postgres|test_document_record_idempotency_postgres|test_document_record_idempotency_isolation_postgres|test_document_record_idempotency_tenant_context_postgres|orgmetra_document_persistence_(owner|executor)' \
  tests docs .github README.md scripts 2>/dev/null || true

echo '== Static syntax checks only =='
for f in "$acl_root" "$main_root" "$isolation_root" "$tenant_root"; do
  bash -n "$f"
done
echo 'shell_syntax=valid'
echo 'Repository executable tests were not run.'

Length of output: 204268


🏁 Script executed:

#!/bin/bash
set -euo pipefail

migration="database/migrations/0024_document_record_idempotent_persistence.sql"
acl_root="tests/test_document_record_idempotency_function_acl_postgres.sh"

echo '== Exact migration sections omitted by prior capped output =='
nl -ba "$migration" | sed -n '1,140p;140,250p;340,410p'

echo '== Reserved-role preflight structure and mutation ordering =='
rg -n -A35 -B12 \
  'pg_roles|orgmetra_document_persistence_owner|orgmetra_document_persistence_executor|RAISE EXCEPTION|CREATE ROLE|CREATE TABLE|CREATE FUNCTION|BEGIN;|COMMIT;' \
  "$migration"

echo '== Persist function definitions, effective settings, and all referenced objects =='
rg -n -A18 -B10 \
  'CREATE FUNCTION public\.persist_document_record_once|LANGUAGE|VOLATILE|SECURITY|SET search_path|SET TimeZone|current_setting|current_tenant_record_id|pg_advisory_xact_lock|digest\(|jsonb_build_object|INSERT INTO|FROM public\.|JOIN public\.' \
  "$migration"

echo '== Trigger definitions for protected tables and referenced trigger function implementations =='
rg -n -A50 -B15 \
  'CREATE TRIGGER.*document|ON (document_record|document_record_persist_receipt)|EXECUTE FUNCTION|CREATE FUNCTION public\.(reject|validate|protect).*document|document_record_persist_receipt' \
  --glob '*.sql' database/migrations/0021_document_record_persistence.sql \
  database/migrations/0022_document_record_evidence_unique_keys.sql \
  database/migrations/0023_document_record_canonical_encoding.sql \
  "$migration"

echo '== Required grants for every function called by the definer and any sequence use =='
rg -n -A16 -B8 \
  'CREATE FUNCTION public\.(current_tenant_record_id|digest|validate_document|reject_document|protect)|GRANT EXECUTE ON FUNCTION|REVOKE EXECUTE ON FUNCTION|nextval|currval|DEFAULT.*nextval|GENERATED' \
  --glob '*.sql' database/migrations/0001_foundation_schema.sql \
  database/migrations/0002_sealed_evidence_digest.sql \
  database/migrations/0021_document_record_persistence.sql \
  database/migrations/0022_document_record_evidence_unique_keys.sql \
  database/migrations/0023_document_record_canonical_encoding.sql \
  "$migration"

echo '== ACL contract coverage versus all direct executor table access modes =='
rg -n -A8 -B8 \
  'has_table_privilege|SELECT count|INSERT INTO public\.document_record|INSERT INTO public\.document_record_persist_receipt|UPDATE public\.document_record|DELETE FROM public\.document_record|TRUNCATE|SET ROLE' \
  "$acl_root"

echo '== Relevant public schema permissions established before migration 0024 =='
rg -n -A14 -B10 \
  'REVOKE (CREATE|ALL) ON SCHEMA public FROM PUBLIC|GRANT .* ON SCHEMA public TO PUBLIC|ALTER DEFAULT PRIVILEGES|GRANT .* ON (TABLE|FUNCTION).*PUBLIC|REVOKE .* ON (TABLE|FUNCTION).*PUBLIC' \
  --glob '*.sql' database/migrations

echo '== Static lexical check for unqualified non-keyword function/table calls in definer body =='
python3 - <<'PY'
from pathlib import Path
import re
text = Path("database/migrations/0024_document_record_idempotent_persistence.sql").read_text()
m = re.search(r'CREATE FUNCTION public\.persist_document_record_once\(.*?\n\$\$(.*?)\n\$\$;', text, re.S)
if not m:
    raise SystemExit("persist function body not found")
body = m.group(1)
for number, line in enumerate(body.splitlines(), 1):
    if re.search(r'\b(?:FROM|JOIN|INSERT INTO|UPDATE|DELETE FROM)\s+(?!public\.|pg_catalog\.)[a-z_]', line):
        print(f"unqualified_relation_body_line={number}:{line.strip()}")
    if re.search(r'(?<![\w.])(?:digest|current_tenant_record_id|hashtextextended|current_setting|jsonb_build_object|convert_to|encode)\s*\(', line):
        print(f"possibly_unqualified_function_body_line={number}:{line.strip()}")
PY

Length of output: 136150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected="8e86c42d5545b9025341dca9afc220666ab56c93"
actual="$(git rev-parse HEAD)"
printf 'expected_head=%s\nactual_head=%s\nhead_matches=%s\n' \
  "$expected" "$actual" "$([[ "$actual" == "$expected" ]] && echo yes || echo no)"
git show -s --format='parents=%P%nsubject=%s' "$expected"
git diff --check "${expected}^" "$expected"
echo 'static_review_evidence=complete'

Length of output: 818


@seonghobae I reviewed exact head 8e86c42d5545b9025341dca9afc220666ab56c93.

I found no new source-level issue.

Migration 0024 rejects either pre-existing reserved role before it changes project objects. It then creates both roles in the same transaction as the persistence relation, function, grants, and ownership handoff.

The owner and executor roles are NOLOGIN, NOSUPERUSER, NOCREATEDB, NOCREATEROLE, NOREPLICATION, and NOBYPASSRLS.

The migration revokes PUBLIC EXECUTE on the exact persist_document_record_once(...) signature before it transfers ownership. It grants the executor only schema USAGE and function EXECUTE.

The owner receives only schema USAGE, helper EXECUTE, and SELECT plus INSERT on document_record and document_record_persist_receipt. The migration grants schema CREATE only for ALTER FUNCTION ... OWNER TO, then revokes it before commit.

The function is SECURITY DEFINER. It has a fixed search_path of pg_catalog, public, pg_temp. Its table, helper, and advisory-lock calls are schema-qualified. FORCE ROW LEVEL SECURITY remains active on both protected relations. The caller tenant context remains checked before advisory-lock acquisition and durable writes.

The owner grants cover the function body. The protected writes use UUID values and do not require sequence privileges. The document-record triggers have fixed search paths. No additional owner table privilege is required by the visible trigger path.

tests/test_document_record_idempotency_function_acl_postgres.sh checks:

  • the owner and executor role attributes;
  • function ownership and SECURITY DEFINER;
  • removal of schema CREATE after handoff;
  • the owner's least-privilege table access;
  • zero direct table privileges for the executor;
  • executor direct-read denial;
  • executor entry into the reviewed validation path through EXECUTE only; and
  • function authorization denial for a run-unique generic role.

The probe-role cleanup is strict after successful assertions. The EXIT cleanup is best-effort, so it does not mask an earlier failure.

The existing replay, tenant, RLS, UTC digest, and advisory-lock behavior remains unchanged in the reviewed source.

git diff --check passed for this exact commit. I did not run PostgreSQL acceptance or treat predecessor evidence as current-head acceptance.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

2026-09-12 exact-head Foundation repair

Current writer head f8d035c2e65401149612023a18d99bba370ea425 reproduced deterministic RED: manifest.json retained predecessor digests for the newly integrated docs/DATA_MODEL.md, docs/ERD.md, scripts/foundation-contract-core.mjs, tests/foundation-contract.test.mjs, and the current docs/SECURITY.md bytes. The repository-provided python3 tests/validate_repository.py --print-manifest candidate was used without changing validation logic or required inventory.

Ordinary non-force child 1ba3a15ef3e0c9f60e3b5f36526271382610cc95 changes only manifest.json and seals all 96 required artifacts (SHA-256 3e8327003635f35a8cb3399a06fffd1fc69e9fb23c51e3b874d52326874d54e0, 14,845 bytes, one JSON line plus terminal LF).

Fresh exact-tree verification: npm run validate passed all 56 Node tests plus Python/Foundation/OpenAPI/dispatcher validation; generated candidate equals committed manifest byte-for-byte; git diff --check passed. PR remains Draft because protected-base PostgreSQL acceptance, exact-head hosted checks, and qualifying independent review are still required.

Copy link
Copy Markdown
Contributor Author

Independent exact-head revalidation at b996e19090e5cc38ef0a4d41a8b4de6d561b89d8:

  • The ordinary successor lineage preserves manifest repair 1ba3a15ef3e0c9f60e3b5f36526271382610cc95, then corrects the ERD to the migration-backed optional receipt relation and reseals those exact bytes.
  • npm run validate passes: Python Foundation validation, Node Foundation/OpenAPI/dispatcher validation, and all 56 Node tests are GREEN.
  • A freshly generated manifest candidate is byte-equivalent to committed manifest.json after canonical JSON normalization; git diff --check is clean.
  • The PR remains Draft, mechanically mergeable, with zero unresolved review threads. No hosted run or qualifying independent approval exists for this successor head, and protected-base PostgreSQL acceptance remains pending.

This COMMENT confirms complete ordinary-forward carryover and deterministic Foundation truth only; it is not hosted-check transfer or merge authorization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority: medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant