Skip to content

fix: quiet-zone, validation and allocation defects; add agent docs - #1

Merged
ferris007 merged 1 commit into
mainfrom
fix/quiet-zone-validation-and-limits
Aug 22, 2026
Merged

ferris007 merged 1 commit into
mainfrom
fix/quiet-zone-validation-and-limits

Conversation

@ferris007

@ferris007 ferris007 commented Aug 22, 2026 •

Copy link
Copy Markdown
Owner

Seven confirmed defects, each with the test that catches it. None were caught by
the existing suite: tests, clippy -D warnings, cargo fmt --check and every
feature combination all passed before this change. These are coverage gaps, not
regressions.

Fixes

Before → after
QR quiet zone Human-readable text was drawn one module below the symbol, putting 708 pixels of ink inside the four-module quiet zone ISO/IEC 18004 requires — right for Code 128, which has no vertical quiet zone, wrong for anything matrix. Text now sits below the quiet zone. Code 128 output is byte-identical.
Entropy vs. parser limit MAX_ENTROPY_BITS (512 → a 128-character body) and the format's length limit (128) were chosen independently, so a 512-bit policy minted IDs that TrackingId::parse then rejected. The limit is now derived from the widest policy, with const _: () = assert!(…) so they cannot drift again. IDs that parsed before still parse.
serde #[serde(transparent)] + derived Deserialize let any string become a TrackingId. "no-separator-here" was accepted and then reported body() == "separator", silently dropping the rest. Deserialisation now runs parse. Serialisation unchanged.
BitMatrix::row Panicked on an out-of-range row while get/set tolerated one, in a crate that promises no panics on bad input. Returns &[] now; from_row's pre-existing panic is documented.
Size guard The 20,000 px cap was per-axis, so 18500×18500 passed validation and asked the rasteriser for 1.27 GiB in a single allocation — exactly what the guard's comment says it exists to prevent. 64-megapixel cap added.
IdGenerator::validate PKG-ZZZZZZZZ passed under the default policy though the generator only emits 0-9A-F. Entropy characters are now checked; the check character still uses the full 36-character alphabet. A multi-byte prefix is reported as a charset error rather than as too long.
Code 128 blitter Clamped only the far end of its slice; a bar at the trailing quiet zone would have sliced backwards and panicked. No released code128 emits one — this is against a future version bump.

Also

  • AGENTS.md — repo map, the invariants a change must not break, where to add a
    symbology or renderer, and the four shapes every bug in this crate has taken
    so far. CLAUDE.md points at it.
  • README section mapping every Error variant to cause and fix.
  • Editor and agent tooling (.claude/, .entire/, CLAUDE.md,
    hello-entire.md) excluded from the published crate — publishing is
    irreversible, so the tarball should carry only what a consumer needs.

Test plan

  • cargo test --all-features — 131 pass, up from 116
  • cargo clippy --all-features --all-targets -- -D warnings — clean
  • cargo fmt --all --check — clean
  • All three CI feature sets, plus all 15 feature combinations compile in isolation
  • cargo build --target thumbv7em-none-eabihf --no-default-features --features code128,svg
  • cargo run --example label round-trips
  • Each fix's test was confirmed to fail without its fix — the QR one by
    reverting the change and watching it go red, then restoring it. The rendered
    QR label was inspected visually: clear margin on all four sides, text below.

Reviewer notes

  • Behavioural, not a patch. Code that deserialised unvalidated ID strings now
    gets an error instead of a silently-wrong value, and entropy_bits(512) is
    affected by the length rework. This is 0.3.0-shaped. Cargo.toml is left at
    0.2.0 and everything is under [Unreleased] — the version bump and tag are
    deliberately not part of this PR, since tagging publishes irreversibly.
  • KNOWN-ISSUES.md was added and removed within this work: it existed to track
    these defects, and the detail now lives in CHANGELOG.md.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved validation for tracking IDs, including malformed characters, prefixes, lengths, and deserialization.
    • Prevented rendering failures from oversized images and corrected QR quiet-zone and text placement.
    • Prevented Code 128 rendering crashes with trailing quiet zones.
    • Clarified safe behavior for out-of-range matrix access.
  • Documentation

    • Added guidance for error handling, development workflows, architecture, and contribution practices.
    • Added an Unreleased changelog covering fixes, tests, and packaging safeguards.

Seven confirmed defects, none of which the test suite caught — every check
(tests, clippy, fmt, every feature combination) passed before this change.
Each fix comes with the test that would have caught it.

- QR human-readable text was drawn one module below the symbol, inside the
  four-module quiet zone ISO/IEC 18004 requires: 708 pixels of ink in the band
  a scanner uses to find the symbol. Correct for Code 128, which has no
  vertical quiet zone; wrong for anything matrix. Linear output is unchanged.
- MAX_ENTROPY_BITS and the ID length limit had been chosen independently, so a
  512-bit policy minted IDs that TrackingId::parse then rejected. The limit is
  now derived from the widest policy, with a static assertion against drift.
- TrackingId derived serde's Deserialize with #[serde(transparent)], so any
  string bypassed parse entirely — "no-separator-here" was accepted and then
  reported body() == "separator", silently dropping the rest.
- BitMatrix::row panicked on an out-of-range row while get and set tolerated
  one, in a crate that promises not to panic on bad input.
- The image size limit was per-axis, so 18500x18500 passed validation and
  asked the rasteriser for 1.27 GiB in one allocation.
- IdGenerator::validate accepted non-hexadecimal bodies the generator could
  never have produced; a multi-byte prefix was reported as too long rather
  than as containing disallowed characters.
- The Code 128 bar blitter clamped only the far end of its slice.

Also adds AGENTS.md (repo map, invariants, and the four shapes these bugs kept
taking), a README table mapping every Error variant to cause and fix, and
excludes editor and agent tooling from the published crate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 01M0MJP4PJ9S5FY5QN2X6RD5J3
@coderabbitai

coderabbitai Bot commented Aug 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f9476f7-dc41-4195-956f-a7752050b87d

📥 Commits

Reviewing files that changed from the base of the PR and between 644b4c3 and 81e5e64.

📒 Files selected for processing (11)
  • AGENTS.md
  • CHANGELOG.md
  • CLAUDE.md
  • Cargo.toml
  • README.md
  • src/id/generator.rs
  • src/id/mod.rs
  • src/render/mod.rs
  • src/symbology/code128.rs
  • src/symbology/mod.rs
  • tests/qr.rs

📝 Walkthrough

Walkthrough

The change adds tracking ID validation, serde parsing, rendering limits, QR quiet-zone placement, safe matrix access, Code 128 bounds handling, regression tests, repository guidance, and package exclusions.

Changes

Validation, Rendering, and Repository Safeguards

Layer / File(s) Summary
Tracking ID validation and deserialization
src/id/mod.rs, src/id/generator.rs
Tracking ID parsing now enforces length, entropy, prefix, and serde validation rules. Generator tests cover supported widths and invalid inputs.
Rendering limits and QR text layout
src/render/mod.rs, tests/qr.rs
Rendering rejects images larger than 64 megapixels. Matrix HRI text is placed below the full quiet zone. QR tests cover both behaviors.
Symbol and matrix bounds handling
src/symbology/code128.rs, src/symbology/mod.rs
Code 128 skips bars outside the row. BitMatrix::row returns an empty slice for out-of-range rows. Tests cover these access paths.
Repository guidance and release metadata
AGENTS.md, CHANGELOG.md, CLAUDE.md, Cargo.toml, README.md
Repository guidance, changelog entries, development commands, error documentation, and package exclusions were updated.

Estimated code review effort: 3 (Moderate) | ~25 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/quiet-zone-validation-and-limits

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@ferris007
ferris007 merged commit 1fbc5e7 into main Aug 22, 2026
6 checks passed
@ferris007
ferris007 deleted the fix/quiet-zone-validation-and-limits branch August 22, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant