@@ -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