Skip to content

benchy-mesh: the mesh validation engine

Six Rust crates for bounded STL, OBJ, GLB/glTF, and 3MF inspection, a versioned decision contract, and a defensive grading corpus.


The crates

benchy-mesh (v0.1.0, dual-licensed MIT OR Apache-2.0) is a Rust workspace of six crates, plus the grading harness alongside them:

CrateRole
benchy-mesh-coreVersioned checks and policy decisions through validate_bytes and the context-aware API
benchy-mesh-formatsContent-based format detection and bounded STL / OBJ / GLB / glTF / 3MF parsing
benchy-mesh-geomGeometry and evidence-backed topology analysis
benchy-mesh-printPrerequisite-based print-readiness assessment without numeric scores
benchy-mesh-cliThe benchy-mesh validate --json binary
benchy-mesh-wasmWASM bindings for Cloudflare Workers and browsers
benchy-mesh-graderThe grading harness — scores implementations over a defensive fixture corpus

One engine, three execution substrates: the same crates run natively in the CLI, compiled to WASM inside Cloudflare Workers, and inside an isolated Container for large files — producing identical reports everywhere.

Hostile input by design

Uploaded bytes are untrusted input. Filename extensions and declared media types are hints, not proof; supported formats are detected from content, then parsed within explicit limits for bytes, counts, allocations, strings, textures, archive entries, and expansion. Defenses include:

  • Truncation and lying headers — binary STLs whose declared triangle count doesn't match the body, GLBs whose chunk lengths overrun the file, header-only files.
  • Poisoned geometry — NaN and infinite vertices (in binary STL, ASCII STL, and OBJ) are reported without contaminating bounds or geometry calculations.
  • Archive attacks in 3MF — zip bombs are caught by compression-ratio and expansion limits, invalid internal paths are rejected, entry counts are capped, and the required OPC relationship identifies the model part.
  • Resource exhaustion — declared-mesh floods (e.g. a GLB claiming 10,001 meshes) and limit overruns fail fast with typed errors.

Failures are never panics: you get stable, typed error codes like TruncatedBinary, PATH_TRAVERSAL_IN_ARCHIVE, or ARCHIVE_COMPRESSED_RATIO_TOO_HIGH in a machine-readable report. Every hostile input that has ever broken a candidate implementation graduates into both the grading corpus and a permanent regression suite.

The JSON contract

Results use a camelCase contract with schemaVersion: 2 and policy version 2026.07.10.3. The schema identifies field meanings; the policy version changes whenever a check, threshold, issue, coverage rule, parser decision, or verdict can change for the same input. Clients branch on stable codes and enums, never English messages.

MeshValidationResult (abridged)
{
  "schemaVersion": 2,
  "policyVersion": "2026.07.10.3",
  "validationProfile": "marketplace_publish",
  "executionMode": "server_enforced",
  "identification": {
    "detectedFormat": "stl",
    "confidence": "high",
    "evidence": ["binary_stl_length_consistent"]
  },
  "decision": { "verdict": "allow", "reasonCodes": [] },
  "checks": [
    { "id": "format.structure", "status": "passed", "coverage": "full", "summary": "…" }
  ],
  "issues": [],
  "printReadiness": {
    "assessment": "ready",
    "checks": [ … ],
    "notes": [],
    "limitations": []
  },
  "ok": true,
  "format": "stl",
  "sha256": "…"
}

The grading harness

The repo doesn't just ship a validator — it ships the exam. The grader builds named candidate implementations of the formats stack (including model-authored ones) into the real CLI and scores them over a committed corpus of 36 fixtures, valid and hostile, every one generated (never hand-edited) and tiny. Each fixture is validated twice under a hard 10-second kill, and four weighted axes make up the score:

AxisWeightPass condition
Correctness50Format, verdict, error codes, and warning codes match the manifest
Robustness30Clean exits only — no panics, signals, timeouts, or non-JSON output
Determinism10Both runs produce identical JSON
Performance10Slowest run within the fixture's time budget
shell
cargo run -p benchy-mesh-grader -- gen-fixtures --check
cargo run -p benchy-mesh-grader -- run --candidate baseline
cargo run -p benchy-mesh-grader -- run --all

Run it yourself

shell
git clone https://github.com/benchystudio/benchy-mesh
cd benchy-mesh
cargo test -p benchy-mesh-core
cargo run -p benchy-mesh-cli -- validate --json path/to/model.stl

Exit code 0 means the selected CLI policy allowed the file; exit code 2 means it emitted a valid result with a non-allowing verdict. The default CLI context is structural and standalone. Benchy's publishing decision is produced separately with the marketplace profile in server-enforced mode; a local structural result cannot grant eligibility.

Use and to move between pages.