Source Hash and Validation Systems for CAD Artifacts in Text‑to‑CAD

The Text‑to‑CAD repository implements a dual-layer integrity system that computes SHA‑256 source hashes for every CAD file and validates them against embedded metadata to detect stale artifacts and schema mismatches.

The earthtojake/text-to-cad project treats every generated artifact—from STEP and STL to GLB and URDF—as a versioned, verifiable object. Understanding the source hash and validation systems for CAD artifacts is essential for maintaining consistency across the generation pipeline and ensuring that downstream consumers always receive current, uncorrupted geometry.

How Source Hashes Work

The source hash is a deterministic SHA‑256 fingerprint of the original file embedded directly into artifact metadata. This allows the system to detect when a generated GLB or other derived format no longer matches its underlying source.

Computing the Hash

The utility function sha256File() in viewer/src/server/catalog/cadDirectoryScanner.mjs (lines 45‑61) streams the file and produces a 64‑character hexadecimal hash:

import { sha256File } from 'viewer/src/server/catalog/cadDirectoryScanner.mjs';

const hash = await sha256File('/models/parts/bracket.step');
// Returns: 'a3f5c8...64 chars...'

Embedding Hash Metadata

During GLB generation, the hash is written to the GLB extension under manifest.sourceHash. The Python generator in packages/cadpy_metadata/src/cadpy_metadata/generator.py populates this field from comment metadata (<!-- cadpy:sourceHash=… -->), while the Node.js compiler in viewer/src/server/step/stepArtifactCompiler.mjs orchestrates the injection:

// From stepArtifactCompiler.mjs
const metadata = {
  sourcePath: relativeSourcePath,
  sourceHash: await sha256File(sourcePath),
  stepHash: await sha256File(stepPath)
};

Reading Stored Hashes

The validateStepTopologyArtifact() function extracts the stored hash from manifest.sourceHash and recomputes the current hash of the underlying STEP file (currentStepHash) for comparison.

The Validation Pipeline

The validation system enforces a strict sequence of checks that return structured results containing ok, error, hash, sourceKind, and other metadata. Any failure returns a machine‑readable error code and human‑readable message.

Step‑by‑Step Validation Sequence

  1. Locate the artifact – inlineStepGlbArtifactPathForSource(sourcePath) builds the path to the inline GLB.
  2. Check existence – Returns missing_glb if the file is absent.
  3. Parse the container – readGlbTopologyContainer() (lines 105‑155) verifies the GLB header and extracts the JSON chunk.
  4. Validate STEP topology extension – Checks for STEP_topology extension (missing_step_topology) and correct schema version (STEP_TOPOLOGY_SCHEMA_VERSION, returns unsupported_step_topology if mismatched).
  5. Validate source identity – Verifies sourcePath exists in manifest (missing_source_path if absent).
  6. Validate hash consistency – Compares stored stepHash against freshly computed SHA‑256 of the STEP file, returning stale_step_artifact on mismatch or missing_step_hash if the field is absent.
  7. Validate topology views – Ensures edge topology (STEP_EDGE_BARYCENTRIC_ATTRIBUTE, STEP_EDGE_CLASS_ATTRIBUTE) and selector views conform to schema, returning missing_edge_topology or missing_selector_topology if required attributes are absent.

Validation Result Structure

On success, validateStepTopologyArtifact() returns:

{
  topology,               // parsed STEP topology description
  stepArtifact: { 
    ok: true, 
    sourceKind, 
    sourcePath, 
    glbPath, 
    ... 
  },
  glbPath,
  stepHash,
  sourceHash,
}

On failure, stepArtifact.ok is false and includes a detailed error object with code and message.

Key Implementation Files

File Role
viewer/src/server/catalog/cadDirectoryScanner.mjs Implements sha256File, validateStepTopologyArtifact, and readStepSourceStatus
viewer/src/server/step/stepArtifactCompiler.mjs Orchestrates GLB generation and metadata injection
viewer/src/server/step/stepMetadata.mjs Parses CAD‑specific comment metadata (<!-- cadpy:sourceHash=… -->)
packages/cadpy_metadata/src/cadpy_metadata/generator.py Python‑side hash computation and GLB manifest population
viewer/src/client/workbench/fileStatusItems.js Maps validation error codes to UI messages

Practical Usage Examples

Validate a STEP File Programmatically

Use validateStepTopologyArtifact() to verify a generated GLB matches its source:

import { validateStepTopologyArtifact } from
  'viewer/src/server/catalog/cadDirectoryScanner.mjs';

const result = validateStepTopologyArtifact({
  repoRoot: '/path/to/repo',
  sourcePath: '/models/parts/bracket.step',
  cadPath: 'parts/bracket.step'
});

if (result.stepArtifact.ok) {
  console.log('✅ GLB is up‑to‑date');
} else {
  console.error('❌ Validation failed:', result.stepArtifact.error);
}

Inspect Embedded Source Hashes

Extract the sourceHash from a generated GLB:

import { readStepCatalogMetadata } from
  'viewer/src/server/catalog/cadDirectoryScanner.mjs';

const meta = readStepCatalogMetadata({
  repoRoot: '/path/to/repo',
  glbPath: '/models/parts/.bracket.step.glb'
});
console.log('Source hash:', meta.sourceHash);

Python Generator Integration

Embed hashes when generating artifacts:


# packages/cadpy_metadata/src/cadpy_metadata/generator.py

def generate_step(source_path: Path, output_glb: Path):
    # ... generate geometry ...

    metadata = {
        "sourcePath": str(source_path.relative_to(repo_root)),
        "sourceHash": compute_sha256(source_path),
        "stepHash": compute_sha256(step_file),
    }
    embed_metadata_into_glb(output_glb, metadata)

Summary

  • Source hashes are SHA‑256 fingerprints computed by sha256File() and embedded in GLB metadata under manifest.sourceHash.
  • Validation occurs through validateStepTopologyArtifact(), which checks file existence, schema versions (STEP_TOPOLOGY_SCHEMA_VERSION), hash consistency, and required topology attributes.
  • Error codes like stale_step_artifact and missing_step_hash provide precise diagnostics for CI/CD pipelines and viewer UIs.
  • The system spans both Node.js (cadDirectoryScanner.mjs, stepArtifactCompiler.mjs) and Python (generator.py) to ensure end‑to‑end integrity.

Frequently Asked Questions

What happens when a STEP file changes but the GLB is not regenerated?

The validator returns a stale_step_artifact error because the stored stepHash in the GLB metadata no longer matches the recomputed SHA‑256 of the current STEP file. This prevents downstream tools from using outdated geometry.

Where is the source hash actually stored inside a GLB file?

According to viewer/src/server/step/stepArtifactCompiler.mjs, the hash is written to the GLB’s JSON chunk under the extension key manifest.sourceHash. Python‑generated artifacts insert this via the cadpy_metadata package as a comment that gets parsed into the same structure.

Can I validate artifacts without loading the full GLB into memory?

Yes. Use readStepSourceStatus() in viewer/src/server/catalog/cadDirectoryScanner.mjs, which provides a lightweight wrapper around the validation logic suitable for quick checks in CLI tools and file watchers.

What error code indicates a schema version mismatch?

If the GLB’s STEP_topology extension exists but uses an outdated schema version, the validator returns unsupported_step_topology. The expected version is defined by the constant STEP_TOPOLOGY_SCHEMA_VERSION in the scanner module.

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 →