How to Validate Files Before SendCutSend Upload: Client and Server Checks in Text-to-CAD

Text-to-CAD validates CAD artifacts through a dual-layer pipeline—first client-side to verify payload schema and file existence, then server-side to enforce repository boundaries and Git-LFS pointer rules—before uploading to Vercel Blob storage for SendCutSend processing.

The earthtojake/text-to-cad repository implements a rigorous validation system to ensure only legitimate, well-formed CAD files reach the SendCutSend cutting service. Before any upload initiates, the system runs comprehensive checks across both client and server environments to prevent malformed submissions, directory traversal attempts, and accidental Git-LFS pointer uploads that could corrupt the manufacturing workflow.

Client-Side Validation with validateGeneratedStepArtifactPayload

The first line of defense runs in the browser immediately after a CAD file generation completes. The validateGeneratedStepArtifactPayload function in viewer/src/client/workbench/stepArtifactStatus.js ensures the generated artifact conforms to expected schema requirements before the user can initiate a SendCutSend upload.

This function performs three critical checks:

  1. Schema validation — verifies required keys (file, url) exist and contain proper types
  2. Path verification — confirms the file path is a non-empty string pointing to a valid workspace location
  3. Custom hook execution — runs optional caller-provided validation for domain-specific requirements like geometry sanity checks
// viewer/src/client/workbench/stepArtifactStatus.js
export function validateGeneratedStepArtifactPayload(payload, { file = "" } = {}) {
  // Basic shape validation
  if (!payload?.file) throw new Error(`Missing file in payload${file && ` for ${file}`}`);
  if (!payload?.url) throw new Error(`Missing URL in payload${file && ` for ${file}`}`);

  // Optional step field (STEP metadata) must be an object if present
  if (payload.step && typeof payload.step !== "object")
    throw new Error(`Invalid step metadata${file && ` for ${file}`}`);

  // Caller-provided extra validation (e.g., geometry sanity checks)
  if (typeof validatePayload === "function") {
    validatePayload(payload);
  }
}

The UI component CadWorkspace triggers this validation immediately after generation finishes. If validation fails, the interface surfaces an error dialog and aborts the upload process before any network requests occur:

// viewer/src/client/components/CadWorkspace.js (excerpt)
validateGeneratedStepArtifactPayload(
  generatedPayload,
  {
    file: generatedFileName,
    validatePayload: (payload) => {
      // Example: ensure STL file size is > 0
      if (fs.statSync(payload.file).size === 0) {
        throw new Error("Generated STL is empty");
      }
    },
  }
);

Server-Side Validation with validateStepTopologyArtifact

Once client-side checks pass, the upload reaches the server-side validation layer in viewer/src/server/catalog/cadDirectoryScanner.mjs. The validateStepTopologyArtifact function implements stricter security controls to protect the repository integrity before files enter Vercel Blob storage.

Repository Boundary Enforcement

The server first confirms the target file lives within the Git work-tree to prevent directory traversal attacks:

// viewer/src/server/catalog/cadDirectoryScanner.mjs
export function validateStepTopologyArtifact({ repoRoot, sourcePath, cadPath }) {
  // 1️⃣ Confirm the file is inside the Git work-tree
  const gitRoot = gitRootPath(repoRoot);
  const relative = path.relative(gitRoot, cadPath);
  if (relative.startsWith("..")) {
    throw new Error(`Upload path ${cadPath} is outside the repository`);
  }

  // 2️⃣ Reject raw Git-LFS pointers unless the user asked to fetch them
  if (readGitLfsPointer(cadPath) && !options.fetchMissingLfs) {
    throw new Error(`Git-LFS pointer found at ${cadPath} – use --fetch-missing-lfs`);
  }

  // 3️⃣ Build the asset metadata for the Blob backend (size, mime type, checksum)
  const metadata = fileAssetMetadata(cadPath);
  // … further checks (e.g., disallow .exe, .dll) …
  return metadata;
}

Git-LFS Pointer Detection

The server explicitly rejects raw Git-LFS pointers unless the fetchMissingLfs option is enabled. This prevents users from accidentally uploading pointer files instead of actual CAD geometry to the SendCutSend service.

The Complete Upload Pipeline

The end-to-end validation flow orchestrates through viewer/scripts/upload-catalog-to-blob.mjs, which coordinates between client and server validation:

  1. Generation — CAD files (STEP, STL) are generated via skills
  2. Client validation — validateGeneratedStepArtifactPayload verifies artifacts in the browser
  3. User initiation — The "Send Cut" action packages artifacts and calls the upload endpoint
  4. Server validation — validateStepTopologyArtifact checks repository boundaries and LFS status for each file
  5. Upload — Only after passing both validation layers do files upload to Vercel Blob for SendCutSend processing

The upload script enumerates candidate files and invokes validateStepTopologyArtifact for each entry before writing to the Vercel Blob backend. Any validation failure returns an informative error to the UI, preventing invalid files from reaching the cutting service.

Summary

  • Client-side validation in viewer/src/client/workbench/stepArtifactStatus.js uses validateGeneratedStepArtifactPayload to enforce schema requirements and file existence before upload initiation
  • Server-side validation in viewer/src/server/catalog/cadDirectoryScanner.mjs employs validateStepTopologyArtifact to prevent directory traversal and block raw Git-LFS pointers
  • The upload pipeline runs through viewer/scripts/upload-catalog-to-blob.mjs, ensuring both validation layers pass before Vercel Blob storage
  • Security focus includes repository boundary checks, path traversal prevention, and explicit handling of Git-LFS artifacts

Frequently Asked Questions

What happens if a Git-LFS pointer file passes client-side validation?

The server-side validateStepTopologyArtifact function specifically detects Git-LFS pointers through the readGitLfsPointer utility and throws an error unless the --fetch-missing-lfs flag is provided. This prevents the SendCutSend service from receiving text pointer files instead of actual binary CAD geometry.

Can I add custom validation rules for specific CAD file types?

Yes. The validateGeneratedStepArtifactPayload function accepts an optional validatePayload callback parameter where you can implement domain-specific checks, such as verifying STL file size is greater than zero or validating STEP file schema compliance before the upload proceeds.

Why does the server need to validate paths if the client already checked them?

The client-side validation primarily ensures the user interface handles malformed artifacts gracefully, while the server-side validation in viewer/src/server/catalog/cadDirectoryScanner.mjs acts as a security boundary. The server confirms paths remain within the Git work-tree using path.relative checks to prevent directory traversal attacks that could expose files outside the repository.

Which component triggers the validation when a user clicks SendCutSend?

The CadWorkspace component in viewer/src/client/components/CadWorkspace.js calls validateGeneratedStepArtifactPayload immediately after file generation completes. When the user initiates the actual SendCutSend upload, the viewer/scripts/upload-catalog-to-blob.mjs script invokes validateStepTopologyArtifact for each file before streaming to Vercel Blob.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →