# zipdiv Rust client

`zipdiv` is a real ZIP list/extract CLI with independently selected runtime
implementations for the nine spec functions in `../specs/zipdiv.toml`. It
supports stored and raw-DEFLATE entries, central and local headers, data
descriptors, CRC-32 validation, UTF-8 and CP437 filenames, archive comments,
and safe extraction. ZIP64, encryption, multi-disk archives, and compression
methods other than stored/DEFLATE are deliberately outside this release.

## Build and use

```sh
cd rust
cargo build --release
cargo test --all-targets --locked

cargo run -- list archive.zip
cargo run -- list archive.zip --json
cargo run -- extract archive.zip output/
cargo run -- verify archive.zip
```

Without configuration, the CLI uses the default safe composition. A local
composition can be supplied with `--composition composition.json` (or
`ZIPDIV_COMPOSITION`). The file can be the full shared composition schema or a
plain spec-function-to-implementation map.

To get a centrally assigned composition and report executions/failures over
HTTP, use:

```sh
cargo run -- \
  --server http://127.0.0.1:8000 \
  --release-id 1 \
  --installation-id my-pseudonymous-installation \
  list archive.zip
```

The equivalent environment variables are `ZIPDIV_SERVER`,
`ZIPDIV_RELEASE_ID`, and `ZIPDIV_INSTALLATION_ID`. The server URL is a normal
base URL and is not restricted to localhost. HTTP requests have a ten-second
timeout. Telemetry contains categorical operational labels and recent spec
calls only; archive names, entry paths, bytes, and contents are never sent.

## Register built-in implementations

```sh
cargo run -- variants --json > zipdiv-release.json
curl -X POST http://127.0.0.1:8000/api/v1/releases \
  -H 'content-type: application/json' \
  --data-binary @zipdiv-release.json
```

The JSON is directly shaped for the backend release endpoint. By default it
excludes controlled-fault variants. Add `--include-experimental` only for a
deliberate population experiment. Assigned IDs are stable, function-qualified
strings such as `validate_crc.chunked`; the backend scopes them to a release,
so a later release may reuse the same catalog IDs. The dispatcher also accepts
short local names.

## Runtime composition

Only the declared high-level functions are dispatched. Each call is recorded
as `spec_function:implementation_id` in a bounded recent-call history. Variant
implementations do not retain hidden persistent state; all cross-call state is
held explicitly by `Engine`, the composition, input/output values, or external
resources.

Every major boundary has at least five accepted built-ins (45 total), yielding
1,953,125 safe runtime compositions. `cargo test` exercises
each non-faulty variant against the same archive contract, in addition to
stored/DEFLATE, data-descriptor, CRC, CP437/UTF-8, malformed archive, long
comment, path traversal, and symlink escape regressions. `cargo clippy
--all-targets -- -D warnings` is also clean.

## Generated candidate modules

The generator writes complete module bodies to `src/generated/*.rs`. `build.rs`
discovers and includes every such file automatically, so `cargo check
--all-targets` and `cargo test` genuinely compile staged candidates. No module
registry edit is needed for the compilation gate. After a candidate passes its
contract and regression tests, making it assignable requires adding its stable
ID and dispatch arm to `src/engine.rs`; compilation alone never exposes it to
clients. See `src/generated/README.md` for the source-file shape.

## Controlled faults

Two opt-in variants reproduce narrow, safe failures: one mishandles EOCDs more
than 1 KiB from the end, and one rejects valid paths with three segments. They
are visibly marked `experimental` in runtime metadata and excluded from normal
release JSON. The experiment-only ground truth is isolated in
`experiment/faulty_variants.json`; neither the analyzer nor normal distribution
logic reads it.

Extraction rejects absolute, parent-traversing, backslash, NUL, and Windows
drive-prefixed names; checks existing ancestors for symlinks; validates local
and central metadata; limits an entry to 512 MiB and an archive to 2 GiB of
declared output; bounds decompression; validates sizes and CRC before writing;
and never intentionally writes outside the canonical destination root.
