Skip to content

feat(ops): add database readiness probe - #40

Draft
seonghobae wants to merge 53 commits into
developfrom
feat/operability-readiness-baseline
Draft

feat(ops): add database readiness probe#40
seonghobae wants to merge 53 commits into
developfrom
feat/operability-readiness-baseline

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Current exact-head state — 2026-09-09

Buyer/operator outcome

Adds database-backed GET /readyz beside process-liveness GET /healthz. Readiness is read-only and fails closed unless the runtime can reach supported PostgreSQL 18, resolve the database-owned tenant binding, and observe the complete checked-in accounting control schema. Responses are non-cacheable. This probe cannot post journals, approve reconciliation, close periods, alter accounting policy, or repair migrations.

Current readiness contract

The branch binds readiness to the repository-owned migrated schema rather than shallow object existence. Current source covers canonical runtime tables/columns, migration-required constraints, RLS/policies, control functions/triggers, balance-trigger semantics, explicit indexes and behaviorally material PostgreSQL catalog definitions. The readiness session installs its bounded statement timeout at PostgreSQL connection startup while preserving any stricter operator timeout.

The compact-libpq-option defect is causally repaired. _readiness_statement_timeout_milliseconds() accepts attached -cstatement_timeout=..., spaced -c statement_timeout=..., and --statement_timeout=.... The real PostgreSQL acceptance regression connects through conninfo_to_dict / make_conninfo with options='-cstatement_timeout=100ms' and asserts SHOW statement_timeout = '100ms'.

Evidence boundary

Historical repository/security evidence on this unchanged source head is predecessor evidence only for a future integration candidate because the PR base is behind live protected develop and #29 has not integrated. Resolved threads are not approval; skipped integrated-head attestations and non-terminal/failed central reviewer lanes remain non-passing.

Merge boundary

Keep Draft. Current live dependency order is #29@12e1a4bb... -> #47@263e4ff... -> #53; #43 is merged history. Integrate prerequisites through ordinary protection, then non-destructively reconcile this branch against the exact protected integrated base and reacquire repository/organization CI, real PostgreSQL readiness acceptance, exact coverage/docstrings, security/dependency, current reviews, package/SBOM/provenance and all live ruleset gates on one unchanged head. Do not merge, enable auto-merge, bypass protection, force-push, destructively rebase, reuse predecessor evidence, version, tag or release.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

GET /readyz가 PostgreSQL 18, 활성 데이터베이스 제어 테넌트 바인딩, migration 0014까지의 전체 회계 스키마 계약을 확인합니다. 연결 시도는 최대 5초로 제한됩니다. 성공 시 200, 실패 시 안전한 메시지와 503을 반환하며 응답은 캐시되지 않습니다.

Changes

준비 상태 프로브

Layer / File(s) Summary
PostgreSQL 준비 상태 검사
src/accounting_information_platform/persistence.py, tests/test_postgres_posting.py, tests/test_postgres_runtime_rls.py, tests/test_postgres_readiness_balance_semantics.py, tests/test_postgres_readiness_definition_contract.py, tests/test_postgres_readiness_trigger_contract.py, tests/test_readiness_fingerprint_inventory_contract.py
check_readiness()가 PostgreSQL 18, 활성 테넌트 바인딩, 제약 조건, 인덱스, 전체 회계 제어 트리거와 함수 지문을 검사합니다. 비활성화, 조건 변경, 열 범위 변경, no-op 함수, 약화된 제약과 인덱스를 실패로 처리합니다.
HTTP 준비 상태 엔드포인트
src/accounting_information_platform/http_api.py, tests/test_postgres_posting.py, tests/test_postgres_runtime_rls.py
GET /readyz를 추가했습니다. 성공 시 {"status":"ready"}200을 반환합니다. 실패 시 {"status":"not_ready"}503을 반환합니다. 양쪽 응답에 Cache-Control: no-store를 설정합니다.
준비 상태 계약 문서화와 검증
README.md, CHANGELOG.md, docs/ARCHITECTURE.md, docs/OPERABILITY.md, docs/adr/0055-http-readiness-probe.md, docs/doctoring/STANDARD_TRACEABILITY.md, docs/doctoring/REFERENCES.md, docs/product-technical-gap-baseline.md, tests/test_operability_documentation_contract.py
liveness와 database-readiness의 범위, migration 0014, 연결 제한, 캐시 제어, PostgreSQL 제어 계약과 운영 범위를 문서화하고 문서 내용을 검증합니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🟡 Moderate · up to 87033

This PR adds a database-backed /readyz endpoint that can keep instances out of service when PostgreSQL or accounting controls are invalid, while each request performs broad catalog checks. Merge readiness remains moderate because required exact-head validation and approval are outstanding, valid index declarations can bypass the inventory guard, and a failing drift-test setup can leave a control trigger deleted; the readiness route also needs owner awareness for traffic containment if externally reachable.

Sequence Diagram(s)

sequenceDiagram
  participant 호출자
  participant HTTP API
  participant PostgresPostingLedger
  participant PostgreSQL
  호출자->>HTTP API: GET /readyz
  HTTP API->>PostgresPostingLedger: check_readiness()
  PostgresPostingLedger->>PostgreSQL: 제한된 연결과 테넌트 바인딩 확인
  PostgresPostingLedger->>PostgreSQL: PostgreSQL 18 및 migration 0014 스키마 계약 확인
  PostgreSQL-->>PostgresPostingLedger: 검사 결과 반환
  PostgresPostingLedger-->>HTTP API: 준비 완료 또는 AccountingValidationError
  HTTP API-->>호출자: 200 ready 또는 503 not_ready, Cache-Control: no-store
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 86.84% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 38 functions across 8 files. (5 skipped: 4 …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 데이터베이스 기반 GET /readyz 준비 상태 프로브 추가라는 주요 변경을 정확하고 간결하게 설명합니다.
✨ 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 feat/operability-readiness-baseline

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.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Current-head validation for 10ac570032313b5d61dbfdd2624c5e694d1ac0b0:

  • Added Cache-Control: no-store to both GET /readyz success and failure responses, with HTTP regression coverage and RFC 9111 traceability.
  • Local PostgreSQL validation: 469 tests passed; production statement and branch coverage 100% (5024 statements, 1810 branches); repository validator, targeted Ruff, compileall, and diff check passed.
  • Current-head hosted results: Accounting Foundation, CodeQL, Semgrep, Security Scan, dependency review, Noema, coverage-source-tree/evidence, and package/security checks passed; CodeRabbit and Devin status checks are green; all review threads are resolved.
  • Remaining protected-gate blockers: opencode-review has no authenticated opencode-agent APPROVED/CHANGES_REQUESTED review for this head, strix is still pending, and no qualifying independent formal approval exists. No bypass or merge was performed.

@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.

Current-head blocker verified against 10ac570032313b5d61dbfdd2624c5e694d1ac0b0: /readyz still proves that the journal-balance function exists, but it does not prove that the database-owned balance triggers are attached and enabled. check_readiness() includes accounting_core.assert_journal_balance() in _READINESS_FUNCTIONS, then only checks to_regprocedure(...); it never inspects pg_trigger. Migration 0005_closed_period_guard.sql makes balance enforcement depend on the DEFERRABLE constraint triggers general_journal_balance_guard and journal_entry_balance_guard. A fully migrated database can therefore DISABLE TRIGGER journal_entry_balance_guard (or drop either balance trigger), retain assert_journal_balance(), and still return ready even though the authoritative DB no longer enforces balanced journals. The earlier trigger finding is therefore not actually resolved on this exact head.

Please repair test-first on the existing branch. RED: provision a real PostgreSQL 18 database through the full checked-in migration set, establish the normal runtime tenant binding, disable or drop one required journal-balance trigger while leaving the function intact, and assert check_readiness() / GET /readyz fails closed with 503. GREEN: verify the required trigger registrations in pg_catalog.pg_trigger against the expected relation/function identity and enabled state; for the two balance guards also preserve their constraint-trigger/deferrable contract. Keep this narrow: readiness verification only; do not change posting authority or relax any ledger invariant. Re-run the real PostgreSQL integration suite, exact 100% owned statement/branch coverage, repository contracts, SAST/security, and package/provenance gates on the successor exact head. Do not transfer the current head's green evidence.

@opencode-agent opencode-agent 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.

Pull request overview

OpenCode reviewed the current-head product diff. Coverage is a separate gate.

Changed files

  • CHANGELOG.md — repository behavior
  • README.md — repository behavior
  • docs/ARCHITECTURE.md — operator or user guidance
  • docs/OPERABILITY.md — operator or user guidance
  • docs/adr/0055-http-readiness-probe.md — operator or user guidance
  • docs/doctoring/REFERENCES.md — operator or user guidance
  • docs/doctoring/STANDARD_TRACEABILITY.md — operator or user guidance
  • src/accounting_information_platform/http_api.py — Python runtime API
  • src/accounting_information_platform/persistence.py — Python runtime API
  • tests/test_operability_documentation_contract.py — regression suite
  • tests/test_postgres_posting.py — regression suite
  • tests/test_postgres_runtime_rls.py — regression suite

Changed behavior

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Repository file: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Repository file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Repository file: README.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: README.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: ARCHITECTURE.md (5 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: ARCHITECTURE.md (5 files)"]
  R3 --> V3["docs review"]
  Evidence --> S4["Python package: http_api.py (2 files)"]
  S4 --> I4["Python runtime API"]
  I4 --> R4["Review risk: Python package: http_api.py (2 files)"]
  R4 --> V4["pytest plus coverage"]
  Evidence --> S5["Test: test_operability_documentation_contract.py (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test: test_operability_documentation_contract.py (3 files)"]
  R5 --> V5["targeted test run"]
Loading

Findings

No source-backed product finding is synthesized from the coverage gate. A coverage miss belongs in the status comment.

  • Head SHA: 10ac570032313b5d61dbfdd2624c5e694d1ac0b0
  • Workflow run: 33240550158
  • Workflow attempt: 1
  • Coverage gate: failure

Review outcome

Coverage is a gate, not the review. This body reviews the changed product files.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Repository file: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Repository file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Repository file: README.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: README.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: ARCHITECTURE.md (5 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: ARCHITECTURE.md (5 files)"]
  R3 --> V3["docs review"]
  Evidence --> S4["Python package: http_api.py (2 files)"]
  S4 --> I4["Python runtime API"]
  I4 --> R4["Review risk: Python package: http_api.py (2 files)"]
  R4 --> V4["pytest plus coverage"]
  Evidence --> S5["Test: test_operability_documentation_contract.py (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test: test_operability_documentation_contract.py (3 files)"]
  R5 --> V5["targeted test run"]
Loading

@opencode-agent

opencode-agent Bot commented Aug 29, 2026

Copy link
Copy Markdown

OpenCode Review Overview

  • Head SHA: 10ac570032313b5d61dbfdd2624c5e694d1ac0b0
  • Workflow run: 33243994171
  • Workflow attempt: 1
  • Gate result: COVERAGE_BLOCKED
  • Coverage gate: failure
  • Model pool: unknown
  • Verdict: COVERAGE_BLOCKED
  • Formal review: feat(ops): add database readiness probe #40 (review)

Coverage evidence did not pass, so approval is blocked. The formal pull-request review is the source-backed diff review, not this status comment.

Copy link
Copy Markdown
Contributor Author

@codex Address the current exact-head readiness false-green on the existing feat/operability-readiness-baseline branch, test-first and without changing accounting authority.

Verified causal boundary on 10ac570032313b5d61dbfdd2624c5e694d1ac0b0: PostgresPostingLedger.check_readiness() proves accounting_core.assert_journal_balance() exists but never inspects pg_catalog.pg_trigger. Migration 0005_closed_period_guard.sql makes the authoritative balance invariant depend on two DEFERRABLE INITIALLY DEFERRED constraint triggers: general_journal_balance_guard on accounting_core.general_journal and journal_entry_balance_guard on accounting_core.journal_entry_line, both executing accounting_core.assert_journal_balance(). A fully migrated DB with either trigger disabled/dropped can therefore report ready while database-owned balance enforcement is absent.

RED first: using real PostgreSQL 18 and the full checked-in migration chain, establish the normal runtime tenant binding, disable one required balance trigger while leaving the function intact, and prove check_readiness() and/or GET /readyz fails closed. Cover both balance triggers or table-drive the cases. Assert a stable 503/not-ready outcome, not driver text.

GREEN: add the narrowest readiness catalog check for the expected trigger name + relation schema/table + trigger-function schema/name + enabled state. For these two guards also require non-internal constraint-trigger registration and preserve the migration contract DEFERRABLE INITIALLY DEFERRED (validate the associated pg_constraint metadata rather than trigger-name existence alone). A same-named ordinary trigger, wrong relation/function, disabled trigger, or non-deferrable constraint trigger must not satisfy readiness.

Update the existing operability/ADR/CHANGELOG/traceability wording only as needed to state that readiness checks critical DB-owned balance-trigger registrations. Preserve Cache-Control: no-store, bounded probe behavior, tenant fail-closed behavior, and all posting/reversal/close authority boundaries. Do not touch central .github or other repositories.

Then run focused real-PostgreSQL tests, the full repository suite, exact 100% owned production statement/branch coverage and public-docstring/repository contracts, SAST/security, and package/SBOM/provenance gates on the successor exact head. Do not reuse predecessor-head green evidence. If any gate fails, inspect its exact job log and repair only the first causal boundary.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits. You can see your limits in the Codex usage dashboard.

@opencode-agent opencode-agent 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.

Pull request overview

OpenCode reviewed the current-head product diff. Coverage is a separate gate.

Changed files

  • CHANGELOG.md — repository behavior
  • README.md — repository behavior
  • docs/ARCHITECTURE.md — operator or user guidance
  • docs/OPERABILITY.md — operator or user guidance
  • docs/adr/0055-http-readiness-probe.md — operator or user guidance
  • docs/doctoring/REFERENCES.md — operator or user guidance
  • docs/doctoring/STANDARD_TRACEABILITY.md — operator or user guidance
  • src/accounting_information_platform/http_api.py — Python runtime API
  • src/accounting_information_platform/persistence.py — Python runtime API
  • tests/test_operability_documentation_contract.py — regression suite
  • tests/test_postgres_posting.py — regression suite
  • tests/test_postgres_runtime_rls.py — regression suite

Changed behavior

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Repository file: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Repository file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Repository file: README.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: README.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: ARCHITECTURE.md (5 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: ARCHITECTURE.md (5 files)"]
  R3 --> V3["docs review"]
  Evidence --> S4["Python package: http_api.py (2 files)"]
  S4 --> I4["Python runtime API"]
  I4 --> R4["Review risk: Python package: http_api.py (2 files)"]
  R4 --> V4["pytest plus coverage"]
  Evidence --> S5["Test: test_operability_documentation_contract.py (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test: test_operability_documentation_contract.py (3 files)"]
  R5 --> V5["targeted test run"]
Loading

Findings

No source-backed product finding is synthesized from the coverage gate. A coverage miss belongs in the status comment.

  • Head SHA: 10ac570032313b5d61dbfdd2624c5e694d1ac0b0
  • Workflow run: 33243994171
  • Workflow attempt: 1
  • Coverage gate: failure

Review outcome

Coverage is a gate, not the review. This body reviews the changed product files.

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Repository file: CHANGELOG.md"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Repository file: CHANGELOG.md"]
  R1 --> V1["required checks"]
  Evidence --> S2["Repository file: README.md"]
  S2 --> I2["repository behavior"]
  I2 --> R2["Review risk: Repository file: README.md"]
  R2 --> V2["required checks"]
  Evidence --> S3["Docs: ARCHITECTURE.md (5 files)"]
  S3 --> I3["operator or user guidance"]
  I3 --> R3["Review risk: Docs: ARCHITECTURE.md (5 files)"]
  R3 --> V3["docs review"]
  Evidence --> S4["Python package: http_api.py (2 files)"]
  S4 --> I4["Python runtime API"]
  I4 --> R4["Review risk: Python package: http_api.py (2 files)"]
  R4 --> V4["pytest plus coverage"]
  Evidence --> S5["Test: test_operability_documentation_contract.py (3 files)"]
  S5 --> I5["regression suite"]
  I5 --> R5["Review risk: Test: test_operability_documentation_contract.py (3 files)"]
  R5 --> V5["targeted test run"]
Loading

devin-ai-integration[bot]

This comment was marked as resolved.

@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.

Current-head verification for 72a26109e9ad7a37ef194dd5d93ef578d4379a6d: the previously reported /readyz false-green is addressed in source. Readiness now verifies both general_journal_balance_guard and journal_entry_balance_guard in pg_catalog.pg_trigger against the expected relation and accounting_core.assert_journal_balance function, requires normal enabled state, exact row/event tgtype, a nonzero constraint identity, and DEFERRABLE INITIALLY DEFERRED. The real PostgreSQL regression disables each required trigger while retaining the function and expects check_readiness() to fail closed, restoring the trigger in finally. Docs/changelog describe the strengthened boundary. I do not count predecessor-head evidence for this successor. Exact-head Accounting Foundation and several required reviewer/scanner jobs are still in progress or non-passing, and no qualifying independent approval is present, so this is verification of the repaired finding only—not merge or release approval.

@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.

Current-head follow-up on 72a26109e9ad7a37ef194dd5d93ef578d4379a6d: Devin's new conditional-trigger finding is valid. The readiness catalog predicate now verifies relation/function identity, enabled state, exact tgtype, constraint identity, and deferrability, but it does not constrain pg_trigger.tgqual or pg_trigger.tgattr. The canonical migration creates both balance guards without a WHEN predicate and without an UPDATE OF column list. A drifted constraint trigger can therefore preserve every currently checked property while adding WHEN (false) or restricting UPDATE columns, causing /readyz to false-green while database-owned balance enforcement is incomplete.

Please repair test-first on this existing branch. RED against real PostgreSQL 18: for each balance guard, replace the canonical trigger with (a) an otherwise-identical WHEN (false) form and (b) an otherwise-identical restricted UPDATE OF form where PostgreSQL permits that trigger shape, then assert check_readiness() / /readyz fails closed; restore the exact checked-in migration definition in finally. GREEN: extend the pg_trigger contract to require tgqual IS NULL and an empty tgattr/no update-column restriction in addition to the existing checks. If PostgreSQL syntax disallows UPDATE OF on a constraint trigger, prove that boundary explicitly and keep the production predicate fail-closed for non-empty tgattr. Preserve the same posting authority and immutable-ledger semantics. Re-run the full real-PostgreSQL suite, exact 100% owned statement/branch coverage, docstrings/contracts, SAST/security, and package/SBOM/provenance on the successor exact head. Keep this thread unresolved until the successor source and exact-head evidence exist; predecessor green evidence does not transfer.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Addressed in 2d07a78 (exact head after push). check_readiness() now fails closed when either required balance trigger has a non-NULL pg_trigger.tgqual (WHEN predicate) or a non-empty pg_trigger.tgattr (UPDATE OF restriction), while retaining the relation/function, enabled, event-mask, constraint, and deferred checks. Real PostgreSQL 18 RED coverage recreates both triggers with each alteration, asserts readiness rejection, and restores the canonical migration definition in finally. Local successor validation: 471 tests passed; 5,025/5,025 statements and 1,810/1,810 branches; repository contracts, public docstrings, compileall, diff-check, and targeted Ruff passed.

coderabbitai[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Addressed in a567b77 (current exact head). ADR 0055 now says stale readiness result, matching the /readyz cache contract and distinguishing it from /healthz liveness.

@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.

Current-head review (82c5a93eecc999bbc3633a499edb0bc0196b37ad): the earlier trigger-registration, WHEN (...), and UPDATE OF ... readiness false-greens are fixed. check_readiness() now validates both canonical balance triggers' relation/function identity, enabled state, event mask, constraint/deferrable properties, tgqual IS NULL, and empty tgattr, and the real-PostgreSQL regressions exercise those drift modes.

One database-owned invariant false-green remains on this exact head. Readiness proves that both triggers still point at the same accounting_core.assert_journal_balance() OID/signature, but it does not prove that the function body still implements the balance check. PostgreSQL CREATE OR REPLACE FUNCTION can replace the PL/pgSQL body while preserving the function identity/OID used by the triggers. An operator/migration drift that replaces assert_journal_balance() with a no-op RETURN NULL body can therefore leave every currently checked trigger property intact while allowing unbalanced journals; /readyz would still report ready.

Please repair test-first on the existing branch. RED: after full migrations on real PostgreSQL 18, replace only accounting_core.assert_journal_balance() with a same-signature no-op implementation (leaving both canonical triggers untouched), prove an unbalanced journal can pass the DB constraint boundary, and assert check_readiness() / /readyz fail closed. GREEN: bind readiness to the canonical balance-function semantics with the narrowest deterministic schema-drift contract, e.g. a repository-owned canonical fingerprint of the stored PL/pgSQL body/definition (pg_proc.prosrc or equivalently normalized pg_get_functiondef) whose expected value is derived/tested against migration 0005_closed_period_guard.sql. Keep this a drift check only: no write-canary from readiness, no weakening of least-privileged runtime access, and preserve the existing exact trigger-property checks.

After the repair, rerun focused + full real-PG validation, exact 100% owned production statement/branch coverage and public docstrings, contracts/SAST/security/package/SBOM/provenance on the successor exact head. Do not transfer the current-head green evidence.

devin-ai-integration[bot]

This comment was marked as resolved.

@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.

Current-head revalidation: the production false-green is fixed on f94360a. Readiness now binds the two canonical balance triggers to their relation/function identity, enabled/event/constraint/deferrable state, unrestricted tgqual/tgattr shape, and the stored accounting_core.assert_journal_balance() definition fingerprint.

One acceptance-evidence gap remains before this exact head is defensible: test_readiness_rejects_same_signature_balance_function_drift replaces the guard with a no-op and immediately checks readiness, but it never demonstrates that the mutation actually removes the database-owned balanced-journal invariant. Strengthen the real PostgreSQL RED so the test first proves an otherwise-invalid/unbalanced journal can commit while the no-op same-signature function is installed (or equivalently proves the canonical DB guard is no longer enforcing balance), then proves /readyz/check_readiness() fails closed, restores the canonical definition, and verifies DB balance enforcement is recovered. Keep the test transactionally isolated and do not weaken forced RLS or append-only constraints.

Do not transfer the current green CI/coverage/package evidence to a successor head: rerun the focused PostgreSQL regression and the full exact-head foundation/100% owned statement+branch coverage/docstring/contracts/security/package/SBOM/provenance gates after the test change. Current OpenCode/Noema/Strix failures are external review-sidecar/provider boundaries, not evidence that this source repair failed.

@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 repair evidence for 13c8b17160631aa179083e043b6d5e954a7854fe:

The first causal boundary in Accounting Foundation job 99127860041 is the intentionally failing temporary probe tests/test_000_readiness_rls_probe.py, not a production-test regression. PostgreSQL 18.4 completed the remaining behavior suite; the probe emitted the canonical isolation evidence before failing: rls_count=33, rls_sha256=eeebc73a149228f197c7d7973d2e3fe64428eccfe6fdc03d5684ab4029491cb6, policy_count=27, policy_sha256=d78459bd56275ddd82c841be1981230b684e25fc06f29d11aa46aba2faa1f77b, tenant_function_md5=9c2cfaea74d193cadc39f46c242dd9a5. The probe also observed forced RLS on the expected authoritative tenant tables.

Use those observed values only to build the repository-owned canonical RLS/policy/tenant-function readiness contract and real PostgreSQL drift regressions for the unresolved tenant-isolation finding. Then remove tests/test_000_readiness_rls_probe.py from the canonical PR branch before validation. This head is intentionally red: coverage, denominator, repository-contract, wheel, SBOM and provenance steps were skipped after the probe failure, so no predecessor evidence transfers.

The separate unresolved full-operation timeout finding remains source-real on this head: connection setup is bounded, but tenant/catalog statements still need a readiness-specific statement timeout with a connected-block regression. Preserve SINGLE-WRITER; this review does not request a competing source commit.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@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.

Current exact-head review for b4c6ca7d40e56755c96f3e706f3becb33f18f2f0.

Two repository-local findings are source-real on this head and should remain unresolved while the active branch writer owns the source lane.

  1. The readiness statement-timeout contract is not installed before the first post-connect SQL. _session(readiness=True) caps connection establishment, but after psycopg.connect() it executes SET lock_timeout, SET idle_in_transaction_session_timeout, and SELECT current_setting('statement_timeout') before it installs the readiness statement_timeout. A server/network that stalls after connection establishment can therefore retain the HTTP worker before the claimed five-second statement bound exists. The current real-PG pg_sleep(10) regression exercises the later tenant lookup only after those setup statements, so it does not cover this causal boundary. This also makes the current ADR/OPERABILITY wording that the complete connected readiness operation is statement-bounded stronger than the implementation.

    Repair test-first and narrowly. RED/contract evidence should prove the default readiness statement timeout is established as a connection-startup property before the first application SQL, while an already stricter operator timeout remains stricter. The smallest robust implementation is to make the readiness timeout part of the libpq/psycopg startup connection options (preserving existing safe options rather than clobbering them), then retain the existing real-PostgreSQL slow-query regression. Do not broaden command-session behavior.

  2. The new migration-inventory parser still has supported PostgreSQL-18 grammar gaps. test_readiness_fingerprint_inventory_contract.py matches only CREATE TABLE schema.table and ALTER TABLE schema.table ... RLS. PostgreSQL 18 permits CREATE TABLE IF NOT EXISTS ... and ALTER TABLE [IF EXISTS] [ONLY] ...; a future checked-in migration using those forms can silently disappear from the table/RLS parity test. Fix the parser contract with focused synthetic-snippet tests before changing the regex/parser. Do not mechanically add IF NOT EXISTS to CREATE POLICY: PostgreSQL 18's CREATE POLICY grammar does not provide that clause. Keep the repair limited to syntax the authoritative PostgreSQL grammar actually accepts.

The separate Readiness forbids additive schema changes observation is not a current merge-safety defect under the checked-in deployment contract: docs/OPERABILITY.md requires applying the exact migration set through 0014 before starting this service version, and ADR 0055 intentionally defines readiness as the complete current schema contract. Exact column equality is therefore a deliberate fail-closed deployment invariant for this version. If the product later adopts rolling expand/contract migrations, add an explicit versioned compatibility-window ADR and tests rather than silently weakening this readiness contract.

Exact-head repository evidence is otherwise materially green: Accounting Foundation run 33264063737 checked out this SHA and completed behavior/repository tests, complete owned branch coverage, denominator/contracts, reproducible wheel and package evidence; exact-head dependency diff, SAST and repository security jobs also passed. Integrated-head attestations remains skipped on the PR event and is non-passing for release evidence. External Security Scan run 33264063799 fails closed at dependency-review job 99130835988: the log verifies the exact head/base checkout and then receives HTTP 403 from GitHub's dependency-graph compare endpoint; Trivy/OSV/Scorecard succeed. That external evidence-availability failure is not a source repair target in this repository.

This is not an approval. PR #29 remains the protected-develop dependency root, no qualifying independent approval is present, and no predecessor-head evidence transfers to a successor.

github-code-quality[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@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.

Current-head verification on c3e4701c299ccc9253b02f80c12c7871e58b39b7 confirms one repository-local defect remains in the readiness timeout parser.

_readiness_statement_timeout_milliseconds() recognizes -c statement_timeout=... and --statement_timeout=..., but its (?:-c\s+)? branch does not recognize the valid attached short-option form -cstatement_timeout=100ms. PostgreSQL/libpq sends options as server command-line arguments; PostgreSQL's getopt path accepts a required short-option argument from the remainder of the same argv element. With that spelling the parser returns None, _session(readiness=True) appends -c statement_timeout=5000ms, and the later setting can widen an operator-supplied stricter timeout.

Repair test-first on the existing branch: add a focused parser RED for the compact form plus a real PostgreSQL 18.4 regression that connects with options='-cstatement_timeout=100ms' and proves readiness preserves the effective stricter timeout instead of appending/winning with 5s. Then make the narrowest parser change that accepts attached -cname=value while preserving spaced -c name=value and --name=value, and rerun the complete exact-head foundation/100% owned statement+branch coverage/docstring/contracts/security/package/SBOM/provenance gates. Do not transfer predecessor-head evidence. The existing unresolved bug thread should remain unresolved until a successor exact head demonstrates that RED→GREEN boundary.

@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.

Current-head revalidation on 32dd690e88201ad96252c228333d64a527ba2afe: the production parser defect from predecessor c3e4701... is causally repaired. _readiness_statement_timeout_milliseconds() now accepts attached -cstatement_timeout=... via the -c\s* branch, while preserving spaced -c statement_timeout=... and --statement_timeout=...; the new focused regression proves the compact parser result is 100ms.

One acceptance-evidence gap remains before this repair is defensible as requested: the real-PostgreSQL stricter-timeout regression still constructs startup options as -c statement_timeout=100ms. The compact spelling that caused the defect is exercised only as a pure parser unit test, so the suite does not prove the repaired value survives conninfo_to_dict/make_conninfo -> libpq startup -> PostgreSQL 18.4 and remains the effective SHOW statement_timeout value without the 5s fallback winning. Strengthen that existing real-PG regression (or add a sibling) to use options='-cstatement_timeout=100ms' and assert the connected readiness session observes 100ms; keep the parser unit test as the narrow causal RED/GREEN.

Accounting Foundation for this exact head is still in progress, so no predecessor coverage/package evidence transfers. After the end-to-end compact-form test exists, rerun the complete exact-head PostgreSQL suite, exact 100% owned statement/branch coverage/public-docstrings/contracts, SAST/security, package/SBOM/provenance. This is not an approval; PR #29 remains the integration dependency root and qualifying independent approval is still required.

@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.

Current-head revalidation on 828ce2d05bee2bff5770ff3b95f9eda4845f2b8b: the predecessor compact-libpq acceptance gap is now closed end to end, not merely at the parser boundary. test_readiness_preserves_a_stricter_configured_statement_timeout builds the runtime DSN through conninfo_to_dict / make_conninfo with options='-cstatement_timeout=100ms', opens the actual readiness session, and asserts PostgreSQL reports SHOW statement_timeout = '100ms'. The focused parser regression for the same attached -c spelling remains present, while the looser-timeout path still proves the 5s readiness cap is inserted at connection startup.

Exact-head Accounting Foundation and repository-owned dependency/SAST/security evidence are successful on this SHA, but this is verification of the repaired finding only, not approval or merge evidence. Integrated-head attestations is skipped, the current opencode-review check is failure, the external dependency-review lane remains failed closed at GitHub's dependency-graph HTTP 403 boundary, and PR #29 remains the protected-develop dependency root. Do not transfer this head's green evidence to a successor or merge/release until all applicable exact-head required gates plus qualifying independent approval pass together.

Copy link
Copy Markdown
Contributor Author

Dependency-order correction (2026-09-07): the body sentence First integrate #47 -> #43 -> #29 is reversed. Protected integration proceeds root-first as #29 -> #43 -> #47 -> #53; this readiness sibling must not merge ahead of the accounting prerequisites it inspects. When its required accounting schema is integrated, adopt that protected head by ordinary non-force reconciliation and reacquire the readiness/PostgreSQL/coverage/security/review/package gates on the new exact head. Do not transfer descendant evidence backward.

Copy link
Copy Markdown
Contributor Author

Dependency-stack correction only; no readiness-probe source change here. Verified lifecycle #43 is merged history, so the open dependency order is now #29@12e1a4bb9d8de5e4b6c72e2893107b07c515416b -> #47 -> #53 -> protected develop, not #29 -> #43 -> #47 -> #53. Preserve #40 exact 828ce2d05bee2bff5770ff3b95f9eda4845f2b8b and its valid readiness evidence until that accounting stack integrates, then reconcile #40 normally/non-force against the exact protected integrated head and reacquire current-head PostgreSQL/readiness/coverage/security/review evidence. #43/root predecessor checks do not transfer; no force/rebase/close/bypass.

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

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants