Skip to content

Commit 9abd0a2

Browse files
committed
docs: capture tar-xz v6 redesign in CHANGELOGs + TODO.md
- packages/tar-xz/CHANGELOG.md: detailed v6.0.0 entry covering API redesign (universal stream API, file helpers, AsyncIterable shape) + security hardening summary (18 vectors closed) + breaking changes list + migration pointer - packages/nxz/CHANGELOG.md: v6.0.0 entry — internal rewiring to tar-xz/file, no CLI behavior change - TODO.md: completed entries for v6 redesign, security hardening, independent versioning infra, CodeQL paths-ignore, anti-flake pattern; updated Last release / Last audit / Last story footer with the npm version matrix proving cross-package independence
1 parent b2c8a8c commit 9abd0a2

3 files changed

Lines changed: 96 additions & 3 deletions

File tree

TODO.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ _None_
1818

1919
## Completed
2020

21+
- [x][tar-xz v6] Universal stream-first redesign: `create()`/`extract()`/`list()` with `AsyncIterable<Uint8Array>`, identical Node/Browser signatures, `tar-xz/file` subpath for fs helpers — published as `tar-xz@6.0.0` + `nxz-cli@6.0.0` (2026-04-27)
22+
- [x][tar-xz v6] Security hardening: 18 path/symlink TOCTOU vectors audited and closed (leaf check, ENOENT walk, hardlink linkSource, NUL/empty rejection, setuid mask, fd-based fs ops with O_NOFOLLOW, pipeline error propagation) — 8 Copilot review rounds + 1 consolidated audit (2026-04-27)
23+
- [x][Infra] Independent versioning per workspace package: `release.yml`/`publish.yml` accept `target_package` input, no cross-package version sync; proven in prod — `tar-xz@6.0.0` published without bumping `node-liblzma` (still at 5.0.0) (2026-04-27)
24+
- [x][Infra] Custom CodeQL workflow with `paths-ignore` for dep-only PRs — Dependabot fire-and-forget unblocked (CodeQL no longer NEUTRAL-blocks dep bumps) (2026-04-24)
25+
- [x][Test] Anti-flake pattern (track + afterEach destroy + timer cleanup) propagated to 4 high-risk integration tests (error_recovery, callbacks, parameter_parsing, constructor_and_sync_processing) (2026-04-26)
26+
- [x][CI] `pnpm/action-setup@v6.0.1+` validated for refresh-lockfile (upstream fix for 2-document YAML corruption); `dependabot-auto-merge.yml` with `--squash` (linear history) (2026-04-19)
27+
- [x][Release] node-liblzma v5.0.0 — Node 22 minimum, TypeScript 6, XZ 5.8.3 (2026-04-09)
2128
- [x][API] Remove deprecated `messages` array — definition, default export, index.d.ts, and 4 test refs removed (2026-03-06)
2229
- [x][Refactor] processBuffer CC reduction: 54→8 (extract), 34→6 (list) via shared tar-parser.ts (2026-03-06)
2330
- [x][CLI] nxz.ts CC reduction: 6 helpers extracted (createTarFile -49%, main -24%) (2026-03-06)
@@ -61,6 +68,14 @@ _None_
6168

6269
**Backlog vide.**
6370

64-
**Last release:** v4.0.1 + v3.2.1 (2026-03-13) — macOS ARM64 native prebuilds, type dedup, API cleanup
65-
**Last audit:** code-health full audit + cleanup (2026-03-06)
66-
**Last story:** v4.0.0 release — breaking: `messages` removed, types consolidated, macOS ARM64 prebuilds (2026-03-13)
71+
**Last release:** `tar-xz@6.0.0` + `nxz-cli@6.0.0` (2026-04-27) — stream-first universal API redesign, security hardening
72+
**Last audit:** symlink/path TOCTOU exhaustive audit (18 vectors closed in single commit) (2026-04-27)
73+
**Last story:** tar-xz v6 redesign — independent versioning proven in prod (`node-liblzma` still at 5.0.0) (2026-04-27)
74+
75+
**Independent versioning matrix (npm):**
76+
77+
| Package | Version |
78+
|---------|---------|
79+
| `node-liblzma` | 5.0.0 |
80+
| `tar-xz` | 6.0.0 |
81+
| `nxz-cli` | 6.0.0 |

packages/nxz/CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [6.0.0] - 2026-04-27
11+
12+
### BREAKING CHANGES
13+
14+
Internal rewiring to consume the new `tar-xz` v6 API. **No CLI behavior
15+
change** — flags, output, and exit codes are unchanged. The major bump
16+
is required because the `tar-xz` peer dependency moved to v6.0.0
17+
(breaking redesign).
18+
19+
### Changed
20+
- Migrated to `tar-xz/file` helpers (`createFile`, `extractFile`,
21+
`listFile`) for path-based archive operations.
22+
- Inline `TarEntry`/`TarXzModule` interfaces removed — types now
23+
imported directly from `tar-xz`.
24+
25+
### Dependencies
26+
- `tar-xz`: `^5.0.0``^6.0.0`
27+

packages/tar-xz/CHANGELOG.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [6.0.0] - 2026-04-27
11+
12+
### BREAKING CHANGES
13+
14+
Complete API redesign. Universal stream-first design — same signatures
15+
in Node and Browser, built around `AsyncIterable<Uint8Array>`.
16+
17+
### Added
18+
- **Universal API**`create()`, `extract()`, `list()` with identical
19+
signatures across Node and Browser.
20+
- **`tar-xz/file` subpath export** (Node only) — opt-in path-based
21+
helpers `createFile()`, `extractFile()`, `listFile()` for filesystem
22+
I/O. Keeps the core SRP-clean (no fs deps in the core).
23+
- **`AsyncIterable<TarEntryWithData>`** from `extract()` — entries are
24+
yielded lazily; each carries a streaming `data` AsyncIterable plus
25+
`bytes()` and `text()` collector helpers.
26+
- **`TarInput` union type** — accepts `AsyncIterable<Uint8Array>`,
27+
`Iterable<Uint8Array>`, `Uint8Array`, `ArrayBuffer`,
28+
`ReadableStream<Uint8Array>` (Web), or `NodeJS.ReadableStream`.
29+
Normalized internally to a single shape.
30+
31+
### Security
32+
Comprehensive symlink/path TOCTOU hardening (18 vectors audited and
33+
closed in a single consolidated commit, after 7 rounds of Copilot review):
34+
- Leaf symlink check (`target` itself, not just ancestors).
35+
- Ancestor symlink walk extended to FILE/DIRECTORY/SYMLINK/HARDLINK.
36+
- ENOENT correctly continues the ancestor walk instead of stopping.
37+
- Hardlink `linkSource` validated for symlink-leaf and symlink-ancestor.
38+
- `strip` option applied to both `name` and `linkname`.
39+
- Empty / NUL-bearing names and linknames rejected.
40+
- Dot-segment placeholder names (`.`, `./`, `..`) rejected.
41+
- Setuid/setgid/sticky bits stripped from extracted modes by default
42+
(mirrors GNU tar `--no-same-permissions`).
43+
- File extraction uses `fs.open(O_NOFOLLOW)` + fd-based `chmod`/`utimes`
44+
on POSIX — eliminates by-path TOCTOU window for permissions/timestamps.
45+
- `pipeline()` instead of `pipe()` so source errors propagate properly.
46+
- Threat-model documentation: concurrent attacker process is explicitly
47+
out of scope (POSIX `openat2(RESOLVE_BENEATH)` not exposed by Node).
48+
49+
### Removed
50+
- `extractToMemory()` — replaced by `extract()` + `entry.bytes()`.
51+
- `createTarXz()` / `extractTarXz()` / `listTarXz()` (browser-prefixed
52+
names) — replaced by unified `create()` / `extract()` / `list()`.
53+
- `BrowserCreateOptions` / `BrowserExtractOptions` — unified into
54+
single `CreateOptions` / `ExtractOptions`.
55+
- `ExtractedFile` — replaced by `TarEntryWithData`.
56+
57+
### Changed
58+
- Source files for `create()` use the new `TarSourceFile` shape:
59+
`{ name, source, mode?, mtime?, linkname? }`. `source` accepts
60+
`AsyncIterable<Uint8Array> | Uint8Array | ArrayBuffer | string`
61+
(string is a Node-only fs path).
62+
- `TarPack` / `TarUnpack` Transform classes are now internal; not
63+
exported from the package root. Use the high-level API.
64+
- Default compression preset is uniform: `6` (Node and Browser).
65+
66+
### Migration v5 → v6
67+
See [README.md § Migration v5 → v6](./README.md#migration-v5--v6) for
68+
full code examples.
69+
1070
## [5.0.1] - 2026-04-27
1171

1272
### Fixed

0 commit comments

Comments
 (0)