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:
| Crate | Role |
|---|---|
benchy-mesh-core | Versioned checks and policy decisions through validate_bytes and the context-aware API |
benchy-mesh-formats | Content-based format detection and bounded STL / OBJ / GLB / glTF / 3MF parsing |
benchy-mesh-geom | Geometry and evidence-backed topology analysis |
benchy-mesh-print | Prerequisite-based print-readiness assessment without numeric scores |
benchy-mesh-cli | The benchy-mesh validate --json binary |
benchy-mesh-wasm | WASM bindings for Cloudflare Workers and browsers |
benchy-mesh-grader | The 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.
{
"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:
| Axis | Weight | Pass condition |
|---|---|---|
| Correctness | 50 | Format, verdict, error codes, and warning codes match the manifest |
| Robustness | 30 | Clean exits only — no panics, signals, timeouts, or non-JSON output |
| Determinism | 10 | Both runs produce identical JSON |
| Performance | 10 | Slowest run within the fixture's time budget |
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 --allRun it yourself
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.stlExit 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.