feat: add trusted local PostgreSQL snapshot CLI - #724
Conversation
📝 WalkthroughWalkthroughPostgreSQL 스냅샷 수집 로직을 별도 함수로 분리했습니다. Unix 소켓 전용 Changes로컬 스냅샷 수집과 CLI
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
backend/app/pg_introspect/snapshot_collect.py (1)
23-50: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win독립적인 카탈로그 조회를 병렬로 실행하는 것을 고려하십시오.
schemas,relations,columns,constraints,indexes,pk_columns,fk_edges,has_citus조회는 서로 의존성이 없습니다. 현재 구현은 이들을 순차적으로await합니다. 이 함수는 이제 CLI와 웹 API 양쪽에서 호출되는 공용 경로이므로, 순차 실행은 원격 데이터베이스 대상에서 왕복 지연시간을 누적시킵니다.asyncio.gather()로 병렬 실행하면 전체 수집 시간을 줄일 수 있습니다.⚡ 병렬 실행 제안
- schemas = await conn.fetch(queries.SCHEMAS_SQL, schema_name, include_system) - relations = await conn.fetch(queries.RELATIONS_SQL, schema_name, include_system) - columns = await conn.fetch(queries.COLUMNS_SQL, schema_name, include_system) - constraints = await conn.fetch( - queries.CONSTRAINTS_SQL, schema_name, include_system - ) - indexes = await conn.fetch(queries.INDEXES_SQL, schema_name, include_system) - pk_columns = await conn.fetch( - queries.PK_COLUMNS_SQL, schema_name, include_system - ) - fk_edges = await conn.fetch(queries.FK_EDGES_SQL, schema_name, include_system) - citus_distributed_tables = [] - has_citus = await conn.fetchval( - "SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_extension WHERE extname = 'citus')" - ) + ( + schemas, + relations, + columns, + constraints, + indexes, + pk_columns, + fk_edges, + has_citus, + ) = await asyncio.gather( + conn.fetch(queries.SCHEMAS_SQL, schema_name, include_system), + conn.fetch(queries.RELATIONS_SQL, schema_name, include_system), + conn.fetch(queries.COLUMNS_SQL, schema_name, include_system), + conn.fetch(queries.CONSTRAINTS_SQL, schema_name, include_system), + conn.fetch(queries.INDEXES_SQL, schema_name, include_system), + conn.fetch(queries.PK_COLUMNS_SQL, schema_name, include_system), + conn.fetch(queries.FK_EDGES_SQL, schema_name, include_system), + conn.fetchval( + "SELECT EXISTS (SELECT 1 FROM pg_catalog.pg_extension WHERE extname = 'citus')" + ), + ) + citus_distributed_tables = []
asyncioimport를 파일 상단에 추가해야 합니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/app/pg_introspect/snapshot_collect.py` around lines 23 - 50, Update the snapshot collection flow around the independent catalog fetches to import asyncio and execute the schemas, relations, columns, constraints, indexes, pk_columns, fk_edges, and has_citus queries concurrently with asyncio.gather(). Preserve the existing result assignments and Citus-specific fallback handling after the parallel fetches complete.backend/tests/test_local_snapshot_cli.py (1)
106-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
main()의 예외 처리 분기에 대한 테스트를 추가하는 것을 고려하십시오.
main()은OSError나asyncpg.PostgresError발생 시 종료 코드 1을 반환합니다. 이 경로에 대한 테스트가 없습니다.asyncio.run을 몽키패치하여 예외를 발생시키고 종료 코드와 stderr 메시지를 검증하는 테스트를 추가하면 회귀를 방지할 수 있습니다.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@backend/tests/test_local_snapshot_cli.py` around lines 106 - 115, backend/tests/test_local_snapshot_cli.py에 main()의 예외 처리 경로를 검증하는 테스트를 추가하십시오. asyncio.run을 몽키패치해 OSError와 asyncpg.PostgresError를 각각 발생시키고, main()이 종료 코드 1을 반환하는지와 예상 stderr 메시지를 검증하십시오.
🤖 Prompt for all review comments with AI agents
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 `@backend/app/local_snapshot_cli.py`:
- Around line 54-129: Add docstrings to the public functions build_parser,
capture_local_snapshot, and main, describing each function’s purpose, inputs,
and return value as appropriate. Keep the existing behavior unchanged and ensure
the module satisfies interrogate’s 100% documentation threshold.
- Around line 68-73: Update the --host argument in the local snapshot CLI parser
so it no longer defaults to the unsafe hardcoded "/tmp" path when PGHOST is
unset. Make the host explicit by requiring the argument or otherwise rejecting
an unset PGHOST with a clear user-facing validation error, while preserving
_socket_directory validation for provided values.
---
Nitpick comments:
In `@backend/app/pg_introspect/snapshot_collect.py`:
- Around line 23-50: Update the snapshot collection flow around the independent
catalog fetches to import asyncio and execute the schemas, relations, columns,
constraints, indexes, pk_columns, fk_edges, and has_citus queries concurrently
with asyncio.gather(). Preserve the existing result assignments and
Citus-specific fallback handling after the parallel fetches complete.
In `@backend/tests/test_local_snapshot_cli.py`:
- Around line 106-115: backend/tests/test_local_snapshot_cli.py에 main()의 예외 처리
경로를 검증하는 테스트를 추가하십시오. asyncio.run을 몽키패치해 OSError와 asyncpg.PostgresError를 각각
발생시키고, main()이 종료 코드 1을 반환하는지와 예상 stderr 메시지를 검증하십시오.
🪄 Autofix (Beta)
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: Pro Plus
Run ID: 1e44f98a-56d9-4101-b42a-b2b4a623a055
📒 Files selected for processing (6)
README.mdbackend/app/local_snapshot_cli.pybackend/app/pg_introspect/introspect.pybackend/app/pg_introspect/snapshot_collect.pybackend/pyproject.tomlbackend/tests/test_local_snapshot_cli.py
|
Reviewed the two summary-only nitpicks on current head a40ebd1:
|
There was a problem hiding this comment.
Pull request overview
OpenCode cannot approve yet because required coverage evidence did not pass.
Review outcome
1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
-
Problem: The required coverage-evidence job result was
failure, so OpenCode cannot establish approval sufficiency for this head. -
Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.
-
Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports
successwith required evidence or explicit no-source not-applicable evidence. -
Regression test: Keep the approval branch checking
needs.coverage-evidence.result == successbefore posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present. -
Result: REQUEST_CHANGES
-
Reason: coverage-evidence result was
failure, so required test/docstring evidence was not proven for current heada40ebd19807588262c370541322909de3416c5ab. -
Head SHA:
a40ebd19807588262c370541322909de3416c5ab -
Workflow run: 30808360272
-
Workflow attempt: 1
Coverage evidence
Coverage Decision
- Result: FAIL
- Test evidence: not proven passing
- Docstring evidence: not proven passing when configured
- Failure count: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: README.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: README.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (5 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (5 files)"]
R2 --> V2["backend tests"]
OpenCode Review Overview
Pull request overviewOpenCode cannot approve yet because required coverage evidence did not pass. Review outcome1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence
Coverage evidenceCoverage Decision
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: README.md"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: README.md"]
R1 --> V1["required checks"]
Evidence --> S2["Backend (5 files)"]
S2 --> I2["API and service runtime"]
I2 --> R2["Review risk: Backend (5 files)"]
R2 --> V2["backend tests"]
|
Dismissed as superseded by current head a785e7e. Current-head CI run 30810197074 now enforces pytest-cov with --cov-fail-under=100, reports 490/490 selected backend statements covered, 394 tests passed, and explicitly checks docstrings for the new public modules. Current-head Security Scan and Semgrep also pass. Independent current-head approval remains required.
|
@opencode-agent @cwl-noema-review Please independently review exact current head |
|
Review follow-up on exact head |
|
@opencode-agent Please re-review exact head |
|
@cwl-noema-review Please independently review exact head |
|
@opencode-agent Please independently review exact current head @cwl-noema-review Please perform the second independent exact-head review after OpenCode and submit APPROVE only if no actionable finding remains. |
|
@opencode-agent @cwl-noema-review Please independently review exact current head |
|
@opencode-agent @cwl-noema-review Please independently review exact current head @coderabbitai review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== checked-out commit =='
git rev-parse HEAD
printf '%s\n' '== changed files against first parent =='
git diff --name-status HEAD^ HEAD
printf '%s\n' '== changed-file outlines =='
for f in \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/introspect.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/tests/test_local_snapshot_cli.py
do
if [ -f "$f" ]; then
echo "--- $f"
ast-grep outline "$f" --items all || true
fi
done
printf '%s\n' '== PostgreSQL connection and allowlist references =='
rg -n -i -C 3 \
'(allowlist|allowed.host|ssrf|introspect_postgres|collect_postgres_snapshot|asyncpg\.connect|create_pool|postgres.*host|host.*postgres)' \
backend/app backend/tests \
-g '*.py' || true
printf '%s\n' '== direct diff =='
git diff --no-ext-diff --unified=80 HEAD^ HEAD -- \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/introspect.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/tests/test_local_snapshot_cli.py \
backend/pyproject.toml \
README.mdLength of output: 47343 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== pull request metadata =='
gh pr view 724 --repo ContextualWisdomLab/pg-erd-cloud \
--json baseRefName,baseRefOid,headRefName,headRefOid,commits \
--jq '{baseRefName,baseRefOid,headRefName,headRefOid, commits: [.commits[] | {oid,messageHeadline}]}'
printf '%s\n' '== candidate merge bases and changed files =='
base_ref="$(gh pr view 724 --repo ContextualWisdomLab/pg-erd-cloud --json baseRefOid --jq .baseRefOid)"
merge_base="$(git merge-base HEAD "$base_ref")"
printf 'base_ref=%s\nmerge_base=%s\n' "$base_ref" "$merge_base"
git diff --name-status "$merge_base" HEAD
printf '%s\n' '== local CLI implementation =='
sed -n '1,220p' backend/app/local_snapshot_cli.py
printf '%s\n' '== canonical collector implementation =='
sed -n '1,280p' backend/app/pg_introspect/snapshot_collect.py
printf '%s\n' '== web PostgreSQL path =='
sed -n '1,180p' backend/app/pg_introspect/introspect.py
printf '%s\n' '== local CLI tests =='
sed -n '1,260p' backend/tests/test_local_snapshot_cli.py
printf '%s\n' '== collector tests =='
sed -n '1,220p' backend/tests/test_pg_snapshot_collect.py
printf '%s\n' '== package entry point and operator documentation =='
sed -n '1,180p' backend/pyproject.toml
rg -n -C 12 'pg-erd-snapshot|Unix-domain|Unix socket|snapshot CLI' README.md || trueLength of output: 25350 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="37873d7b5421117bf3e08d488ce98b565a109034"
printf '%s\n' '== full PR diff, excluding lockfiles =='
git diff --no-ext-diff --unified=25 "$base" HEAD -- \
.github/workflows/ci.yml \
CHANGELOG.md \
README.md \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/introspect.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/pyproject.toml \
backend/tests/test_docstrings.py \
backend/tests/test_local_snapshot_cli.py \
backend/tests/test_pg_snapshot_collect.py
printf '%s\n' '== changed-path references to connection authority and defaults =='
git diff --no-ext-diff -U0 "$base" HEAD -- \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/introspect.py \
backend/app/pg_introspect/snapshot_collect.py \
README.md \
| rg -n -i -C 2 \
'(asyncpg\.connect|dsn|password|passfile|PGHOST|/tmp|localhost|host=|allowlist|validate_postgres_dsn_target|asyncio\.gather|UndefinedTableError)' \
|| true
printf '%s\n' '== docstring coverage rules and changelog entry =='
sed -n '1,260p' backend/tests/test_docstrings.py
rg -n -C 8 'snapshot|Unix|socket|CLI' CHANGELOG.md .github/workflows/ci.yml || true
printf '%s\n' '== all collector call sites =='
rg -n -C 3 '\bcollect_postgres_snapshot\s*\(' backend -g '*.py'
printf '%s\n' '== local CLI environment and connect argument references =='
rg -n -C 2 '(PGHOST|PGDATABASE|PGPORT|PGUSER|asyncpg\.connect|password|dsn)' \
backend/app/local_snapshot_cli.py backend/tests/test_local_snapshot_cli.pyLength of output: 42967
I found no blocking issue.
The README [approve] You are interacting with an AI system. |
Pull request was converted to draft
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
.github/workflows/ci.yml (1)
40-44: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winCoverage 범위를 목표 모듈과 일치시키세요.
backend/pyproject.toml은--cov범위를 고정하지만 10개 파일을 포함합니다.app/snowflake_introspect/introspect.py도 포함하지 않습니다. 세 모듈만 100% 검사하려면include를 해당 모듈로 제한하거나 CI 명령에 각--cov=<module>옵션을 추가하세요.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/ci.yml around lines 40 - 44, Update the “Tests and coverage (pytest)” step so coverage explicitly targets only the three intended modules, matching the configured scope in backend/pyproject.toml and excluding app/snowflake_introspect/introspect.py; use an appropriate coverage include setting or explicit --cov=<module> options while preserving the 100% threshold.
🤖 Prompt for all review comments with AI agents
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 `@backend/tests/test_local_snapshot_cli.py`:
- Around line 43-54: Update local_snapshot_cli.build_parser and its related
runtime configuration flow to stop reading PGDATABASE or PGHOST directly from
os.environ; obtain these values through the established KV or credential
registry, using environment variables only during registry bootstrap. Revise
test_parser_requires_explicit_host_without_pghost to mock registry lookups
instead of setting or deleting runtime environment variables, while preserving
the explicit-host validation and SystemExit behavior.
In `@backend/tests/test_pg_snapshot_collect.py`:
- Around line 47-52: Add docstrings to the following four public test functions
to document the behavior they validate:
test_collect_postgres_snapshot_handles_each_citus_state in
backend/tests/test_pg_snapshot_collect.py (lines 47-52) should document that it
validates snapshot collection behavior for each Citus mode state; the test in
backend/tests/test_local_snapshot_cli.py (lines 43-46) should document required
host validation when PGHOST environment variable is absent; the test in
backend/tests/test_local_snapshot_cli.py (lines 116-121) should document compact
and pretty JSON output formatting behavior; and the test in
backend/tests/test_local_snapshot_cli.py (lines 161-167) should document
connection error message sanitization behavior. Each docstring should be brief
and placed immediately after the function definition.
---
Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 40-44: Update the “Tests and coverage (pytest)” step so coverage
explicitly targets only the three intended modules, matching the configured
scope in backend/pyproject.toml and excluding
app/snowflake_introspect/introspect.py; use an appropriate coverage include
setting or explicit --cov=<module> options while preserving the 100% threshold.
🪄 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: Pro Plus
Run ID: 389a4334-c76b-4260-a792-24a7d392d671
📒 Files selected for processing (8)
.github/workflows/ci.ymlCHANGELOG.mdbackend/app/local_snapshot_cli.pybackend/app/pg_introspect/snapshot_collect.pybackend/pyproject.tomlbackend/tests/test_docstrings.pybackend/tests/test_local_snapshot_cli.pybackend/tests/test_pg_snapshot_collect.py
🚧 Files skipped from review as they are similar to previous changes (3)
- backend/app/pg_introspect/snapshot_collect.py
- backend/pyproject.toml
- backend/app/local_snapshot_cli.py
|
@cwl-noema-review Independently review exact head |
|
Exact-current-head review request for @coderabbitai review Do not modify the branch, bypass protection, merge, tag, release, or publish. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/pg-erd-cloud"
pr="724"
expected="b3d4ce7e3e03fb1b44ff5ffbb70217e05281a93e"
printf '%s\n' '== exact revision =='
checked_out="$(git rev-parse HEAD)"
pr_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"
printf 'expected=%s\nchecked_out=%s\npr_head=%s\n' "$expected" "$checked_out" "$pr_head"
printf '%s\n' '== current checks =='
gh pr view "$pr" --repo "$repo" --json statusCheckRollup \
--jq '.statusCheckRollup[] | {name, status, conclusion, detailsUrl}'
base="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
merge_base="$(git merge-base HEAD "$base")"
printf '== merge base ==\n%s\n== changed paths ==\n' "$merge_base"
git diff --name-status "$merge_base" HEAD
printf '%s\n' '== source outlines =='
for file in \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/app/pg_introspect/introspect.py \
backend/tests/test_local_snapshot_cli.py \
backend/tests/test_pg_snapshot_collect.py \
backend/tests/test_docstrings.py
do
printf '%s\n' "--- $file"
ast-grep outline "$file" --items all
done
printf '%s\n' '== CLI and collector implementation =='
sed -n '1,360p' backend/app/local_snapshot_cli.py
sed -n '1,440p' backend/app/pg_introspect/snapshot_collect.py
sed -n '1,280p' backend/app/pg_introspect/introspect.py
printf '%s\n' '== tests, packaging, CI, and documentation =='
sed -n '1,520p' backend/tests/test_local_snapshot_cli.py
sed -n '1,340p' backend/tests/test_pg_snapshot_collect.py
sed -n '1,340p' backend/tests/test_docstrings.py
sed -n '1,320p' backend/pyproject.toml
sed -n '1,300p' .github/workflows/ci.yml
rg -n -C 8 'pg-erd-snapshot|Unix-domain|Unix socket|snapshot CLI' README.md CHANGELOG.md || true
printf '%s\n' '== focused authority, error, output, and reuse references =='
rg -n -C 3 \
'(asyncpg\.connect|PGPASSWORD|PGPASSFILE|passfile|password|dsn|PGHOST|PGPORT|PGDATABASE|PGUSER|/tmp|localhost|host=|validate_postgres_dsn_target|collect_postgres_snapshot\s*\(|asyncio\.gather|UndefinedTableError|json\.dump|json\.dumps|sort_keys|PostgresError|OSError)' \
backend README.md CHANGELOG.md -g '*.py' -g '*.md'
printf '%s\n' '== unresolved review threads =='
gh api graphql -F owner="ContextualWisdomLab" -F name="pg-erd-cloud" -F number="$pr" -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
path
line
comments(first: 1) { nodes { body author { login } } }
}
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved == false)
| {path, line, body: .comments.nodes[0].body, author: .comments.nodes[0].author.login}' || true
printf '%s\n' '== diff since merge base for reviewed paths =='
git diff --no-ext-diff --unified=35 "$merge_base" HEAD -- \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/app/pg_introspect/introspect.py \
backend/tests/test_local_snapshot_cli.py \
backend/tests/test_pg_snapshot_collect.py \
backend/tests/test_docstrings.py \
backend/pyproject.toml \
.github/workflows/ci.yml \
README.md \
CHANGELOG.mdLength of output: 208006
I found no blocking issue.
[approve] You are interacting with an AI system. |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
|
@opencode-agent review Re-read the exact current head and submit a formal review-only verdict for the Unix-socket-only snapshot CLI, explicit empty authentication preventing ambient password/passfile fallback, validated libpq bootstrap inputs, sequential single-connection catalog reads, Citus states, deterministic JSON, redacted failures, 100% coverage/docstrings, and direct exact-head CI/Security/SAST evidence. Do not mutate or merge. |
|
@coderabbitai full review Perform a fresh exact-current-head review of the Unix-socket-only snapshot CLI and ambient-credential exclusion boundary. Submit the current-head verdict without mutating or merging. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/pg-erd-cloud"
pr="724"
printf '%s\n' '== exact live head =='
checked_out="$(git rev-parse HEAD)"
live_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"
printf 'checked_out=%s\nlive_head=%s\n' "$checked_out" "$live_head"
printf '%s\n' '== current checks =='
gh pr view "$pr" --repo "$repo" --json statusCheckRollup \
--jq '.statusCheckRollup[] | {name,status,conclusion,detailsUrl}'
printf '%s\n' '== review scope =='
base="$(gh pr view "$pr" --repo "$repo" --json baseRefOid --jq .baseRefOid)"
merge_base="$(git merge-base HEAD "$base")"
printf 'merge_base=%s\n' "$merge_base"
git diff --name-status "$merge_base" HEAD
printf '%s\n' '== implementation outlines =='
for file in \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/app/pg_introspect/introspect.py \
backend/tests/test_local_snapshot_cli.py \
backend/tests/test_pg_snapshot_collect.py \
backend/tests/test_docstrings.py
do
printf '%s\n' "--- $file"
ast-grep outline "$file" --items all
done
printf '%s\n' '== CLI implementation =='
sed -n '1,380p' backend/app/local_snapshot_cli.py
printf '%s\n' '== collector and web path =='
sed -n '1,460p' backend/app/pg_introspect/snapshot_collect.py
sed -n '1,300p' backend/app/pg_introspect/introspect.py
printf '%s\n' '== targeted tests and contracts =='
sed -n '1,560p' backend/tests/test_local_snapshot_cli.py
sed -n '1,360p' backend/tests/test_pg_snapshot_collect.py
sed -n '1,360p' backend/tests/test_docstrings.py
sed -n '1,340p' backend/pyproject.toml
sed -n '1,320p' .github/workflows/ci.yml
printf '%s\n' '== focused authority, collector, output, and error references =='
rg -n -C 4 \
'(asyncpg\.connect|PGPASSWORD|PGPASSFILE|passfile|password|dsn|PGHOST|PGPORT|PGDATABASE|PGUSER|/tmp|localhost|host=|validate_postgres_dsn_target|collect_postgres_snapshot\s*\(|asyncio\.gather|UndefinedTableError|json\.dump|json\.dumps|sort_keys|PostgresError|OSError)' \
backend README.md CHANGELOG.md -g '*.py' -g '*.md'
printf '%s\n' '== unresolved review threads =='
gh api graphql -F owner="ContextualWisdomLab" -F name="pg-erd-cloud" -F number="$pr" -f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
path
line
comments(first: 1) { nodes { body author { login } } }
}
}
}
}
}' --jq '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved == false)
| {path, line, body: .comments.nodes[0].body, author: .comments.nodes[0].author.login}' || true
printf '%s\n' '== relevant diff =='
git diff --no-ext-diff --unified=40 "$merge_base" HEAD -- \
backend/app/local_snapshot_cli.py \
backend/app/pg_introspect/snapshot_collect.py \
backend/app/pg_introspect/introspect.py \
backend/tests/test_local_snapshot_cli.py \
backend/tests/test_pg_snapshot_collect.py \
backend/tests/test_docstrings.py \
backend/pyproject.toml \
.github/workflows/ci.yml \
README.md \
CHANGELOG.mdLength of output: 226948
I found no blocking issue.
[approve] You are interacting with an AI system. |
|
@cwl-noema-review A qualifying formal current-head GitHub review is required for protected merge. Submit |
|
Submit a formal current-head GitHub review after checks settle. Approve only if the exact head is green and no actionable finding remains; otherwise post the concrete blocker. Do not mutate or merge. |
|
Please submit the formal current-head review conclusion after the latest exact-head checks complete. Do not mutate or merge. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/pg-erd-cloud"
pr="724"
printf '%s\n' '== live revision =='
checked_out="$(git rev-parse HEAD)"
live_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"
printf 'checked_out=%s\nlive_head=%s\n' "$checked_out" "$live_head"
printf '%s\n' '== status checks =='
gh pr view "$pr" --repo "$repo" --json statusCheckRollup \
--jq '.statusCheckRollup[] | {name,status,conclusion,detailsUrl}'
printf '%s\n' '== unresolved review threads =='
gh api graphql \
-F owner="ContextualWisdomLab" \
-F name="pg-erd-cloud" \
-F number="$pr" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
path
line
comments(first: 1) {
nodes { body author { login } }
}
}
}
}
}
}' \
--jq '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved == false)
| {path, line, author: .comments.nodes[0].author.login, body: .comments.nodes[0].body}' || trueLength of output: 6674
I verified exact head The checked-out revision matches the live PR head. The substantive checks completed successfully. This includes backend, frontend, coverage evidence, CodeQL analysis, Semgrep, dependency review, Trivy, OSV scan, and Strix. The No unresolved review threads remain. The prior exact-head implementation review found no actionable issue in the Unix-socket-only boundary, ambient credential exclusion, shared collector behavior, sequential asyncpg access, Citus handling, deterministic output, or error redaction. [approve] You are interacting with an AI system. |
|
@opencode-agent review Use the newest exact head only. If every required check is green and there is no actionable finding, submit formal approval; otherwise state the blocker. Do not mutate or merge. |
|
@cwl-noema-review review Use exact-current-head evidence only. Approve formally only when required checks are green and no actionable finding remains; otherwise identify the blocker. Do not mutate or merge. |
|
@opencode-agent review Do not post another top-level acknowledgement. Submit the formal exact-head review verdict through the GitHub review API when current-head checks are complete; approve only if no blocker remains. Do not mutate or merge. |
|
@coderabbitai full review Use the exact current head only and submit the review verdict through the formal GitHub review surface; do not post another summary comment, mutate, or merge. |
Rate Limit Exceeded
|
|
@cwl-noema-review Please use the GitHub review API rather than another comment for the final exact-head verdict. Do not mutate or merge. |
|
Final action expected: use the GitHub review API for the exact current head. Approve only if current required checks are successful and no actionable finding remains; otherwise post one concrete blocking review. Do not mutate or merge. |
|
@cwl-noema-review Submit one formal exact-current-head review through GitHub's review API. Do not add another discussion comment, mutate, or merge. |
|
Do not acknowledge. Submit exactly one formal review on the exact current head through GitHub's review API after checks complete. Do not mutate or merge. |
|
@cwl-noema-review Do not acknowledge. Submit exactly one formal review on the exact current head through GitHub's review API after checks complete. Do not mutate or merge. |
|
Do not acknowledge. Submit exactly one formal review on the exact current head through GitHub's review API after checks complete. Do not mutate or merge. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="ContextualWisdomLab/pg-erd-cloud"
pr="724"
printf '%s\n' '== revision identity =='
checked_out="$(git rev-parse HEAD)"
pr_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"
printf 'checked_out=%s\npr_head=%s\n' "$checked_out" "$pr_head"
printf '%s\n' '== status checks =='
gh pr view "$pr" --repo "$repo" --json statusCheckRollup \
--jq '.statusCheckRollup[] | {
name,
status,
conclusion,
workflowName,
detailsUrl
}'
printf '%s\n' '== unresolved review threads =='
gh api graphql \
-F owner="ContextualWisdomLab" \
-F name="pg-erd-cloud" \
-F number="$pr" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
isResolved
path
line
comments(first: 1) {
nodes { author { login } body }
}
}
}
}
}
}' \
--jq '.data.repository.pullRequest.reviewThreads.nodes[]
| select(.isResolved == false)
| {
path,
line,
author: .comments.nodes[0].author.login,
body: .comments.nodes[0].body
}'Length of output: 7646
[approve] You are interacting with an AI system. |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
|
Queued @cwl-noema-review for PR #724 at head |
Buyer-visible capability
Adds a Unix-domain-socket-only
pg-erd-snapshotCLI for trusted local PostgreSQL schema snapshots without weakening the web API SSRF boundary or exposing password-bearing DSNs. The canonical PostgreSQL collector is shared by the web and CLI paths so both surfaces produce the same snapshot contract.Safety and compatibility
/tmpfallback and accepts no TCP host or password-bearing DSN;asyncpg.connect, preventing ambientPGPASSWORDor passfile fallback while preserving peer/trust authentication over the local socket;PGPASSWORDand proves the connection call receives the explicit empty value instead of inheriting the environment;The review request to add a new KV/credential registry was rejected after verification: no such established CLI registry exists in this repository, and introducing one solely for this command would create a competing configuration contract.
PGHOSTremains constrained by the existing Unix-socket directory validator.Test-first correction
0c17794aa97a7ec0c795f28f2842bf2a27f766c9: added the failing regression that setsPGPASSWORDand requires an explicit empty connection value;b3d4ce7e3e03fb1b44ff5ffbb70217e05281a93e: implemented the explicit empty authentication policy in production code.Exact-head validation
Current head:
b3d4ce7e3e03fb1b44ff5ffbb70217e05281a93e.Exact-head CI, security gates, automated review, unresolved threads, and independent non-author approval must be revalidated after the correction. The PR must not merge until repository policy and every required gate pass on this exact head.
Release status
CHANGELOG.mdrecords the operator-facing capability. No standalone release is proposed until the repository's broader release acceptance gates are satisfied.