kaiv 0.6.0

Reference implementation of the kaiv format (Levels 0-3): lexer, compiler, denormalizer, schema compiler, validator
Documentation

kaiv-rs

Reference implementation of the kaiv format (Levels 0–3) in Rust. A cargo workspace with two crates:

  • kaiv — the library. The certifiable reference pipeline; the Levels 0–2 core is zero-dependency, Level 3 collation rides ICU4X behind the default-on collation-icu feature (with a lightweight collation-colligo alternative).
  • kaiv-cli — the kaiv command-line binary, a thin shell over the library. Kept out of the library crate so its (future) dependencies never reach library consumers.

kaiv is an immutable structural type system for data at rest; the specification and design documents live in the sibling spec repository. The library implements the build pipeline:

.kaiv --[Compiler]--> .raiv --[Denormalizer]--> .daiv
.saiv --[schema compiler]--> .csaiv
.daiv + .csaiv --[Validator]--> pass / fail

CLI

kaiv compile  <file.kaiv>       authored -> relational canonical (.raiv)
kaiv denorm   <file.raiv>       relational -> denormalized (.daiv)
kaiv build    <file.kaiv>       authored -> .daiv (compile + denorm)
kaiv schema   <file.saiv>       authored schema -> compiled (.csaiv)
kaiv validate <data> <schema>   .daiv/.kaiv against .csaiv/.saiv -> pass/error
kaiv unit     <expr>            canonicalize a unit expression
kaiv infer    [--name ID] [f]   infer an authored .saiv from an example
                                document (kaiv or any import format); the
                                example validates against the result
kaiv import-schema [--name] [f] foreign schema -> authored .saiv, as a sound
                                weakening: inexpressible constraints are
                                dropped with // comments, never invented.
                                Formats: JSON Schema, .proto, Avro Schema
                                (.avsc), GraphQL SDL, XSD — from the flag
                                (--json --proto --avro --graphql --xsd) or
                                the extension; --message picks the root
                                message/type/element when several exist
kaiv import   [--FMT] [file]    foreign format -> authored .kaiv: structures
                                import natively (inline ;= := +:= forms where
                                homogeneous and short); only empty containers,
                                anonymous nested arrays, non-flat strings,
                                XML mixed content, and binary byte strings
                                embed as std/enc types. Formats: JSON, YAML,
                                TOML, XML, CBOR, Avro, Protocol Buffers
                                (--proto needs --schema <file.proto>, plus
                                --message <Name> for multi-message schemas),
                                and ASN.1 BER/DER (--asn1; PEM auto-strips);
                                inferred from the extension (.json .yaml .yml
                                .toml .xml .cbor .avro .pb .binpb .der .pem
                                .crt .cer), the option required for stdin;
                                --flat embeds all containers (json only)
kaiv export   --FMT [file]      kaiv -> any of the same formats (.kaiv built
                                first; .daiv as is; the binary formats write
                                raw bytes; --proto needs --schema/--message
                                like import)

The nearest kaiv.kaiv up from the working directory configures registry resolution (SPEC.md § Layer 2) — the toolchain's own configuration is a kaiv document — with KAIV_REGISTRY_* environment variables overriding. Exit 0 on success/pass, 1 otherwise; output on stdout, diagnostics on stderr.

Library modules

Module Role
lexer Six-rule line classifier + document checks (SPEC.md § Parsing Requirements). Eager model: whole text validated before any token is emitted.
anno Constraint grammar, both surface forms (annotation position and constraint-line position), including the alternative-delimiter pattern form re{sep}…{sep} (lowered to canonical /…/).
rex Backtracking matcher for the pinned finite-state regex dialect.
unit Compound-unit canonicalization (base-name-sorted factors) and built-in-set membership.
taiv / faiv Type-library (.taiv) and unit-definition (.faiv) parsing; std/core and std/enc ship embedded as real .taiv files.
config / resolve / net kaiv.kaiv Layer 2 configuration (the format bootstrap) and Layer 1–4 registry resolution: filesystem bases, and — behind the default-on net feature — http(s) fetching with redirect aliasing, Layer 4 default hosts, and an immutable on-disk cache.
compiler .kaiv.raiv: variables, sugar (+=, ;=, :=, +:=, blocks, maps), &name resolution via .!types, unit membership via .!units.
denorm .raiv.daiv: $field reference resolution, nothing else.
schema .saiv.csaiv: transitive named-type lowering, constrained-union groups, map entry lines, ;= vector declarations and [/@name …] element blocks with Level 2 table headers (unique/ref/min/max collection constraint lines), .!schema inheritance (flat, /ns-encapsulated, /@arr element-wise; redeclaration narrows in place), =/?= operators, strict-modifier passthrough.
infer Canonical kaiv → an authored .saiv the example validates against: types from annotations, {int,float} widening, null unions, ;= vectors, [/@name] blocks with per-element-field optionality.
jsonschema (feature json) JSON Schema → authored .saiv as a sound weakening: types/unions, pattern (dialect-checked, / escaped), length/range (exclusiveMin/Max exact for integers), enum/const, required/defaults, format date-time→std/time, nested objects, typed maps, scalar vectors and struct-array blocks (minItems/maxItems graduate to table-header cardinality), local $ref inlining; everything else drops with a comment.
schema converters (proto/avro/graphql/xsd features) .proto, Avro Schema, GraphQL SDL, and XSD → authored .saiv, under the same sound-weakening contract. The proto/Avro converters reuse their data converters' schema parsers; XSD parses with the crate's XML parser; GraphQL adds a hand-rolled SDL parser. Sized integers carry exact wire ranges; open proto3 enums emit `!int
validator Parallel scan of .daiv against .csaiv, plus the Level 2 post-scan pass (uniqueness, referential integrity, cardinality).
json (feature json) JSON import/export with a hand-rolled parser: number tokens and nested containers stay raw source slices, so a compact import/export roundtrip is byte-identical. The library's default build stays zero-dependency; format features are additive.
yaml / toml / xml / cbor / avro (features) Thin adapters over the value hub: each converts its parse tree to the shared interchange tree and reuses the shared emission engine, so every rule (inline forms, embedding, the line budget) is format-agnostic by construction. Fidelity is semantic (formatting and comments do not survive). TOML datetimes ride the typed channel as std/time named types; TOML cannot represent null or integers beyond i64. XML maps attributes to @name members, text-beside-attributes to #text, repeated siblings to arrays; mixed content embeds verbatim as std/enc/xml and splices back; the well-formed-subset parser is hand-rolled (zero deps, no DTD). CBOR (RFC 8949) and Avro (Object Container Files) are the binary formats, both hand-rolled and zero-dep: byte strings ride as std/enc/bin, datetimes as std/time (CBOR tag 0; the Avro date/time/timestamp logical types, micros on export), integers are exact at any width (CBOR bignums; Avro decimal logical type), CBOR output is preferred serialization, Avro reads the null and deflate codecs (hand-rolled inflate) and export infers a schema from the tree (field-wise record unification with null-unions). Deps (yaml-rust2, toml) gated behind their features.
proto (feature) Protocol Buffers, hand-rolled and zero-dep, schema-driven in both directions (the wire format is not self-describing): a proto3 .proto parser (nested/recursive messages, enums, oneof, maps, packages; import statements rejected) plus wire decode/encode against a chosen message. Nested messages are namespaces, repeated fields arrays (packed and unpacked), maps stringify their keys, enum numbers become symbol names, bytes ride as std/enc/bin. Absent fields stay absent (proto3 cannot tell absence from default); unknown field numbers skip, like every protobuf decoder; null is an export error (proto3 has none). Wire round trips are byte-identical to protoc's encoding.
asn1 (feature) ASN.1 BER/DER import and DER export, hand-rolled and zero-dep, schema-less: universal tags drive the mapping, PEM armor strips automatically. Structures are positional, so every element is a single-member wrapper namespace naming its type (seq/set/int/oid/bits/utc/printable/c0/… with u9p-style fallbacks — total coverage). INTEGERs exact at any width; UTCTime/GeneralizedTime ride std/time. DER round-trips byte-identically (verified on openssl-generated X.509 certificates); BER-only forms normalize to DER. A generic multi-member namespace has no DER form — ASN.1 field names live in schemas, not on the wire.

Conformance

The executable definition of "correct" is the conformance tree in the spec repo (spec/kaiv/conformance/). cargo test runs it from ../../spec/kaiv/conformance (relative to the kaiv crate) by default; override with KAIV_CONFORMANCE_DIR.

Scope and known limits (seed)

Levels 0–3. Type, schema, and unit resolution covers all four layers: .!registry (Layer 1) and kaiv.kaiv (Layer 2) over filesystem or http(s) bases, redirect aliasing (Layer 3), and the canonical default hosts t.kaiv.io/s.kaiv.io/f.kaiv.io (Layer 4; the k*aiv.com production domains take over when those zones go live). Network resolution is the net feature — on by default, disabled via default-features = false for embedded/offline builds, where an http(s) base is a SchemaResolutionError. Fetched artifacts are immutable eternalinks, cached without revalidation under ~/.cache/kaiv (KAIV_CACHE_DIR / /cache::dir in kaiv.kaiv override); KAIV_OFFLINE=1 or kaiv --offline resolves from the cache only. Level 3 locale collation (..lex[locale]) has two mutually exclusive backends: collation-icu — on by default, full-fidelity ICU4X, every locale and -u- override the spec recognizes (the CLDR data grows the binary by roughly 1.3 MB) — and the opt-in collation-colligo, a lightweight context-free backend (colligo, ~100 KB) that serves its exactly-reproducible locales and honestly rejects the rest (fr-CA, ja, -u- extensions → CollationUnsupportedError). Enabling both is a compile error; collation remains an alias for collation-icu. With neither (default-features = false) you get a lean Level 0–2 runtime where ..lex[locale] is a CollationUnsupportedError and only the built-in byte order remains — never a silent byte-order fallback. The embedded data is CLDR 48 (kaiv::collate::CLDR_VERSION) under either backend, matching the spec's pinned reference version. Not yet implemented, by design at this stage: Level 4 entirely, map key-pattern clauses, quoted names as interior path segments, and ..time/..ver span semantics beyond canonical-form string comparison. Each unimplemented path fails loudly rather than guessing.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.