pgserve 2.6.1 → 2.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -14,6 +14,187 @@ All notable changes to `pgserve` are documented here. The format follows
14
14
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres
15
15
  to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
16
16
 
17
+ ## [2.6.4] - 2026-05-12
18
+
19
+ **Final v2.x maintenance release** — the last `pgserve`-named npm publish.
20
+ Cut from the `release/v2.6.x` maintenance branch (off `1489d7d`, pre-V3
21
+ cutover) so consumers like `@withone/cli` (and any other `pgserve: ^2.x`
22
+ dependent) continue to receive backward-compatible updates without the
23
+ V3 rename, V3-1 verb cutover, or npm-publish drop. **Future development
24
+ moves to the `autopg` package starting at v3.0.0** (see
25
+ `distribution-exodus` wish in main).
26
+
27
+ ### Added (since 2.6.1)
28
+
29
+ - **Signed-app delivery pipeline** — `pgserve create-app <slug>` writes a
30
+ per-consumer manifest with cosign locked trust roots; `pgserve verify
31
+ --slug <slug>` differentiates lock-vs-live identities and exit-codes
32
+ per outcome.
33
+ - **Cosign keyless OIDC signing** for release tarballs — Sigstore bundles
34
+ + SLSA L3 provenance + GitHub Attestations API attestation per
35
+ platform tarball. Verifiable via `cosign verify-blob`, `slsa-verifier
36
+ verify-artifact`, or `gh attestation verify`.
37
+ - **Trust-list hardcoded roots** — `automagik-genie-release`,
38
+ `automagik-omni-release`, and `automagik-pgserve-release` entries in
39
+ `src/cosign/trust-list.js`. All three anchor on `sign-attest.yml@`
40
+ (the canonical Fulcio SAN URI shape across Namastex automagik
41
+ signed apps).
42
+ - **`pgserve gc`** — orphan-DB sweep + per-day rotating audit log under
43
+ `~/.pgserve/audit/` (90-day retention, current-day boundary guard).
44
+ - **Console + docs** — operator-facing migration guide
45
+ (`docs/migrations/v2.6-from-v2.5.md`), cosign trust reference
46
+ (`docs/security/cosign-trust.md`), schema docs (`pgserve_meta`,
47
+ trust-store, signed-app delivery).
48
+ - **Integration test scaffolds** — `tests/integration/gc-provision.test.sh`,
49
+ `tests/integration/verify-slug-rotation.test.sh`,
50
+ `tests/integration/wave-a-e2e.test.sh`,
51
+ `tests/integration/v2.6-cohort-smoke.sh`.
52
+ - **Postinstall guardrail** — soft-fails on git-worktree dev installs
53
+ with a stderr warning, preventing accidental `~/.pgserve` mutation
54
+ during package development.
55
+
56
+ ### Fixed (since 2.6.1)
57
+
58
+ - **CV-1**: `pgserve provision` / `pgserve gc` no longer auth-fail on
59
+ fresh installs (hot-fix from PR #101).
60
+ - **B5/B6/B7 trio** — audit-log rotation boundary, dual-mode keyless
61
+ verify, JSON-escape OIDC issuer in aggregate manifest.
62
+ - **CV-VERIFY-BUNDLE-NAMING** — consumer-side bundle resolve falls
63
+ through `.bundle` → `.sig` + `.cert` detached pair when the bundle
64
+ filename doesn't match, so older signing artifacts continue to verify.
65
+ - **Wave B bundle-format** — `pgserve verify` accepts both sigstore
66
+ bundle (`.bundle`) and detached cosign (`<tarball>.sig` +
67
+ `<tarball>.cert`) artifact shapes.
68
+
69
+ ### Preserved (intentional — for backward compatibility)
70
+
71
+ - **`pgserve` CLI bin** — both `pgserve` and `autopg` bins remain
72
+ declared in package.json. `pgserve <verb>` works the same as it did
73
+ in v2.6.1.
74
+ - **`pgserve upgrade` verb** — V3-1's clean cutover to `pgserve update`
75
+ was reverted on this maintenance branch (V3-1 is a v3.0.0 breaking
76
+ change, not safe for a patch release). Operators continue to use
77
+ `pgserve upgrade` on v2.x.
78
+ - **npm publish workflow** — V3-2 dropped npm publishing from main's
79
+ release path; reverted on this maintenance branch so v2.6.4 publishes
80
+ to npm normally via the existing OIDC trusted publisher entry.
81
+ - **Default port 8432** — unchanged from v2.6.1.
82
+
83
+ ### Removed
84
+
85
+ (none — additive release)
86
+
87
+ ### Notes for `@withone/cli` + other npm dependents
88
+
89
+ - `pgserve: ^2.2.3` satisfies — semver range resolves to 2.6.4.
90
+ - No code changes required on the consumer side.
91
+ - The next major (`autopg@v3.0.0`) ships from the new
92
+ `automagik-dev/autopg` repo + drops npm; if/when you migrate, switch
93
+ to `install.sh` + GitHub Releases per the autopg distribution model.
94
+
95
+ ## [2.6.0] / [2.6.1] - 2026-05-09
96
+
97
+ The 2.6 cohort closes the singleton-G3 sprint and the
98
+ `autopg-distribution-cutover-finalize` Wave 1+2 work. v2.6.0 cut the singleton
99
+ verbs to npm; v2.6.1 followed with the B2/B3/B4 CLI fix trio.
100
+
101
+ ### Added
102
+
103
+ - **`pgserve doctor`** — read-only health probe for postmaster, pm2 supervision,
104
+ on-disk roots, and trust store. JSON output via `--json`. See
105
+ [`docs/migrations/v2.6-from-v2.5.md`](docs/migrations/v2.6-from-v2.5.md).
106
+ - **`pgserve trust add | list | remove`** — manage the user-extensible cosign
107
+ trust store at `~/.pgserve/trust/identities.json`. Layered on top of the
108
+ hardcoded `TRUSTED_IDENTITIES` (frozen at build time). See
109
+ [`docs/trust-store.md`](docs/trust-store.md).
110
+ - **`pgserve gc [--dry-run | --apply]`** — sweep orphan databases (rows in
111
+ `pgserve_meta` whose `source_path` no longer exists). One-line-per-event audit
112
+ log at `~/.pgserve/audit/gc-<YYYY-MM-DD>.log`. Rotates files >90 days old at
113
+ start of each run. See [`docs/pgserve-meta.md`](docs/pgserve-meta.md) for the
114
+ underlying schema.
115
+ - **`pgserve provision <fingerprint>`** — idempotent DB + role provisioning for
116
+ an app fingerprint. Concurrency-safe via `pg_advisory_lock` keyed on
117
+ fingerprint hash; `42P04` ("database already exists") accepted as success.
118
+ - **`pgserve create-app <slug>`** — per-consumer app registration with manifest
119
+ LOCK 1 cosign verifier. Writes `~/.autopg/<slug>/admin.json` + sibling
120
+ `manifest.json`, registers in `autopg_meta`, freezes `TRUSTED_IDENTITIES` for
121
+ this consumer at create time. `pgserve verify --slug <slug>` consults the
122
+ frozen snapshot.
123
+ - **`pgserve verify --slug <slug>`** — verify a binary against an app's locked
124
+ roots (instead of the live `TRUSTED_IDENTITIES`). Allows trust rotation
125
+ without invalidating already-registered consumers.
126
+ - **`pgserve_meta` schema** — base table for `provision`/`gc`. Cosign verification
127
+ columns (`verified_at`, `verified_identity`, `verified_tier`) layered on top
128
+ via additive ALTER TABLE migration. Schema reference at
129
+ [`docs/pgserve-meta.md`](docs/pgserve-meta.md).
130
+ - **`autopg_meta` schema** — separate table keyed on `slug` for `create-app`
131
+ registrations. Frozen `locked_roots` JSONB. Idempotent re-runs preserve
132
+ `locked_roots` and only touch `last_updated`.
133
+ - **GitHub Releases as the canonical distribution channel** — `install.sh`
134
+ fetches per-platform binaries from
135
+ `github.com/namastexlabs/pgserve/releases/download/v<version>/`. Cosign
136
+ attestations live in Sigstore Rekor; verification via `gh attestation verify`
137
+ (no custom verifier server). See
138
+ [`.github/workflows/release-publish.yml`](.github/workflows/release-publish.yml).
139
+ - **Hardcoded blocklist** — `pgserve install` refuses to start against known-bad
140
+ versions with exit code `EBLOCKEDVERSION`.
141
+
142
+ ### Changed
143
+
144
+ - **`pgserve install`** now runs port pre-flight (IPv4 + IPv6 connect probe on
145
+ 5432) and refuses to start on collision. Closes the silent-failure mode
146
+ where pm2 reported `online` while postgres had crashed.
147
+ - **`pgserve install --help`** respects `--help` / `-h` and exits 0 without
148
+ performing the install.
149
+ - **Unknown verbs** (`pgserve foo`) exit non-zero with an "unknown verb" error
150
+ instead of printing top-level help and exiting 0.
151
+ - **`pgserve doctor`** surfaces a missing `pgaudit` extension as a non-PASS
152
+ finding (was silently fall-through).
153
+ - **`pgserve config --help`** exits 0 with a usage block instead of running the
154
+ config logic against `--help` as if it were a key.
155
+ - **`install.sh`** replaced in-place with the ≤80-line GitHub Releases path.
156
+ No legacy or shim companions; the npm + pm2 install path is preserved via
157
+ `pgserve install` (`npm install -g pgserve && pgserve install`).
158
+
159
+ ### Fixed
160
+
161
+ - **`fix(pg-query)`** — default `PGPASSWORD` to `'postgres'` on fresh install
162
+ (CV-1 release blocker).
163
+ - **`fix(cosign)`** — correct trust-list github org refs (omni →
164
+ `automagik-dev`, pgserve → `namastexlabs`).
165
+ - **`fix(cosign)`** — correct `publisher` field for pgserve + reconcile
166
+ `SHARED-DESIGN.md` org refs.
167
+ - **`fix(postinstall)`** — worktree guard + non-CI pre-warning + dev-setup
168
+ docs. Closes the bug where every `bun install` in a pgserve worktree
169
+ triggered `autopg upgrade` against the real `~/.autopg/data/`.
170
+ - **`fix(verify-binary)`** — `resolveBundlePath` fall-through to
171
+ `provenance.intoto.jsonl` and sibling provenance.
172
+ - **`fix(verify-binary)`** — support detached `<tarball>.sig` +
173
+ `<tarball>.cert` cosign format alongside `<tarball>.bundle`.
174
+ - **`fix(cli-install)`** — use `process.exitCode + throw` to avoid stdio-pipe
175
+ race on `process.exit(1)` against piped stdout.
176
+ - **`fix(doctor)`** — timeout supervisor probes + `pgserve upgrade` hint when
177
+ pm2 is missing.
178
+ - **`fix(install)`** — drop npm references in `install.sh`; canonical path is
179
+ the GitHub Releases curl-pipe.
180
+
181
+ ### Notes
182
+
183
+ - The 2.6 cohort lands as **additive** changes — existing `pgserve` invocations
184
+ continue to work unchanged. See
185
+ [`docs/migrations/v2.6-from-v2.5.md`](docs/migrations/v2.6-from-v2.5.md) for
186
+ the operator action checklist.
187
+ - **Signing artifacts on GitHub Releases are NOT yet shipping** as of v2.6.1.
188
+ The release workflow's `sign-attest.yml` produces cosign signatures + SLSA
189
+ L3 provenance, but the `release-publish.yml` upload step does not yet wire
190
+ those artifacts into the published release. Tracked as Wave A in
191
+ `agents/genie-pgserve/SIGNED-APPS-MISSION-STATE.md`. Will land in a follow-up
192
+ patch release.
193
+ - **Connectivity fanout test** — `tests/integration/consumer-fanout.sh`
194
+ (verifying brain / omni / rlmx / hapvida-eugenia / email all reach the
195
+ postmaster) is owned by `pgserve-singleton-no-proxy` Group 9 and ships in a
196
+ separate cohort.
197
+
17
198
  ## [2.2.3] - 2026-05-03
18
199
 
19
200
  ### Changed
package/README.md CHANGED
@@ -141,6 +141,26 @@ autopg restart # pm2-aware: pm2 restart pgserve, else SI
141
141
  autopg ui [--port N] [--no-open] # local web console on 127.0.0.1
142
142
  ```
143
143
 
144
+ ### v2.6 cohort verbs
145
+
146
+ The 2.6 release adds five operator-facing verbs for health probing, trust-store
147
+ management, orphan-database GC, fingerprint provisioning, and per-consumer app
148
+ registration:
149
+
150
+ ```
151
+ pgserve doctor [--json] # read-only health probe
152
+ pgserve trust <list|add|remove> [...] # manage ~/.pgserve/trust/identities.json
153
+ pgserve gc [--dry-run|--apply] # sweep orphan databases (audit log)
154
+ pgserve provision <fingerprint> # idempotent DB + role provisioning
155
+ pgserve create-app <slug> # per-consumer manifest LOCK 1
156
+ pgserve verify [--slug <slug>] <bin> # cosign verify against trust list or locked roots
157
+ ```
158
+
159
+ Full reference:
160
+ [`docs/migrations/v2.6-from-v2.5.md`](docs/migrations/v2.6-from-v2.5.md) ·
161
+ [`docs/pgserve-meta.md`](docs/pgserve-meta.md) ·
162
+ [`docs/trust-store.md`](docs/trust-store.md).
163
+
144
164
  Foreground options accepted by `autopg` / `pgserve` (no subcommand):
145
165
 
146
166
  ```
@@ -66,6 +66,15 @@ const __installSubcommands = new Set([
66
66
  // src/commands/provision.js header for why). Pure node + child_process,
67
67
  // must skip bun probe.
68
68
  'provision',
69
+ // autopg-distribution-cutover-finalize (v2.6) — wish Group 3.
70
+ // `create-app` registers a consumer slug in autopg_meta + writes the
71
+ // per-consumer admin.json + manifest.json under ~/.autopg/<slug>/,
72
+ // freezing TRUSTED_IDENTITIES into locked_roots at create time. Pure
73
+ // node + psql shellout — must skip bun probe like the rest of the G3
74
+ // verbs. Adding here makes BOTH `pgserve create-app` and
75
+ // `autopg create-app` work via the same dispatcher (autopg-wrapper.cjs
76
+ // delegates to pgserve-wrapper.cjs per Decision #7).
77
+ 'create-app',
69
78
  ]);
70
79
  if (__subcommand && __installSubcommands.has(__subcommand)) {
71
80
  const cli = require(path.join(__dirname, '..', 'src', 'cli-install.cjs'));
@@ -79,8 +88,24 @@ if (__subcommand && __installSubcommands.has(__subcommand)) {
79
88
  result.then(
80
89
  (code) => process.exit(typeof code === 'number' ? code : 0),
81
90
  (err) => {
82
- process.stderr.write(`pgserve: ${err?.message ?? err}\n`);
83
- process.exit(1);
91
+ // CV103-2 (v2.6.2): the cli-install.cjs EADDRINUSE catch handler
92
+ // already wrote the message to stderr AND set process.exitCode = 1
93
+ // before throwing. If we ALSO write here we'd double-print, AND
94
+ // if we call process.exit(1) we re-introduce the stdio-pipe race
95
+ // the catch handler avoided by switching to exitCode + throw.
96
+ //
97
+ // Suppress the duplicate stderr write for already-handled error
98
+ // codes. Don't call process.exit() — Node will exit naturally
99
+ // once the event loop drains, using process.exitCode (which the
100
+ // throwing handler already set) so stderr flushes cleanly even
101
+ // under the piped-stdout / inherited-stderr shape that exposed
102
+ // the race (qa repro R6: `pgserve install | cat`).
103
+ if (err && err.code !== 'EADDRINUSE') {
104
+ process.stderr.write(`pgserve: ${err?.message ?? err}\n`);
105
+ }
106
+ if (process.exitCode === undefined || process.exitCode === 0) {
107
+ process.exitCode = 1;
108
+ }
84
109
  },
85
110
  );
86
111
  return;