pgserve 2.6.1 → 2.6.5

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,211 @@ 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.5] - 2026-05-12
18
+
19
+ **Hot-fix follow-up to v2.6.4.** v2.6.4 published to npm cleanly but the
20
+ GitHub Releases pipeline failed at `build-tarballs.yml` due to a latent
21
+ bug in `scripts/fetch-postgres-bins.sh` — `stage_from_url` declared
22
+ `local scratch` without initialization, and the function's RETURN trap
23
+ referenced `$scratch` under `set -u`, triggering an `unbound variable`
24
+ error that propagated across function frames and masked the real
25
+ fetch state. (Codex P2 caught the same pattern in `stage_from_pkg`
26
+ during PR #84 review; `stage_from_url` was missed at that time.)
27
+
28
+ ### Fixed
29
+
30
+ - `scripts/fetch-postgres-bins.sh:156` — initialize `local scratch=""`
31
+ before installing the RETURN trap, mirroring the fix already applied
32
+ to `stage_from_pkg` at line 119.
33
+
34
+ ### Same payload as v2.6.4
35
+
36
+ All v2.6.4 changes carry forward unchanged. v2.6.5 is purely the
37
+ GitHub Releases pipeline completion — npm consumers on
38
+ `pgserve: ^2.x` who already picked up v2.6.4 will see v2.6.5 on next
39
+ install but the runtime surface is identical.
40
+
41
+ ## [2.6.4] - 2026-05-12
42
+
43
+ **Final v2.x maintenance release** — the last `pgserve`-named npm publish.
44
+ Cut from the `release/v2.6.x` maintenance branch (off `1489d7d`, pre-V3
45
+ cutover) so consumers like `@withone/cli` (and any other `pgserve: ^2.x`
46
+ dependent) continue to receive backward-compatible updates without the
47
+ V3 rename, V3-1 verb cutover, or npm-publish drop. **Future development
48
+ moves to the `autopg` package starting at v3.0.0** (see
49
+ `distribution-exodus` wish in main).
50
+
51
+ ### Added (since 2.6.1)
52
+
53
+ - **Signed-app delivery pipeline** — `pgserve create-app <slug>` writes a
54
+ per-consumer manifest with cosign locked trust roots; `pgserve verify
55
+ --slug <slug>` differentiates lock-vs-live identities and exit-codes
56
+ per outcome.
57
+ - **Cosign keyless OIDC signing** for release tarballs — Sigstore bundles
58
+ + SLSA L3 provenance + GitHub Attestations API attestation per
59
+ platform tarball. Verifiable via `cosign verify-blob`, `slsa-verifier
60
+ verify-artifact`, or `gh attestation verify`.
61
+ - **Trust-list hardcoded roots** — `automagik-genie-release`,
62
+ `automagik-omni-release`, and `automagik-pgserve-release` entries in
63
+ `src/cosign/trust-list.js`. All three anchor on `sign-attest.yml@`
64
+ (the canonical Fulcio SAN URI shape across Namastex automagik
65
+ signed apps).
66
+ - **`pgserve gc`** — orphan-DB sweep + per-day rotating audit log under
67
+ `~/.pgserve/audit/` (90-day retention, current-day boundary guard).
68
+ - **Console + docs** — operator-facing migration guide
69
+ (`docs/migrations/v2.6-from-v2.5.md`), cosign trust reference
70
+ (`docs/security/cosign-trust.md`), schema docs (`pgserve_meta`,
71
+ trust-store, signed-app delivery).
72
+ - **Integration test scaffolds** — `tests/integration/gc-provision.test.sh`,
73
+ `tests/integration/verify-slug-rotation.test.sh`,
74
+ `tests/integration/wave-a-e2e.test.sh`,
75
+ `tests/integration/v2.6-cohort-smoke.sh`.
76
+ - **Postinstall guardrail** — soft-fails on git-worktree dev installs
77
+ with a stderr warning, preventing accidental `~/.pgserve` mutation
78
+ during package development.
79
+
80
+ ### Fixed (since 2.6.1)
81
+
82
+ - **CV-1**: `pgserve provision` / `pgserve gc` no longer auth-fail on
83
+ fresh installs (hot-fix from PR #101).
84
+ - **B5/B6/B7 trio** — audit-log rotation boundary, dual-mode keyless
85
+ verify, JSON-escape OIDC issuer in aggregate manifest.
86
+ - **CV-VERIFY-BUNDLE-NAMING** — consumer-side bundle resolve falls
87
+ through `.bundle` → `.sig` + `.cert` detached pair when the bundle
88
+ filename doesn't match, so older signing artifacts continue to verify.
89
+ - **Wave B bundle-format** — `pgserve verify` accepts both sigstore
90
+ bundle (`.bundle`) and detached cosign (`<tarball>.sig` +
91
+ `<tarball>.cert`) artifact shapes.
92
+
93
+ ### Preserved (intentional — for backward compatibility)
94
+
95
+ - **`pgserve` CLI bin** — both `pgserve` and `autopg` bins remain
96
+ declared in package.json. `pgserve <verb>` works the same as it did
97
+ in v2.6.1.
98
+ - **`pgserve upgrade` verb** — V3-1's clean cutover to `pgserve update`
99
+ was reverted on this maintenance branch (V3-1 is a v3.0.0 breaking
100
+ change, not safe for a patch release). Operators continue to use
101
+ `pgserve upgrade` on v2.x.
102
+ - **npm publish workflow** — V3-2 dropped npm publishing from main's
103
+ release path; reverted on this maintenance branch so v2.6.4 publishes
104
+ to npm normally via the existing OIDC trusted publisher entry.
105
+ - **Default port 8432** — unchanged from v2.6.1.
106
+
107
+ ### Removed
108
+
109
+ (none — additive release)
110
+
111
+ ### Notes for `@withone/cli` + other npm dependents
112
+
113
+ - `pgserve: ^2.2.3` satisfies — semver range resolves to 2.6.4.
114
+ - No code changes required on the consumer side.
115
+ - The next major (`autopg@v3.0.0`) ships from the new
116
+ `automagik-dev/autopg` repo + drops npm; if/when you migrate, switch
117
+ to `install.sh` + GitHub Releases per the autopg distribution model.
118
+
119
+ ## [2.6.0] / [2.6.1] - 2026-05-09
120
+
121
+ The 2.6 cohort closes the singleton-G3 sprint and the
122
+ `autopg-distribution-cutover-finalize` Wave 1+2 work. v2.6.0 cut the singleton
123
+ verbs to npm; v2.6.1 followed with the B2/B3/B4 CLI fix trio.
124
+
125
+ ### Added
126
+
127
+ - **`pgserve doctor`** — read-only health probe for postmaster, pm2 supervision,
128
+ on-disk roots, and trust store. JSON output via `--json`. See
129
+ [`docs/migrations/v2.6-from-v2.5.md`](docs/migrations/v2.6-from-v2.5.md).
130
+ - **`pgserve trust add | list | remove`** — manage the user-extensible cosign
131
+ trust store at `~/.pgserve/trust/identities.json`. Layered on top of the
132
+ hardcoded `TRUSTED_IDENTITIES` (frozen at build time). See
133
+ [`docs/trust-store.md`](docs/trust-store.md).
134
+ - **`pgserve gc [--dry-run | --apply]`** — sweep orphan databases (rows in
135
+ `pgserve_meta` whose `source_path` no longer exists). One-line-per-event audit
136
+ log at `~/.pgserve/audit/gc-<YYYY-MM-DD>.log`. Rotates files >90 days old at
137
+ start of each run. See [`docs/pgserve-meta.md`](docs/pgserve-meta.md) for the
138
+ underlying schema.
139
+ - **`pgserve provision <fingerprint>`** — idempotent DB + role provisioning for
140
+ an app fingerprint. Concurrency-safe via `pg_advisory_lock` keyed on
141
+ fingerprint hash; `42P04` ("database already exists") accepted as success.
142
+ - **`pgserve create-app <slug>`** — per-consumer app registration with manifest
143
+ LOCK 1 cosign verifier. Writes `~/.autopg/<slug>/admin.json` + sibling
144
+ `manifest.json`, registers in `autopg_meta`, freezes `TRUSTED_IDENTITIES` for
145
+ this consumer at create time. `pgserve verify --slug <slug>` consults the
146
+ frozen snapshot.
147
+ - **`pgserve verify --slug <slug>`** — verify a binary against an app's locked
148
+ roots (instead of the live `TRUSTED_IDENTITIES`). Allows trust rotation
149
+ without invalidating already-registered consumers.
150
+ - **`pgserve_meta` schema** — base table for `provision`/`gc`. Cosign verification
151
+ columns (`verified_at`, `verified_identity`, `verified_tier`) layered on top
152
+ via additive ALTER TABLE migration. Schema reference at
153
+ [`docs/pgserve-meta.md`](docs/pgserve-meta.md).
154
+ - **`autopg_meta` schema** — separate table keyed on `slug` for `create-app`
155
+ registrations. Frozen `locked_roots` JSONB. Idempotent re-runs preserve
156
+ `locked_roots` and only touch `last_updated`.
157
+ - **GitHub Releases as the canonical distribution channel** — `install.sh`
158
+ fetches per-platform binaries from
159
+ `github.com/namastexlabs/pgserve/releases/download/v<version>/`. Cosign
160
+ attestations live in Sigstore Rekor; verification via `gh attestation verify`
161
+ (no custom verifier server). See
162
+ [`.github/workflows/release-publish.yml`](.github/workflows/release-publish.yml).
163
+ - **Hardcoded blocklist** — `pgserve install` refuses to start against known-bad
164
+ versions with exit code `EBLOCKEDVERSION`.
165
+
166
+ ### Changed
167
+
168
+ - **`pgserve install`** now runs port pre-flight (IPv4 + IPv6 connect probe on
169
+ 5432) and refuses to start on collision. Closes the silent-failure mode
170
+ where pm2 reported `online` while postgres had crashed.
171
+ - **`pgserve install --help`** respects `--help` / `-h` and exits 0 without
172
+ performing the install.
173
+ - **Unknown verbs** (`pgserve foo`) exit non-zero with an "unknown verb" error
174
+ instead of printing top-level help and exiting 0.
175
+ - **`pgserve doctor`** surfaces a missing `pgaudit` extension as a non-PASS
176
+ finding (was silently fall-through).
177
+ - **`pgserve config --help`** exits 0 with a usage block instead of running the
178
+ config logic against `--help` as if it were a key.
179
+ - **`install.sh`** replaced in-place with the ≤80-line GitHub Releases path.
180
+ No legacy or shim companions; the npm + pm2 install path is preserved via
181
+ `pgserve install` (`npm install -g pgserve && pgserve install`).
182
+
183
+ ### Fixed
184
+
185
+ - **`fix(pg-query)`** — default `PGPASSWORD` to `'postgres'` on fresh install
186
+ (CV-1 release blocker).
187
+ - **`fix(cosign)`** — correct trust-list github org refs (omni →
188
+ `automagik-dev`, pgserve → `namastexlabs`).
189
+ - **`fix(cosign)`** — correct `publisher` field for pgserve + reconcile
190
+ `SHARED-DESIGN.md` org refs.
191
+ - **`fix(postinstall)`** — worktree guard + non-CI pre-warning + dev-setup
192
+ docs. Closes the bug where every `bun install` in a pgserve worktree
193
+ triggered `autopg upgrade` against the real `~/.autopg/data/`.
194
+ - **`fix(verify-binary)`** — `resolveBundlePath` fall-through to
195
+ `provenance.intoto.jsonl` and sibling provenance.
196
+ - **`fix(verify-binary)`** — support detached `<tarball>.sig` +
197
+ `<tarball>.cert` cosign format alongside `<tarball>.bundle`.
198
+ - **`fix(cli-install)`** — use `process.exitCode + throw` to avoid stdio-pipe
199
+ race on `process.exit(1)` against piped stdout.
200
+ - **`fix(doctor)`** — timeout supervisor probes + `pgserve upgrade` hint when
201
+ pm2 is missing.
202
+ - **`fix(install)`** — drop npm references in `install.sh`; canonical path is
203
+ the GitHub Releases curl-pipe.
204
+
205
+ ### Notes
206
+
207
+ - The 2.6 cohort lands as **additive** changes — existing `pgserve` invocations
208
+ continue to work unchanged. See
209
+ [`docs/migrations/v2.6-from-v2.5.md`](docs/migrations/v2.6-from-v2.5.md) for
210
+ the operator action checklist.
211
+ - **Signing artifacts on GitHub Releases are NOT yet shipping** as of v2.6.1.
212
+ The release workflow's `sign-attest.yml` produces cosign signatures + SLSA
213
+ L3 provenance, but the `release-publish.yml` upload step does not yet wire
214
+ those artifacts into the published release. Tracked as Wave A in
215
+ `agents/genie-pgserve/SIGNED-APPS-MISSION-STATE.md`. Will land in a follow-up
216
+ patch release.
217
+ - **Connectivity fanout test** — `tests/integration/consumer-fanout.sh`
218
+ (verifying brain / omni / rlmx / hapvida-eugenia / email all reach the
219
+ postmaster) is owned by `pgserve-singleton-no-proxy` Group 9 and ships in a
220
+ separate cohort.
221
+
17
222
  ## [2.2.3] - 2026-05-03
18
223
 
19
224
  ### 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;