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
|
@opencode-agent Please review exact current head |
|
@cwl-noema-review Please independently review exact current head |
|
@opencode-agent review Review exact current head |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
expected='9dbd3025e40de1105eb00afc4738ef5f02f849b6'
actual="$(git rev-parse HEAD)"
printf 'expected_head=%s\nactual_head=%s\n' "$expected" "$actual"
printf '\n== PR metadata and checks ==\n'
gh pr view 724 --repo ContextualWisdomLab/pg-erd-cloud \
--json baseRefOid,headRefOid,statusCheckRollup \
--jq '{baseRefOid,headRefOid,statusCheckRollup:[.statusCheckRollup[]|{name,conclusion,status}]}'
base="$(gh pr view 724 --repo ContextualWisdomLab/pg-erd-cloud --json baseRefOid --jq .baseRefOid)"
merge_base="$(git merge-base HEAD "$base")"
printf '\nmerge_base=%s\n== changed paths ==\n' "$merge_base"
git diff --name-status "$merge_base" HEAD
printf '\n== implementation outlines ==\n'
for f 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
echo "--- $f"
ast-grep outline "$f" --items all || true
done
printf '\n== CLI, collector, and web path ==\n'
sed -n '1,260p' backend/app/local_snapshot_cli.py
sed -n '1,360p' backend/app/pg_introspect/snapshot_collect.py
sed -n '1,220p' backend/app/pg_introspect/introspect.py
printf '\n== tests and coverage configuration ==\n'
sed -n '1,360p' backend/tests/test_local_snapshot_cli.py
sed -n '1,260p' backend/tests/test_pg_snapshot_collect.py
sed -n '1,300p' backend/tests/test_docstrings.py
sed -n '1,260p' backend/pyproject.toml
sed -n '1,240p' .github/workflows/ci.yml
printf '\n== connection authority, collector calls, and deterministic serialization references ==\n'
rg -n -C 3 \
'(asyncpg\.connect|collect_postgres_snapshot\s*\(|validate_postgres_dsn_target|PGPASSWORD|passfile|password|dsn|PGHOST|/tmp|asyncio\.gather|json\.dump|json\.dumps|sort_keys|UndefinedTableError)' \
backend README.md CHANGELOG.md -g '*.py' -g '*.md'
printf '\n== PR diff for reviewed paths ==\n'
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: 190709 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '== asyncpg pinned dependency references =='
rg -n -C 4 'asyncpg(==|>=|@)|name = "asyncpg"' \
backend/requirements*.lock backend/pyproject.toml 2>/dev/null || true
printf '%s\n' '== repository handling of PGPASSWORD =='
rg -n -C 4 '\bPGPASSWORD\b|os\.environ\.pop\(\s*["'\'']PGPASSWORD|password\s*=' \
backend/app backend/tests -g '*.py'
printf '%s\n' '== exact-head failed check details =='
gh api \
'repos/ContextualWisdomLab/pg-erd-cloud/commits/9dbd3025e40de1105eb00afc4738ef5f02f849b6/check-runs?per_page=100' \
--jq '.check_runs[]
| select(.name == "strix")
| {
name,
conclusion,
status,
details_url,
output: {
title: .output.title,
summary: .output.summary,
text: .output.text,
annotations_count: .output.annotations_count
}
}'
printf '%s\n' '== workflow/job context for strix =='
gh run list --repo ContextualWisdomLab/pg-erd-cloud \
--commit 9dbd3025e40de1105eb00afc4738ef5f02f849b6 \
--json databaseId,name,workflowName,status,conclusion,event,url \
--jq '.[] | select(.name | ascii_downcase | contains("strix"))'Length of output: 17299 🤖 web_search executed:
Length of output: 10784
Set an explicit non-environment password policy for the CLI connection. Add a regression test that sets The Unix-socket validation, absence of CLI DSNs, shared collector use, web SSRF guard, sequential catalog reads, Citus fallback, deterministic JSON key order, redacted tested failures, docstrings, and 100% coverage command are otherwise correct. I also cannot approve while the exact-head You are interacting with an AI system. |
|
Exact-head independent review requested for |
|
@opencode-agent @cwl-noema-review @coderabbitai review Review the exact current head only. Verify the Unix-domain-socket-only PostgreSQL snapshot CLI, absence of TCP/password DSN paths, unchanged web SSRF boundary, canonical collector reuse, redacted failures, deterministic JSON, and full current-head quality/security evidence. Please submit a formal current-head verdict. |
|
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 head =='
git_head="$(git rev-parse HEAD)"
pr_head="$(gh pr view "$pr" --repo "$repo" --json headRefOid --jq .headRefOid)"
printf 'checked_out=%s\npr_head=%s\n' "$git_head" "$pr_head"
if [ "$git_head" != "$pr_head" ]; then
printf '%s\n' 'ERROR: checked-out revision is not the current PR head.'
fi
printf '%s\n' '== PR checks =='
gh pr view "$pr" --repo "$repo" --json statusCheckRollup \
--jq '.statusCheckRollup[] | {name, status, conclusion, detailsUrl}'
printf '%s\n' '== Changed paths from merge base =='
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' '== Relevant implementation outlines =='
for f in backend/app/local_snapshot_cli.py backend/app/pg_introspect/snapshot_collect.py backend/app/pg_introspect/introspect.py; do
echo "--- $f"
ast-grep outline "$f" --items all
done
printf '%s\n' '== CLI, collector, and web boundary =='
sed -n '1,300p' backend/app/local_snapshot_cli.py
sed -n '1,400p' backend/app/pg_introspect/snapshot_collect.py
sed -n '1,240p' backend/app/pg_introspect/introspect.py
printf '%s\n' '== Tests, packaging, and CI coverage contract =='
sed -n '1,420p' backend/tests/test_local_snapshot_cli.py
sed -n '1,280p' backend/tests/test_pg_snapshot_collect.py
sed -n '1,300p' backend/tests/test_docstrings.py
sed -n '1,280p' backend/pyproject.toml
sed -n '1,260p' .github/workflows/ci.yml
printf '%s\n' '== Focused authority, redaction, determinism, and reuse references =='
rg -n -C 3 \
'(asyncpg\.connect|PGPASSWORD|password|dsn|PGHOST|/tmp|localhost|host=|validate_postgres_dsn_target|collect_postgres_snapshot\s*\(|asyncio\.gather|UndefinedTableError|json\.dump|json\.dumps|sort_keys)' \
backend README.md CHANGELOG.md -g '*.py' -g '*.md'Length of output: 165610
I found one blocking implementation issue.
The exact-head The remaining reviewed conditions are correct:
You are interacting with an AI system. |
|
@opencode-agent review Review exact current head |
|
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 head =='
actual="$(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" "$actual" "$pr_head"
printf '%s\n' '== pull-request status 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' "$merge_base"
printf '%s\n' '== changed files =='
git diff --name-status "$merge_base" HEAD
printf '%s\n' '== relevant file outlines =='
for f 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' "--- $f"
ast-grep outline "$f" --items all
done
printf '%s\n' '== CLI implementation =='
sed -n '1,320p' backend/app/local_snapshot_cli.py
printf '%s\n' '== CLI tests =='
sed -n '1,460p' backend/tests/test_local_snapshot_cli.py
printf '%s\n' '== collector and web call path =='
sed -n '1,400p' backend/app/pg_introspect/snapshot_collect.py
sed -n '1,240p' backend/app/pg_introspect/introspect.py
printf '%s\n' '== collector tests and docstring contract =='
sed -n '1,300p' backend/tests/test_pg_snapshot_collect.py
sed -n '1,320p' backend/tests/test_docstrings.py
printf '%s\n' '== packaging, coverage, and docs =='
sed -n '1,280p' backend/pyproject.toml
sed -n '1,260p' .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 references =='
rg -n -C 3 \
'(asyncpg\.connect|PGPASSWORD|PGPASSFILE|passfile|password|dsn|PGHOST|/tmp|validate_postgres_dsn_target|collect_postgres_snapshot\s*\(|asyncio\.gather|json\.dump|json\.dumps|sort_keys|UndefinedTableError)' \
backend README.md CHANGELOG.md -g '*.py' -g '*.md'
printf '%s\n' '== diff since prior reviewed head =='
git diff --no-ext-diff --unified=60 \
9dbd3025e40de1105eb00afc4738ef5f02f849b6 HEAD -- \
backend/app/local_snapshot_cli.py \
backend/tests/test_local_snapshot_cli.py \
backend/pyproject.toml \
backend/tests/test_docstrings.py \
.github/workflows/ci.yml \
README.md CHANGELOG.mdLength of output: 173531
I found no blocking implementation issue.
I cannot approve yet. The exact-head You are interacting with an AI system. |
|
@opencode-agent @cwl-noema-review Please perform a fresh independent review of current 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.