All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.7.1 - 2026-03-13
- Clear stale
manifest.securityref when writing a document with no signatures or encryption - Map ZIP
FileNotFounderrors toMissingFileand other ZIP errors toInvalidArchive(was mapping all toMissingFile) - Improve freeze error message to mention
set_lineagefor root documents
- Update
modifiedtimestamp indefine_extension_accessors!macro (set_*,clear_*,*_mutmethods) - Update
modifiedtimestamp inset_encryptionandclear_encryption
- Add
zeroizecrate for key material cleanup on drop (Aes256GcmEncryptor,ChaCha20Poly1305Encryptor,Pbes2KeyWrapper,Pbes2KeyUnwrapper,MlDsaSignerseed) - Enforce PBKDF2 iteration bounds (10,000 - 10,000,000) in
Pbes2KeyWrapper::newandPbes2KeyUnwrapper::unwrap - Fix
permissions_forto check specific User/Group/Role grants beforeEveryonewildcard - Correct error variants: 7 security modules switched from
invalid_manifest()toSignatureError - Propagate OCSP/CRL errors in revocation checker instead of silently falling through
- Validate subfigure blocks and IDs in
validate_figure - Clamp heading level to 1-6 on deserialization (was accepting any u8)
- Add
PartialDatevalidation: month 1-12, day 1-31 (on deserialization and viatry_year_month/try_full)
- Add warning that content-level encrypt/decrypt is not yet implemented
- Return non-zero exit code from
add-timestamp(wasOk(())for unimplemented feature) - Replace
std::process::exit(1)withanyhow::bail!inproveandtimestampcommands - Return non-zero exit code from disabled-feature JSON paths in
decrypt,timestamp - Fix
truncate_tokento use char-boundary-safe truncation (was byte-indexing)
- Implement recursive
get_mutforCommentThread(now finds nested replies, was top-level only) - Fix OTS
verify_timestampto returnvalid: falsefor unverified proofs (wastrue) - Fix Ethereum
verify_offlineto sethash_matches: false(offline cannot verify on-chain data) - Update
matches_documentdoc to clarify it only checks token presence
PartialDate::try_year_monthandPartialDate::try_fullfallible constructorsPbes2KeyWrapper::MIN_ITERATIONSandMAX_ITERATIONSconstantsmerge_stylesregression test covering all 35Stylefields- Tests for stale security ref, lineage error, mutation timestamps, subfigure validation, heading clamping, PBKDF2 bounds, permissions specificity, recursive thread
get_mut
- Breaking:
Pbes2KeyWrapper::newnow returnsResult(validates iteration bounds)
0.7.0 - 2026-02-16
- Breaking:
ExtensionMark::glossary()now emits"ref"instead of"termId"to match the spec'sglossaryMarkschema - Breaking:
GlossaryRef.term_idserializes as"ref"instead of"termId" - Deserialization accepts both old
"termId"and new"ref"for backward compatibility
ExtensionMark::get_glossary_ref()helper supporting both"ref"and legacy"termId"keysExtensionMark::normalize_glossary_attrs()to migrate"termId"→"ref"in-place- Backward-compatibility tests for glossary
"termId"deserialization
0.6.0 - 2026-02-16
- Breaking:
Citation.reference(String) renamed toCitation.refs(Vec<String>) to support multi-citation clusters (e.g.,[smith2023; jones2024]) - Breaking:
ExtensionMark::citation()andcitation_with_page()now emit"refs"(array) instead of"ref"(string) - Deserialization accepts both old
"ref"(string) and new"refs"(array) for backward compatibility
Citation::multi()constructor for multi-reference citationsCitation::first_ref()andCitation::refs()accessorsExtensionMark::multi_citation()convenience constructorExtensionMark::get_string_array_attribute()for array-typed attributesExtensionMark::get_citation_refs()helper supporting both"refs"and legacy"ref"keysExtensionMark::normalize_citation_attrs()to migrate"ref"→"refs"in-placeExtensionBlock::get_string_array_attribute()for parity withExtensionMark- Backward-compatibility conformance tests for singular
"ref"deserialization - Multi-reference citation roundtrip tests
0.5.0 - 2026-02-16
- Breaking:
Mark::Math { value }field renamed toMark::Math { source }to match spec - Breaking: Simple marks (Bold, Italic, etc.) now serialize as strings (
"bold") instead of objects ({"type":"bold"}) - Breaking: Extension marks serialize with colon-delimited type (
"semantic:citation") instead of wrapper ({"type":"extension","namespace":"semantic","markType":"citation"}) - Breaking: Extension blocks serialize with colon-delimited type (
"academic:theorem") instead of wrapper format - Breaking:
Block::block_type()returnsCow<'_, str>instead of&'static str; extension blocks return"namespace:blockType"instead of"extension" FigCaptionblock type serializes as"figcaption"(lowercase) instead of"figCaption"- All old formats are accepted on deserialization for backward compatibility
- Split
cdx-cli/src/main.rsintocli.rs(argument definitions),dispatcher.rs(command dispatch), andmain.rs(entry point)
- Conformance test suite (
tests/conformance.rs) covering all 78 testable spec requirements - Conformance matrix (
docs/conformance-matrix.md) mapping spec sections to tests — 78/79 PASS, 0 TODO - Hash boundary tests verifying document ID includes/excludes correct fields
- Asset embedding tests: hash verification, missing file detection, hash mismatch errors
- State machine enforcement tests for review/frozen/published requirements
- Provenance/lineage validation tests
- Property-based tests using proptest for hash determinism, metadata inclusion, block round-trips
- Fuzz targets for Block, Mark, and Content deserialization (
fuzz/fuzz_targets/)
- Added
SECURITY.mdwith supported versions and vulnerability reporting process
0.4.0 - 2026-02-16
ContentAnchorfor block-level, point, and range anchorsContentAnchorUrifor URI format parsing/formatting (#blockId/start-end)Mark::Anchor { id }variant for named anchor marks in text- Full bidirectional conversion between anchor types
PhantomClustersfor off-page annotation clustersPhantomClusterwith anchor, scope, author, and metadataPhantomwith position, size, content, and connectionsPhantomScopefor visibility control (Shared, Private, Role-based)PhantomConnectionwith style options (Line, Arrow, Dashed)- Connection validation with cycle detection
- Archive integration:
read_phantoms()andwrite_phantoms()
SignatureScopefor layout attestation- JCS (RFC 8785) serialization for deterministic scope hashing
Signature.scopefield for scoped signature supportwith_layout()builder for adding layout hashes
ValidationRule::ContainsUppercase- requires uppercase letterValidationRule::ContainsLowercase- requires lowercase letterValidationRule::ContainsDigit- requires digitValidationRule::ContainsSpecial- requires special characterValidationRule::MatchesField- cross-field validation
Collaborator.colorfield for real-time cursor coloringwith_color()builder method
PhantomsRefstruct andphantomsfield onManifestKeyManagementAlgorithmenum andkey_managementfield onEncryptionMetadataephemeral_public_keyfield onRecipientTrustedTimestampstruct andtimestampfield onSignature
CodeTokenstruct,highlightingandtokensfields onCodeBlockFigureNumberingenum,Subfigurestruct,numberingandsubfiguresfields onFigureBlockusesandrestatefields onTheoremStructuralInduction,Counting,Probabilisticvariants onProofMethodstart_linefield onAlgorithmdocketfield onCaption
EcdhEsKeyWrapperandEcdhEsKeyUnwrapperfor ECDH-ES+A256KW key agreement (RFC 7518 / RFC 3394)WrappedKeyDatastruct for wrapped content encryption keys- New
key-wrappingfeature flag (depends onencryption, addsaes-kwandhkdf)
RsaOaepKeyWrapperandRsaOaepKeyUnwrapperfor RSA-OAEP-256 key wrappingPbes2KeyWrapperandPbes2KeyUnwrapperfor PBES2-HS256+A256KW password-based key wrapping- New
key-wrapping-rsaandkey-wrapping-pbes2feature flags - UTF-8 BOM stripping for all JSON files in archive reader
ConditionalValidation,Condition,ConditionOperator,ConditionalActiontypesconditional_validationfield on all 7 form field types- Supports
equals,notEquals,isEmpty,isNotEmptyoperators
TypographyConfigwithLineNumbering,BaselineGrid,HyphenationConfigColumnLayoutandGridLayoutwithGridAreafor multi-column and CSS Grid layoutsTocConfigwithTocLeadersfor table of contents configurationFootnotesConfig,FootnotePosition,FootnoteSeparatorfor footnote placement and stylingEndnotesConfigfor endnote section configuration
- Relax lineage validation: root (non-forked) documents can now reach Frozen/Published without lineage
- Enforce manifest-first ordering in archive reader (error instead of silent acceptance)
- Add decompression bomb protection: 256 MiB file size limit with declared-size pre-check and bounded reads
- Add
is_url_safe_path()utility for spec SHOULD-level asset path validation - Add
FileTooLargeandInvalidArchiveStructureerror variants
- Coordinated RustCrypto ecosystem upgrade:
rand_core0.6 → 0.10 (stable);der0.7 → 0.8 (stable)p2560.13 → 0.14.0-rc;p3840.13 → 0.14.0-rc;ecdsa0.16 → 0.17.0-rcrsa0.9 → 0.10.0-rc;x509-cert0.2 → 0.3.0-rc- Migrate from
OsRng/fill_bytestogetrandom::fillandGeneratetrait - Use
rsa::sha2::Sha256for RSA operations (sha2 0.10 → 0.11 split) - Use
PublicKey::from_sec1_bytesfor P-256 key parsing (replacesEncodedPointchain) - Use
tbs_certificate()/serial_number()/extensions()accessors (x509-cert 0.3 made fields private)
- Replace
fips204with RustCryptoml-dsa0.1.0-rc for ML-DSA-65 signatures (uses standardsignature::Signer/Verifiertraits, 32-byte seed key format) - Bump
zipfrom 7.2 to 8.0 (resolves yanked 7.4.0; no code changes required) - Bump
assert_cmdfrom 2.0 to 2.1.2 - Update
keccakfrom 0.1.5 (yanked) to 0.1.6
- Enable
clippy::pedanticincdx-cli(already zero warnings; prevents regressions) - Remove unused
PropertySchemavariants (Integer,Number,Boolean) and their match arms - Replace
strumderive macros for ~10 enum Display implementations (PR #55) - Extract shared crypto helpers into
crypto_commonmodule (PR #57) - Fix all pedantic lint warnings across workspace (PR #58)
- Tighten
cargo-denyconfiguration:yanked = "deny", remove unused license allowances - Replace
clippy::too_many_argumentssuppressions with parameter structs in CLI (PR #64) - Bump
uniffifrom 0.28 to 0.31 incdx-swift-bridge(PR #65)
- Paginated presentation:
blockRefrenamed toblockId,blockRefstoblockIds - Forms: Removed
ValidationRule::Custom(executable expressions prohibited per DD-010/DD-019) - EquationGroup (PR #74):
Equationrenamed toEquationLine,latexfield renamed tovalue,equationsfield renamed tolines, addedtagfield, addedAlignatenvironment variant - Legal SignatureBlock (PR #74):
SignatoryandFirmInfoflattened intoLegalSigner, addedrolefield onLegalSignatureBlock - ML-DSA (PR #78): Switched from
fips204to RustCryptoml-dsacrate;MlDsaSigner::from_bytesnow accepts a 32-byte seed (was 4032-byte expanded key); key/signature bytes are incompatible with priorfips204-based output
- Increase cargo-tarpaulin timeout to 180s and make coverage non-blocking (
continue-on-error)
- Clarified lineage requirements: parent only required for forked documents
- Clarified hash scope: document ID covers semantic content only, not layout
- Fix MSRV in CONTRIBUTING.md (1.85 → 1.88)
- Add security audit documentation (
cargo audit,cargo deny) to CONTRIBUTING.md
0.3.0 - 2025-01-25
MerkleTreefor content-addressable tree structuresMerkleNodefor individual tree nodes (leaf and branch)BlockProoffor selective disclosure proofsProofVerificationfor detailed verification results- Tree building from items or pre-computed hashes
- Proof generation for any leaf by index
TimestampRequestfor RFC 3161 timestamp requestsTimestampResponsefor TSA responsesTimestampTokenfor timestamp tokensTimestampStatusandTimestampAccuracytypes- Message imprint computation from document IDs
- Nonce support for replay protection
provenancemodule is now public and fully implemented
0.2.0 - 2025-01-25
EddsaSignerfor Ed25519 digital signaturesEddsaVerifierfor Ed25519 signature verification- Full PEM key support for EdDSA keys
- New
eddsafeature flag
Aes256GcmEncryptorfor AES-256-GCM authenticated encryptionEncryptionMetadatatype for encryption configuration- Key derivation function support (PBKDF2, Argon2id)
- Multi-recipient encryption metadata
- New
encryptionfeature flag
fullfeature now includesencryptionandeddsa
0.1.0 - 2025-01-25
Initial release implementing Codex Document Format Specification v0.1.
Documenttype with high-level API for working with Codex documentsDocumentBuilderfor fluent document creationDocumentStateenum with state machine (Draft, Review, Frozen, Published)DocumentIdfor content-addressable document identificationManifesttype with full serialization support
CdxReaderfor reading.cdxZIP archivesCdxWriterfor creating.cdxarchives with proper structure- Path traversal security checks
- Support for Deflate and Zstandard compression
- Reading from files, bytes, or any
Read + Seeksource
- All 13 block types: Paragraph, Heading, List, ListItem, Blockquote, CodeBlock, HorizontalRule, Image, Table, TableRow, TableCell, Math, Break
- Text nodes with marks (Bold, Italic, Underline, Strikethrough, Code, Superscript, Subscript, Link)
- Content validation with detailed error reporting
- Block attributes (dir, lang) support
- Dublin Core metadata support with all standard terms
- Single value and array support for multi-valued fields
- Full serialization/deserialization
Paginatedpresentation for print/PDF outputContinuouspresentation for screen/scroll layouts- CSS-like
Styletype with common properties - Page size, margins, and positioning support
- ECDSA P-256 (ES256) signing and verification
SignerandVerifiertraits for extensibilityEcdsaSignerandEcdsaVerifierimplementationsSignerInfowith name, email, organization, certificate support- Signature file structure per Codex security extension
ImageAssetwith format support (AVIF, WebP, PNG, JPEG, SVG)FontAssetwith format support (WOFF2, WOFF, TTF, OTF)EmbedAssetfor arbitrary file embeddingAssetIndexfor managing asset collections- Asset hash verification
- SHA-256 (default), SHA-3-256, and BLAKE3 support
- Streaming hash computation for large files
Hasherutility for computing hashes
- Document ID verification
- Content hash verification
VerificationReportwith detailed results
zstd(default) - Zstandard compression supportsignatures(default) - Digital signature supportwasm- WebAssembly compilation supportfull- All features enabled
create_document- Create a document from scratchopen_and_verify- Open and verify document integritysign_document- Sign a document with ES256extract_content- Extract text content from blocks