Skip to content

test(book): enforce non-overlapping accounting-book reference - #59

Draft
seonghobae wants to merge 30 commits into
developfrom
test/accounting-book-active-reference-identity
Draft

test(book): enforce non-overlapping accounting-book reference#59
seonghobae wants to merge 30 commits into
developfrom
test/accounting-book-active-reference-identity

Conversation

@seonghobae

@seonghobae seonghobae commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

RED-only Accounting Book catalog prerequisite

Fixes #58 only after a production invariant exists. This Draft intentionally carries realistic PostgreSQL REDs first.

Protected parent/current base: develop@239008c4edc7d305c97704c5102b593c6622b36f.
Current exact head: c805707dddc2db22fd42c2995b9c62c9a145765f.
State: open / Draft / mergeable / intentionally RED.

Defect and effective-time contract

ADR 0022 exposes accounting_book.book_name as durable accounting_book_reference / book_reference, but protected migration 0001 does not prevent different Accounting Book Entities under one tenant/legal entity from carrying the same reference over overlapping effective-time intervals. A current-row-only rule such as uniqueness where valid_to IS NULL is incomplete because finite rows can overlap an open-ended row or each other. Application-only preflight is incomplete because concurrent writers can both pass read-before-write validation. Insert-only or one-sided update enforcement is also incomplete: a lawful adjacent/disjoint pair can be edited into overlap by moving successor valid_from backward or predecessor valid_to forward.

Protected resolver behavior is also temporally incorrect. Multiple accounting paths resolve book_name with valid_to IS NULL and .fetchone(). That can admit a future-scheduled open-ended book before valid_from, exclude a finite book effective at the selected accounting instant, and collapse corrupt multiplicity to row order. Historical/period-scoped accounting reads must supply their accounting-effective instant instead of substituting current database time.

The same defect reaches authoritative relationships and writes:

  • PostgresPostingLedger.post_adjusting_journal() owns journal_date, but independently selects accounting_book by tenant + legal entity + book_name + valid_to IS NULL and .fetchone(). A book whose valid_from is after the journal accounting date can therefore receive immutable adjusting-journal facts merely because it is effective at database-current time.
  • accept_bank_account_assignment() owns the effective-dated relationship's explicit valid_from, but resolves Accounting Book with the same current-only shortcut. A bank account can therefore be bound to a book before that book becomes effective.
  • A lawfully created bank_account_assignment can later be stranded outside the Book interval by shortening the parent Book, extending assignment valid_to, or moving assignment valid_from before the Book start. Admission-only validation cannot preserve temporal referential integrity after later master-data mutation.

The durable-reference interval is half-open [valid_from, valid_to), with valid_to IS NULL extending to positive infinity. One (tenant_account_id, legal_entity_id, book_name) identity may retain historical rows only when intervals do not overlap; [a,b) / [b,c) adjacency is lawful. The invariant must hold for serial INSERT, concurrent writers, and UPDATE of either effective-time boundary. Resolver selection uses one explicit effective_at: valid_from <= effective_at and (valid_to IS NULL OR valid_to > effective_at), followed by fail-closed 0/1/>1 handling. Authoritative paths supply their own accounting-effective instant: adjusting journals use journal_date; bank-account assignments use assignment valid_from.

For the scoped Bank Reconciliation relationship, every bank_account_assignment [a,b) must remain contained in its referenced Accounting Book interval [p,q): p <= a and, when the Book has a finite end, b <= q. This contract is deliberately limited to bank_account_assignment; it does not silently generalize policy to every effective-dated relationship. It must hold when either the parent Book boundaries or the assignment boundaries are mutated. Upgrade/preflight must surface pre-existing violations for accounting-master-data resolution rather than silently truncate, rebind, merge, rename or delete accounting history.

This catalog identity is a prerequisite for #56/#57's later General Ledger persistence repair. It is not permission to choose the first match, infer book_role_code, substitute system time for historical accounting effective time, or rewrite immutable posted facts.

TDD lineage

  • a600d61b4fb5a92294964a33d4a497175c302e0d: duplicate open-ended same-reference PostgreSQL RED; non-overlapping expired history stays lawful.
  • 7d8ea2e1d5acdff81e0db62621cf64ef09c8c8a4: RLS fixture repair by binding app.tenant_account_id on direct sessions.
  • 446b3c93ce7d1d1d7348eecebdf06e771f64af5c: open-ended/finite overlap RED; rejection generalized to psycopg.IntegrityError.
  • c887c7890094ba11646c31fbb69a3a362169c0a7 + 72e8e342eaeb4edd40c11284f11473a8622aea79: finite/finite overlap RED, exact-boundary adjacency positive case, and half-open semantics.
  • f2df2e59e5db2c0310980940c4b9fd108de288ed, then e9768f10336941f92355068c313a88f5b4c9710f + fd7601724d27ed1327e547ec8317dd95fac17e96: two-connection RED followed by the stronger oracle that observes the competing INSERT at PostgreSQL before releasing the first writer.
  • fc62c76e0ba2673c8727cf6ec15e197922abd964: resolver-cardinality REDs require 0/1/>1 fail-closed semantics.
  • f48878d1293a82884da1e33f640ec883fe6dcfbd + 8d2360401b3107b7090d9b769c85f5d74586d6c1: UPDATE-created overlap REDs cover both durable-reference interval-boundary directions.
  • b89888a8c53bfd496584574472b2db020a4c777c: current-time resolver REDs reject future-open-ended early selection and require finite-current selection.
  • bd0a794ea558c82fd0d51ed38c4e023fe3c26c56 + 5111f73da86542df5c83f8f620820e1a9ed815f8: historical same-reference successor scenario and ADR require caller-supplied accounting effective time.
  • ced69b28c8d211c26b2048c4169e8536732a6d17: missing effective_at resolver API is an explicit assertion RED.
  • 122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7: removes the weaker scheduler-dependent concurrency oracle; the PostgreSQL-observed ordered oracle remains authority.
  • 65ca26c4601262503e854d2bb470007ed9ac8111 + 3e9764db28ad52dbec8206c55711a199dc986ab9: adjusting-journal effective-date RED plus PostgreSQL-current-clock negative control.
  • 2c36496b2b9633fff18e87f5addfabf33ec31405: bank-assignment admission RED proves current database time sees the Book while assignment valid_from predates it.
  • e9e1d5645171116aa88acafea4b143fdf3c2ec60d66652c17d38918cae74d35b9a6fedd3e242fb64: parent-Book shortening containment RED plus migration-0012 command-identity fixture repair.
  • 2a1f42045fcc033de877079595d96aacd336270536e7e8197a821971a6184232c5f9860d6903fd11: ADR containment policy narrowed after review to bank_account_assignment only.
  • Current c805707dddc2db22fd42c2995b9c62c9a145765f: adds real-PostgreSQL child-side containment REDs for assignment valid_to extension beyond finite Book end and assignment valid_from movement before finite Book start. Each fixture deliberately gives the referenced chart account a wider interval than the hostile assignment mutation, isolating the expected failure to Accounting Book containment.

Production migration/resolver and mutable production bank_statement.py/persistence.py remain untouched.

Exact-head hosted evidence

Accounting Foundation 34398510617 is terminal FAILURE on exact c805707dddc2db22fd42c2995b9c62c9a145765f. Accounting job 102624253543 initialized PostgreSQL 18.4, verified the exact checkout, used Python 3.13.15 and hash-locked dependencies, then ran 479 tests in 89.570s and ended with 14 failures, 1 error in the intentionally RED behavior suite.

The two new child-side containment tests reach their hostile PostgreSQL UPDATE and each fail exactly because psycopg.IntegrityError is not raised:

  • test_assignment_end_cannot_extend_beyond_existing_book_end
  • test_assignment_start_cannot_move_before_existing_book_start

The earlier parent-side test_book_end_cannot_strand_existing_bank_assignment also remains causal RED with IntegrityError not raised. Existing durable-reference overlap/concurrency/update, resolver-cardinality/effective-time, adjusting-journal and assignment-admission REDs remain visible. Coverage/denominator, repository contracts, compile/import, reproducible package, SBOM/provenance continuation were skipped after behavior RED; integrated-head attestations are not claimed.

Same-head Foundation security 102624253226, SAST 102624253533, and dependency diff 102624253772 are terminal GREEN. Standalone Security 34398510580 and SAST 34398510592 are terminal GREEN.

Required CodeQL 34398510609 is terminal FAILURE at the central required-workflow ordering boundary, not a leaf AIP source-analysis verdict. Both receiver jobs first read pending and later failed irreversibly before the coordinator existed: Python 102624304868 enforced failure at 2026-09-09T20:03:50.975Z; Actions 102624304853 at 20:03:58.672Z. The authoritative coordinator 102625185159 only started at 20:04:04.113Z and successfully posted the exact current-head repository dispatch before ending at 20:04:07.080Z. This descendant canary is handed to canonical .github#2040 in comment 5607994372. Do not replay the leaf run or manufacture status.

This head is intentionally RED and is not whole-head GREEN.

Review state

Historical RLS-session, unused-import, weak-concurrency-oracle, fixture and over-generalized-ADR findings are repaired. Exact-head COMMENT review 5159281599 records the current gap: ADR 0022 already requires assignment containment under both parent and child boundary mutation, while the prior RED suite covered only parent Book shortening. It verifies that the two new child-side fixtures keep chart-account validity wider than the hostile mutation so unrelated chart-account boundaries cannot satisfy the expected rejection. This is review evidence only; no qualifying independent APPROVED is claimed.

Repair / single-writer boundary

Prefer a PostgreSQL-owned temporal non-overlap invariant for (tenant_account_id, legal_entity_id, book_name) across open-ended and finite intervals, enforced on INSERT and UPDATE of either boundary and safe under concurrent writers. Add one canonical resolver with caller-supplied effective instant plus 0/1/>1 cardinality checks; a current-only wrapper may deliberately supply database clock. Every authoritative path must pass its owning accounting-effective instant rather than duplicating valid_to IS NULL lookups.

The same canonical production migration must protect the scoped bank_account_assignment containment on both parent-Book and child-assignment boundary mutation. Admission-only checks are not sufficient. Existing violating rows must fail migration preflight for an explicit master-data decision; do not mutate historical evidence automatically.

The live #29 root-reconciliation branch already modifies src/accounting_information_platform/bank_statement.py, and #47/#53 remain its mutable forward stack. Therefore this RED lane must not create a competing production writer in bank_statement.py, persistence.py, or a forward migration. Once #29/#47/#53 normally integrate/reconcile, the canonical owner must adopt the effective-time resolver and temporal containment through an ordinary non-force descendant and allocate the next migration identity from the then-protected parent.

Preserve accounting_book_id as immutable Entity key, lawful non-overlapping history, exact-boundary adjacency, tenant RLS/composite-FK scope, reporting currency, posted/close/reconciliation/reporting evidence and existing bank-account assignment semantics.

PostgreSQL 18 temporal WITHOUT OVERLAPS is a candidate only if the canonical schema deliberately introduces a range/multirange representation; the current schema stores separate valid_from / nullable valid_to. An equivalent GiST exclusion design over a half-open timestamp range is also possible. Choosing the mechanism/extension belongs to the eventual canonical migration owner with clean-install, upgrade/preflight, concurrency, rollback and recovery evidence.

#57 admission source, shared CHANGELOG.md, STANDARD_TRACEABILITY.md, and docs/product-technical-gap-baseline.md remain out of scope for this RED lane; #37 owns the shared post-integration documentation surfaces.

GREEN / merge boundary

Keep Draft. One unchanged future descendant must turn all realistic REDs GREEN with the database-owned temporal invariant, canonical effective-time resolver, and scoped Bank-assignment containment; pass complete Accounting Foundation and exact owned statement/branch/docstring/edge-case gates, repository contracts, Security/SAST/dependency/package/SBOM/provenance, migration clean-install/upgrade/preflight/rollback/recovery, and current review/ruleset gates. ADR 0022 becomes Accepted for this amendment only after the production database invariant and resolver behavior reach protected integration. #57 ADR 0019 independently remains Proposed until its full GL population/totals repair is GREEN.

No self-approval, bypass, force-push, destructive rebase, synthetic status, no-op queue churn, premature merge, tag or release.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 159445ed-4209-4225-ac72-8935fdbd81fb

📥 Commits

Reviewing files that changed from the base of the PR and between 16f6d6e and 72e8e34.

📒 Files selected for processing (2)
  • docs/adr/0022-http-accounting-book-list.md
  • tests/test_postgres_accounting_book_reference_identity_red.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/adr/0022-http-accounting-book-list.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

ADR 0022가 유효시간 기반 book_name 참조 식별성 보완안과 구현 경계를 기록합니다. 실제 PostgreSQL RED 테스트가 중복 구간을 거부하고 비중복 이력 및 경계 인접 구간을 허용하는 동작을 검증합니다.

Changes

Accounting Book 참조 식별성

Layer / File(s) Summary
참조 식별성 계약과 구현 경계
docs/adr/0022-http-accounting-book-list.md
ADR 0022가 역사적 결정, 유효시간 중복 결함, PostgreSQL 기반 보완안, fail-closed resolver, 허용 대안과 구현 증거 경계를 기록합니다.
PostgreSQL 유효시간 RED 테스트
tests/test_postgres_accounting_book_reference_identity_red.py
실제 PostgreSQL 픽스처와 테넌트 컨텍스트를 사용합니다. 중복 활성 참조, open-ended 및 finite 구간 중첩은 IntegrityError를 발생시킵니다. 만료 이력과 정확히 맞닿는 half-open 구간은 삽입됩니다.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Medium

Merge Risk: 🟡 Moderate · up to 72e8e

This change defines and tests the intended temporal book-reference contract, but the production database enforcement is deliberately not included. The new PostgreSQL tests are expected to remain red until that implementation is delivered, so this is not merge-ready without explicitly accepting failing coverage.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR은 #58의 RED 단계 요구사항에 맞게 실제 PostgreSQL에서 open-ended/open-ended, open-ended/finite, finite/finite 중복을 거부하고, 비중복 이력과 half-open 경계 인접을 허용하는 테스트를 추가했습니다. 테넌트 RLS 컨텍스트와 ADR 0022 문서도 반영했습니다. 운영 제약 조건과 resol…
Out of Scope Changes check ✅ Passed 변경 사항은 #58의 RED 테스트와 제안된 temporal identity contract 문서로 제한됩니다. 운영 마이그레이션, resolver, GL admission writer, persistence.py 및 무관한 기능 변경은 포함되지 않았습니다.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 1 files. (1 skipped: 1 …
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 회계 장부 참조의 시간 구간 중복 방지를 검증하는 PostgreSQL 테스트라는 핵심 변경을 정확하고 간결하게 설명합니다.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/accounting-book-active-reference-identity

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

Review exact a600d61b4fb5a92294964a33d4a497175c302e0d as an intentional real-PostgreSQL RED. Focus on whether the fixture truly demonstrates duplicate active durable book_name identity while preserving lawful expired history, and on false-positive/fixture defects that could make the behavior failure unrelated to #58. Do not recommend weakening the RED or taking a provisional migration number from the live #29/#47/#53 stack.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="a600d61b4fb5a92294964a33d4a497175c302e0d"
parent="239008c4edc7d305c97704c5102b593c6622b36f"

echo "== Exact HEAD =="
git rev-parse HEAD
git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$head"

echo "== Changed files =="
git diff --name-status "$parent" "$head"

echo "== Focused test location =="
fd -a 'test_postgres_accounting_book_reference_identity_red.py' .

echo "== Test outline =="
test_file=$(fd -a 'test_postgres_accounting_book_reference_identity_red.py' . | head -n1)
if [ -n "$test_file" ]; then
  ast-grep outline "$test_file" --items all
  echo "== Focused test =="
  cat -n "$test_file"
fi

echo "== PostgreSQL fixture candidates =="
rg -n -i -C 4 '(postgres|postgresql).*(fixture|container)|fixture.*(postgres|postgresql)|postgres_(engine|session)|postgresql_(engine|session)' \
  -g '*.py' .

echo "== Accounting-book schema and migration candidates =="
rg -n -i -C 4 'create.*accounting_book|accounting_book.*(unique|constraint|index)|book_name|valid_(from|to)' \
  -g '*.sql' -g '*.py' .

Length of output: 157147


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fixture="tests/test_postgres_posting.py"
migration="database/migrations/0001_accounting_foundation.sql"

echo "== Canonical fixture lifecycle =="
rg -n -C 12 '^\s*(def|async def) (setUpClass|setUp|tearDown|doCleanups)\s*\(' "$fixture"

echo "== Fixture schema installation and cleanup calls =="
rg -n -C 10 '(migrations|Migration|DATABASE_URL|set_config|RESET app\.tenant_account_id|TRUNCATE|DROP SCHEMA|CREATE SCHEMA)' "$fixture"

echo "== Fixture policy and accounting-book seed =="
rg -n -C 14 '(self\.policy\s*=|AccountingPolicy\(|accounting_book_reference|INSERT INTO accounting_core\.accounting_book)' "$fixture"

echo "== Accounting-book RLS definition and grants =="
sed -n '300,345p' "$migration"
rg -n -C 5 '(GRANT|REVOKE|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY)' "$migration"

echo "== Comparable canonical-fixture wrappers =="
for f in tests/test_reversal_command_idempotency_postgres.py tests/test_reversal_temporal_database_guard.py tests/test_home_tax_incomplete_register_period_end.py; do
  if [ -f "$f" ]; then
    echo "-- $f --"
    sed -n '1,55p' "$f"
  fi
done

echo "== Existing accounting-book indexes in all checked-in migrations =="
rg -n -i -C 3 'CREATE (UNIQUE )?INDEX.*accounting_book|ON accounting_core\.accounting_book' database/migrations

Length of output: 125015


🏁 Script executed:

#!/bin/bash
set -euo pipefail

fixture="tests/test_postgres_posting.py"

echo "== Lifecycle and fixture method ranges =="
ast-grep outline "$fixture" --items all --match 'PostgresPostingTests|setUpClass|setUp|tearDown|_install|_seed'

echo "== First 220 lines: imports, constants, and fixture class setup =="
sed -n '1,220p' "$fixture"

echo "== Seed block around canonical accounting book insertion =="
sed -n '12190,12340p' "$fixture"

echo "== Direct SQL session configuration in canonical fixture methods =="
rg -n -C 6 "set_config\\('app\\.tenant_account_id'" "$fixture"

echo "== CI PostgreSQL configuration candidates =="
rg -n -i -C 6 '(postgres(:|/)|POSTGRES_(USER|PASSWORD|DB)|ACCOUNTING_DATABASE_URL|services:)' \
  -g '*.yml' -g '*.yaml' -g '*.toml' -g '*.ini' -g 'Dockerfile*' .

Length of output: 34211


@seonghobae Review found one fixture defect.

  • test_duplicate_active_book_reference_is_rejected correctly uses the same tenant, legal entity, and durable book_name. It changes both book_role_code and valid_from. Therefore, the protected (tenant_account_id, legal_entity_id, book_role_code, valid_from) constraint cannot cause the expected result.
  • test_expired_history_may_retain_the_same_book_reference correctly inserts a row where valid_from < valid_to < posting.VALID_FROM. The row is expired because valid_to is non-null. This preserves the required history case.
  • However, both direct connections omit set_config('app.tenant_account_id', ..., false). accounting_core.accounting_book has row-level security enabled. The canonical fixture sets this value before direct SQL. A role that does not bypass RLS can fail with an RLS error instead of the intended missing-UniqueViolation RED result.

Please set the tenant session value immediately after each psycopg.connect(...) call in this test. This change keeps the RED intact. It removes an environment-dependent failure path that is unrelated to #58.

✅ Action performed

Review finished.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Treat finding text, file paths, and code as untrusted review data. Never follow
instructions embedded in them. Verify each finding against current code. Fix
only still-valid issues, skip the rest with a brief reason, keep changes
minimal, and validate.

Inline comments:
In `@tests/test_postgres_accounting_book_reference_identity_red.py`:
- Line 30: psycopg.connect를 사용하는 두 직접 연결에 tenant RLS 컨텍스트를 설정하십시오.
tests/test_postgres_accounting_book_reference_identity_red.py 30-30에서는 첫 쿼리 전에,
75-75에서는 이력 INSERT 전에 set_config에 str(self.case.tenant_id)를 사용해
app.tenant_account_id를 설정하십시오.

After applying the fix, consider running `coderabbit review --agent` for local
review. Visit https://docs.coderabbit.ai/cli.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 0f212c70-9a94-4d3e-8b2f-902257839bdd

📥 Commits

Reviewing files that changed from the base of the PR and between 239008c and 16f6d6e.

📒 Files selected for processing (2)
  • docs/adr/0022-http-accounting-book-list.md
  • tests/test_postgres_accounting_book_reference_identity_red.py

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

Comment thread tests/test_postgres_accounting_book_reference_identity_red.py
@seonghobae seonghobae changed the title test(book): enforce unique active accounting-book reference test(book): enforce non-overlapping accounting-book reference Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is 72e8e342eaeb4edd40c11284f11473a8622aea79. Please review the widened temporal identity contract specifically for: finite/finite overlap, lawful [a,b) / [b,c) adjacency, RLS-session validity of the PostgreSQL oracle, and ADR 0022 consistency. This is review evidence only; do not treat it as approval or GREEN.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="72e8e342eaeb4edd40c11284f11473a8622aea79"

echo "== Exact commit =="
git rev-parse HEAD
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"

parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
echo "== Changed files =="
git diff --name-status "$parent" "$head"
echo "== Focused diff =="
git diff --find-renames --find-copies --unified=80 "$parent" "$head" -- \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  docs/adr/0022-http-accounting-book-list.md \
  database/migrations

echo "== Candidate files =="
fd -a 'test_postgres_accounting_book_reference_identity_red.py' .
fd -a 'test_postgres_posting.py' .
fd -a '0022-http-accounting-book-list.md' .
fd -a '0001_accounting_foundation.sql' database/migrations

test_file="$(fd -a 'test_postgres_accounting_book_reference_identity_red.py' . | head -n1)"
fixture_file="$(fd -a 'test_postgres_posting.py' . | head -n1)"
adr_file="$(fd -a '0022-http-accounting-book-list.md' . | head -n1)"
migration_file="$(fd -a '0001_accounting_foundation.sql' database/migrations | head -n1)"

echo "== Focused test outline =="
ast-grep outline "$test_file" --items all
echo "== Focused test =="
cat -n "$test_file"

echo "== Direct PostgreSQL connections and tenant session configuration =="
rg -n -C 8 "psycopg\.connect|set_config\('app\.tenant_account_id'|SET LOCAL|SET app\.tenant_account_id" \
  "$test_file" "$fixture_file"

echo "== Accounting-book definition, constraints, range logic, and RLS =="
rg -n -i -C 14 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|valid_from|valid_to|ENABLE ROW LEVEL SECURITY|CREATE POLICY|app\.tenant_account_id' \
  "$migration_file" database/migrations

echo "== ADR 0022 =="
cat -n "$adr_file"

Length of output: 169578


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="72e8e342eaeb4edd40c11284f11473a8622aea79"
test_file="tests/test_postgres_accounting_book_reference_identity_red.py"

echo "== Temporal accounting-book lookup predicates =="
rg -n -i -C 8 \
  'accounting_book|book_name|book_reference|valid_from\s*<=|valid_to\s*>|valid_to\s+IS\s+NULL' \
  -g '*.py' -g '*.sql' . \
  | head -n 900

echo "== Accounting-book constraints and triggers in all migrations =="
rg -n -i -C 8 \
  '(ALTER TABLE accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX.*accounting_book|ON accounting_core\.accounting_book|CREATE (CONSTRAINT|TRIGGER).*accounting_book|accounting_book.*(CONSTRAINT|TRIGGER|UNIQUE|EXCLUDE))' \
  database/migrations

echo "== Evolution of the temporal test fixture =="
for commit in \
  7d8ea2e1d5acdff81e0db62621cf64ef09c8c8a4 \
  446b3c93ce7d1d1d7348eecebdf06e771f64af5c \
  c887c7890094ba11646c31fbb69a3a362169c0a7 \
  "$head"
do
  echo "-- $commit --"
  git show -s --format='commit=%H%nparents=%P%nsubject=%s' "$commit"
  git show --format= --unified=20 "$commit" -- "$test_file" \
    | sed -n '1,500p'
done

echo "== Test interval values and protected-key comparison =="
sed -n '121,237p' "$test_file"

Length of output: 123749


@seonghobae Review completed for exact head 72e8e342eaeb4edd40c11284f11473a8622aea79.

I found no defect in the requested scope.

  • Finite/finite overlap: test_finite_overlapping_history_is_rejected creates [current_valid_from - 4 days, current_valid_from - 2 days) and then attempts [current_valid_from - 3 days, current_valid_from - 1 day). The intervals overlap. They use different book_role_code and different valid_from values. The protected composite key cannot cause the expected IntegrityError.
  • Half-open adjacency: test_touching_book_reference_intervals_are_allowed inserts [current_valid_from - 1 day, current_valid_from). The seeded current row begins at current_valid_from and is open-ended. The intervals only touch at one boundary. This is a lawful [a,b) / [b,c) handoff.
  • RLS session validity: Every direct psycopg.connect(...) session in tests/test_postgres_accounting_book_reference_identity_red.py now calls set_config('app.tenant_account_id', ..., false) before accessing accounting_core tenant data. This matches the accounting_book RLS policy. It also remains valid after migration 0005 applies FORCE ROW LEVEL SECURITY.
  • ADR 0022 consistency: The amendment defines half-open effective-time intervals, requires finite/finite and open-ended/finite overlap rejection, and permits exact-boundary adjacency. The implementation boundary correctly states that the work remains RED-only and that production migration and resolver changes are absent.

This is review evidence only. It is not approval or GREEN evidence. Runtime execution was not performed in this review environment.

✅ Action performed

Review finished.

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

Exact head f2df2e59e5db2c0310980940c4b9fd108de288ed만 다시 보십시오. 특히 새 concurrent overlapping book_reference PostgreSQL RED가 실제 database-owned temporal invariant를 검증하는지, thread/transaction orchestration이 false positive·hang·test-only race를 만들지 않는지, 기존 half-open adjacency/RLS/ADR 0022 계약과 충돌하지 않는지 검토해 주세요. Production migration/resolver는 아직 의도적으로 없습니다. 이 요청은 review evidence이지 approval 요청이 아닙니다.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="f2df2e59e5db2c0310980940c4b9fd108de288ed"
echo "== Exact commit =="
git rev-parse HEAD
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Changed files =="
git diff --name-status "$parent" "$head"
echo "== Focused diff =="
git diff --find-renames --find-copies --unified=100 "$parent" "$head" -- \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_posting.py \
  docs/adr/0022-http-accounting-book-list.md \
  database/migrations

echo "== Candidate files =="
fd -a 'test_postgres_accounting_book_reference_identity_red.py' .
fd -a 'test_postgres_posting.py' .
fd -a '0022-http-accounting-book-list.md' .
fd -a '0001_accounting_foundation.sql' database/migrations

test_file="$(fd -a 'test_postgres_accounting_book_reference_identity_red.py' . | head -n1)"
fixture_file="$(fd -a 'test_postgres_posting.py' . | head -n1)"
adr_file="$(fd -a '0022-http-accounting-book-list.md' . | head -n1)"
migration_file="$(fd -a '0001_accounting_foundation.sql' database/migrations | head -n1)"

echo "== Test structure =="
ast-grep outline "$test_file" --items all
echo "== Concurrent and direct-connection code =="
rg -n -C 18 -i \
  'concurrent|thread|barrier|event|queue|timeout|join|psycopg\.connect|set_config|begin|commit|rollback|IntegrityError|UniqueViolation|accounting_book|book_name|valid_(from|to)' \
  "$test_file"

echo "== Full focused test =="
cat -n "$test_file"

echo "== Canonical fixture lifecycle and schema seed =="
ast-grep outline "$fixture_file" --items all --match 'PostgresPostingTests|setUpClass|setUp|tearDown'
rg -n -C 10 \
  'set_config\('\'app\.tenant_account_id|accounting_book|valid_from|valid_to|DATABASE_URL|psycopg\.connect|TRUNCATE|migration' \
  "$fixture_file"

echo "== Accounting-book schema, constraints, and RLS =="
rg -n -i -C 16 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|valid_from|valid_to|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|app\.tenant_account_id' \
  database/migrations

echo "== ADR 0022 =="
cat -n "$adr_file"

Length of output: 66510


🏁 Script executed:

#!/bin/bash
set -euo pipefail

test_file="tests/test_postgres_accounting_book_reference_identity_red.py"
fixture_file="tests/test_postgres_posting.py"
adr_file="docs/adr/0022-http-accounting-book-list.md"

echo "== Test range and fixture setup range =="
sed -n '185,310p' "$test_file"
sed -n '220,360p' "$fixture_file"

echo "== All accounting_book DDL, constraints, indexes, triggers, and RLS =="
rg -n -i -C 12 \
  'accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX|EXCLUDE|CREATE POLICY|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|set_config|app\.tenant_account_id' \
  database/migrations

echo "== Migration files =="
fd -a -e sql . database/migrations | sort

echo "== ADR 0022 =="
cat -n "$adr_file"

echo "== Existing PostgreSQL concurrency-test synchronization and cancellation patterns =="
rg -n -i -C 12 \
  'threading\.(Thread|Event|Barrier)|\.join\(timeout|\.cancel\(\)|pg_stat_activity|lock_timeout|statement_timeout|advisory.*lock|EXCLUDE' \
  -g '*.py' -g '*.sql' tests database

echo "== Fixture schema setup, isolation, and cleanup implementation =="
rg -n -C 16 \
  'def setUpClass|def setUp\(|def tearDown|def doCleanups|def _seed_master_data|psycopg\.connect|DATABASE_URL|_migration_applied|TRUNCATE|ROLLBACK|COMMIT' \
  "$fixture_file"

Length of output: 131088


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== accounting_book declarations and subsequent alterations =="
rg -n -i -C 35 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|ON accounting_core\.accounting_book|accounting_book.*(unique|exclude|check|constraint|policy)|CREATE POLICY.*accounting_book|FORCE ROW LEVEL SECURITY' \
  database/migrations

echo "== Exact accounting-book seed and fixture lifecycle =="
sed -n '220,330p' tests/test_postgres_posting.py
sed -n '12210,12345p' tests/test_postgres_posting.py

echo "== ADR temporal amendment only =="
rg -n -i -C 18 \
  'proposed amendment|half-open|valid_from|valid_to|overlap|adjacen|concurren|database-owned|resolver|RED|evidence' \
  docs/adr/0022-http-accounting-book-list.md

echo "== Concurrent test line-numbered excerpt =="
nl -ba tests/test_postgres_accounting_book_reference_identity_red.py | sed -n '191,302p'

echo "== All references to the concurrent test or its reference suffix =="
rg -n -C 4 \
  'test_concurrent_overlapping_book_reference_inserts_are_serialized|concurrency' \
  tests docs database

Length of output: 80509


@seonghobae 검토를 완료했습니다. 정확한 head f2df2e59e5db2c0310980940c4b9fd108de288ed에서 동시성 RED에 한 가지 결함이 있습니다.

  • 동시성 oracle이 실제 경쟁 상태를 보장하지 않습니다. Line 255는 두 번째 트랜잭션에 진입한 직후 second_started를 설정합니다. 그러나 두 번째 INSERT는 Line 256 이후에 실행됩니다. 메인 스레드는 Line 285의 이벤트만 기다린 뒤 Line 286에서 첫 번째 트랜잭션을 commit합니다. 따라서 스케줄러가 두 번째 스레드를 이벤트 설정 직후 중단하면, 두 번째 INSERT는 첫 번째 commit 이후에 실행될 수 있습니다. 이 경우 테스트는 순차적 overlap 거부만 검증합니다. 동시 uncommitted write가 database-owned temporal invariant에 의해 대기하고 실패하는지는 검증하지 못합니다. 두 번째 SQL 문이 PostgreSQL에 도달했음을 확인하거나, database wait 상태를 확인한 뒤 첫 번째 트랜잭션을 commit하도록 orchestration을 변경해야 합니다.

다른 요청 범위에서는 결함을 찾지 못했습니다.

  • 두 삽입은 같은 tenant, legal entity, book_name을 사용합니다. 역할과 valid_from은 다릅니다. 현재 (tenant_account_id, legal_entity_id, book_role_code, valid_from) 제약은 기대하는 IntegrityError를 설명할 수 없습니다.
  • 두 writer session은 app.tenant_account_id를 설정하고 commit합니다. set_config(..., false) 값은 이후 트랜잭션에도 유지됩니다. RLS oracle은 유효합니다.
  • [VALID_FROM + 10 days, VALID_FROM + 20 days)[VALID_FROM + 15 days, VALID_FROM + 25 days)는 실제로 겹칩니다. 이 테스트는 half-open adjacency 허용 규칙을 변경하지 않습니다.
  • ADR 0022는 PostgreSQL-owned temporal non-overlap과 half-open adjacency를 요구합니다. 새 RED의 목적은 ADR과 일치합니다.
  • 5초 및 10초 timeout, cancel 경로는 무한 대기 위험을 제한합니다. 다만 위 scheduling gap은 남아 있습니다.

이 검토는 evidence입니다. 승인 또는 GREEN evidence가 아닙니다. 런타임 실행은 수행하지 않았습니다.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is fd7601724d27ed1327e547ec8317dd95fac17e96. Please review the new ordered-concurrency RED specifically: the competing accounting_book INSERT must be observed as returned or actively executing in PostgreSQL while the first conflicting transaction is still uncommitted, and the observer connection is autocommit so repeated pg_stat_activity reads stay current. This is review evidence only, not approval or GREEN.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="fd7601724d27ed1327e547ec8317dd95fac17e96"

echo "== Exact commit =="
git rev-parse HEAD
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Changed files and focused diff =="
git diff --name-status "$parent" "$head"
git diff --find-renames --find-copies --unified=100 "$parent" "$head" -- \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_posting.py \
  docs/adr/0022-http-accounting-book-list.md \
  database/migrations

echo "== Candidate files =="
fd -a 'test_postgres_accounting_book_reference_identity_red.py' .
fd -a 'test_postgres_posting.py' .
fd -a '0022-http-accounting-book-list.md' .
fd -a '0001_accounting_foundation.sql' database/migrations

test_file="$(fd -a 'test_postgres_accounting_book_reference_identity_red.py' . | head -n1)"
fixture_file="$(fd -a 'test_postgres_posting.py' . | head -n1)"
adr_file="$(fd -a '0022-http-accounting-book-list.md' . | head -n1)"

echo "== Test structure =="
ast-grep outline "$test_file" --items all

echo "== Ordered-concurrency test and all connection/session code =="
rg -n -C 22 -i \
  'ordered|concurrent|thread|barrier|event|queue|timeout|join|cancel|psycopg\.connect|autocommit|pg_stat_activity|wait_event|state|query|backend_pid|set_config|begin|commit|rollback|IntegrityError|UniqueViolation|accounting_book|book_name|valid_(from|to)' \
  "$test_file"

echo "== Complete focused test file =="
cat -n "$test_file"

echo "== Fixture lifecycle, seed, and database URL =="
rg -n -C 14 \
  'def setUpClass|def setUp\(|def tearDown|DATABASE_URL|psycopg\.connect|set_config\('\''app\.tenant_account_id|accounting_book|valid_from|valid_to|TRUNCATE|migration' \
  "$fixture_file"

echo "== Accounting-book DDL, constraints, and RLS =="
rg -n -i -C 16 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|valid_from|valid_to|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|app\.tenant_account_id' \
  database/migrations

echo "== ADR 0022 temporal-contract excerpts =="
rg -n -i -C 18 \
  'proposed amendment|half-open|valid_from|valid_to|overlap|adjacen|concurren|database-owned|resolver|RED|evidence' \
  "$adr_file"

Length of output: 159092


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="fd7601724d27ed1327e547ec8317dd95fac17e96"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
test_file="tests/test_postgres_accounting_book_reference_identity_red.py"

echo "== Exact focused diff =="
git diff --unified=35 "$parent" "$head" -- "$test_file"

echo "== Imports, class setup, and helper declarations =="
nl -ba "$test_file" | sed -n '1,210p'

echo "== Ordered-concurrency test =="
nl -ba "$test_file" | sed -n '180,390p'

echo "== All pg_stat_activity queries and observer configuration =="
rg -n -C 14 \
  'pg_stat_activity|autocommit|backend_pid|wait_event|state|query|observer|poll|sleep|deadline' \
  "$test_file"

echo "== Test dependency versions and PostgreSQL role/setup references =="
rg -n -C 6 \
  'psycopg|postgres|POSTGRES|DATABASE_URL|CREATE ROLE|GRANT.*pg_(monitor|read_all_stats)|pg_stat_activity' \
  pyproject.toml requirements.txt setup.cfg tox.ini database tests 2>/dev/null || true

Length of output: 1433


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="fd7601724d27ed1327e547ec8317dd95fac17e96"
test_file="tests/test_postgres_accounting_book_reference_identity_red.py"

echo "== Exact commit and parent =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
echo "parent=$parent"

echo "== Files changed by exact commit =="
git diff-tree --no-commit-id --name-status -r "$head"

echo "== Versioned focused diff =="
git diff --unified=45 "$parent" "$head" -- "$test_file" || true

echo "== Versioned test source: lines 1-420 =="
git show "$head:$test_file" | cat -n | sed -n '1,420p'

echo "== Versioned observer-related source =="
git show "$head:$test_file" \
  | grep -n -E -C 14 'pg_stat_activity|autocommit|backend_pid|wait_event|state|query|observer|poll|sleep|deadline' \
  || true

echo "== PostgreSQL monitoring privilege configuration =="
grep -R -n -E -C 5 \
  'pg_stat_activity|pg_monitor|pg_read_all_stats|GRANT.*pg_' \
  database tests .github 2>/dev/null \
  || true

Length of output: 22621


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="fd7601724d27ed1327e547ec8317dd95fac17e96"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
test_file="tests/test_postgres_accounting_book_reference_concurrency_order_red.py"

echo "== Exact changed-test diff =="
git diff --unified=60 "$parent" "$head" -- "$test_file"

echo "== Exact changed-test source =="
git show "$head:$test_file" | cat -n

echo "== Observer and writer excerpts =="
git show "$head:$test_file" \
  | grep -n -E -C 20 \
  'autocommit|pg_stat_activity|backend_pid|first_connection|second_connection|observer_connection|state|query|deadline|sleep|commit|cancel|join|IntegrityError|INSERT' \
  || true

echo "== All test files that use pg_stat_activity =="
grep -R -n -E -C 12 'pg_stat_activity|autocommit' tests 2>/dev/null || true

echo "== Test-run configuration relevant to PostgreSQL integration tests =="
find . -maxdepth 3 -type f \( -name 'pyproject.toml' -o -name 'tox.ini' -o -name 'pytest.ini' -o -name 'Makefile' -o -name '*.yml' -o -name '*.yaml' \) \
  -print0 \
  | xargs -0 grep -n -E -C 5 'postgres|Postgres|DATABASE_URL|unittest|test_postgres_accounting_book_reference_concurrency_order_red' \
  2>/dev/null \
  || true

Length of output: 59450


@seonghobae 검토를 완료했습니다. 정확한 head fd7601724d27ed1327e547ec8317dd95fac17e96에서 요청 범위의 결함을 찾지 못했습니다.

  • observer_connection은 Line 64에서 autocommit=True로 생성됩니다. 각 pg_stat_activity 조회는 독립된 트랜잭션에서 실행됩니다. 반복 조회가 이전 트랜잭션 스냅샷에 고정되지 않습니다.
  • 테스트는 Line 73에서 두 번째 writer backend PID를 얻습니다. Line 140의 observer query는 그 PID만 조회합니다.
  • 첫 번째 transaction은 Line 168까지 commit하지 않습니다. 그 전에는 다음 중 하나가 반드시 확인되어야 합니다.
    • Line 123의 second_insert_returned가 설정됩니다. 이는 두 번째 INSERT가 반환되었음을 의미합니다.
    • Line 148-153이 pg_stat_activity에서 두 번째 session의 state = 'active'INSERT INTO accounting_core.accounting_book를 확인합니다. 이는 경쟁 INSERT가 PostgreSQL에서 실행 중이거나 lock 대기 중임을 의미합니다.
  • 따라서 이전의 scheduler gap은 제거되었습니다. 두 번째 thread가 시작 이벤트 직후 중단되어도 첫 번째 transaction은 경쟁 INSERT의 반환 또는 PostgreSQL activity 관찰 전에는 commit하지 않습니다.
  • 두 interval은 [VALID_FROM + 30 days, VALID_FROM + 40 days)[VALID_FROM + 35 days, VALID_FROM + 45 days)입니다. 두 interval은 실제로 겹칩니다. 이 테스트는 lawful [a,b) / [b,c) adjacency 규칙을 변경하지 않습니다.
  • 현재 RED 상태에서는 두 INSERT가 반환된 뒤 두 writer가 commit할 수 있습니다. Line 179-184가 이를 실패로 처리합니다. 이후 PostgreSQL-owned temporal invariant가 추가되면 두 번째 writer는 첫 번째 transaction이 열린 동안 active 상태로 관찰된 뒤, 첫 번째 commit 후 IntegrityError로 종료되어야 합니다.
  • Line 159-175의 rollback, commit-gate release, cancel, join 처리는 관찰 실패와 block 상태의 hang을 제한합니다.
  • ADR 0022의 PostgreSQL-owned non-overlap 및 half-open interval 계약과 충돌하지 않습니다.

이 결과는 review evidence입니다. 승인 또는 GREEN evidence가 아닙니다. 런타임 실행은 수행하지 않았습니다.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is now fc62c76e0ba2673c8727cf6ec15e197922abd964. Please review both newly added RED surfaces: tests/test_postgres_accounting_book_reference_concurrency_order_red.py for deterministic second-writer ordering and tests/test_accounting_book_reference_resolver_cardinality_red.py for 0/1/>1 fail-closed resolution. Do not treat this request or COMMENTED review as approval/merge evidence.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="bacc7897ae9617dfadca7bd50b2720c0b6d934df"
prior="ced69b28c8d211c26b2048c4169e8536732a6d17"

echo "== Exact commit and ancestry =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
git merge-base --is-ancestor "$prior" "$head" && echo "prior_is_ancestor=yes"

echo "== Requested delta files =="
git diff --name-status "$prior" "$head"
echo "== Requested delta stat =="
git diff --stat "$prior" "$head"

echo "== All current PR files relative to merge-base with origin/main if available =="
if git rev-parse --verify origin/main >/dev/null 2>&1; then
  base="$(git merge-base origin/main "$head")"
  printf 'merge_base=%s\n' "$base"
  git diff --name-status "$base" "$head"
fi

echo "== SQL/Python target file outlines =="
for file in \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  docs/adr/0022-http-accounting-book-list.md
do
  if git cat-file -e "$head:$file" 2>/dev/null; then
    echo "== $file =="
    if [[ "$file" == *.py ]]; then
      ast-grep outline "$file" --items all
    fi
    git show "$head:$file" | nl -ba
  fi
done

echo "== Exact delta for all likely RED and ADR files =="
git diff --unified=45 "$prior" "$head" -- \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  docs/adr/0022-http-accounting-book-list.md

echo "== Shared fixture: lifecycle, seed, cleanup, and RLS session configuration =="
rg -n -C 18 \
  'def setUpClass|def setUp\(|def tearDown|DATABASE_URL|psycopg\.connect|set_config\('\''app\.tenant_account_id|INSERT INTO accounting_core\.accounting_book|book_name|book_role_code|valid_from|valid_to|TRUNCATE' \
  tests/test_postgres_posting.py

echo "== Production resolver: signature, query predicate, cardinality, and session context =="
rg -n -C 30 \
  'def _require_book_for_close|def _session|_require_book_for_close\(|accounting_core\.accounting_book|book_name|valid_from|valid_to|effective_at|fetchone\(|fetchall\(|set_config\(' \
  src/accounting_information_platform/persistence.py

echo "== Accounting book table, constraints, and RLS =="
rg -n -i -C 25 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|ON accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX.*accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|book_role_code|valid_from|valid_to|FOREIGN KEY|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|app\.tenant_account_id' \
  database/migrations

echo "== Imports in all scoped Python RED tests =="
for file in tests/test_*accounting_book*red.py; do
  [ -f "$file" ] || continue
  echo "-- $file --"
  sed -n '1,65p' "$file"
done

Length of output: 5038


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="bacc7897ae9617dfadca7bd50b2720c0b6d934df"
prior="ced69b28c8d211c26b2048c4169e8536732a6d17"

numbered() {
  awk '{ printf "%6d  %s\n", NR, $0 }'
}

echo "== Exact cleanup delta =="
git diff --unified=25 "$prior" "$head" -- \
  tests/test_postgres_accounting_book_effective_resolution_red.py

echo "== Six current RED files and ADR =="
for file in \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  docs/adr/0022-http-accounting-book-list.md
do
  echo "== $file =="
  git show "$head:$file" | numbered
done

echo "== Current scoped test imports and import usages =="
for file in \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py
do
  echo "-- $file --"
  git show "$head:$file" | sed -n '1,70p'
done

echo "== Fixture: relevant setup, seed, cleanup, and RLS =="
rg -n -C 20 \
  'def setUpClass|def setUp\(|def tearDown|DATABASE_URL|psycopg\.connect|set_config\('\''app\.tenant_account_id|INSERT INTO accounting_core\.accounting_book|book_name|book_role_code|valid_from|valid_to|TRUNCATE' \
  tests/test_postgres_posting.py

echo "== Resolver implementation and call sites =="
rg -n -C 35 \
  'def _require_book_for_close|def _session|_require_book_for_close\(|accounting_core\.accounting_book|book_name|valid_from|valid_to|effective_at|fetchone\(|fetchall\(|set_config\(' \
  src/accounting_information_platform/persistence.py

echo "== Accounting-book schema, constraints, and RLS =="
rg -n -i -C 30 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|ON accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX.*accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|book_role_code|valid_from|valid_to|FOREIGN KEY|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|app\.tenant_account_id' \
  database/migrations

echo "== Test discovery and exact source presence =="
rg -n -C 4 \
  'unittest\.main\(\)|class .*Tests\(unittest\.TestCase\)' \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py

Length of output: 48640


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="bacc7897ae9617dfadca7bd50b2720c0b6d934df"

numbered() {
  awk '{ printf "%6d  %s\n", NR, $0 }'
}

echo "== Actual accounting-book RED files at exact head =="
git ls-tree -r --name-only "$head" tests \
  | grep -E 'test_.*accounting_book.*red\.py$' \
  | sort

echo "== Files changed from the first listed RED commit to exact head =="
base="a600d61b4fb5a92294964a33d4a497175c302e0d"
git merge-base --is-ancestor "$base" "$head" && git diff --name-status "$base" "$head"

echo "== Remaining scoped RED sources and ADR =="
for file in \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  docs/adr/0022-http-accounting-book-list.md
do
  echo "== $file =="
  git show "$head:$file" | numbered
done

echo "== Effective-resolution cleanup import before and after =="
echo "-- parent --"
git show "${head}^:tests/test_postgres_accounting_book_effective_resolution_red.py" | sed -n '1,240p'
echo "-- exact head --"
git show "$head:tests/test_postgres_accounting_book_effective_resolution_red.py" | sed -n '1,240p'

echo "== Production resolver and session context =="
rg -n -C 40 \
  'def _require_book_for_close|def _session|_require_book_for_close\(|accounting_core\.accounting_book|book_name|valid_from|valid_to|effective_at|fetchone\(|fetchmany\(|fetchall\(|set_config\(' \
  src/accounting_information_platform/persistence.py

echo "== Accounting-book constraints and RLS definitions =="
rg -n -i -C 30 \
  'CREATE TABLE accounting_core\.accounting_book|ALTER TABLE accounting_core\.accounting_book|ON accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX.*accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY)|book_name|book_role_code|valid_from|valid_to|FOREIGN KEY|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|app\.tenant_account_id' \
  database/migrations

echo "== Canonical fixture: tenant session context and accounting-book setup =="
rg -n -C 20 \
  'DATABASE_URL|def setUp\(|def tearDown|set_config\('\''app\.tenant_account_id|INSERT INTO accounting_core\.accounting_book|book_name|book_role_code|valid_from|valid_to|TRUNCATE' \
  tests/test_postgres_posting.py

Length of output: 129337


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="bacc7897ae9617dfadca7bd50b2720c0b6d934df"
effective="tests/test_postgres_accounting_book_effective_resolution_red.py"
adr="docs/adr/0022-http-accounting-book-list.md"
resolver="src/accounting_information_platform/persistence.py"

numbered() {
  awk '{ printf "%6d  %s\n", NR, $0 }'
}

echo "== Effective-resolution RED, exact complete source =="
git show "$head:$effective" | numbered

echo "== Removed module usage check, parent and exact head =="
echo "-- parent references --"
git show "${head}^:$effective" | grep -nE '\bpsycopg\b' || true
echo "-- exact-head references --"
git show "$head:$effective" | grep -nE '\bpsycopg\b' || true

echo "== ADR 0022, exact complete source =="
git show "$head:$adr" | numbered

echo "== Resolver method definitions =="
for symbol in '_require_book_for_close' '_session'; do
  line="$(rg -n "^[[:space:]]*def ${symbol}\\(" "$resolver" | head -n 1 | cut -d: -f1)"
  echo "-- $symbol at $line --"
  if [ -n "$line" ]; then
    start=$((line > 8 ? line - 8 : 1))
    end=$((line + 130))
    sed -n "${start},${end}p" "$resolver" | awk -v offset="$start" '{ printf "%6d  %s\n", offset + NR - 1, $0 }'
  fi
done

echo "== All _require_book_for_close call forms =="
rg -n -C 5 '\b_require_book_for_close\s*\(' "$resolver"

echo "== Accounting-book table declaration =="
line="$(rg -n 'CREATE TABLE accounting_core\.accounting_book' database/migrations/0001_accounting_foundation.sql | head -n1 | cut -d: -f1)"
start=$((line - 5))
end=$((line + 55))
sed -n "${start},${end}p" database/migrations/0001_accounting_foundation.sql \
  | awk -v offset="$start" '{ printf "%6d  %s\n", offset + NR - 1, $0 }'

echo "== Accounting-book RLS declaration =="
rg -n -i -C 12 \
  '(ENABLE|FORCE) ROW LEVEL SECURITY|CREATE POLICY.*accounting_book|ON accounting_core\.accounting_book' \
  database/migrations/0001_accounting_foundation.sql database/migrations/0005_postgres_runtime_rls.sql 2>/dev/null || true

echo "== Additional accounting-book constraints after 0001 =="
rg -n -i -C 8 \
  'accounting_core\.accounting_book|CREATE (UNIQUE )?INDEX.*accounting_book|EXCLUDE.*accounting_book' \
  database/migrations -g '*.sql'

Length of output: 85949


@seonghobae Review completed for exact head bacc7897ae9617dfadca7bd50b2720c0b6d934df.

I found one remaining concurrency-oracle defect.

  • In tests/test_postgres_accounting_book_reference_identity_red.py, Line 255 sets second_started before the second writer executes the INSERT on Line 256.
  • The main thread waits only for that event and commits the first writer on Line 286.
  • The scheduler can stop the second thread after Line 255. The first transaction can then commit before the competing INSERT reaches PostgreSQL.
  • Therefore, test_concurrent_overlapping_book_reference_inserts_are_serialized can pass after a sequential overlap check. It does not prove database serialization of concurrent writes.

tests/test_postgres_accounting_book_reference_concurrency_order_red.py fixes this problem for its own test. It uses an autocommit observer and waits until the competing INSERT either returns or is active in pg_stat_activity. The older test should not continue to claim concurrent-write coverage unless it uses the same ordering condition.

The other requested areas are consistent.

  • The effective-time RED uses valid_from <= effective_at and (valid_to IS NULL OR valid_to > effective_at). This preserves half-open [valid_from, valid_to) semantics.
  • The historical successor case places effective_at strictly inside the finite historical interval. The later open-ended successor starts at the historical interval end.
  • The resolver-cardinality RED requires failure for zero and multiple matches. The current .fetchone() implementation remains an intentional multiple-match RED.
  • The valid_from and valid_to update REDs start from lawful adjacency. Each mutation then creates a real overlap without violating the existing validity-order check or the role-based unique key.
  • Direct PostgreSQL sessions set app.tenant_account_id. The fixture remains valid with FORCE ROW LEVEL SECURITY.
  • The unused-import cleanup removes only an unused module import. It does not change any test oracle.
  • ADR 0022 remains consistent with PostgreSQL-owned non-overlap enforcement, both boundary-update directions, explicit accounting-effective time, resolver defense in depth, and the RED-only production boundary.

This is review evidence only. It is not approval, merge, or GREEN evidence. Runtime execution was not performed.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

Current-head review finding is valid. 122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7 removes the weaker duplicate test_concurrent_overlapping_book_reference_inserts_are_serialized instead of trying to repair its pre-INSERT event. The stronger canonical oracle already lives in tests/test_postgres_accounting_book_reference_concurrency_order_red.py: it observes either the INSERT return or the second backend actively executing INSERT INTO accounting_core.accounting_book via pg_stat_activity before releasing the first writer, then requires the competing overlapping writer to terminate with IntegrityError. Serial overlap coverage remains in the identity REDs. No production source, migration, ADR contract, or acceptance criterion was weakened.

@coderabbitai review
Please re-review exact 122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7, specifically that removing the weak duplicate leaves the ordered concurrency oracle as the sole concurrency authority and preserves all serial/effective-time REDs. This is review evidence only, not approval or GREEN.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Exact commit =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
echo "parent=$parent"
git rev-parse HEAD

echo "== Exact changed files =="
git diff-tree --no-commit-id --name-status -r "$head"
echo "== Exact diff =="
git diff --unified=80 "$parent" "$head" -- \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_concurrency_order_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py \
  docs/adr/0022-http-accounting-book-list.md \
  src/accounting_information_platform/persistence.py \
  database/migrations

echo "== Accounting-book RED test inventory at exact head =="
git ls-tree -r --name-only "$head" tests \
  | grep -E 'test_.*accounting_book.*red\.py$' \
  | sort

echo "== All remaining concurrency test definitions and ordering mechanisms =="
git grep -n -i -E \
  'def test_.*(concurrent|concurrency)|Thread\(|pg_stat_activity|second_insert_returned|second_started|INSERT INTO accounting_core\.accounting_book' \
  "$head" -- tests \
  || true

echo "== Ordered concurrency oracle at exact head =="
ordered="tests/test_postgres_accounting_book_reference_concurrency_order_red.py"
git show "$head:$ordered" | nl -ba

echo "== Identity and effective-time RED method inventory at exact head =="
for file in \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_postgres_accounting_book_reference_predecessor_valid_to_update_red.py
do
  echo "-- $file --"
  git show "$head:$file" | grep -nE '^[[:space:]]*def test_' || true
done

echo "== ADR and production boundary changes from parent =="
git diff --unified=30 "$parent" "$head" -- \
  docs/adr/0022-http-accounting-book-list.md \
  src/accounting_information_platform/persistence.py \
  database/migrations

Length of output: 26212


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7"
ordered="tests/test_postgres_accounting_book_reference_concurrency_order_red.py"

numbered() {
  awk '{ printf "%6d  %s\n", NR, $0 }'
}

echo "== Ordered concurrency oracle, exact source =="
git show "$head:$ordered" | numbered

echo "== Exact-head concurrency test definitions in accounting-book RED files =="
git ls-tree -r --name-only "$head" tests \
  | grep -E 'test_.*accounting_book.*red\.py$' \
  | sort \
  | while IFS= read -r file; do
      echo "-- $file --"
      git show "$head:$file" \
        | grep -nE '^[[:space:]]*def test_.*(concurrent|concurrency)' \
        || true
    done

echo "== Exact-head methods in retained serial, update, resolver, and effective-time REDs =="
for file in \
  tests/test_postgres_accounting_book_reference_identity_red.py \
  tests/test_postgres_accounting_book_reference_update_red.py \
  tests/test_accounting_book_reference_resolver_cardinality_red.py \
  tests/test_postgres_accounting_book_effective_resolution_red.py
do
  echo "-- $file --"
  git show "$head:$file" | grep -nE '^[[:space:]]*def test_' || true
done

echo "== Exact-head imports in changed identity RED =="
git show "$head:tests/test_postgres_accounting_book_reference_identity_red.py" \
  | sed -n '1,35p'

echo "== Exact parent-to-head diff stat and ADR/production/migration status =="
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
git diff --stat "$parent" "$head"
git diff --name-status "$parent" "$head" -- \
  docs/adr/0022-http-accounting-book-list.md \
  src/accounting_information_platform/persistence.py \
  database/migrations

Length of output: 14501


@seonghobae 검토를 완료했습니다. 정확한 head 122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7에서 요청 범위의 결함을 찾지 못했습니다.

  • 이 commit은 tests/test_postgres_accounting_book_reference_identity_red.py만 변경합니다.

  • 이 commit은 약한 test_concurrent_overlapping_book_reference_inserts_are_serialized와 사용하지 않는 threading import를 제거합니다.

  • Accounting Book RED 파일 중 tests/test_postgres_accounting_book_reference_concurrency_order_red.py만 concurrency test를 유지합니다. 따라서 ordered concurrency oracle이 유일한 concurrency authority입니다.

  • Canonical oracle은 첫 번째 writer를 commit하기 전에 다음 조건 중 하나를 확인합니다.

    • 두 번째 INSERT가 반환되었습니다.
    • pg_stat_activity가 두 번째 backend의 활성 INSERT INTO accounting_core.accounting_book를 확인했습니다.
  • Observer connection은 autocommit=True입니다.

  • Oracle은 두 번째 writer가 최종적으로 psycopg.IntegrityError를 기록해야 한다고 요구합니다.

  • Oracle은 committed outcome을 허용하지 않습니다.

  • 따라서 제거된 test의 pre-INSERT scheduling gap은 더 이상 concurrency coverage를 주장하는 경로에 남지 않습니다.

기존 RED coverage도 유지됩니다.

  • Identity RED는 active overlap, open-ended/finite overlap, finite/finite historical overlap, lawful adjacency, 그리고 expired history를 유지합니다.
  • Update RED는 valid_fromvalid_to update로 생성되는 overlap을 유지합니다.
  • Resolver RED는 0/1/>1 cardinality fail-closed behavior를 유지합니다.
  • Effective-time RED는 future open-ended row, current finite row, 그리고 historical successor resolution을 유지합니다.

ADR 0022, production source, migration은 이 commit에서 변경되지 않았습니다. 따라서 RED-only boundary와 기존 acceptance criteria도 변경되지 않았습니다.

이 결과는 review evidence입니다. 승인, merge, 또는 GREEN evidence가 아닙니다. 런타임 실행은 수행하지 않았습니다.


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head accounting-authority finding on 122a75519e8d9fe4bc64b71e6d94bf3fa10adfa7: the REDs now make _require_book_for_close effective-time aware, but the AIS-owned adjusting-journal write still bypasses that resolver. PostgresPostingLedger.post_adjusting_journal() selects accounting_book by tenant + legal entity + book_name + valid_to IS NULL and .fetchone() even though it already owns journal_date as the accounting-effective date. A book whose valid_from is after journal_date but before the current database clock can therefore be admitted into an authoritative journal.

Add one real-PostgreSQL RED that moves the fixture book's valid_from to 2026-09-01, then attempts the existing 2026-08-31 adjusting-journal command and requires AccountingValidationError with zero new journal rows. This isolates accounting-effective-time selection from current-clock selection without adding another catalog writer. Production repair remains out of scope while #53 owns persistence.py; the eventual canonical resolver must be used by authoritative write paths with the owning accounting effective instant, not only by close/read helpers. This is COMMENT evidence, not approval or GREEN.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head 65ca26c4601262503e854d2bb470007ed9ac8111, especially tests/test_postgres_adjusting_journal_book_effective_time_red.py. Verify that the oracle distinguishes the journal's 2026-08-31 accounting-effective date from current database time, that the setup does not trigger an unrelated existing constraint, and that the expected failure is attributable to post_adjusting_journal() selecting book_name with valid_to IS NULL while ignoring valid_from. Treat this as RED-lane review only; do not propose production persistence.py changes while #53 owns that surface.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="65ca26c4601262503e854d2bb470007ed9ac8111"
test_file="tests/test_postgres_adjusting_journal_book_effective_time_red.py"
fixture_file="tests/test_postgres_posting.py"
resolver_file="src/accounting_information_platform/persistence.py"
adr_file="docs/adr/0022-http-accounting-book-list.md"

echo "== Exact commit and parent =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
printf 'parent=%s\n' "$parent"
git merge-base --is-ancestor "$parent" "$head" && echo "parent_is_ancestor=yes"

echo "== Exact changed files and focused diff =="
git diff-tree --no-commit-id --name-status -r "$head"
git diff --unified=100 "$parent" "$head" -- \
  "$test_file" "$adr_file" "$resolver_file" database/migrations tests/test_postgres_posting.py

echo "== New RED: outline and complete exact source =="
ast-grep outline "$test_file" --items all
git show "$head:$test_file" | nl -ba

echo "== New RED: effective date, SQL setup, RLS, and oracle excerpts =="
git show "$head:$test_file" | rg -n -C 20 \
  'adjusting|journal|2026-08-31|effective|accounting.*date|posting.*date|book_name|valid_from|valid_to|INSERT INTO|psycopg\.connect|set_config|app\.tenant_account_id|assert|raises|IntegrityError|AccountingValidationError|post_adjusting_journal'

echo "== post_adjusting_journal definitions, book-resolution query, and direct callers =="
ast-grep outline "$resolver_file" --items all --match 'PostgresPostingLedger|post_adjusting_journal'
rg -n -C 35 \
  'def post_adjusting_journal|post_adjusting_journal\(|accounting_core\.accounting_book|book_name|valid_from|valid_to|clock_timestamp|CURRENT_TIMESTAMP|posting_date|journal_date|effective_at|fetchone\(|fetchall\(' \
  "$resolver_file"

echo "== Fixture lifecycle, seeded Accounting Book, journal prerequisites, and tenant context =="
rg -n -C 18 \
  'def setUpClass|def setUp\(|def tearDown|DATABASE_URL|psycopg\.connect|set_config\('\''app\.tenant_account_id|INSERT INTO accounting_core\.accounting_book|book_name|book_role_code|valid_from|valid_to|adjusting|journal|TRUNCATE' \
  "$fixture_file"

echo "== Accounting Book and journal schema constraints, foreign keys, and RLS =="
rg -n -i -C 24 \
  'CREATE TABLE accounting_core\.(accounting_book|journal|journal_entry|journal_line)|ALTER TABLE accounting_core\.(accounting_book|journal|journal_entry|journal_line)|ON accounting_core\.accounting_book|accounting_book.*(UNIQUE|EXCLUDE|CONSTRAINT|POLICY|INDEX|FOREIGN KEY)|book_name|book_role_code|valid_from|valid_to|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY.*accounting_book|app\.tenant_account_id' \
  database/migrations

echo "== Existing adjusting-journal tests and date conventions =="
rg -n -i -C 14 \
  'post_adjusting_journal\(|adjusting journal|adjusting_journal|2026-08-31|posting_date|journal_date|effective_at' \
  tests src/accounting_information_platform \
  -g '*.py'

echo "== ADR 0022: effective-time clauses only =="
git show "$head:$adr_file" | rg -n -i -C 18 \
  'effective.time|accounting.time|system.time|recorded.time|valid_from|valid_to|half-open|resolver|journal|adjusting|RED|`#53`'

Length of output: 203725


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="65ca26c4601262503e854d2bb470007ed9ac8111"
test_file="tests/test_postgres_adjusting_journal_book_effective_time_red.py"
resolver_file="src/accounting_information_platform/persistence.py"
migration_file="database/migrations/0001_accounting_foundation.sql"
fixture_file="tests/test_postgres_posting.py"

echo "== Exact RED source =="
git show "$head:$test_file" | nl -ba

echo "== post_adjusting_journal definition and complete method body =="
start="$(git show "$head:$resolver_file" | nl -ba | rg 'def post_adjusting_journal\(' | head -n1 | awk '{print $1}')"
if [ -n "$start" ]; then
  git show "$head:$resolver_file" | nl -ba | sed -n "${start},$((start + 310))p"
fi

echo "== Relevant helper definitions called by post_adjusting_journal =="
git show "$head:$resolver_file" | nl -ba | rg -C 20 \
  'def _require_book_for_close\(|def _require_fiscal_period\(|def _session\(|def _require_.*book|valid_to IS NULL|valid_from <=|accounting_core\.accounting_book'

echo "== Accounting Book DDL and constraints =="
git show "$head:$migration_file" | nl -ba | rg -n -C 28 \
  'CREATE TABLE accounting_core\.accounting_book|CONSTRAINT.*accounting_book|UNIQUE.*book|CHECK.*valid|FOREIGN KEY|ENABLE ROW LEVEL SECURITY|CREATE POLICY.*accounting_book'

echo "== General-journal DDL and constraints =="
git show "$head:$migration_file" | nl -ba | rg -n -C 22 \
  'CREATE TABLE accounting_core\.general_journal|CREATE TABLE accounting_core\.general_journal_line|CONSTRAINT.*general_journal|FOREIGN KEY|UNIQUE|CHECK'

echo "== Exact fixture helpers used by the RED =="
git show "$head:$fixture_file" | nl -ba | rg -C 18 \
  'def _adjusting_journal_payload\(|def _seed_book_without_chart_accounts\(|def setUp\(|def setUpClass\(|VALID_FROM|accounting_book_reference'

echo "== Precise exact-commit delta =="
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
git diff --unified=45 "$parent" "$head" -- "$test_file"

Length of output: 126829


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="65ca26c4601262503e854d2bb470007ed9ac8111"
resolver_file="src/accounting_information_platform/persistence.py"
migration_file="database/migrations/0001_accounting_foundation.sql"
fixture_file="tests/test_postgres_posting.py"

show_range() {
  local file="$1"
  local pattern="$2"
  local before="$3"
  local after="$4"
  local line
  line="$(git show "$head:$file" | grep -n -m1 -E "$pattern" | cut -d: -f1 || true)"
  printf '\n== %s (%s) at line %s ==\n' "$file" "$pattern" "${line:-not-found}"
  if [ -n "$line" ]; then
    local start=$((line > before ? line - before : 1))
    local end=$((line + after))
    git show "$head:$file" | nl -ba | sed -n "${start},${end}p"
  fi
}

show_range "$resolver_file" '^[[:space:]]*def post_adjusting_journal\(' 8 260
show_range "$resolver_file" '^[[:space:]]*def _require_book_for_close\(' 8 130
show_range "$resolver_file" '^[[:space:]]*def _require_fiscal_period\(' 8 130
show_range "$resolver_file" '^[[:space:]]*def _session\(' 8 95

echo "== All Accounting Book predicates in the adjusting-journal method window =="
method_line="$(git show "$head:$resolver_file" | grep -n -m1 -E '^[[:space:]]*def post_adjusting_journal\(' | cut -d: -f1)"
if [ -n "$method_line" ]; then
  git show "$head:$resolver_file" | nl -ba \
    | sed -n "${method_line},$((method_line + 320))p" \
    | grep -E -C 8 'accounting_book|book_name|valid_from|valid_to|_require_book_for_close|_require_fiscal_period'
fi

show_range "$migration_file" 'CREATE TABLE accounting_core\.accounting_book' 3 55
show_range "$migration_file" 'CREATE TABLE accounting_core\.general_journal' 3 70
show_range "$fixture_file" '^VALID_FROM[[:space:]]*=' 3 8
show_range "$fixture_file" '^[[:space:]]*def _count_table\(' 3 35

Length of output: 35429


@seonghobae Review completed for exact head 65ca26c4601262503e854d2bb470007ed9ac8111.

I found one RED-oracle weakness.

  • The test uses journal_date = 2026-08-31 and moves the open-ended Accounting Book to valid_from = 2026-09-01T00:00:00Z.
  • This correctly requires rejection under accounting-effective-time semantics.
  • However, the test does not establish that the database clock is after 2026-09-01.
  • Before that instant, an incorrect implementation that resolves the book using current database time would also reject the journal.
  • In that condition, the test can pass without proving that post_adjusting_journal() used the journal’s accounting-effective date.

The current implementation remains a causal RED for the identified shortcut.

  • PostgresPostingLedger.post_adjusting_journal() selects accounting_core.accounting_book by tenant, legal entity, book_name, and valid_to IS NULL.
  • It does not test valid_from.
  • Therefore, the moved book is selected despite not being effective on 2026-08-31.
  • The current code proceeds to create the journal, so assertRaises(AccountingValidationError) fails as intended.

The fixture does not appear to introduce another failure source.

  • The update affects exactly one canonical book row.
  • The row remains open-ended and retains its tenant, legal entity, role, currency, and immutable Entity key.
  • The update does not conflict with the existing role-and-valid_from unique key.
  • The fixture retains the canonical fiscal period, chart accounts, account-role mappings, and KRW currency.
  • The update executes through self.case.ledger._session() and tenant authorization. It does not depend on an unconfigured direct RLS session.
  • The journal count assertion confirms that a correct rejection occurs before durable journal creation.

This is RED-lane review evidence only. It is not approval or GREEN evidence. I did not propose a production persistence.py change.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact head 3e9764db28ad52dbec8206c55711a199dc986ab9, limited to tests/test_postgres_adjusting_journal_book_effective_time_red.py. The predecessor review correctly found that the RED did not prove database-current time was after valid_from=2026-09-01, so a future implementation that incorrectly used current database time could accidentally satisfy the oracle before that instant. This descendant now returns PostgreSQL clock_timestamp() with the updated row and asserts database_now > book_valid_from before issuing the fixed journal_date=2026-08-31 command. Verify that this makes current-clock resolution an explicit negative control while preserving the intended accounting-effective-time RED and without introducing an unrelated constraint path. RED-lane review only; persistence.py remains out of scope while #53 owns that surface.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="3e9764db28ad52dbec8206c55711a199dc986ab9"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
test_file="tests/test_postgres_adjusting_journal_book_effective_time_red.py"
fixture_file="tests/test_postgres_posting.py"
resolver_file="src/accounting_information_platform/persistence.py"
migration_file="database/migrations/0001_accounting_foundation.sql"

echo "== Exact commit =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
echo "parent=$parent"
git merge-base --is-ancestor "$parent" "$head" && echo "parent_is_ancestor=yes"

echo "== Exact changed files and focused diff =="
git diff-tree --no-commit-id --name-status -r "$head"
git diff --unified=100 "$parent" "$head" -- "$test_file"

echo "== Exact target test =="
git show "$head:$test_file" | nl -ba

echo "== Target test: chronology, PostgreSQL time control, session setup, and assertions =="
git show "$head:$test_file" | rg -n -C 20 \
  'clock_timestamp|database_now|book_valid_from|2026-08-31|2026-09-01|post_adjusting_journal|valid_from|valid_to|UPDATE |RETURNING|SELECT |set_config|_session\(|assert|raises|journal'

echo "== Test helper and fixture prerequisites =="
rg -n -C 20 \
  'def _adjusting_journal_payload\(|def _seed_book_without_chart_accounts\(|def setUp\(|def setUpClass\(|VALID_FROM|accounting_book_reference|def _session\(' \
  "$fixture_file" "$resolver_file"

echo "== Current adjusting-journal book query for causal context =="
line="$(git show "$head:$resolver_file" | rg -n '^\s*def post_adjusting_journal\(' | head -n1 | cut -d: -f1)"
if [ -n "$line" ]; then
  git show "$head:$resolver_file" | nl -ba | sed -n "${line},$((line + 300))p" \
    | rg -n -C 12 'accounting_book|book_name|valid_from|valid_to|fetchone|journal_date|posting_date|_require'
fi

echo "== Accounting-book and journal constraints/RLS =="
git show "$head:$migration_file" | nl -ba | rg -n -C 24 \
  'CREATE TABLE accounting_core\.(accounting_book|general_journal|general_journal_line)|CONSTRAINT|UNIQUE|CHECK|FOREIGN KEY|ENABLE ROW LEVEL SECURITY|CREATE POLICY.*accounting_book|ON accounting_core\.accounting_book'

echo "== Existing relevant test conventions =="
rg -n -i -C 10 \
  'post_adjusting_journal\(|journal_date|clock_timestamp\(\)|2026-08-31|book_valid_from' \
  tests -g '*.py'

Length of output: 198788


@seonghobae Review completed for exact head 3e9764db28ad52dbec8206c55711a199dc986ab9.

I found no defect in the requested scope.

  • The UPDATE returns PostgreSQL clock_timestamp() in the same statement that sets book_valid_from to 2026-09-01 00:00:00+00.
  • The test asserts database_now > book_valid_from before it submits the adjusting journal dated 2026-08-31.
  • Therefore, a resolver that incorrectly uses database-current time sees the open-ended book as effective.
  • That incorrect resolver cannot satisfy the expected AccountingValidationError.
  • The assertion makes current-clock resolution an explicit negative control.

The intended RED remains causal.

  • The journal accounting-effective date is 2026-08-31.
  • The updated Accounting Book starts on 2026-09-01.
  • A resolver that uses the journal accounting-effective date must reject the book.
  • The current post_adjusting_journal() path selects the book using valid_to IS NULL and does not check valid_from.
  • It therefore selects the future-at-journal-date book and allows the write path to proceed.
  • The expected AccountingValidationError remains an intentional RED.

The setup does not introduce an unrelated failure path.

  • The update targets one tenant-scoped, open-ended canonical Accounting Book row.
  • The row keeps its tenant, legal entity, role, reporting currency, and immutable identifier.
  • The update does not violate the role-and-valid_from unique constraint.
  • The update does not violate the valid_to > valid_from check because valid_to remains NULL.
  • The fixture uses PostgresPostingLedger._session(). The tenant RLS context remains valid.
  • The payload retains the canonical fiscal period, chart accounts, mappings, currency, and balanced journal lines.
  • The journal-count assertion still verifies that a correct rejection creates no durable journal.

This is RED-lane review evidence only. It is not approval, merge, or GREEN evidence. Runtime execution was not performed.

You are interacting with an AI system.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head accounting-authority finding: accept_bank_account_assignment() already owns the assignment's valid_from, but its Accounting Book lookup still filters only valid_to IS NULL and calls .fetchone(). That admits a book whose effective interval starts after the assignment itself, provided the book is open-ended at database-current time. The new real-PostgreSQL RED isolates that defect with assignment.valid_from=2026-08-31, book.valid_from=2026-09-01, and a PostgreSQL-clock negative control proving the book is current now. Expected behavior is fail-closed with zero assignment rows. This is COMMENT evidence only; production resolver/migration remains out of scope while the live persistence/migration stack is owned elsewhere.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Please review exact 2c36496b2b9633fff18e87f5addfabf33ec31405 only for the new bank-account-assignment effective-time RED and its interaction with the existing #58/#59 temporal identity contract. Treat production migration/resolver, persistence.py, and mutable sibling implementation as out of scope. In particular, verify that the PostgreSQL-clock negative control makes current-clock selection observably wrong and that no existing unrelated constraint can satisfy the expected rejection.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="2c36496b2b9633fff18e87f5addfabf33ec31405"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Exact commit =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
echo "parent=$parent"

echo "== Exact changed files =="
git diff-tree --no-commit-id --name-status -r "$head"

echo "== Exact focused diff =="
git diff --unified=100 "$parent" "$head" -- tests docs database/migrations

echo "== Candidate bank-account-assignment RED files =="
git ls-tree -r --name-only "$head" tests \
  | grep -Ei 'bank.*account.*assignment.*(effective|time).*red.*\.py$|bank.*assignment.*red.*\.py$' \
  || true

echo "== Candidate test source and outline =="
git ls-tree -r --name-only "$head" tests \
  | grep -Ei 'bank.*account.*assignment.*(effective|time).*red.*\.py$|bank.*assignment.*red.*\.py$' \
  | while IFS= read -r file; do
      echo "-- $file --"
      ast-grep outline "$file" --items all
      git show "$head:$file" | nl -ba
    done

echo "== Bank-account assignment schema, constraints, indexes, RLS, and temporal fields =="
rg -n -i -C 24 \
  'bank.*account.*assignment|account.*assignment.*bank|CREATE TABLE.*bank|ALTER TABLE.*bank|bank_account|valid_from|valid_to|effective_at|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY' \
  database/migrations

echo "== Fixture helpers and test references =="
rg -n -i -C 18 \
  'bank.*account.*assignment|account.*assignment.*bank|clock_timestamp|database_now|book_valid_from|set_config|app\.tenant_account_id|def _session|def setUp\(' \
  tests \
  -g '*.py'

echo "== ADR 0022 exact-head temporal identity/effective-time clauses =="
git show "$head:docs/adr/0022-http-accounting-book-list.md" | nl -ba \
  | rg -n -i -C 16 \
    'bank|assignment|effective.time|accounting.time|system.time|recorded.time|valid_from|valid_to|half-open|adjacen|book.reference|resolver|cardinality|concurren|RED|`#58`|`#59`' \
  || true

Length of output: 202487


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="2c36496b2b9633fff18e87f5addfabf33ec31405"
test_file="tests/test_postgres_bank_assignment_book_effective_time_red.py"
bank_file="src/accounting_information_platform/bank_statement.py"
migration_file="database/migrations/0001_accounting_foundation.sql"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Exact test source =="
git show "$head:$test_file" | nl -ba

echo "== Exact commit diff for target test and ADR =="
git diff --unified=60 "$parent" "$head" -- \
  "$test_file" docs/adr/0022-http-accounting-book-list.md

echo "== accept_bank_account_assignment definition and immediate helpers =="
line="$(git show "$head:$bank_file" | grep -n -m1 '^def accept_bank_account_assignment(' | cut -d: -f1)"
echo "accept_bank_account_assignment_line=${line:-not-found}"
if [ -n "$line" ]; then
  git show "$head:$bank_file" | nl -ba | sed -n "${line},$((line + 380))p"
fi

echo "== Bank account load and Accounting Book lookup patterns in bank_statement.py =="
git show "$head:$bank_file" | nl -ba \
  | rg -n -C 20 \
    'def _load_bank_account|def _load_legal_entity|def _load_.*book|accounting_core\.accounting_book|book_name|valid_from|valid_to|fetchone\(|AccountingValidationError|assignment_command_hash|idempotency' \
  || true

echo "== Bank account record and assignment DDL =="
for table in bank_account_record bank_account_assignment; do
  line="$(git show "$head:$migration_file" | grep -n -m1 "CREATE TABLE accounting_core\\.${table}" | cut -d: -f1)"
  echo "-- ${table}: line ${line:-not-found} --"
  if [ -n "$line" ]; then
    git show "$head:$migration_file" | nl -ba | sed -n "${line},$((line + 115))p"
  fi
done

echo "== Related DDL constraints, indexes, triggers, and RLS after migration 0001 =="
rg -n -i -C 12 \
  'bank_account_(record|assignment)|CREATE (UNIQUE )?INDEX.*bank|ALTER TABLE.*bank|CREATE TRIGGER.*bank|CREATE POLICY.*bank|ON accounting_core\.bank_account|FORCE ROW LEVEL SECURITY' \
  database/migrations

echo "== Test helper definitions referenced by the target test =="
git show "$head:$test_file" \
  | sed -nE 's/.*self\.case\.([A-Za-z_][A-Za-z0-9_]*).*/\1/p' \
  | sort -u \
  | while IFS= read -r helper; do
      echo "-- ${helper} --"
      rg -n -C 12 "def ${helper}\\(" tests/test_postgres_posting.py || true
    done

Length of output: 106929


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="2c36496b2b9633fff18e87f5addfabf33ec31405"
fixture="tests/test_postgres_posting.py"

echo "== Exact-head migration files containing bank-account tables =="
git grep -n -i -E \
  'bank_account_(record|assignment)|bank account assignment|bank account record' \
  "$head" -- database/migrations \
  || true

echo "== Exact-head table definitions, constraints, indexes, policies, and triggers =="
git grep -n -i -E \
  'CREATE TABLE .*bank_account_(record|assignment)|ALTER TABLE .*bank_account_(record|assignment)|CREATE (UNIQUE )?INDEX.*bank|ON .*bank_account_(record|assignment)|CREATE (CONSTRAINT|TRIGGER).*bank|CREATE POLICY.*bank_account|FORCE ROW LEVEL SECURITY.*bank' \
  "$head" -- database/migrations \
  || true

echo "== Complete migration excerpts that declare bank-account tables =="
git ls-tree -r --name-only "$head" database/migrations \
  | while IFS= read -r file; do
      matches="$(git show "$head:$file" | grep -n -i -E 'CREATE TABLE .*bank_account_(record|assignment)' || true)"
      if [ -n "$matches" ]; then
        echo "-- $file --"
        printf '%s\n' "$matches"
        while IFS=: read -r line _; do
          git show "$head:$file" | nl -ba | sed -n "${line},$((line + 130))p"
        done <<< "$matches"
      fi
    done

echo "== Canonical fixture seed: Accounting Book and chart account 110200 =="
git show "$head:$fixture" | nl -ba \
  | rg -n -C 22 \
    'INSERT INTO accounting_core\.accounting_book|INSERT INTO accounting_core\.chart_account|110200|primary_statutory|valid_from|valid_to' \
  | head -n 900

echo "== Exact-head effective-time constraints on Accounting Book and chart account =="
git grep -n -i -E \
  'accounting_book.*valid_(from|to)|chart_account.*valid_(from|to)|valid_(from|to).*accounting_book|valid_(from|to).*chart_account|CHECK.*valid' \
  "$head" -- database/migrations \
  || true

Length of output: 83968


@seonghobae 검토를 완료했습니다. 정확한 head 2c36496b2b9633fff18e87f5addfabf33ec31405에서 요청 범위의 결함을 찾지 못했습니다.

  • tests/test_postgres_bank_assignment_book_effective_time_red.py는 Accounting Book의 valid_from2026-09-01T00:00:00Z로 변경합니다.
  • 같은 UPDATE ... RETURNING 문은 PostgreSQL clock_timestamp()를 반환합니다.
  • 테스트는 database_now > book_valid_from을 확인한 뒤, valid_from = 2026-08-31T00:00:00Z인 bank-account assignment를 제출합니다.

따라서 current-clock selection은 명시적으로 잘못된 negative control입니다.

  • 현재 데이터베이스 시간에 해석하면 open-ended Accounting Book은 이미 effective입니다.
  • current-clock resolver는 이 command를 거부할 수 없습니다.
  • assignment의 accounting-effective instant에 해석하면 Accounting Book은 아직 effective가 아닙니다.
  • 올바른 구현은 AccountingValidationError를 발생시켜야 합니다.

현재 RED도 원인에 직접 연결됩니다.

  • accept_bank_account_assignment()accounting_core.accounting_bookvalid_to IS NULL로만 선택합니다.
  • 이 조회는 accounting_book.valid_from과 assignment valid_from을 비교하지 않습니다.
  • 따라서 현재 구현은 미래 시작 Accounting Book을 선택하고 assignment를 생성합니다.
  • assertRaises(AccountingValidationError)는 의도적으로 실패합니다.

기존 제약은 기대한 거부를 대체하지 않습니다.

  • 테스트는 새 bank-account reference와 새 assignment idempotency key를 사용합니다.
  • 따라서 bank-account uniqueness와 command-idempotency uniqueness가 충돌하지 않습니다.
  • chart_account_code = "110200"은 canonical Accounting Book에 속한 KRW chart account입니다.
  • tenant, legal entity, Accounting Book, chart account의 composite foreign keys는 모두 유효합니다.
  • assignment valid_toNULL입니다. 따라서 assignment 자체의 valid_to > valid_from check도 거부 원인이 아닙니다.
  • 테스트와 command path는 tenant RLS session binding을 사용합니다.
  • active-assignment unique index도 새 bank account에 기존 assignment가 없으므로 적용되지 않습니다.

이 RED는 #58/#59 계약과 일관됩니다. Durable book_reference는 assignment가 시작하는 accounting-effective instant에 [valid_from, valid_to) 규칙으로 해석되어야 합니다. 이 테스트는 production migration, resolver, persistence.py, 또는 mutable sibling 구현을 규정하지 않습니다.

이 결과는 RED-lane review evidence입니다. 승인, merge, 또는 GREEN evidence가 아닙니다. 런타임 실행은 수행하지 않았습니다.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Fresh exact head is e9e1d5645171116aa88acafea4b143fdf3c2ec60. Please review only the new tests/test_postgres_bank_assignment_book_interval_integrity_red.py descendant for oracle validity and false-positive paths. The intended invariant is database-owned temporal referential integrity: a lawful bank-account assignment interval may not become effective outside its referenced Accounting Book interval after the parent book is shortened. The fixture deliberately keeps the chart account ending before the proposed shortened book end so an eventual rejection cannot be attributed to chart-account validity. This remains a RED-only Draft; do not infer production GREEN or approval.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="e9e1d5645171116aa88acafea4b143fdf3c2ec60"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"
fixture_file="tests/test_postgres_posting.py"
bank_file="src/accounting_information_platform/bank_statement.py"
migration_dir="database/migrations"

echo "== Exact commit and parent =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"
printf 'parent=%s\n' "$parent"
git merge-base --is-ancestor "$parent" "$head" && echo "parent_is_ancestor=yes"

echo "== Exact changed files and focused diff =="
git diff-tree --no-commit-id --name-status -r "$head"
git diff --unified=100 "$parent" "$head" -- \
  "$test_file" \
  docs/adr/0022-http-accounting-book-list.md \
  "$fixture_file" \
  "$bank_file" \
  "$migration_dir"

echo "== Exact target test =="
ast-grep outline "$test_file" --items all
git show "$head:$test_file" | nl -ba

echo "== Test setup, intervals, parent update, RLS, and oracle =="
git show "$head:$test_file" | rg -n -C 20 \
  'psycopg\.connect|_session\(|set_config|app\.tenant_account_id|clock_timestamp|database_now|INSERT INTO|UPDATE |RETURNING|accounting_book|bank_account|assignment|chart_account|valid_from|valid_to|assert|raises|IntegrityError|AccountingValidationError'

echo "== Referenced fixture helpers =="
git show "$head:$test_file" \
  | sed -nE 's/.*self\.case\.([A-Za-z_][A-Za-z0-9_]*).*/\1/p' \
  | sort -u \
  | while IFS= read -r helper; do
      echo "-- $helper --"
      rg -n -C 18 "def ${helper}\\(" "$fixture_file" || true
    done

echo "== Bank assignment command and all related lookup/write predicates =="
ast-grep outline "$bank_file" --items all --match 'accept_bank_account_assignment'
line="$(git show "$head:$bank_file" | rg -n '^\s*def accept_bank_account_assignment\(' | head -n1 | cut -d: -f1)"
if [ -n "$line" ]; then
  git show "$head:$bank_file" | nl -ba | sed -n "${line},$((line + 420))p"
fi

echo "== Accounting Book, chart account, and bank-account DDL/constraints/RLS =="
rg -n -i -C 30 \
  'CREATE TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ALTER TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ON accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|CREATE (UNIQUE )?INDEX.*(accounting_book|chart_account|bank_account)|FOREIGN KEY|CHECK|CREATE POLICY.*(accounting_book|chart_account|bank_account)|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|valid_from|valid_to' \
  "$migration_dir"

echo "== Later migrations that alter the involved tables =="
git grep -n -i -E \
  'accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|bank_account_assignment|chart_account' \
  "$head" -- "$migration_dir" \
  || true

Length of output: 236730


@seonghobae I found one fixture defect in exact head e9e1d5645171116aa88acafea4b143fdf3c2ec60.

tests/test_postgres_bank_assignment_book_interval_integrity_red.py does not reach its temporal-integrity oracle.

  • Line 117 inserts an accounting_core.bank_account_assignment row.
  • The insert omits assignment_idempotency_key and assignment_command_hash.
  • database/migrations/0012_bank_assignment_command_identity.sql defines both columns as NOT NULL.
  • Therefore, the assignment insert fails with an unrelated NOT NULL violation before Line 142 can test the Accounting Book valid_to update.

Please supply valid, unique values for both columns in the fixture insert. This keeps the RED focused on shortening the Accounting Book interval after a lawful assignment exists.

The temporal setup is otherwise correctly isolated:

  • The initial Accounting Book interval contains the assignment interval.
  • The shortened Accounting Book end is before assignment_valid_to.
  • chart_valid_to < shortened_book_valid_to, so chart-account validity cannot cause the expected rejection.
  • The direct PostgreSQL session sets app.tenant_account_id, so RLS does not create the failure path.
  • The existing foreign keys validate identity and same-book scope. They do not enforce temporal containment.

This is RED-only review evidence. It is not approval or GREEN evidence. Runtime execution was not performed.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Supersedes the predecessor review request: exact head is now d66652c17d38918cae74d35b9a6fedd3e242fb64. e9e1d564... exposed a fixture defect because migration 0012 requires assignment command identity; d66652c... repairs only that setup by supplying unique assignment_idempotency_key and canonical SHA-256 command evidence. Please verify the new temporal-parent oracle reaches the intended accounting_book.valid_to UPDATE and has no unrelated constraint or chart-account validity false-positive. This remains RED-only review evidence, not approval/GREEN.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="d66652c17d38918cae74d35b9a6fedd3e242fb64"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"
fixture_file="tests/test_postgres_posting.py"
migration_dir="database/migrations"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Exact commit and parent =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
printf 'parent=%s\n' "$parent"
git merge-base --is-ancestor "$parent" "$head" && echo "parent_is_ancestor=yes"

echo "== Exact changed files and focused diff =="
git diff-tree --no-commit-id --name-status -r "$head"
git diff --unified=100 "$parent" "$head" -- "$test_file"

echo "== Exact target test =="
ast-grep outline "$test_file" --items all
git show "$head:$test_file" | nl -ba

echo "== Target setup, command identity, intervals, parent update, and assertions =="
git show "$head:$test_file" | rg -n -C 20 \
  'psycopg\.connect|_session\(|set_config|app\.tenant_account_id|INSERT INTO|UPDATE |RETURNING|assignment_idempotency_key|assignment_command_hash|sha256|accounting_book|bank_account|assignment|chart_account|valid_from|valid_to|assert|raises|IntegrityError|AccountingValidationError'

echo "== Assignment command-identity migration and all later assignment constraints =="
git show "$head:database/migrations/0012_bank_assignment_command_identity.sql" | nl -ba
git grep -n -i -E -C 18 \
  'bank_account_assignment|assignment_idempotency_key|assignment_command_hash|CREATE (UNIQUE )?INDEX|ALTER TABLE|CONSTRAINT|FOREIGN KEY|CHECK|TRIGGER|POLICY' \
  "$head" -- "$migration_dir"

echo "== Accounting Book, chart account, and bank-assignment declarations =="
git grep -n -i -E -C 35 \
  'CREATE TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ALTER TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ON accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY.*(accounting_book|chart_account|bank_account)' \
  "$head" -- "$migration_dir"

echo "== Referenced fixture helpers and canonical temporal values =="
git show "$head:$test_file" \
  | sed -nE 's/.*self\.case\.([A-Za-z_][A-Za-z0-9_]*).*/\1/p' \
  | sort -u \
  | while IFS= read -r helper; do
      echo "-- $helper --"
      rg -n -C 20 "def ${helper}\\(" "$fixture_file" || true
    done
rg -n -C 20 \
  'def setUp\(|def setUpClass|def _session|INSERT INTO accounting_core\.accounting_book|INSERT INTO accounting_core\.chart_account|VALID_FROM|set_config\(' \
  "$fixture_file"

echo "== Other temporal integrity enforcement on the involved relations =="
git grep -n -i -E -C 15 \
  '(EXCLUDE|valid_from|valid_to|temporal|contain|range|accounting_book_id)' \
  "$head" -- "$migration_dir" \
  | head -n 1600

Length of output: 203425


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="d66652c17d38918cae74d35b9a6fedd3e242fb64"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"
parent="$(git show -s --format=%P "$head" | awk '{print $1}')"

echo "== Exact repair diff =="
git diff --unified=50 "$parent" "$head" -- "$test_file"

echo "== Exact test source =="
git show "$head:$test_file" | nl -ba

echo "== Parent book update and setup statements =="
git show "$head:$test_file" | nl -ba \
  | sed -n '/def test_/,/^[[:space:]]*def /p'

echo "== Accounting Book RLS and update triggers =="
git grep -n -i -E -C 12 \
  '(ENABLE|FORCE) ROW LEVEL SECURITY|CREATE POLICY.*accounting_book|ON accounting_core\.accounting_book|UPDATE OF .*valid_to|BEFORE UPDATE|AFTER UPDATE' \
  "$head" -- database/migrations

echo "== Chart-account temporal checks and update triggers =="
git grep -n -i -E -C 12 \
  'chart_account.*(valid_from|valid_to)|ON accounting_core\.chart_account|UPDATE OF .*valid_to|CREATE TRIGGER.*chart' \
  "$head" -- database/migrations

echo "== Assignment temporal containment checks or triggers =="
git grep -n -i -E -C 16 \
  '(bank_account_assignment.*(valid_from|valid_to|accounting_book)|accounting_book.*bank_account_assignment|containment|temporal.*assignment|assignment.*temporal|ON accounting_core\.bank_account_assignment)' \
  "$head" -- database/migrations

Length of output: 99990


@seonghobae Review completed for exact head d66652c17d38918cae74d35b9a6fedd3e242fb64.

I found no defect in the requested scope.

  • The repaired assignment insert supplies both fields required by migration 0012.
  • assignment_idempotency_key is nonblank and unique for each fixture.
  • assignment_command_hash has the required sha256: prefix and 64 hexadecimal characters.
  • The command-identity unique index cannot reject this new fixture row.

The test reaches the intended parent update.

  • The fixture creates the Accounting Book, chart account, bank account, and bank-account assignment before the assertRaises block.
  • The fixture uses a tenant-bound PostgreSQL session. RLS does not create the expected failure path.
  • The assignment references the same tenant, legal entity, Accounting Book, and chart account. The foreign keys are valid.
  • The assignment has a finite valid_to. The active-assignment unique index does not apply.
  • The update changes only accounting_core.accounting_book.valid_to. No current update trigger on that table can reject this update.

The temporal oracle is isolated.

  • The initial Accounting Book interval is [anchor - 10 days, anchor + 10 days).
  • The assignment interval is [anchor - 1 day, anchor + 5 days). It is initially contained in the Accounting Book interval.
  • The shortened Accounting Book interval ends at anchor + 3 days.
  • The assignment remains effective from anchor + 3 days until anchor + 5 days.
  • The parent update therefore creates the intended temporal containment violation.
  • The updated valid_to remains after valid_from. The Accounting Book validity check cannot explain a rejection.
  • The chart account ends at anchor + 2 days, before the shortened Accounting Book end. Chart-account validity cannot explain a rejection.
  • Existing foreign keys enforce identity and scope only. They do not enforce effective-time containment.

The expected psycopg.IntegrityError remains a causal RED for the missing database-owned temporal referential-integrity invariant. No production GREEN or approval is implied. Runtime execution was not performed.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Current exact head is now 2a1f42045fcc033de877079595d96aacd3362705. The only descendant after d66652c... is ADR 0022 synchronization: it records the same database-owned temporal referential-integrity invariant proved by the new RED, namely that a later parent-book validity mutation may not strand an existing effective-dated bank_account_assignment. Please review the test plus ADR together for causal isolation, half-open interval consistency, and unintended policy expansion. No production GREEN/approval is claimed.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="2a1f42045fcc033de877079595d96aacd3362705"
base="d66652c17d38918cae74d35b9a6fedd3e242fb64"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"
adr_file="docs/adr/0022-http-accounting-book-list.md"

echo "== Exact commits and ancestry =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$base"
git merge-base --is-ancestor "$base" "$head" && echo "base_is_ancestor=yes"

echo "== Requested descendant delta =="
git diff --name-status "$base" "$head"
git diff --unified=100 "$base" "$head" -- "$test_file" "$adr_file"

echo "== Exact-head temporal integrity RED =="
git show "$head:$test_file" | nl -ba

echo "== Exact-head ADR 0022 =="
git show "$head:$adr_file" | nl -ba

echo "== ADR clauses relevant to parent updates, containment, intervals, and scope =="
git show "$head:$adr_file" | rg -n -i -C 16 \
  'bank.account.assignment|parent|child|referential|contain|valid_from|valid_to|half-open|adjacen|update|concurren|resolver|cardinality|migration|RED|production|policy'

echo "== Accounting Book, chart account, and bank assignment schema/constraints/RLS =="
rg -n -i -C 26 \
  'CREATE TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ALTER TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ON accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|CREATE (UNIQUE )?INDEX.*(accounting_book|chart_account|bank_account)|FOREIGN KEY|CHECK|CREATE POLICY.*(accounting_book|chart_account|bank_account)|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|assignment_idempotency_key|assignment_command_hash|valid_from|valid_to' \
  database/migrations

echo "== All later migrations that modify the involved relations =="
git grep -n -i -E -C 12 \
  'accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|bank_account_assignment|assignment_idempotency_key|assignment_command_hash|valid_from|valid_to|temporal|contain' \
  "$head" -- database/migrations

echo "== Shared fixture helpers, tenant session, and canonical accounting-book seed =="
rg -n -C 18 \
  'def _session|def setUp\(|def setUpClass|INSERT INTO accounting_core\.(accounting_book|chart_account)|set_config\('\''app\.tenant_account_id|VALID_FROM|valid_from|valid_to' \
  tests/test_postgres_posting.py \
  src/accounting_information_platform/persistence.py

Length of output: 203073


🏁 Script executed:

#!/bin/bash
set -euo pipefail

head="2a1f42045fcc033de877079595d96aacd3362705"
base="d66652c17d38918cae74d35b9a6fedd3e242fb64"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"
adr_file="docs/adr/0022-http-accounting-book-list.md"

echo "== Exact descendant delta =="
git diff --unified=70 "$base" "$head" -- "$adr_file"

echo "== Exact-head RED source =="
git show "$head:$test_file" | nl -ba

echo "== Exact-head ADR section: temporal referential integrity and boundary =="
git show "$head:$adr_file" | nl -ba | sed -n '1,220p'

echo "== Test SQL statement inventory =="
git show "$head:$test_file" | rg -n -C 8 \
  'INSERT INTO accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|UPDATE accounting_core\.accounting_book|valid_from|valid_to|assignment_idempotency_key|assignment_command_hash|set_config|assertRaises|IntegrityError|commit'

echo "== Exact constraint definitions affecting the parent update =="
git show "$head:database/migrations/0001_accounting_foundation.sql" | nl -ba \
  | rg -n -C 16 \
  'CREATE TABLE accounting_core\.(accounting_book|chart_account)|CHECK \(valid_to|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY.*accounting_book'
git show "$head:database/migrations/0011_bank_statement_evidence.sql" | nl -ba \
  | sed -n '19,43p;192,203p'
git show "$head:database/migrations/0012_bank_assignment_command_identity.sql" | nl -ba | sed -n '15,38p'

Length of output: 60509


@seonghobae Review completed for exact head 2a1f42045fcc033de877079595d96aacd3362705.

I found one unintended ADR policy expansion.

  • tests/test_postgres_bank_assignment_book_interval_integrity_red.py proves temporal containment for bank_account_assignment.
  • The fixture starts with the Book interval [anchor - 10 days, anchor + 10 days) and the assignment interval [anchor - 1 day, anchor + 5 days).
  • The parent update changes the Book end to anchor + 3 days.
  • The assignment then remains effective on [anchor + 3 days, anchor + 5 days), which is outside the parent interval under half-open semantics.
  • The fixture sets the tenant RLS context and supplies valid assignment command identity.
  • The chart account ends at anchor + 2 days, before the shortened Book end.
  • Existing foreign keys, per-row validity checks, and assignment identity indexes cannot explain the expected IntegrityError.

However, ADR 0022 Line 37 requires containment for “effective-dated relationships to an Accounting Book” in general. The new RED proves only the bank_account_assignment relationship. This wording can require new containment rules for other relationships, such as chart_account or account_role_mapping, without a stated acceptance criterion or RED coverage.

Please limit the new requirement to bank_account_assignment, or explicitly identify the additional relationship types that must be in scope. This keeps the ADR synchronized with the tested invariant and avoids expanding the #58/#59 policy boundary.

The remaining ADR content is consistent with half-open [valid_from, valid_to) semantics. It correctly states that parent and child boundary updates can break containment. It also retains the RED-only and no-production-migration boundary.

This is review evidence only. It is not approval, merge, or GREEN evidence. Runtime execution was not performed.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

Exact head is now 36e7e8197a821971a6184232c5f9860d6903fd11. This is the minimal repair for review comment 5607333987: ADR 0022 now scopes the new temporal-referential-integrity requirement specifically to bank_account_assignment, including upgrade preflight and parent/assignment boundary mutation. It no longer generalizes the RED to chart_account, account_role_mapping, or unspecified Accounting Book relationships. The PostgreSQL RED itself is unchanged from d66652c.... Please verify that the policy expansion is removed and the tested half-open containment invariant remains intact. Review evidence only; no approval/GREEN claim.

@coderabbitai

coderabbitai Bot commented Sep 9, 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

head="36e7e8197a821971a6184232c5f9860d6903fd11"
base="2a1f42045fcc033de877079595d96aacd3362705"
adr="docs/adr/0022-http-accounting-book-list.md"
test_file="tests/test_postgres_bank_assignment_book_interval_integrity_red.py"

echo "== Exact head, base, and ancestry =="
git show -s --format='commit=%H%nparents=%P%nsubject=%s%n%n%b' "$head"
git show -s --format='base=%H%nparents=%P%nsubject=%s' "$base"
git merge-base --is-ancestor "$base" "$head" && echo "base_is_ancestor=yes"

echo "== Delta from prior reviewed head =="
git diff --name-status "$base" "$head"
git diff --unified=100 "$base" "$head" -- "$adr" "$test_file" \
  src/accounting_information_platform/persistence.py database/migrations

echo "== Exact-head ADR =="
git show "$head:$adr" | nl -ba

echo "== Exact-head ADR scope and policy terms =="
git show "$head:$adr" | rg -n -i -C 14 \
  'bank_account_assignment|bank.account.assignment|effective-dated relationships|chart_account|account_role_mapping|contain|parent|child|valid_from|valid_to|half-open|adjacen|preflight|migration|RED-only|production'

echo "== Exact-head retained RED =="
git show "$head:$test_file" | nl -ba

echo "== RED interval setup, identity requirements, RLS, and parent mutation =="
git show "$head:$test_file" | rg -n -C 18 \
  'INSERT INTO accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|UPDATE accounting_core\.accounting_book|valid_from|valid_to|assignment_idempotency_key|assignment_command_hash|set_config|app\.tenant_account_id|assertRaises|IntegrityError|commit'

echo "== Relevant schema constraints and later changes =="
git grep -n -i -E -C 18 \
  'CREATE TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ALTER TABLE accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|ON accounting_core\.(accounting_book|chart_account|bank_account_record|bank_account_assignment)|CHECK.*valid|FOREIGN KEY|assignment_idempotency_key|assignment_command_hash|ENABLE ROW LEVEL SECURITY|FORCE ROW LEVEL SECURITY|CREATE POLICY.*(accounting_book|bank_account)' \
  "$head" -- database/migrations

Length of output: 239092


@seonghobae 검토를 완료했습니다. 정확한 head 36e7e8197a821971a6184232c5f9860d6903fd11에서 요청 범위의 결함을 찾지 못했습니다.

  • 이 commit은 docs/adr/0022-http-accounting-book-list.md만 변경합니다.
  • ADR은 일반적인 “effective-dated relationships” 요구를 제거합니다.
  • ADR은 temporal referential integrity의 관계 범위를 bank_account_assignment로 명시합니다.
  • Line 21, Line 37, Line 40, Line 42, Line 46, Line 54가 모두 같은 범위를 사용합니다.
  • ADR은 더 이상 chart_account, account_role_mapping, 또는 이름 없는 Accounting Book 관계에 containment를 요구하지 않습니다.

테스트된 half-open containment invariant도 유지됩니다.

  • tests/test_postgres_bank_assignment_book_interval_integrity_red.py는 변경되지 않았습니다.
  • 초기 Accounting Book interval은 [anchor - 10 days, anchor + 10 days)입니다.
  • 초기 bank_account_assignment interval은 [anchor - 1 day, anchor + 5 days)입니다.
  • 따라서 assignment interval은 처음에는 parent Accounting Book interval 안에 있습니다.
  • parent valid_toanchor + 3 days로 단축됩니다.
  • assignment는 [anchor + 3 days, anchor + 5 days)에서 parent 밖에 남습니다.
  • 이는 half-open [valid_from, valid_to) semantics와 일관됩니다.
  • chart account는 anchor + 2 days에 끝납니다. 따라서 chart-account validity는 예상 IntegrityError의 원인이 될 수 없습니다.

ADR은 upgrade preflight와 parent/assignment boundary mutation도 bank_account_assignment로 제한합니다. 이전의 정책 확장은 제거되었습니다.

이 결과는 review evidence입니다. 승인, merge, 또는 GREEN evidence가 아닙니다. 런타임 실행은 수행하지 않았습니다.

You are interacting with an AI system.

Copy link
Copy Markdown
Contributor Author

Current exact-head authority — 36e7e8197a821971a6184232c5f9860d6903fd11.

This descendant adds one new database-owned temporal referential-integrity RED for bank_account_assignment and repairs its review scope without production implementation:

  • e9e1d5645171116aa88acafea4b143fdf3c2ec60: first parent-book-shortening PostgreSQL oracle; setup was incomplete because migration 0012 requires assignment command identity.
  • d66652c17d38918cae74d35b9a6fedd3e242fb64: causal fixture repair only — unique assignment_idempotency_key plus canonical SHA-256 command evidence, so the test reaches the intended parent accounting_book.valid_to mutation.
  • 2a1f42045fcc033de877079595d96aacd3362705: synchronized ADR 0022, but CodeRabbit comment 5607333987 correctly found that the prose generalized the tested relationship invariant beyond bank_account_assignment.
  • 36e7e8197a821971a6184232c5f9860d6903fd11: minimal ADR repair; containment, upgrade preflight, and later-boundary mutation requirements are now scoped specifically to bank_account_assignment. Fresh CodeRabbit reply 5607379561 found no remaining defect in that requested exact-head scope. Treat it as COMMENT review evidence, not APPROVED or runtime GREEN.

Exact hosted PostgreSQL evidence on Accounting Foundation run 34394124913, Accounting job 102609470635: exact checkout 36e7e819..., PostgreSQL 18.4, Python 3.13.15, hash-locked dependencies; 477 tests ran in 85.216s and ended 12 failures + 1 error. The new test_book_end_cannot_strand_existing_bank_assignment reaches the parent UPDATE accounting_core.accounting_book SET valid_to = ... and fails exactly because psycopg.IntegrityError is not raised. That proves the current schema permits a later book-end mutation to strand an existing assignment beyond the book interval. Same-head Foundation SAST 102609470467, dependency diff 102609470567, and security 102609470661 are GREEN; standalone SAST 34394124662 and Security 34394124737 are GREEN. Coverage/contracts/compile/package/SBOM/provenance after behavior are not claimed because the intentional RED stopped continuation.

The invariant remains half-open: if assignment [a,b) references book [p,q), require p <= a and b <= q (with nullable ends handled by the canonical effective-time policy). Admission-time validation alone is insufficient because a later parent-book boundary mutation bypasses it. This run does not generalize that new relationship containment rule to chart_account, account_role_mapping, or unspecified relationships.

Production migration/resolver remains intentionally absent. #29/#47/#53 still own the live unreleased migration/persistence.py stack, so this RED lane must not allocate a migration number or copy production bytes before normal integration and non-force reconciliation.

@seonghobae seonghobae left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact-head accounting-master-data finding on c805707dddc2db22fd42c2995b9c62c9a145765f: ADR 0022 already requires bank_account_assignment to remain temporally contained in its referenced Accounting Book when either the parent or assignment boundaries change, but the preceding RED suite covered only parent-book shortening. This descendant adds real-PostgreSQL child-side mutation REDs for both directions: extending assignment valid_to beyond a finite Book end, and moving assignment valid_from before a finite Book start. Each fixture deliberately keeps the referenced chart-account interval wider than the hostile assignment mutation, so an eventual IntegrityError must come from Book containment rather than an unrelated chart-account boundary. This is COMMENT evidence only; production migration/resolver remains out of scope while the live migration/source stack is owned elsewhere.

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

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

[P1 Accounting Book Catalog] Enforce non-overlapping durable book-reference identity

1 participant