Nocter v0.60.0 Release Notes
Nocter v0.60.0 adds one bounded streaming path from raw DEFLATE bytes through gzip integrity and POSIX ustar entries to a practical archive-inspection application. The implementation requires no external gzip, tar, or zlib process and keeps compressed input, decoded history, entry metadata, and application output policy in separate owners.
Streaming DEFLATE
std.compress.InflateDecoder accepts fragmented input and bounded caller-owned output. It reports the exact bytes consumed and produced and distinguishes input exhaustion, output exhaustion, completion, and format invalidity. Stored, fixed-Huffman, and dynamic-Huffman blocks share one LSB-first bit reservoir, canonical table builder, symbol validator, and 32 KiB history ring.
Malformed trees, reserved block types, invalid repeats, invalid symbols, impossible distances, and missing end-of-block markers remain typed failures. Decoder terminals are sticky, and the decoder retains neither caller input nor output slices between operations.
Concatenated Gzip Members
std.compress.GzipDecoder adds bounded gzip framing over the raw decoder. It validates magic, method, reserved flags, optional fields, optional header checksum, payload CRC-32, and the modulo-2^32 uncompressed size. Explicit member boundaries preserve concatenation, while explicit end-of-input classification keeps a clean end distinct from every truncated header, payload, and trailer.
BlockingGzipReader<R> and GzipReader<R> expose the same decoder through the existing blocking and executor-safe reader contracts. Both use one transport-independent cursor. Deadlines and cancellation remain properties of the composed source rather than gzip-specific APIs.
Bounded POSIX ustar Observation
std.archive.TarReader validates 512-byte POSIX ustar headers, checksums, octal sizes, body boundaries, padding, and the two-block terminal marker. It retains one bounded metadata record and returns body ranges without allocating a complete entry.
Entry paths combine ustar prefix and name fields, require UTF-8, and normalize empty and . components. Absolute paths, parent components, empty normalized paths, malformed UTF-8, and paths beyond the retained capacity are rejected before metadata is published. File, directory, and unsupported entry kinds stay explicit so applications choose policy rather than inheriting hidden filesystem behavior.
TarStream drives either a blocking or asynchronous reader through one shared event cursor. A finished event is not published until the outer source reaches EOF, so a gzip-composed archive cannot appear successful before its trailer and integrity checks pass.
Safe Archive Inspection
The runnable archive-inspect package composes a bounded file source, BlockingGzipReader, and TarStream. It applies explicit compressed-input, complete decoded-byte, declared-body, entry-count, and path-length limits; rejects duplicate normalized paths and unsupported entries; and retains only bounded metadata. Decoded-byte accounting includes tar headers, bodies, padding, end markers, and trailing bytes drained while the outer gzip representation is validated.
The application publishes no report line until the tar end marker, complete gzip trailer, and transport EOF have all passed. A late checksum or framing failure therefore cannot expose a partially trusted report. Declared tests cover one-byte fragmentation, damaged integrity, truncation, traversal, duplicates, unsupported entries, and every resource limit.
One Authority per Decision
std/internal/deflate owns bit and Huffman representation, std/compress owns compression and gzip progress, std/checksum owns CRC-32, std/archive owns tar and archive-path interpretation, and std/io owns transport. The application owns policy only. Blocking and asynchronous paths do not repeat any format decision.
Editor qualification uses the real application and standard-library sources. Hover, completion, definition, implementation, semantic highlighting, and inlay hints consume the same checked contracts as compilation; no archive-specific editor path exists.
Compatibility and Non-goals
v0.60.0 changes no source syntax and removes no public API. Its standard-library changes are additive. Existing byte codecs, checksums, readers, paths, and filesystem contracts remain unchanged.
ZIP, encryption, cryptographic authentication, archive creation, symbolic archive schemas, host-endian APIs, device-node extraction, and compression-ratio optimization remain outside this release. CRC-32 and tar header checksums detect accidental damage; they do not authenticate an archive.
Release Qualification
Release-content commit 290960a0959769bb000f315f15271aff84463d33 passed replacement qualification after adversarial release-candidate review. The corrected source passed the complete disposable compiler gate, and deterministic documentation generation produced 332 pages. Two independent optimized builds produced byte-identical archives and recursively identical installed homes. The retained archive is 9,390,443 bytes with SHA-256 4173c2fd814de633f71161d53f998f5391d0de2226f05fc5bdb267da20217c2e and contains exactly 375 standard-library files. A fresh extraction passed version and installation diagnosis, locked/offline package workflows, native build and execution, every public example, all declared archive-inspection tests, interactive LSP analysis of installed compression and archive sources, edit recovery, immutability checks, and compiler and standard-library tamper rejection. Publication must reuse this exact retained archive without rebuilding it.