diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..729481c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog + +All notable ZstdScope project releases are documented here. + +The reusable `zstdscope` library and the `zstdscope-cli` package use independent versions from the v0.3 project release onward. Each entry states the affected package versions explicitly. + +## [v0.3.0] - 2026-08-27 + +### Package versions + +- `zstdscope`: remains at `0.2.0`; no parser or public Rust API release is required. +- `zstdscope-cli`: `0.3.0`; first crates.io release of the CLI package. + +### Breaking changes + +- `zstdscope inspect --json` now emits an explicit schema-version-1 DTO instead of serializing the public Rust model directly. +- The top-level document includes `"schema_version": 1`. +- Values originating from Rust `u64` fields are decimal strings rather than JSON numbers. This includes input size, byte offsets and lengths, derived window size, and Frame Content Size values. +- Existing JSON consumers must parse those decimal strings explicitly, for example with `BigInt` in JavaScript when exact arithmetic is required. + +### Added + +- Dedicated private CLI JSON DTOs, decoupled from future Rust model refactors. +- Explicit CLI JSON compatibility and breaking-change policy. +- crates.io packaging metadata for `zstdscope-cli`; the package installs the `zstdscope` binary. +- Package-boundary publish dry-run, install, `--version`, text-output, and JSON smoke tests. +- Immutable GitHub Actions revisions, least-privilege permissions, superseded-PR cancellation, and job timeouts. +- `cargo-deny` advisory, license, dependency-ban, and source checks. +- Weekly Dependabot updates for Cargo and GitHub Actions. +- `wasm32-unknown-unknown` compile-only coverage for the dependency-light core crate. + +### Unchanged + +- Zstandard parsing and validation behavior. +- Public Rust API of the `zstdscope` library. +- Human-readable CLI output. +- Bounds checking, resource-limit semantics, and malformed-input handling. + +## [v0.2.0] - 2026-08-27 + +- Added configurable frame and block metadata limits through `inspect_with_limits()`. +- Added manual `cargo-fuzz` coverage and successful-parse model-invariant checks. +- Added a default 256 MiB CLI encoded-input guard with `--max-input-bytes` override. +- Defined and verified Rust 1.85.0 as the workspace MSRV. + +## [v0.1.0] - 2026-08-18 + +- Released the initial Pure Rust structural Zstandard inspector library and CLI. +- Added Standard and Skippable Frame parsing, frame-header and block metadata, source spans, typed errors, human-readable output, and the original pre-versioned JSON output. + +[v0.3.0]: https://github.com/tappe9/zstdscope/compare/v0.2.0...v0.3.0 +[v0.2.0]: https://github.com/tappe9/zstdscope/compare/v0.1.0...v0.2.0 +[v0.1.0]: https://github.com/tappe9/zstdscope/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock index 36825e7..d2e95ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,7 +248,7 @@ dependencies = [ [[package]] name = "zstdscope-cli" -version = "0.2.0" +version = "0.3.0" dependencies = [ "clap", "serde", diff --git a/Cargo.toml b/Cargo.toml index 053cdea..baeab33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,6 @@ exclude = ["fuzz"] resolver = "3" [workspace.package] -version = "0.2.0" edition = "2024" rust-version = "1.85.0" license = "MIT OR Apache-2.0" diff --git a/README.ja.md b/README.ja.md index 79a13b8..3760a2e 100644 --- a/README.ja.md +++ b/README.ja.md @@ -9,9 +9,9 @@ ZstdScopeは、Zstandard圧縮データ形式の構造を解析する **Pure Rus 主目的は圧縮・展開ではなく、`.zst`などのZstandard streamに含まれるFrame、Header、Block、offset、sizeなどのencoded structureを、安全かつ再利用可能なRust APIとCLIから取得することです。Compressed Blockのpayload内部はopaqueとして扱います。 -> **`zstdscope` library v0.2.0を[crates.io](https://crates.io/crates/zstdscope)で公開しています。** pre-1.0のため、Rust Public APIとversioned CLI JSON contractは、明示的な方針に基づいて変更される可能性があります。 +> **`zstdscope` libraryはv0.2.0を公開済みです。v0.3.0 project releaseでは、`zstdscope-cli` v0.3.0を初めてcrates.ioへ公開します。** Rust APIとCLI/JSONのcompatibility contractは別々に進化するため、package versionを独立して管理します。 -**リンク:** [crates.io](https://crates.io/crates/zstdscope) · [docs.rs](https://docs.rs/zstdscope) · [v0.2.0 Release](https://github.com/tappe9/zstdscope/releases/tag/v0.2.0) +**リンク:** [library crates.io](https://crates.io/crates/zstdscope) · [CLI crates.io](https://crates.io/crates/zstdscope-cli) · [docs.rs](https://docs.rs/zstdscope) · [Changelog](CHANGELOG.md) · [Releases](https://github.com/tappe9/zstdscope/releases) ## インストール @@ -38,13 +38,13 @@ cargo add zstdscope --features serde ### CLI -CLI package名は`zstdscope-cli`、installされるbinary名は`zstdscope`です。公開済みCLI releaseはcrates.ioからinstallします。 +CLI package名は`zstdscope-cli`、installされるbinary名は`zstdscope`です。 ```bash -cargo install zstdscope-cli --locked +cargo install zstdscope-cli --version 0.3.0 --locked ``` -CLI crateの初回release公開前に現在の`main`を利用する場合は、repositoryを手動cloneせず次のコマンドでinstallできます。 +crates.io releaseではなく現在のrepository revisionをinstallする場合: ```bash cargo install --git https://github.com/tappe9/zstdscope zstdscope-cli --locked @@ -54,6 +54,8 @@ cargo install --git https://github.com/tappe9/zstdscope zstdscope-cli --locked Source buildはGitHub-hosted runner上のUbuntu x86_64、Windows x86_64、macOS arm64で継続検証します。その他のRust対応targetはbest effortです。これはsource buildのsupport範囲であり、prebuilt binary提供を保証するものではありません。 +LibraryとCLIは独立したpackage versionを使用します。v0.3 project releaseではparserとPublic Rust APIに変更がないため、`zstdscope-cli 0.3.0`は公開済みの`zstdscope 0.2.0` APIへ依存します。 + ## 解析する範囲 現在のstructural scopeでは以下を扱います。 @@ -202,7 +204,7 @@ CLIはPublic Rust modelを直接serializeせず、専用JSON DTOを利用しま I/O error、parse error、input size limit超過は非0で終了し、diagnosticをstderrへ出力します。Partial-success JSONは出力しません。Output write failureでpanicせず、downstream processが通常どおりpipeを閉じた場合は正常終了として扱います。 -詳細は[ADR 0005](docs/adr/0005-versioned-cli-json.md)と[ADR 0006](docs/adr/0006-cli-distribution.md)を参照してください。 +詳細は[ADR 0005](docs/adr/0005-versioned-cli-json.md)、[ADR 0006](docs/adr/0006-cli-distribution.md)、[ADR 0007](docs/adr/0007-independent-package-versioning.md)を参照してください。 ## 構成 @@ -223,6 +225,8 @@ Public API方針は[Public API設計](docs/API-DESIGN.md)で管理していま - [アーキテクチャ](ARCHITECTURE.md) - [Zstandardフォーマットメモ](docs/ZSTD-FORMAT.md) - [Public API設計](docs/API-DESIGN.md) +- [Changelog](CHANGELOG.md) +- [Release手順](docs/RELEASING.md) - [Supply-chain policy](docs/SUPPLY-CHAIN.md) - [Fuzzing guide](FUZZING.md) - [Roadmap](ROADMAP.md) diff --git a/README.md b/README.md index 2b1060f..2fbf9e8 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ ZstdScope is a pure-Rust parser and structural inspection toolkit for the Zstand The project is intentionally focused on **inspection**, not compression or decompression. It exposes encoded structure and source-byte metadata through a reusable Rust API and a CLI, while leaving compressed block payloads opaque. -> **v0.2.0 of the `zstdscope` library is available on [crates.io](https://crates.io/crates/zstdscope).** ZstdScope remains pre-1.0, so the Rust API and versioned CLI JSON contract may still evolve intentionally. +> **The `zstdscope` library is published as v0.2.0. The v0.3.0 project release publishes `zstdscope-cli` v0.3.0 for the first time.** The packages use independent versions because the Rust API and CLI/JSON compatibility contracts evolve separately. -**Links:** [crates.io](https://crates.io/crates/zstdscope) · [docs.rs](https://docs.rs/zstdscope) · [v0.2.0 release](https://github.com/tappe9/zstdscope/releases/tag/v0.2.0) +**Links:** [library on crates.io](https://crates.io/crates/zstdscope) · [CLI on crates.io](https://crates.io/crates/zstdscope-cli) · [docs.rs](https://docs.rs/zstdscope) · [changelog](CHANGELOG.md) · [releases](https://github.com/tappe9/zstdscope/releases) ## Installation @@ -38,13 +38,13 @@ cargo add zstdscope --features serde ### CLI -The supported CLI package is named `zstdscope-cli`; it installs the `zstdscope` binary. Released CLI versions use crates.io: +The CLI package is named `zstdscope-cli`; it installs the `zstdscope` binary: ```bash -cargo install zstdscope-cli --locked +cargo install zstdscope-cli --version 0.3.0 --locked ``` -Until the first CLI crate release is published, install the current `main` revision without manually cloning the repository: +To install the current repository revision instead of a crates.io release: ```bash cargo install --git https://github.com/tappe9/zstdscope zstdscope-cli --locked @@ -54,6 +54,8 @@ The crates.io package is the selected release distribution channel. Prebuilt Git Source builds are continuously tested on GitHub-hosted Ubuntu x86_64, Windows x86_64, and macOS arm64 runners. Other Rust-supported targets are best effort. This is a source-build support statement, not a promise of prebuilt binaries for those targets. +The library and CLI use independent package versions. `zstdscope-cli 0.3.0` depends on the published `zstdscope 0.2.0` API because the parser and public Rust API did not change in the v0.3 project release. + ## What ZstdScope inspects The current structural scope includes: @@ -201,7 +203,7 @@ Before 1.0, backward-compatible additive fields may remain within schema version I/O and parse failures return a non-zero exit status, write diagnostics to stderr, and do not emit partial-success JSON. An input that exceeds the CLI byte limit also returns a non-zero exit status with a structured CLI error. Output write failures are handled without panicking; a downstream process closing a pipe normally is treated as normal CLI termination. -See [ADR 0005](docs/adr/0005-versioned-cli-json.md) for the JSON decision and [ADR 0006](docs/adr/0006-cli-distribution.md) for distribution policy. +See [ADR 0005](docs/adr/0005-versioned-cli-json.md) for the JSON decision, [ADR 0006](docs/adr/0006-cli-distribution.md) for distribution policy, and [ADR 0007](docs/adr/0007-independent-package-versioning.md) for package versioning. ## Workspace @@ -244,6 +246,8 @@ ZstdScope is not intended to be: - [Architecture](ARCHITECTURE.md) - [Zstandard format notes](docs/ZSTD-FORMAT.md) - [Public API design](docs/API-DESIGN.md) +- [Changelog](CHANGELOG.md) +- [Release process](docs/RELEASING.md) - [Supply-chain policy](docs/SUPPLY-CHAIN.md) - [Fuzzing guide](FUZZING.md) - [Roadmap](ROADMAP.md) diff --git a/ROADMAP.md b/ROADMAP.md index b69e07e..be98b34 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,6 +2,8 @@ This roadmap is directional. Milestones may change as implementation and specification review uncover better boundaries. +The reusable `zstdscope` library and the `zstdscope-cli` package use independent versions from the v0.3 project release onward. Repository release notes identify the exact package versions included in each milestone. + ## v0.1 — Structural inspector MVP Status: **completed and released as v0.1.0.** @@ -52,11 +54,16 @@ Released scope: - a manual `cargo-fuzz` target with structural model-invariant checks on successful parses; - bounded CLI file reads with a default 256 MiB encoded-input guard and explicit `--max-input-bytes` override. -## Post-v0.2 maintenance — Contract and distribution hardening +## v0.3 — Versioned CLI contract, distribution, and supply-chain hardening + +Status: **implementation complete and prepared for release.** + +Package versions: -Status: **completed on `main`; release publication is a separate release operation.** +- `zstdscope` remains at `0.2.0`; the parser and public Rust API are unchanged; +- `zstdscope-cli` advances to `0.3.0` for its first crates.io release and the intentional CLI JSON compatibility change. -Completed scope: +Release scope: - dedicated CLI JSON schema-version-1 DTOs, decoupled from the public Rust model; - decimal-string representation for JSON values originating from Rust `u64` fields; @@ -66,7 +73,9 @@ Completed scope: - immutable GitHub Actions pins, least-privilege permissions, concurrency controls, and job timeouts; - documented `cargo-deny` advisory/license/source policy; - weekly Cargo and GitHub Actions Dependabot updates; -- `wasm32-unknown-unknown` compile-only coverage for the dependency-light core boundary. +- `wasm32-unknown-unknown` compile-only coverage for the dependency-light core boundary; +- independent library and CLI package versioning, documented by ADR 0007; +- a repeatable manual release procedure and project changelog. Deferred candidate scope for later releases: @@ -77,7 +86,7 @@ Deferred candidate scope for later releases: - prebuilt, checksummed, and signed GitHub Release binaries; - CLI output refinements. -## v0.3 — Compressed-block structural metadata +## v0.4 — Compressed-block structural metadata Candidate scope: @@ -88,7 +97,7 @@ Candidate scope: This milestone should not be started until the frame/block model proves extensible enough to represent nested structures cleanly. -## v0.4 — Entropy metadata inspection +## v0.5 — Entropy metadata inspection Candidate scope: @@ -96,7 +105,7 @@ Candidate scope: - FSE table metadata; - visualization-oriented models for entropy structures. -## v0.5 — WebAssembly and browser inspector +## v0.6 — WebAssembly and browser inspector Candidate scope: @@ -109,7 +118,7 @@ Candidate scope: The Web UI should remain a consumer of the same `zstdscope` core rather than a separate parser. -## v0.6 — Analysis and benchmark tooling +## v0.7 — Analysis and benchmark tooling Candidate scope: diff --git a/crates/zstdscope-cli/Cargo.toml b/crates/zstdscope-cli/Cargo.toml index a2b4424..fb1bd61 100644 --- a/crates/zstdscope-cli/Cargo.toml +++ b/crates/zstdscope-cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zstdscope-cli" -version.workspace = true +version = "0.3.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/crates/zstdscope/Cargo.toml b/crates/zstdscope/Cargo.toml index a040c61..ef42111 100644 --- a/crates/zstdscope/Cargo.toml +++ b/crates/zstdscope/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zstdscope" -version.workspace = true +version = "0.2.0" edition.workspace = true rust-version.workspace = true license.workspace = true diff --git a/docs/RELEASING.md b/docs/RELEASING.md new file mode 100644 index 0000000..79d9f14 --- /dev/null +++ b/docs/RELEASING.md @@ -0,0 +1,122 @@ +# Releasing ZstdScope + +This document defines the manual release procedure. Pull-request CI never receives crates.io credentials. + +## Package versioning + +The library and CLI use independent versions: + +- `zstdscope` versions the public Rust parser API and inspection model; +- `zstdscope-cli` versions command-line behavior and the CLI JSON wire contract. + +For project release `v0.3.0`, publish only `zstdscope-cli 0.3.0`. The library remains `zstdscope 0.2.0` because its parser implementation and public Rust API are unchanged. + +## Preconditions + +1. Start from the latest `main` and confirm the worktree is clean. +2. Confirm the release-preparation PR is merged and `main` CI is green. +3. Confirm `CHANGELOG.md`, README files, package manifests, and `Cargo.lock` describe the intended package versions. +4. Confirm the target package version does not already exist on crates.io. +5. Authenticate locally with a least-privilege crates.io token using Cargo's supported credential mechanism. + +Do not reuse or overwrite a published crate version or an existing Git tag. + +## Required quality gates + +Run from the repository root: + +```bash +cargo fmt --check +cargo clippy --workspace --all-targets --all-features --locked -- -D warnings +cargo test --workspace --all-features --locked +RUSTDOCFLAGS="-D warnings" cargo doc -p zstdscope --all-features --no-deps --locked +cargo test -p zstdscope --no-default-features --locked +rustup target add wasm32-unknown-unknown +cargo check -p zstdscope --target wasm32-unknown-unknown --no-default-features --locked +cargo package -p zstdscope --list --locked +cargo publish -p zstdscope --dry-run --locked +cargo package -p zstdscope-cli --list --locked +cargo publish -p zstdscope-cli --dry-run --locked +``` + +The core dry-run remains a regression gate even when the release publishes only the CLI. + +## Verify the generated CLI package + +```bash +rm -rf target/package /tmp/zstdscope-install +cargo package -p zstdscope-cli --locked +package_dir="$(find target/package -maxdepth 1 -type d -name 'zstdscope-cli-*' -print -quit)" +test -n "$package_dir" +cargo install --path "$package_dir" --locked --root /tmp/zstdscope-install + +/tmp/zstdscope-install/bin/zstdscope --version +printf '\x28\xb5\x2f\xfd\x00\x00\x01\x00\x00' > /tmp/minimal.zst +/tmp/zstdscope-install/bin/zstdscope inspect /tmp/minimal.zst +/tmp/zstdscope-install/bin/zstdscope inspect /tmp/minimal.zst --json +``` + +For `v0.3.0`, the version command must print: + +```text +zstdscope 0.3.0 +``` + +The JSON output must contain: + +```json +{ + "schema_version": 1 +} +``` + +## Publish `zstdscope-cli 0.3.0` + +Reconfirm the exact package contents and then publish: + +```bash +cargo publish -p zstdscope-cli --dry-run --locked +cargo publish -p zstdscope-cli --locked +``` + +Wait for crates.io index propagation, then verify the registry entry: + +```bash +cargo info zstdscope-cli@0.3.0 +``` + +Install from crates.io into a clean root and repeat the smoke checks: + +```bash +rm -rf /tmp/zstdscope-crates-io-install +cargo install zstdscope-cli --version 0.3.0 --locked --root /tmp/zstdscope-crates-io-install +/tmp/zstdscope-crates-io-install/bin/zstdscope --version +/tmp/zstdscope-crates-io-install/bin/zstdscope inspect /tmp/minimal.zst +/tmp/zstdscope-crates-io-install/bin/zstdscope inspect /tmp/minimal.zst --json +``` + +## Tag and create the GitHub Release + +Tag the exact verified `main` commit; do not create a release from an unmerged branch commit. + +```bash +git switch main +git pull --ff-only origin main +git status --short +git tag -a v0.3.0 -m "ZstdScope v0.3.0" +git push origin v0.3.0 +``` + +Create a non-prerelease GitHub Release named `ZstdScope v0.3.0`. Use the `v0.3.0` section of `CHANGELOG.md` as the release notes and explicitly state: + +- `zstdscope-cli 0.3.0` is published on crates.io; +- `zstdscope` remains at `0.2.0` because its Rust API and parser behavior are unchanged; +- CLI JSON schema version 1 is a breaking change from the source-built v0.2 CLI output. + +After creating the release, verify that the tag targets the expected `main` commit and that the repository's latest-release page resolves to `v0.3.0`. + +## Failure handling + +- If validation fails before publication, fix the repository and repeat all affected gates. +- If crates.io publication fails before acceptance, correct the local cause and retry the same version only when crates.io confirms it was not published. +- If a published crate is critically broken, do not overwrite it. Consider yanking it, prepare a new patch version, document the reason, and preserve the original tag and release history. diff --git a/docs/adr/0007-independent-package-versioning.md b/docs/adr/0007-independent-package-versioning.md new file mode 100644 index 0000000..d223319 --- /dev/null +++ b/docs/adr/0007-independent-package-versioning.md @@ -0,0 +1,69 @@ +# ADR 0007: Version library and CLI packages independently + +- Status: Accepted +- Date: 2026-08-27 + +## Context + +The workspace originally inherited one package version for both `zstdscope` and `zstdscope-cli`. That was convenient while the CLI was not published, but the two packages now have different compatibility contracts and can change independently: + +- `zstdscope` exposes the reusable Rust parsing API and inspection model; +- `zstdscope-cli` exposes command-line behavior and the versioned CLI JSON wire contract. + +The post-v0.2 work changes the CLI JSON contract and makes the CLI publishable, but it does not change the parser, validation behavior, or public Rust API in the library crate. Publishing an unchanged `zstdscope` version solely to keep package numbers aligned would create an unnecessary library release. + +A unified workspace version also complicates pre-publication validation. A CLI package pinned to an unreleased new library version cannot complete package-boundary installation and `cargo publish --dry-run` verification until that library version already exists on crates.io. + +## Decision + +### Independent package versions + +`zstdscope` and `zstdscope-cli` use explicit, independent package versions. + +For the v0.3 project release: + +- `zstdscope` remains at `0.2.0` because its Rust API and parser implementation are unchanged; +- `zstdscope-cli` is released as `0.3.0` because its machine-readable JSON contract intentionally changes and it becomes available through crates.io for the first time. + +The CLI continues to depend on the released `zstdscope = 0.2.0` API that it actually requires. + +### Release tags and notes + +Repository-level Git tags and GitHub Releases describe the project release milestone. Release notes must state the exact crate versions included or intentionally unchanged whenever package versions differ. + +A later change may update one package or both. Versions should be aligned only when the compatibility impact and released content justify alignment; numerical alignment is not itself a release requirement. + +### Compatibility signaling + +Each package follows its own pre-1.0 compatibility boundary: + +- Rust API compatibility is communicated by the `zstdscope` crate version; +- CLI behavior and JSON wire compatibility are communicated by the `zstdscope-cli` package and `zstdscope --version`; +- JSON breaking changes additionally require a new `schema_version` as defined by ADR 0005. + +## Consequences + +### Positive + +- Published versions correspond to actual changes in each package. +- The unchanged library does not receive a meaningless release. +- CLI packaging, installation, and publish dry-runs can be validated before publication using an already released library dependency. +- Future library-only and CLI-only releases remain straightforward. + +### Trade-offs + +- A repository release may contain different library and CLI version numbers. +- Documentation and release notes must name package versions explicitly. +- Workspace manifests no longer inherit one shared version field. + +## Verification + +Release preparation must verify: + +```bash +cargo metadata --format-version 1 --locked +cargo package -p zstdscope-cli --list --locked +cargo publish -p zstdscope-cli --dry-run --locked +``` + +The generated CLI package must install successfully and report the expected CLI package version through `zstdscope --version`.