diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e74288c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,119 @@ +# Changelog + +All notable changes to this crate are documented here. The format is +based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and +this crate adheres to [Semantic Versioning](https://semver.org/). + +## [0.2.0] - 2026-08-17 + +A breaking release that replaces the v0.1.0 `AlkType:*` custom-keyword +JSON Schema format with BAST (Binary Abstract Syntax Tree) — a JSON +document that describes binary layouts using a `kind`-based vocabulary +with `$defs`/`$ref` for composition. BAST is itself a valid JSON Schema +instance (it has a meta-schema), making it self-validating, +editor-friendly, and trivially consumable from any language with a JSON +parser. The engine works the same way as before: compile a document +once into an `AlkTypeEngine`, then read/write fields at computed offsets +and validate bytes/JSON. The pivot was made now because v0.1.0 has no +real consumers (≈15 crates.io downloads, mostly bots/scanners), so the +custom-keyword wart could be removed cleanly. + +### Breaking changes + +- **Schema format.** The v0.1.0 `AlkType:*` custom-keyword JSON Schema + format (`{ "AlkType:Struct": true, "fields": [...] }`) is removed. + Schemas are now BAST documents: + `{ "$defs": { "": { "kind": "struct", "fields": [...] } } }`. + The `kind`-based vocabulary covers 18 binary kinds (integers, floats, + bytes, string, struct, union, enum, array, etc.). +- **`AlkTypeEngine::compile` signature.** Now takes + `(bast_doc: &Value, root_name: &str, mode: LayoutMode, json_schema: Option<&Value>)`. + The root type name is a required parameter — it selects which `$defs` + entry is the top-level type (previously the root was implicit from the + single top-level schema object). +- **Builder API output.** `Definitions`/`Schema`/`Discriminator` now + produce BAST JSON via `Definitions::build_doc(name, schema)`. The + builder method names are unchanged; only the emitted JSON shape + changed. `Schema::struct_()` produces a BAST struct; + `Schema::object()` produces a standard JSON Schema (for the + `validate_json` path). +- **Validation split.** v0.1.0 used a single `jsonschema` validator + with 19 custom `AlkType:*` keywords for both bytes and JSON + validation. 0.2.0 splits this into two independent paths: + - `validate_bytes` uses a new BAST-native validator + (`bast_validation`) — a recursive walker over the BAST type tree. + - `validate_json` / `is_valid_json` use a standard + `jsonschema::Validator` built from a consumer-provided JSON Schema + (passed to `compile` as the `json_schema` parameter). No custom + keywords; BAST is not involved — BAST describes bytes, not JSON + shape. + Both paths return `AlkTypeError::Validation` with a uniform + `jsonschema::ValidationError<'static>` payload. +- **Removed.** The v0.1.0 custom-keyword accessor layer + (`AlkTypeKind::FromStr`, `parse_*`, `resolve_ref*`, + `DiscriminatorKind`) is removed. The BAST parser (`bast` module) + exposes a cleaner typed surface (`BastDoc`/`BastDef`/`BastStruct`/ + `BastField`/`BastType`/etc.) that borrows from the source + `serde_json::Value` without cloning field data. +- **Public module surface.** New public modules: `bast`, `bast_meta`, + `bast_validation`, `builder`, `materialize`. The `schema` module is + retained but now holds only `Endian`/`AlkTypeKind`/`VariableEncoding` + (the binary-kind vocabulary); the v0.1.0 custom-keyword machinery is + gone. + +### Additions + +- **BAST meta-schema.** Embedded in the crate as + `BAST_META_SCHEMA` (re-exported from the crate root) and published at + `https://alk.dev/bast/v1/schema`. BAST documents are validated against + it at compile time (`AlkTypeEngine::compile` calls + `validate_bast_doc` before parsing). +- **`materialize` module.** Materializes a `serde_json::Value` tree from + a binary buffer by walking the BAST typed tree. Used by + `AlkTypeEngine::validate_bytes` (ADR-010). +- **Builder for JSON Schemas.** `Schema::object()` produces a standard + JSON Schema object (for the `validate_json` path), complementing + `Schema::struct_()` which produces a BAST struct (for the bytes path). + One builder, two output shapes — the method name selects which. + +### Bug fixes vs v0.1.0 + +- **Enum index bounds are now checked.** The v0.1.0 validator had a + dead constraint: enum variant indices were never bounds-checked + against `values.len()`. The BAST-native validator enforces it + (`validate_enum` checks `idx < values.len()`). +- **Offset-indirect, field-level endian, and aligned materialization** + bugs found during review #003 are fixed. + +### Non-breaking improvements + +- `$ref` is restricted to `#/$defs/` — one hash lookup, no + `normalize_refs` pass (the v0.1.0 engine needed one). +- Schemas remain untrusted input: every engine path that walks a BAST + document returns `Err` on a malformed document, never `panic!`/ + `unreachable!`. Overflow-safe arithmetic (`checked_add`, + `usize::try_from`) on all offset/count casts. +- Still two dependencies (`jsonschema` with `default-features = false`, + `serde_json` with `preserve_order`), no `async`, no `unsafe`, no + platform deps, no feature flags. Compiles to + `wasm32-unknown-unknown`. + +### Upgrade notes + +There is no migration path from v0.1.0 `AlkType:*` schemas — the format +is incompatible. Rewrite schemas as BAST documents (the `builder` API +produces them; see the README usage example) and update `compile` calls +to pass the root type name and the optional JSON Schema. The +read/write/validate API surface (`read_field`, `write_field`, +`sequential_reader`, `validate_bytes`, `validate_json`, +`is_valid_json`) is unchanged. + +## [0.1.0] - 2025-11-10 + +Initial crates.io release. Custom-keyword JSON Schema format +(`AlkType:*`), single `jsonschema` validator for both bytes and JSON, +`AlkTypeEngine` with packed/aligned layout modes, builder API producing +`serde_json::Value`. + +[0.2.0]: https://git.alk.dev/alkdev/alktype/releases/tag/v0.2.0 +[0.1.0]: https://git.alk.dev/alkdev/alktype/releases/tag/v0.1.0 \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 69f3a1c..85d78be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "alktype" -version = "0.1.0" +version = "0.2.0" dependencies = [ "jsonschema", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index dfdfb8f..d794a25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alktype" -version = "0.1.0" +version = "0.2.0" edition = "2021" rust-version = "1.85" license = "MIT OR Apache-2.0" @@ -9,7 +9,7 @@ repository = "https://git.alk.dev/alkdev/alktype" readme = "README.md" keywords = ["binary", "jsonschema", "wire-format", "serialization", "layout"] categories = ["encoding", "data-structures", "parsing"] -exclude = [".opencode/", "docs/reviews/", "docs/research/", "docs/sdd_process.md", "Cargo.lock"] +exclude = [".opencode/", "docs/reviews/", "docs/research/", "docs/sdd_process.md", "Cargo.lock", "AGENTS.md"] [lib] name = "alktype"