pack-io 1.0.1

Compact binary wire format with schema evolution and zero-copy deserialization for Rust. The serialization substrate under network-protocol and Hive DB.
Documentation
# pack-io v0.7.0 — Hardening + API freeze

**The hardening release.** v0.7.0 ships zero new public API and zero wire-format changes — what it adds is the proof that the v0.6 surface is production-ready. Three new infrastructure pieces land together: an 8-target `cargo-fuzz` continuous harness wired into CI, a 29-test cross-platform byte-equivalence golden vector suite, and a 17-test hand-crafted hostile-input sweep. Plus the formal public-API freeze recorded as the authoritative v1.0 contract in [`docs/API.md`](https://github.com/jamesgober/pack-io/blob/main/docs/API.md#frozen-public-surface).

## API status: FROZEN

The complete public surface — every type, trait, free function, inherent method, derive macro, schema attribute, `SerialError` variant, and feature flag — is enumerated in [`docs/API.md`](https://github.com/jamesgober/pack-io/blob/main/docs/API.md#frozen-public-surface) with the version each was frozen at. **That list is the v1.0 contract.** Source-breaking changes are deferred to v2.0.

Pre-1.0 minor releases (v0.7.x → v0.9.x) ship:

- Bug fixes
- Hardening passes (more fuzz targets, more hostile-input cases)
- Performance work (against the existing surface only)
- Strictly *additive* changes (new `SerialError` variants under the existing `#[non_exhaustive]` enum; new derive macro support for new field types)

Anything not in those four categories waits for v2.0.

## What landed

### 1. cargo-fuzz harness — 8 targets, CI-integrated

New [`fuzz/`](https://github.com/jamesgober/pack-io/tree/main/fuzz) crate, workspace-excluded so stable / MSRV builds never touch it (`libfuzzer-sys` requires nightly plus AddressSanitizer instrumentation). One target per public decode entry point:

| Target                  | What it hardens                                            |
|-------------------------|------------------------------------------------------------|
| `decode_string`         | varint length + UTF-8 validation                           |
| `decode_vec_u8`         | byte-run fast path (`u8::deserialize_many`)                |
| `decode_tuple`          | mixed primitive + length-prefixed shape                    |
| `decode_collection`     | `HashMap<String, Vec<u8>>` — count cap + per-entry decode  |
| `decode_view_str`       | zero-copy `&str` decode + lifetime / UTF-8 validation      |
| `decode_struct_derive`  | derive-generated struct deserialiser                       |
| `decode_enum_derive`    | derive-generated enum deserialiser + variant-index varint  |
| `decode_versioned`      | schema-evolution body-length cap                           |

Every push to `main` runs every target for 30 seconds on Ubuntu nightly via the new CI `fuzz` job. Catches regressions fast. Longer continuous fuzzing (hours / days) happens out-of-band on dedicated infrastructure; post-1.0 the plan is ossfuzz integration.

Reproduce locally:

```bash
cd fuzz
cargo +nightly fuzz run decode_string -- -max_total_time=30
```

The contract every target asserts: decoder MUST NOT panic, MUST NOT read past the input, MUST NOT allocate above `Config::max_alloc`. Any failure is a bug filed with the offending input attached.

### 2. Cross-platform byte-equivalence — 29 golden vectors

[`tests/byte_equivalence.rs`](https://github.com/jamesgober/pack-io/blob/main/tests/byte_equivalence.rs) asserts known input → known exact bytes. Runs on every CI matrix cell — **Linux × macOS × Windows × stable × MSRV = six platform/toolchain combinations.** Passing on all six *is* the cross-platform byte-equivalence proof: if any platform produced different bytes for the same input, the assertions would fail there but not elsewhere.

Coverage:

- Every primitive integer type (u8/u16/u32/u64/u128, i8/i64) with edge values (0, 42, 128, MAX) and ZigZag corners (−1, 1, −2).
- `bool`, `f32`, `f64`, `()`, `String`, `Vec<u8>`.
- Every compound type: `Option`, `Result`, tuples, arrays.
- `BTreeMap` canonical-ordering verification with the exact byte sequence proving "beta" sorts before "alpha" / "gamma" (because the length-prefix `0x04` < `0x05`).
- `HashMap` ≡ `BTreeMap` byte equivalence over the same logical data.
- A nested-struct end-to-end round-trip with the exact expected byte concatenation laid out in the test.

Treat each `assert_eq!` as the wire-format spec asserting itself. Any byte sequence that changes is a wire-format-breaking change requiring a corresponding [`docs/WIRE_FORMAT.md`](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md) update.

### 3. Hostile-input sweep — 17 hand-crafted attack vectors

[`tests/hostile_inputs.rs`](https://github.com/jamesgober/pack-io/blob/main/tests/hostile_inputs.rs) complements the existing `proptest` random-byte coverage with targeted adversarial cases:

- **Length-prefix corners:** `varint(u64::MAX)` as the length prefix across `String`, `Vec<u8>`, `HashMap<String, u64>`, and `Vec<Vec<u8>>`. Each must surface `SerialError::InvalidLength` before allocating.
- **Tight `max_alloc` enforcement:** a configured 64-byte cap rejects a payload declaring length 1024 — well under the default 1 GiB but above the tight cap — before touching the heap.
- **Varint corners:** 11-byte overlong `u64` varint and 20-byte overlong `u128` rejected as `VarintOverflow`; tenth byte of a `u64` varint with bit 1 set rejected (only bit 0 of byte 10 is legal under LEB128).
- **Recursion bombs:** deeply-nested `Option<Option<Option<...>>>` payloads at modest depth (8 levels) decode or error without stack overflow; longer payloads than the type permits surface as `TrailingBytes`.
- **`decode_view` attack surface:** the zero-copy path enforces the same `InvalidLength` and `InvalidUtf8` checks as owning decode.
- **Truncation sweep:** every prefix length of a known-good nested-struct encoding either decodes to a valid prefix value or errors. Never a panic.
- **Trailing-garbage rejection:** both `decode` and `decode_view` reject any byte past the value they consumed.

### Plus

- README status updated from "pre-1.0, in active development" to "pre-1.0, API frozen as of v0.7.0".
- Roadmap entry for v0.7 marked shipped.

## Breaking changes

**None.** Every v0.6 source file compiles unchanged, every v0.6 wire payload decodes identically.

## Verification

All gates green on **both stable and MSRV 1.85**:

```bash
cargo fmt --all -- --check
cargo +1.85 fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo +1.85 clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo +1.85 test --all-features
cargo build --no-default-features
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
cargo audit
cargo deny check

# Fuzz crate (nightly, syntax-only on platforms without libfuzzer):
cd fuzz && cargo +nightly check

# Fuzz smoke run (Linux, requires `cargo install cargo-fuzz`):
cd fuzz && cargo +nightly fuzz run decode_string -- -max_total_time=30
```

Test counts at this tag (stable, `--all-features`): **266 total**, all passing.

| Suite                            | Count | Note                              |
|----------------------------------|------:|-----------------------------------|
| Unit tests                       |    71 | unchanged from v0.6               |
| roundtrip / determinism / adversarial proptests | 25 / 21 / 20 | unchanged from v0.6 |
| collections / streaming          | 19 / 11 | unchanged from v0.6             |
| derive / schema_evolution        | 14 / 15 | unchanged from v0.6             |
| **byte_equivalence** *(new)*     |  **29** | golden vectors on every platform |
| **hostile_inputs** *(new)*       |  **17** | hand-crafted attack vectors      |
| Doctests                         |    24 | unchanged from v0.6               |

## What's next

- **v0.8.0 → v0.9.x — Alpha → Beta → RC.** Real-consumer integration. `network-protocol`, `wire-codec`, and Hive DB pick pack-io up. Bugs they surface get fixed. No new public API; the v0.7 freeze holds. Beta enters when a stable stretch passes with no outstanding bugs; RC enters when the audit checklist is fully resolved.
- **v1.0.0 — Stable.** API + wire format frozen for the entire 1.x line. Published to crates.io; tag pushed; release note in `docs/release/v1.0.0.md`.

## Installation

```toml
[dependencies]
pack-io = { version = "0.7", features = ["schema"] }   # everything

# Or à la carte:
pack-io = { version = "0.7", features = ["derive"] }   # derive macros only
pack-io = "0.7"                                         # in-memory + streaming codec only
pack-io = { version = "0.7", default-features = false } # no_std
```

MSRV: Rust 1.85 (2024 edition).

## Documentation

- [README](https://github.com/jamesgober/pack-io/blob/main/README.md)
- **[API Reference](https://github.com/jamesgober/pack-io/blob/main/docs/API.md) — now with `Frozen public surface` section listing the v1.0 contract**
- [Wire Format Spec](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md) (v1.2 — unchanged from v0.5)
- [Performance](https://github.com/jamesgober/pack-io/blob/main/docs/PERFORMANCE.md) — unchanged from v0.6
- [CHANGELOG](https://github.com/jamesgober/pack-io/blob/main/CHANGELOG.md)

---

**Full diff:** [`v0.6.0...v0.7.0`](https://github.com/jamesgober/pack-io/compare/v0.6.0...v0.7.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/pack-io/blob/main/CHANGELOG.md#070---2026-06-04).