Skip to content

feat(singleton#1): foundation — postmaster + admin.json writer (Tier A pm2)#75

Merged
namastex888 merged 3 commits into
mainfrom
dream-pgserve-v2-4
May 8, 2026
Merged

feat(singleton#1): foundation — postmaster + admin.json writer (Tier A pm2)#75
namastex888 merged 3 commits into
mainfrom
dream-pgserve-v2-4

Conversation

@namastex888

Copy link
Copy Markdown
Contributor

Implements Group 1 of pgserve-singleton-no-proxy wish. Cohort foundation for v2.4.

What ships

  • bin/postgres-server.js (new): postmaster wrapper with -k <socketDir> -p 5432, dual-transport binding (UDS + TCP loopback).
  • src/lib/socket-dir.js (new): resolveSocketDir()$XDG_RUNTIME_DIR/pgserve (preferred) or /tmp/pgserve (CI fallback).
  • src/lib/admin-json.js (new): cohort-shared atomic writer + reader + assertSupervisor() helper. Schema: { supervisor, socketDir, port, installedAt } with supervisor ∈ { "pm2" | "systemd-user" | "launchd" | "external" }. Atomic via <file>.tmp + fs.rename. Co-owned with cohort sibling canonical-pgserve-pm2-supervision Group 1.
  • src/cli-install.cjs (refactored): Tier A pm2 register (autopg-server); --no-pm2 flag for CI / Tier B-bound hosts; refuses if admin.json.supervisor ∈ {systemd-user, launchd}.
  • src/postgres.js (modified): postmaster spawn with new socket-dir wiring.
  • Tests: 18/18 pass on tests/lib/admin-json.test.js; cli-install tests updated.

Acceptance criteria (per wish G1)

  • pgserve install on fresh host creates $XDG_RUNTIME_DIR/pgserve/ mode 0700.
  • psql -h $XDG_RUNTIME_DIR/pgserve (no -p) connects post-install.
  • psql -h 127.0.0.1 -p 5432 connects post-install.
  • pgserve port outputs 5432.
  • pm2 jlist | jq '.[] | select(.name=="autopg-server")' non-empty post-install.
  • ~/.autopg/admin.json records supervisor: "pm2" with the resolved socketDir.
  • pgserve install refuses when admin.json records systemd-user (Tier B host); locked remediation hint matches cohort.
  • pgserve install --no-pm2 skips pm2 register, writes supervisor: "external".

Cohort dream context

Layer 1 (foundation) of v2.4 cohort dream batch (DREAM.md tracked under PR #74, PG task #6 / #7).

Unblocks Layer 2:

  • singleton G2-G9 (delete bun proxy, CLI verbs, cosign, blocklist, self-healing update, roles+grants, migration tooling, tests)
  • canonical Group 1 (libraries — pm2-args.js shipped via this commit's src/cli-install.cjs refactor; library extraction follow-up in canonical wish)

And Layer 3:

  • cutover G11/G19/G20 (Tier A binary subcommand + dual-transport runtime.json + Tier B systemd-user installer)

Test plan

  • bun test tests/lib/admin-json.test.js — 18 pass / 0 fail (98.18% lines covered)
  • CI: bun test full suite (will run on push)
  • CI: bun run lint && bun run typecheck
  • Integration test on Linux Blacksmith fixture (G1 acceptance criteria)

namastex888 and others added 3 commits May 8, 2026 03:54
….4 dream-readiness

Reconciliation with two-tier supervisor model:
- Group 1 (postmaster + dual-transport): scoped to Tier A pm2 only.
  Tier B systemd-user / launchd ships separately via cutover G11.6.
  Added admin.json writer module; refuses to claim "pm2" if already on Tier B.
  Added --no-pm2 flag for Tier B-bound hosts.
  Tightened acceptance criteria (admin.json supervisor field, pm2 jlist check,
  refuse-when-already-Tier-B, --no-pm2 path).

- Group 6 (self-healing update): made supervisor-aware. Restart-primitive
  dispatcher reads admin.json.supervisor and calls matching restart command:
    pm2          → pm2 restart autopg-server
    systemd-user → systemctl --user restart autopg.service
    launchd      → launchctl kickstart -k gui/$UID/dev.automagik.autopg
    external     → no-op + advisory log
  Added Tier B + external integration tests.

Wave 2 dependency graph fix:
- Wave description said G4→G3→G7 but depends-on lines all pointed at G1.
- Corrected: G3.depends-on=G4 (provision needs cosign schema), G7.depends-on=G3
  (roles/grants build on provision skeleton).

Doctor passive-reporting contract baked into G3 acceptance criteria:
- doctor reads admin.json.supervisor and runs matching liveness check.
- Never suggests swapping tiers (Felipe directive 2026-05-08).
- Cat 1 mutation: if admin.json says pm2 but entry missing, --fix re-registers.

Risk register expanded:
- Tier A + Tier B double-supervision (HIGH) — mitigated by hard MIGRATE
  contract in cutover G11.6 + Group 1 refuse-when-Tier-B check.
- admin.json corruption (LOW) — doctor --fix Cat 1 rewrites from observed state.
- Tier B operator runs pgserve update (MEDIUM) — G6 supervisor-aware dispatch.

Cross-wish dependencies expanded:
- paired-with autopg-distribution-cutover (cohort sibling, owns G11.6 contract).
- paired-with canonical-pgserve-pm2-supervision (cohort sibling, Tier A only).
- blocks autopg-service-install-system (parked next-version wish).

Success criteria additions:
- doctor reports active supervisor by reading admin.json (passive).
- MIGRATE contract honor across pm2 → systemd-user transition is verifiable.

genie wish lint: clean (no violations).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
MEDIUM — terminology + file-path pin:
- 5 occurrences of "G11.6" → "G20" (cutover wish renumbered group during /wish pass).
- Group 1 deliverable 6 admin.json writer: pinned the file path to
  `src/lib/admin-json.js`, declared co-ownership with cohort sibling
  canonical-pgserve-pm2-supervision Group 1 deliverable 2, and made the
  schema/enum explicit (supervisor ∈ {pm2, systemd-user, launchd, external}).

genie wish lint: clean (no violations).

Per /review verdict 2026-05-08 — non-blocking MEDIUM gaps closed.
W1 verdict was already SHIP*; these fixes were optional pre-flight tightening.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…son writer (cohort foundation)

Lays the data-plane foundation for pgserve 2.4. Group 1 of the
`pgserve-singleton-no-proxy` wish (cohort dream of the v2.4 trio).

What ships:

- bin/postgres-server.js — new `postmaster` subcommand. Spawns
  PostgresManager directly with `-k <socket-dir>` and `-p 5432`. No
  router, no bun proxy, no daemon control socket. This is the entry
  point pm2 (Tier A) — and later systemd-user / launchd (Tier B,
  separate wish) — invokes for the `autopg-server` process.

- src/lib/socket-dir.js — `resolveSocketDir()` returns
  `$XDG_RUNTIME_DIR/pgserve` (preferred, freedesktop convention) or
  `/tmp/pgserve` (fallback for CI / minimal containers without XDG).
  `ensureSocketDir()` creates with mode 0700 and probes writability so
  failure surfaces here, not as a libpq bind error mid-pm2-backoff.

- src/lib/admin-json.js — cohort-shared atomic reader / merge-writer /
  `assertSupervisor()` for `~/.autopg/admin.json`. Schema:
  `{ supervisor, socketDir, port, installedAt }` with supervisor ∈
  `{ "pm2" | "systemd-user" | "launchd" | "external" }`. Refuses to
  downgrade Tier B → Tier A (operator must `autopg service uninstall`
  first). Merge-aware: preserves the scrypt Basic-Auth scheme written
  by the autopg console UI.

- src/postgres.js — PostgresManager honors an explicit `socketDir`
  option. When set, the install path owns directory lifecycle: stop()
  no longer rm's an operator-supplied dir.

- src/cli-install.cjs — DEFAULT_PORT 8432 → 5432; PM2_PROCESS_NAME
  `pgserve` → `autopg-server`; new `--no-pm2` flag for CI fixture
  provisioning and Tier B-bound hosts; pre-install
  `assertSupervisor('pm2'|'external')` refuses to claim hosts already
  owned by Tier B; canonical socket dir created + admin.json
  supervisor record written atomically post-install. The existing
  scrypt admin-password writer becomes merge-safe so both schemas
  coexist on the same file.

Tests:

- tests/lib/admin-json.test.js — 18 tests covering write/read, atomic
  semantics, merge with existing fields, Tier B downgrade refusal,
  enum validation, assertSupervisor matrix.

- tests/cli-install.test.js — updated for the v2.4 surface
  (autopg-server pm2 name, port 5432, postmaster subcommand args) +
  6 new singleton tests: socket dir creation w/ mode 0700,
  --socket-dir threading through pm2 args, admin.json fields,
  --no-pm2 path, systemd-user lock refusal, /tmp fallback.

Acceptance (per wish Group 1):

- ✅ pgserve install creates `$XDG_RUNTIME_DIR/pgserve/` with mode
  0700.
- ✅ pgserve port outputs 5432.
- ✅ pm2 entry name is `autopg-server` (renamed from `pgserve`).
- ✅ admin.json records supervisor: "pm2" + canonical socketDir.
- ✅ pgserve install refuses with non-zero when admin.json records
  supervisor: "systemd-user".
- ✅ pgserve install --no-pm2 skips pm2 register but still writes
  admin.json with supervisor: "external".

Validation (run in worktree):

- bun test tests/lib/admin-json.test.js → 18 pass / 0 fail.
- bun test tests/cli-install.test.js → 26 pass / 0 fail.
- bun run lint → clean.
- bun test (full) → 328 pass / 2 fail; the 2 pre-existing failures
  are console/dist/ asset tests unaffected by this change.

`bun run typecheck` is referenced by the wish but does not exist as a
package script; the project relies on lint + tests for static gates.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@namastex888 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 25 minutes and 41 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0fb8ff35-73de-47b7-8641-76f4b02bf6da

📥 Commits

Reviewing files that changed from the base of the PR and between 145b1d4 and 36ff931.

📒 Files selected for processing (8)
  • .genie/wishes/pgserve-singleton-no-proxy/WISH.md
  • bin/postgres-server.js
  • src/cli-install.cjs
  • src/lib/admin-json.js
  • src/lib/socket-dir.js
  • src/postgres.js
  • tests/cli-install.test.js
  • tests/lib/admin-json.test.js
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dream-pgserve-v2-4

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 and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements the first phase of the pgserve singleton architecture, transitioning the data plane to a direct postmaster supervision model. Key changes include the introduction of a "postmaster" subcommand in bin/postgres-server.js for direct PostgreSQL management, the migration of the default port to 5432, and the renaming of the PM2 process to "autopg-server". A new coordination mechanism using ~/.autopg/admin.json is established to track active supervisors and prevent conflicting installations between PM2 and system-level services. Additionally, the PR introduces dedicated modules for atomic configuration management and canonical socket directory resolution. I have no feedback to provide.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

https://github.com/namastexlabs/pgserve/blob/36ff93114b1addd043b3d551c3fab2e406c79b2a/src/cli-install.cjs#L644
P1 Badge Detect legacy pm2 process before starting new install

When upgrading a host that already has the pre-v2.4 pm2 entry (pgserve), this idempotency check only looks for autopg-server, so pgserve install treats the host as fresh and attempts a second pm2 start. On real upgrades this can fail with port/data-dir lock conflicts or leave the CLI reporting the wrong runtime state. The commit even defines LEGACY_PM2_PROCESS_NAME but never uses it, so the migration path is effectively broken until Group 6 lands.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@namastex888 namastex888 merged commit e6e5b9f into main May 8, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant