Upload and validate 3D models
The upload → check → decide pipeline on benchy.world: ingest grants, server policy decisions, print-readiness evidence, and recovery.
The pipeline at a glance
The whole system fits in one line: uploading, checking, and publishing are separate states. A model becomes available to its creator when the bytes land. A queue then runs the open-source benchy-mesh engine and records the exact policy decision those checks support.
upload (web, CLI, or MCP)
→ ingest grant (HMAC-signed, short-lived)
→ PUT bytes to uploads.benchy.world → quarantined pending/ key
→ finalize → promoted to the models bucket
→ asset + validating release + exact package created
→ checks queued:
fast client-style preflight (feedback only)
+ server-enforced marketplace policy (queue → WASM or Container)
→ report JSON stored → applied to the model
{ validationStatus, decision, checks, issues, printReadiness, ... }
→ package finalized with artifact hashes, rights, dependencies, and manifestUploading
Choose one primary preview or model file in glb, gltf, stl, obj, usdz, 3mf, up to 250 MB. With Private visibility and Free download distribution, a package can also include up to 49 companion files and 1 GB total: native CAD and DCC sources, interchange files, textures, materials, animations, drawings, simulation data, documentation, and license notices. Select several files or a folder; relative paths and roles are preserved.
Public, Unlisted, and Shop listings currently accept one primary model file. Generic archives, scripts, executables, SVG, and macro-enabled documents are rejected. Files up to 64 MiB transfer in one PUT; larger files use multipart transfer in 32 MiB parts.
Public publishing checks currently support GLB, glTF, STL, OBJ, and 3MF. USDZ can be stored as a private or unlisted draft, but it cannot be published publicly or used for Shop purchase in this release. STL and OBJ uploads must state the unit used by their coordinates; changing that assumption invalidates the old result and reruns checks. Public intent also requires an explicit human-created or AI-generated declaration; Benchy never guesses when that declaration is missing.
Under the hood every upload is a three-step ingest session:
- Grant — you receive a short-lived, HMAC-signed grant that can write one specific key in a quarantined ingest bucket, with a byte ceiling. Clients physically cannot address the public buckets.
- Transfer — PUT the bytes to
uploads.benchy.worldwith the grant attached. - Finalize — a separate server-side promote step copies pending → the models bucket, computing the file's SHA-256 in-stream, then the model row is created against the stored key.
The easiest heavy-file client is benchy-cli — it streams from disk and handles single-vs-multipart automatically:
benchy upload ./robot.glb --title "Articulated robot" --tags=robot --visibility=public
benchy publish <modelId> ./robot-v2.glb --note "thicker hinge pins"Packages and releases
A listing is the approachable page people discover. Behind it, Benchy keeps an immutable asset graph: an asset has numbered releases; each release contains content-addressed artifacts and one exact package. Paths, roles, formats, byte sizes, SHA-256 hashes, origins, workflow metadata, variants, and pinned dependencies are written into a deterministic manifest. The public page can download that manifest without exposing storage keys.
Replacing source bytes creates a file release. Editing release-scoped rights, files, dependencies, variants, or technical details creates a metadata release and deprecates the old one. A variant is a supported configuration and a workflow recipe is a set of settings for an exact release; neither pretends to be a new source-file version.
Use Package and workflows from a model you own to describe one or more workflows: 3D printing, CAD and engineering, games and realtime, VFX and animation, AR/VR and Web3D, robotics and simulation, scans and GIS, architecture and BIM, education and research, or CNC/laser/craft. Technical fields are typed per workflow and state their evidence level; creator-entered values are labelled creator-attested.
Validation
Two things happen after a model is created, with deliberately different authority:
- Initial preflight — fast content-based format detection and basic checks for immediate feedback. It uses
executionMode: client_advisory, cannot grant Shop eligibility, and cannot overwrite a completed server decision. - Server-enforced marketplace policy — a queued job runs the Rust
benchy-meshengine over the stored bytes withvalidationProfile: marketplace_publishandexecutionMode: server_enforced. Files up to 24 MiB run in a Cloudflare Worker; files from 24 MiB to 256 MiB run in an isolated Cloudflare Container without internet access.
Primary-model reports are stamped with schemaVersion: 2 and policy version 2026.07.10.3. File checks passed requires a completed marketplace/server-enforced allow, the required checks at their specified coverage, no error issues, full finite geometry and topology evidence, known units, and an exact match to the model's current SHA-256, byte length, format, and unit context. Engine names are provenance, not authority. Historical v1 rows remain readable but never grant a new publishing, linking, or purchase decision; they are queued for current checks.
You can inspect a file locally with cargo run -p benchy-mesh-cli -- validate --json model.stl. The default CLI context is structural and standalone, so it is intentionally informational rather than a replacement for Benchy's server marketplace decision.
Additive file-check assessments
For additive workflows the engine does not invent a probability-like score. It evaluates explicit prerequisites and reports one assessment with supporting checks and limitations. File checks passed is a named server policy decision — it is not a claim that a model is print-ready, slice-ready, or that every mesh property was inspected.
| Assessment | Meaning |
|---|---|
ready | Shown as File checks passed: every required prerequisite passed with sufficient evidence. |
needs_attention | Shown as Passed with notes: all required prerequisites passed, with non-blocking setup guidance to review. Not the same as overall Needs attention (issues that block publishing or selling). |
not_ready | Shown as Checks failed: a required prerequisite failed. |
not_assessed | Shown as Checks incomplete: required evidence was unavailable, unsupported, or not run. |
Each check reports passed, failed, not_run, or unsupported, plus coverage such as full, sampled, or header_only. Closed-surface, edge-manifold, volume, and scale-dependent results appear only when their prerequisites were actually checked. Human messages are display text; integrations use stable issue and reason codes.
Policy decisions
The server marketplace policy returns allow, deny, or inconclusive. The file and model row remain intact in every case:
allowbecomes File checks passed only when the complete, current evidence contract also matches the stored file. A pending Public intent then enters discovery automatically.- A structural or unsafe
denybecomes Needs attention. A requested Public listing remains unlisted, and purchase remains disabled until the reported issues are fixed. - A quality-only finding can remain publicly hosted with clear notes, but it does not grant Shop eligibility. Hosting and commerce intentionally use different gates.
inconclusiveor an execution failure becomes Checks incomplete: no publishing decision was made. When the failure is retryable, the owner can select Retry checks; otherwise, replace the file.- A structural, standalone, or client preflight result may provide useful diagnostics but cannot grant commerce eligibility, even if its own verdict is
allow.
Rights and your library
Downloading a free package while signed in records the exact release, package, manifest, and license grant in your library. A later metadata or license change never rewrites that acquisition. Shop purchases use the same release-scoped ledger after Benchy Shop confirms the order and product ownership.
The package view lists what the stored rights snapshot grants: private use, commercial projects, sale of physical outputs, modification, sharing original files, and sharing modified files, plus attribution, share-alike, change-notice, and component exceptions. These plain-language fields help comparison; the named license and its legal text remain authoritative.
Older acquisitions that already contain companion files stay in the library with their release and rights record intact. Their downloads show Package inspection pendinguntil every file completes the current safety checks. Approval is recorded against the package's exact manifest digest, so replacing any artifact requires a new result.
Debugging
- Upload PUT fails 401/403 — the grant expired or the key mismatches. Request a fresh grant; grants are single-session.
- Upload PUT fails 413 — the file is over the granted ceiling, or over the 64 MiB single-PUT limit and needs multipart.
- Model create fails after finalize — the object probe didn't find the promoted key; make sure finalize succeeded before creating.
- File checks remain in Checking file — the queue is backed up or a consumer is down; the upload remains stored while it waits.
Agents can learn this whole pipeline from the Upload and Check 3D Models skill, and the engine internals are documented under Open source.
Use ← and → to move between pages.