fix: bootstrap PostgreSQL without a working service manager (#823) - #824
Conversation
b3c8c3f to
1b66266
Compare
1b66266 to
e2ea586
Compare
ReviewSound fix, no blockers. Three things I'd want changed before merge, all localized to What I verified — applied the two Go files to current
Moderate1. The fallback multiplies the timeout by the number of service attempts — confirmed, not theoretical. Moving Worst case is now 20 + 20 (services) + 30 ( Fix: drop the 2. Confirmed via the initdb args: Fix: the socket directory is already 3. The The hunk inserts at line ~322; on current Fix: rebase and move the row to the end of the table. Minor
ChecklistBug-fix requirements met: symptom row added, tests accompany the fix, The Thanks for the thorough stub-test coverage — the ready/non-ready service split and the idempotency cases are exactly the right seams to pin down. 🤖 Generated with Claude Code |
e2ea586 to
79dae2b
Compare
|
Thanks for the thorough review, @ako — all seven points are addressed. Rebased onto Moderate
Minor
Each new test was proven to fail on the un-fixed code (reverted each change in a throwaway worktree and watched the matching test fail with the reported symptom). |
79dae2b to
a99673e
Compare
Review (round 2)Thanks — I re-verified all seven points from the previous round and they are all addressed. Three new issues, one of which is a regression introduced by the fix for point 1. What I verified — merged the branch into current
Blocker1. The short probe turns "slow but working" into a hard failure.
Against real PostgreSQL that The likely trigger is not exotic: crash recovery after a reaped container. PostgreSQL refuses connections while replaying WAL ( Fix — in // Something already owns the port (e.g. a service-started server still in
// crash recovery). Never initdb a competitor — EnsureDatabase's authoritative
// 20s wait decides.
if pingTCP(net.JoinHostPort(host, port), time.Second) == nil {
return nil
}A short probe should answer "should I look further?", never "should I build a competitor?". Moderate2.
That directory mode is the entire access control behind Fix: 3. The 0700-socket control lives only in a command-line flag, not in the cluster.
Fix: persist it in the cluster's own config — write Minor
ChecklistBug-fix requirements met: symptom row appended at the end of the table, tests accompany the fix, the sync source skill ( The stub-test coverage is a real strength here — the port-guard and idempotency cases in particular made the two remaining defects cheap to demonstrate rather than argue about. 🤖 Generated with Claude Code |
d035f8a to
8efbd32
Compare
|
Thanks, @ako — round 2 is fully addressed in Blocker
Moderate
Minor and follow-through
The final tree passed |
8efbd32 to
01cd6c5
Compare
|
Final self-audit amended the single commit to |
|
Confirmed — and one of the six is weaker than it first looked, which changed what I'd say. Here's the text to paste: Reviewed by fetching the PR head and reading the full diff locally ( The design is sound and the security work is careful — private 1.
|
2bb8a73 to
2afab5c
Compare
|
Addressed all six follow-ups in
Additional hardening found during the pass:
Validation performed:
One transparent local-environment note: a whole-repository |
Follow-up audit: one system-cluster blocker before mergeI re-checked
There is, however, one blocker in the retained system-cluster path.
|
…s#823) Fall back to a user-owned initdb/pg_ctl cluster under ~/.mxcli/postgres when no service-managed PostgreSQL becomes ready. Provision through its private Unix socket without requiring a postgres OS account or sudo, while retaining a guarded system-cluster path. Harden the fallback across all review rounds: bound service probes, remove the invalid pg_ctlcluster placeholder, avoid competing with an occupied port, use SCRAM on TCP, enforce 0700 socket access, persist the endpoint atomically, reject legacy host-trust clusters, and validate running-cluster endpoints. Keep sudo/psql non-interactive on the peer-authenticated system socket at the requested port, propagate the canonical endpoint to the runtime, accept bracketed IPv6, force SCRAM password storage on older defaults, and keep password-bearing SQL out of process arguments. Add focused regressions and update the run-local documentation, changelog, and fix-issue record.
2afab5c to
18b133a
Compare
|
Addressed the follow-up finding in
Local validation on the exact pushed tree: full build/unit/lint, focused and race database tests, Windows/macOS amd64+arm64 package compilation, all MDL and skill/docs block checks, mdBook, tunnel dependency checks, and The two ordinary fork workflows were triggered again but remain in
|
|
Re-reviewed at 18b133a. All six items from the previous round are addressed, and I mutation-checked three of them — reverting each fix makes a test fail, so the guards detect something. go vet clean, ./cmd/mxcli/docker/ green. Verified individually: sudo host/port — -p s.port is now unconditional and -h is deliberately omitted for the sudo path to keep peer auth on the system socket. Dropping either makes TestSuperuserPSQL_SudoUsesPeerSocketPortAndNeverPrompts and TestResolveSuperuser/sudo_fallback fail. Two non-blocking observations:
Neither blocks merge. |
What & why
Closes #823.
mxcli run --ensure-dbonly knewserviceand a non-working Debianpg_ctlclusterplaceholder. On Arch neither produced a server, so bootstrap failed even though the portableinitdb,pg_ctl, andpsqltools were available.Fix
service postgresql startwith a bounded readiness probe, then fall back to a user-owned cluster under~/.mxcli/postgreswhen no service becomes ready. The unusablepg_ctlcluster -- startplaceholder is removed.0700.listen_addresses,port,unix_socket_directories, andunix_socket_permissions = 0700inpostgresql.conf; a plain laterpg_ctl -D ... starttherefore preserves the safe endpoint without mxcli-only runtime flags.sudo -u postgres psqlfor system clusters without prompting. It uses the distribution's peer-authenticated default Unix socket at the exact requested port, rather than forcing TCP where changing the OS user supplies no database password. InheritedPGHOST/PGHOSTADDR/PGSERVICEvalues cannot redirect that path.Tests
Focused command-stub regressions cover service readiness, the occupied-port race, the removed placeholder, first/repeated/running starts, port and socket mismatches, existing-directory permissions, persistent and idempotent configuration, legacy host trust, authentication arguments, superuser resolution, validation, and actionable failures.
The system-cluster regression models a Debian-style setup: the sudo probe succeeds only when
-his absent (Unix socket/peer auth) and the requested non-default port is still present. It also verifies that libpq target environment overrides are removed.Validation completed on the rebased
18b133a1tree:make buildmake testmake lint-gogo test ./cmd/mxcli/docker -count=1go test -racefor the changed database pathsmake check-mdland both skill/docs MDL-block checksmdbook build docs-sitegit diff --checkThe unchanged user-owned-cluster path was previously verified against real PostgreSQL 18.x for bootstrap, app login, repeat provisioning, socket/file permissions, plain
pg_ctlrestart, reconnect, SCRAM verifier, special-character password transport, and legacy-host-trust refusal.Docs and scope
Updated only the implementation, its focused tests, the two runtime call sites, CLI help, run-local skill/docs, CHANGELOG, and the final fix-issue table row: nine files, one concern, one commit on current
main. No MDL fixture is applicable because this change has no MDL surface.