llm-cli-gateway 1.17.7 → 1.17.9

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
@@ -4,6 +4,124 @@ All notable changes to the llm-cli-gateway project.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## [1.17.9] - 2026-06-04: prod-only shrinkwrap + registry-fidelity verification
8
+
9
+ Patch release shipping a prod-only `npm-shrinkwrap.json` and correcting the
10
+ 1.17.8 record: registry installs **do** honour the published shrinkwrap (the
11
+ real distribution channel), so consumers of `npm install llm-cli-gateway`
12
+ already get the pinned `tar-stream@3.1.7`. The 1.17.8 changelog called the
13
+ shrinkwrap "inert today because of npm/cli#7977" — that was wrong. npm/cli#7977
14
+ covers a remote-registry edge case; what we actually reproduced on this host
15
+ (npm 11.12.1) is that **local-tarball** installs ignore a nested shrinkwrap
16
+ (npm/cli#5349/#5325 class), while registry installs honour it via the
17
+ packument's `hasShrinkwrap` flag. This release verifies the registry path end
18
+ to end with a verdaccio reproduction.
19
+
20
+ ### Added
21
+
22
+ - `scripts/make-prod-shrinkwrap.mjs`: deterministic generator that projects
23
+ `package-lock.json` into a prod-only `npm-shrinkwrap.json` — drops every
24
+ dev-only (`dev === true`) `packages` entry and deletes the root
25
+ `devDependencies` field. A byte-identical copy of the lockfile (1.17.8's
26
+ approach) reified all ~316 packages into consumer trees (npm/cli#4323); the
27
+ prod-only projection ships ~124 and eliminates the dev-dep bloat for registry
28
+ consumers. Output is byte-deterministic; the security audit regenerates and
29
+ compares for parity. `optional` (and any `devOptional`) entries are kept —
30
+ prod installs need them. The shrinkwrap is GENERATED at pack/publish time
31
+ and never committed: a committed npm-shrinkwrap.json is treated by
32
+ `npm ci`/`npm install` as the authoritative lockfile, and the prod-only
33
+ projection (no dev deps) breaks every dev/CI install with EUSAGE "lock
34
+ file out of sync" — discovered when the first 1.17.9 release attempt
35
+ failed all four `npm ci`-based workflows. `.gitignore` now covers it; the
36
+ CI, publish, and tag-release workflows generate it just before the
37
+ security audit / pack / publish steps.
38
+ - `scripts/verify-registry-install.sh`: registry-fidelity gate (run by
39
+ `scripts/pre-release.sh` and standalone). Publishes the current tree to an
40
+ ephemeral verdaccio, installs it into a fresh consumer dir, and asserts (a)
41
+ `tar-stream` resolves to `3.1.7` (shrinkwrap honoured), (b) no dev-dep markers
42
+ (`vitest`/`typescript`/`eslint`/`prettier`) in the consumer tree, (c) the
43
+ installed bin prints the expected version, (d) `better-sqlite3` loads from the
44
+ installed package (binding built through the pinned tar chain). The publish /
45
+ consumer-install / assertion flow runs entirely against throwaway temp dirs
46
+ (registry storage, npm cache, userconfig) and the localhost registry — the
47
+ package under test never reaches the public registry. One exception: the
48
+ verdaccio bootstrap itself (`npx --yes verdaccio`) resolves through the user's
49
+ normal npm config and npx cache (unavoidable for an ephemeral tool), touching
50
+ only verdaccio's own packages. Sets the packument's
51
+ `_hasShrinkwrap` flag to mirror what npmjs sets at publish (verdaccio does not
52
+ compute it), so the reproduction faithfully matches the real registry. Logs
53
+ the observed reified-package count (not hard-asserted in this release).
54
+
55
+ ### Changed
56
+
57
+ - `scripts/pre-release.sh` / `scripts/refresh-release-lockfile.sh`: replace
58
+ `cp package-lock.json npm-shrinkwrap.json` with
59
+ `node scripts/make-prod-shrinkwrap.mjs`; pre-release now also runs
60
+ `scripts/verify-registry-install.sh` after the shrinkwrap regeneration and the
61
+ release gate.
62
+ - `scripts/release-security-audit.sh`: the shrinkwrap parity gate no longer does
63
+ byte-identity against the lockfile (that no longer holds — the shrinkwrap is a
64
+ prod-only projection). It regenerates the expected projection from
65
+ `package-lock.json` via the same deterministic generator into a temp file and
66
+ `cmp -s` against the shipped `npm-shrinkwrap.json`.
67
+
68
+ ### Fixed (record correction)
69
+
70
+ - The 1.17.8 claim that the shipped shrinkwrap is "inert today because of
71
+ npm/cli#7977" was incorrect. Registry installs honour it (verified via the new
72
+ verdaccio reproduction); only **local-tarball** installs ignore it
73
+ (npm/cli#5349/#5325 class — our live repro). The packed-consumer-install
74
+ advisory in the audit is requalified accordingly: registry installs get
75
+ `tar-stream@3.1.7`, local-tarball installs still resolve `tar-stream@2.2.0`,
76
+ and the advisory (warn, not fail) stays until Phase B drops `better-sqlite3`
77
+ from the prod graph. The 1.17.8 entry itself is left unedited.
78
+
79
+ ### Known residuals
80
+
81
+ - Consumer `npm ls` exits ELSPROBLEMS: the pinned `tar-stream@3.1.7` sits
82
+ outside `tar-fs`'s `^2.1.4` range. Inherent to the out-of-range pin; disappears
83
+ in 2.0.0 (Phase B / node:sqlite) when the `better-sqlite3 → prebuild-install
84
+ → tar-fs` chain leaves the prod graph entirely.
85
+ - Local-tarball installs still resolve `tar-stream@2.2.0` (shrinkwrap ignored on
86
+ that path); the audit's advisory carve-out stays until Phase B.
87
+
88
+ ## [1.17.8] - 2026-06-04: release-audit integrity fix + shrinkwrap groundwork
89
+
90
+ Patch release fixing a masking bug in the release security audit and documenting
91
+ the consumer-side tar-stream@2.2.0 exposure honestly: `package.json#overrides`
92
+ only pins tar-stream 3.1.7 in this repo's own tree — npm overrides never
93
+ propagate to dependents, so `npm install llm-cli-gateway` still resolves
94
+ tar-stream@2.2.0 under better-sqlite3 → prebuild-install → tar-fs in the
95
+ consumer's tree. The canonical remedy, a published `npm-shrinkwrap.json`, is
96
+ currently **ignored by npm itself** (npm/cli#7977, verified empirically against
97
+ npm 11.12.1 with lockfileVersion 2 and 3): no mechanism available to this
98
+ package can pin a dependent's transitive resolution today.
99
+
100
+ ### Fixed
101
+
102
+ - `scripts/release-security-audit.sh`: lockfile package names were derived with
103
+ `path.split('/node_modules/')`, which never matches top-level
104
+ `node_modules/<pkg>` entries — the packed-consumer-install check silently
105
+ passed 1.17.7 despite tar-stream@2.2.0 in the consumer tree. Names now derive
106
+ from a `node_modules/` split that handles top-level and nested entries.
107
+
108
+ ### Added
109
+
110
+ - Ship `npm-shrinkwrap.json` (byte-identical copy of `package-lock.json`,
111
+ regenerated by `scripts/pre-release.sh`; the audit fails the release if the
112
+ two diverge). Inert today because of npm/cli#7977, but it becomes effective
113
+ the moment npm honours published shrinkwraps again — the audit detects that
114
+ flip and says so.
115
+ - Consumer-tree tar-stream 2.x is now a **documented advisory** in the audit
116
+ (warn, not fail): the exposure is upstream (better-sqlite3's install path),
117
+ install-time only (extracting the prebuilt binding fetched over HTTPS from
118
+ better-sqlite3's GitHub releases), and unfixable from this package until
119
+ npm/cli#7977 is resolved or better-sqlite3 drops `prebuild-install`. Any
120
+ other blocked version in the consumer tree still hard-fails.
121
+ - `scripts/pre-release.sh`: better-sqlite3 native-binding sanity check
122
+ (auto-`npm rebuild` when `npm install` re-lays the subtree without running
123
+ its install script) and deterministic shrinkwrap regeneration.
124
+
7
125
  ## [1.17.7] - 2026-06-04: Socket supply-chain score restoration
8
126
 
9
127
  Patch release restoring the npm Socket supply-chain posture from 1.17.5
package/dist/index.js CHANGED
@@ -1444,9 +1444,7 @@ export function prepareGrokRequest(params, runtime = resolveGatewayServerRuntime
1444
1444
  args.push("--prompt-file", params.promptFile);
1445
1445
  }
1446
1446
  if (params.promptJson !== undefined) {
1447
- const promptJsonValue = typeof params.promptJson === "string"
1448
- ? params.promptJson
1449
- : JSON.stringify(params.promptJson);
1447
+ const promptJsonValue = typeof params.promptJson === "string" ? params.promptJson : JSON.stringify(params.promptJson);
1450
1448
  if (!promptJsonValue.trim()) {
1451
1449
  return createErrorResponse(params.operation, 1, "", corrId, new Error("promptJson: must be a non-empty JSON string or serializable value"));
1452
1450
  }
@@ -3454,10 +3452,7 @@ export function createGatewayServer(deps = {}) {
3454
3452
  .optional()
3455
3453
  .describe("Grok --verbatim: send the prompt exactly as given. Also skips gateway optimizePrompt when true."),
3456
3454
  agents: z
3457
- .union([
3458
- z.string().min(1),
3459
- z.record(z.string(), z.record(z.string(), z.unknown())),
3460
- ])
3455
+ .union([z.string().min(1), z.record(z.string(), z.record(z.string(), z.unknown()))])
3461
3456
  .optional()
3462
3457
  .describe("Grok --agents <JSON>: inline subagent definitions (JSON string or name → { description, prompt, … } map)."),
3463
3458
  promptFile: z
@@ -3478,10 +3473,16 @@ export function createGatewayServer(deps = {}) {
3478
3473
  .boolean()
3479
3474
  .optional()
3480
3475
  .describe("Grok --experimental-memory: enable cross-session memory."),
3481
- noAltScreen: z.boolean().optional().describe("Grok --no-alt-screen: run inline without alt screen."),
3476
+ noAltScreen: z
3477
+ .boolean()
3478
+ .optional()
3479
+ .describe("Grok --no-alt-screen: run inline without alt screen."),
3482
3480
  noMemory: z.boolean().optional().describe("Grok --no-memory: disable cross-session memory."),
3483
3481
  noPlan: z.boolean().optional().describe("Grok --no-plan: disable plan mode."),
3484
- noSubagents: z.boolean().optional().describe("Grok --no-subagents: disable subagent spawning."),
3482
+ noSubagents: z
3483
+ .boolean()
3484
+ .optional()
3485
+ .describe("Grok --no-subagents: disable subagent spawning."),
3485
3486
  oauth: z.boolean().optional().describe("Grok --oauth: use OAuth during authentication."),
3486
3487
  restoreCode: z
3487
3488
  .boolean()
@@ -4258,10 +4259,7 @@ export function createGatewayServer(deps = {}) {
4258
4259
  .optional()
4259
4260
  .describe("Grok --verbatim: send the prompt exactly as given. Also skips gateway optimizePrompt when true."),
4260
4261
  agents: z
4261
- .union([
4262
- z.string().min(1),
4263
- z.record(z.string(), z.record(z.string(), z.unknown())),
4264
- ])
4262
+ .union([z.string().min(1), z.record(z.string(), z.record(z.string(), z.unknown()))])
4265
4263
  .optional()
4266
4264
  .describe("Grok --agents <JSON>: inline subagent definitions (JSON string or name → { description, prompt, … } map)."),
4267
4265
  promptFile: z
@@ -4286,7 +4284,10 @@ export function createGatewayServer(deps = {}) {
4286
4284
  .boolean()
4287
4285
  .optional()
4288
4286
  .describe("Grok --no-alt-screen: run inline without alt screen."),
4289
- noMemory: z.boolean().optional().describe("Grok --no-memory: disable cross-session memory."),
4287
+ noMemory: z
4288
+ .boolean()
4289
+ .optional()
4290
+ .describe("Grok --no-memory: disable cross-session memory."),
4290
4291
  noPlan: z.boolean().optional().describe("Grok --no-plan: disable plan mode."),
4291
4292
  noSubagents: z
4292
4293
  .boolean()