You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(changelog): condense older entries to public-facing style
Follow-up to 5.21.0 — applies the same tight, consumer-focused
format to entries 5.20.1 → 5.14.0: drop internal file paths,
bundle-size breakdowns, and implementation commentary that
belonged in PR descriptions. Prefer `@socketsecurity/lib/<path>`
over `src/<file>`.
No content is removed — every public-facing change and bugfix
from those releases still has a line. Only internal-implementation
detail was trimmed.
Older entries (5.13 and earlier) were already terse; left as-is.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+56-98Lines changed: 56 additions & 98 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,88 +52,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
52
52
53
53
### Fixed
54
54
55
-
-`src/ipc.ts`: harden stub-file writes against local symlink/TOCTOU. Previously `writeIpcStub` used `mkdir {recursive, mode: 0o700}` + `writeFile`, which on multi-user Linux (`/tmp` sticky-bit but world-writable) let a pre-positioned attacker-owned `.socket-ipc/<app>/` survive the mode argument and redirect the subsequent `writeFile` through symlinks to victim files. Now validates directory ownership + mode on POSIX after `mkdir`, then opens the stub with `O_CREAT | O_WRONLY | O_EXCL | O_NOFOLLOW`so pre-existing inodes trigger EEXIST and final-component symlinks trigger ELOOP rather than silent file overwrite
56
-
-`src/cache-with-ttl.ts``getOrFetch()` — the inflight-map check ran _after_`await get(key)`, so two concurrent cold-cache callers both suspended on the same disk read, both saw no cached value, both skipped the inflight check, and both fired `fetcher()`. Moves the inflight check before the persistent-cache lookup (with a re-check afterward) so the advertised dedupe guarantee actually holds
57
-
-`src/cache-with-ttl.ts` — cap the in-memory `memoCache`with LRU eviction (`memoMaxSize`, default 1000). Previously a long-running process (devserver, editor extension) querying many distinct keys grew memory without bound — expired entries were only reclaimed when the same key was read again
58
-
-`src/memoization.ts``memoizeAsync()` — `entry.timestamp` was set when a cache miss STARTED its `fn(...)` call, so a fn taking longer than `ttl` produced a value classified as expired the moment it resolved; every subsequent caller past the first ttl window re-fetched instead of hitting the cache. Now refreshes the timestamp in the resolve handler. Also bumps `accessOrder` on the stale-dedup branch so an entry mid-refresh isn't evicted while a peer is computing on its behalf
59
-
-`src/tables.ts` — `displayWidth`measured columns by `.length` of the ANSI-stripped string, i.e. UTF-16 code units rather than rendered terminal cells. CJK, emoji, and combined code points misaligned tables. Routes measurement through `stringWidth` (Intl.Segmenter + East Asian Width)
60
-
-`src/paths/packages.ts` — `resolvePackageJsonDirname` / `resolvePackageJsonPath`gated on `filepath.endsWith('package.json')`, which misidentified any file whose name ended in that suffix (e.g. `/foo/my-package.json`) as a manifest. Now checks for the literal final segment
61
-
-`src/json/edit.ts` — `@example`for `getEditableJsonClass` imported from `@socketsecurity/lib/json`, which is not a package export; fixed to `@socketsecurity/lib/json/edit`
55
+
-`@socketsecurity/lib/ipc` — harden stub-file writes against symlink/TOCTOU attacks on shared-tmp filesystems (POSIX ownership + mode validation, `O_EXCL | O_NOFOLLOW`open)
56
+
-`@socketsecurity/lib/cache-with-ttl``getOrFetch()` — close concurrent-caller race that let two cold-cache awaits both skip the inflight-dedupe check and fire the fetcher twice
57
+
-`@socketsecurity/lib/cache-with-ttl` — cap the in-memory memo layer with LRU eviction (`memoMaxSize`, default 1000); long-running processes no longer grow unbounded
58
+
-`@socketsecurity/lib/memoization``memoizeAsync()` — refresh cache entry timestamp on resolve so slow fetches (longer than `ttl`) aren't classified as expired the moment they land
-`@socketsecurity/lib/validation/validate-schema` — universal Zod-style schema validator with `validateSchema` (tagged result) and `parseSchema` (throwing); `Infer<S>`, `ValidateResult<T>`, `ValidationIssue`, `AnySchema` types. No runtime `zod` dependency
66
68
67
-
-`@socketsecurity/lib/validation/validate-schema` — universal validator that accepts any Zod-style schema (Zod v3/v4, or any `safeParse`-shaped duck type) and returns a tagged `{ ok: true, value } | { ok: false, errors }` result with normalized `{ path, message }` issues. Type inference flows through: callers get `z.infer<…>`, no casts. Zod is detected purely structurally via `.safeParse` — no runtime import of the `zod` package required
68
-
-`parseSchema(schema, data)` — throwing twin of `validateSchema` for fail-fast trust-boundary validation
> **Deprecated in 5.21.0**: moved to `@socketsecurity/lib/schema/*`.
70
70
71
71
### Fixed
72
72
73
-
-`src/promise-queue.ts`: wrap `task.fn()` invocation via `Promise.resolve().then()` so a **synchronous** throw inside a queued task converts to a proper rejection on `task.reject` instead of escaping as an uncaught exception
74
-
-`src/stdio/progress.ts``formatTime()`: clamp negative milliseconds so an over-ticking or clock-skewed progress bar no longer renders a negative ETA like `-1m59s`
75
-
-`src/dlx/lockfile.ts`: wrap the scratch-directory cleanup in `finally` with its own `try/catch` so a cleanup failure cannot clobber the real exception from the main try-block
76
-
-`src/dlx/package.ts``parsePackageSpec`: normalize a bare trailing `@` (e.g. `"pkg@"`) to `version: undefined` so downstream "no version provided" checks behave consistently
77
-
-`src/stdio/prompts.ts`: tighten the `selectModule` destructure type to the two properties actually used (`default`, `Separator`) instead of an `as any` cast
78
-
-`src/http-request.ts`: hoist `CHECKSUM_BSD_RE` and `CHECKSUM_GNU_RE` regex literals to module scope so `parseChecksums()` no longer re-declares them once per line inside its loop
79
-
-`src/dlx/manifest.ts`: correct the `@fileoverview` "Primary API" list to match the actual `DlxManifest` methods (`get/set/clear/clearAll/isFresh/getManifestEntry`) and flag `setPackageEntry` / `setBinaryEntry` as deprecated
73
+
-`@socketsecurity/lib/promise-queue` — synchronous throws inside a queued task now convert to proper rejections instead of escaping as uncaught exceptions
5.19.0 shipped a breaking change that was not called out in its changelog or version bump: a refactor commit removed `stdio/prompts`, `stdio/progress`, `stdio/clear`, and the vendored `external/@inquirer/*` shims. socket-cli and other consumers import `stdio/prompts` directly and broke on upgrade.
Restore `@socketsecurity/lib/stdio/prompts`, `@socketsecurity/lib/stdio/progress`, and `@socketsecurity/lib/stdio/clear` — accidentally removed in 5.19.0 without a major-bump callout. Downstream consumers that import `stdio/prompts` directly are unbroken.
-`HashSpec`, `NormalizedHash`, `ComputedHashes` types. `HashSpec` accepts a bare string (sha512 SRI or sha256 hex, sniffed) or an explicit `{ type, value }` object
100
-
-`normalizeHash()`, `computeHashes()`, `verifyHash()` — `verifyHash` uses `crypto.timingSafeEqual` for constant-time comparison
101
-
-`DlxHashMismatchError` — carries `expected` + `actual` for diagnostics
-`writeSafeNpmrc()` — defense-in-depth `.npmrc` writer matching the Arborist overrides
107
-
- Optional `before?: Date` on `safeIdealTree` for release-age enforcement during resolution
108
-
109
-
### Added — dlx/lockfile (new module)
110
-
111
-
-`generatePackagePin({ package, minReleaseDays?, minReleaseMins? })` — returns `PinDetails { name, version, hash: ComputedHashes, packageJson, lockfile }`. Runs Arborist in `packageLockOnly: true` mode against a tmp directory and auto-cleans
112
-
-**Default `minReleaseDays: 7`** — resolution refuses to select versions published in the last week. Pass `0` to disable. `minReleaseMins` is a pnpm-style alias (mutually exclusive with `minReleaseDays`)
113
-
-`LockfileSpec` type — export for use as the new `lockfile` option on `downloadPackage`
114
-
115
-
### Added — dlx existing modules
88
+
### Added
116
89
117
-
-`DlxPackageOptions.hash?: HashSpec` and `DlxPackageOptions.lockfile?: LockfileSpec` — passing a lockfile materializes it into the install dir (path → `fs.copyFileSync`, content → `fs.writeFileSync`) and drops a hardened `.npmrc` alongside before Arborist runs
118
-
-`DlxBinaryOptions.hash?: HashSpec` — ergonomic alternative to the lower-level `integrity` and `sha256` fields (both still accepted)
-`@socketsecurity/lib/dlx/arborist` — hardened `@npmcli/arborist` wrappers: `safeIdealTree()`, `safeReify()`, `writeSafeNpmrc()`. Locks down `audit`, `fund`, `ignoreScripts`, `saveBundle`, etc. Supports `before?: Date` for release-age enforcement
92
+
-`@socketsecurity/lib/dlx/lockfile` — `generatePackagePin()` returns `{ name, version, hash, packageJson, lockfile }` for a resolved package. Default `minReleaseDays: 7` refuses versions published in the last week (`0` to disable); `minReleaseMins` accepted as pnpm-style alias
93
+
-`DlxPackageOptions.hash`, `DlxPackageOptions.lockfile`, `DlxBinaryOptions.hash` — first-class integrity + lockfile options on the dlx entry points
119
94
120
-
### Fixed — external
95
+
### Fixed
121
96
122
-
-`pacote` shim now exposes `tarball`, `manifest`, `packument` alongside `extract`. **Fixes a latent runtime crash** in `src/packages/manifest.ts` callers (`fetchPackageManifest` / `fetchPackagePackument`called `.manifest(...)` / `.packument(...)` on a shim that previously only had `extract`, raising `TypeError: not a function`)
97
+
-`pacote` shim — exposes `tarball`, `manifest`, `packument` alongside `extract`. Fixes a latent runtime crash in `fetchPackageManifest` / `fetchPackagePackument`callers
123
98
124
-
### Changed — build (bundle size)
99
+
### Changed
125
100
126
-
-`dist/external/npm-pack.js`: 2,526,598 → 1,755,460 bytes (−771 KB, −30.5%). New `STUB_MAP` entries for code paths our callers never reach:
127
-
-`@sigstore/{bundle,core,protobuf-specs,sign,tuf,verify}`, `sigstore`, `tuf-js`, `@tufjs/{canonical-json,models}` — Sigstore attestation, only reached via `arb.audit()`
-`proggy` — progress tracker, gated by `progress: false`
135
-
-`debug/src/browser.js` — Node-only bundle
136
-
-`dist/external/zod.js`: 597,238 → 291,430 bytes (−306 KB, −51.2%). Stubbed `zod/v4/{core,classic,mini}`'s eager `locales/index.cjs` barrel (40+ translation modules). Opt-in via `z.config(z.locales.xx())` is never called by us
101
+
Reduced bundle size of `dist/external/npm-pack.js` (−771 KB, −30.5%) and `dist/external/zod.js` (−306 KB, −51.2%) by stubbing code paths our callers never reach (Sigstore attestation, arborist audit/query, zod locale translations, etc.)
- Socket Firewall API check before package downloads — resolves dependency tree via `buildIdealTree`, checks all packages against `firewall-api.socket.dev/purl` in parallel, blocks on critical/high severity alerts
119
+
-`@socketsecurity/lib/dlx` — Socket Firewall API check before package downloads. Resolves the dependency tree and blocks on critical/high severity alerts
156
120
157
-
### Changed — http-request
121
+
### Changed
158
122
159
-
-Default `User-Agent` header updated from `socket-registry/1.0` to `socketsecurity-lib/{version}`
123
+
-`@socketsecurity/lib/http-request` — default `User-Agent` updated from `socket-registry/1.0` to `socketsecurity-lib/{version}`
-`normalizePath()`now converts MSYS drive letters on Windows (`/c/path` → `C:/path`)
170
-
-`fromUnixPath()`now produces native Windows paths with backslashes (`/c/path` → `C:\path`), making it the true inverse of `toUnixPath()`
133
+
-`@socketsecurity/lib/paths``normalizePath()`— converts MSYS drive letters on Windows (`/c/path` → `C:/path`)
134
+
-`@socketsecurity/lib/paths``fromUnixPath()`— produces native Windows paths with backslashes (`/c/path` → `C:\path`), making it the true inverse of `toUnixPath()`
-`fromUnixPath()` — convert MSYS/Git Bash Unix-style paths (`/c/path`) back to native Windows format (`C:/path`), inverse of `toUnixPath` (#168)
140
+
-`@socketsecurity/lib/paths``fromUnixPath()` — convert MSYS/Git Bash Unix-style paths (`/c/path`) back to native Windows format (`C:/path`), inverse of `toUnixPath` (#168)
177
141
178
-
### Fixed — dlx
142
+
### Fixed
179
143
180
-
-Normalize dlx directory path in `isInSocketDlx` for Windows compatibility
144
+
-`@socketsecurity/lib/dlx``isInSocketDlx` — normalize the dlx directory path for Windows compatibility
-`stream` option on `HttpRequestOptions` — resolves with `HttpResponse` immediately after headers arrive, leaving `rawResponse` unconsumed for piping to files
187
-
-`headers`, `ok`, `status`, `statusText` fields on `HttpDownloadResult`
188
-
189
-
### Changed — http-request
148
+
### Added
190
149
191
-
-`httpDownload` now uses `httpRequest` with `stream: true` internally, eliminating ~120 lines of duplicated HTTP plumbing
150
+
-`@socketsecurity/lib/http-request` — `stream` option on `HttpRequestOptions` resolves with `HttpResponse` immediately after headers arrive, leaving `rawResponse` unconsumed for piping to files
151
+
-`@socketsecurity/lib/http-request` — `headers`, `ok`, `status`, `statusText` fields on `HttpDownloadResult`
-`HttpResponseError` class — thrown on non-2xx when `throwOnError` is enabled, carries the full `HttpResponse`
198
-
-`throwOnError` option on `HttpRequestOptions` — non-2xx responses throw instead of resolving with `ok: false`, enabling retry of HTTP errors
199
-
-`onRetry` callback on `HttpRequestOptions` — customize retry behavior per-attempt (return `false` to stop, a `number` to override delay, `undefined` for default backoff)
200
-
- Streaming body support — `body` accepts `Readable` streams (incl. `form-data` npm package), auto-merges `getHeaders()` when present
0 commit comments