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

> Learn how to validate files before SendCutSend upload using Text-to-CAD. Discover dual-layer client and server checks for schema, file existence, repository boundaries, and Git LFS rules.

- Repository: [earthtojake/text-to-cad](https://github.com/earthtojake/text-to-cad)
- Tags: how-to-guide
- Published: 2026-07-29

---

**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`](https://github.com/earthtojake/text-to-cad/blob/main/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

```javascript
// 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:

```javascript
// 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:

```javascript
// 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`](https://github.com/earthtojake/text-to-cad/blob/main/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`](https://github.com/earthtojake/text-to-cad/blob/main/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.