How the Modly Artifact Registry Service Works: A Deep Dive into IPC-Driven Asset Management

The Modly artifact registry service is a secure, IPC-driven layer in electron/main/artifact-registry-service.ts that lists, reads, and opens workspace assets through strict path sandboxing, type classification, and metadata-driven linking.

The artifact registry is a core Electron main process service that bridges the renderer process with user workspace files. It exposes three IPC channels—workspace:library:list, workspace:library:read, and workspace:library:open—while enforcing that no file operations can escape the workspace sandbox. The implementation prioritizes security-by-default through path normalization, traversal prevention, and capability-based asset classification.

Path Safety and Normalization

Before any file operation occurs, the registry validates and normalizes all paths to prevent directory traversal attacks.

Strict Path Validation

The assertSafeWorkspaceRelativePath function (lines 84-95) enforces four rules:

  • The path must be relative (no leading slash or drive letter)
  • No URL-encoded escapes (e.g., %2e%2e for ..)
  • No traversal segments (.. anywhere in the path)
  • No disallowed root patterns (hidden internals)
// This would throw an error
assertSafeWorkspaceRelativePath('../../../etc/passwd');
assertSafeWorkspaceRelativePath('Exports/../../secret.txt');

Workspace-Root Resolution

The normalizeWorkspaceAssetPath function (lines 97-104) resolves the validated relative path against the workspace root, guaranteeing the final absolute path remains inside the sandbox. Even if the validation logic had subtle bugs, the resolution step provides a defense-in-depth boundary.

Asset Classification System

The registry determines what each file is and what it can do through classifyAssetLibraryCandidate (lines 118-143).

Capability Detection

Classification inspects both file extensions and accompanying metadata files (.rig.json sidecars):

Pattern Capability Openable?
.glb with no rig mesh Yes
.glb with .rig.json rigged-mesh Yes
.fbx animation clip animation-motion Yes
_landmarks.json sidecar landmark-data No
world.json manifest generated-world Yes

Special cases—landmark sidecars, generated worlds, and scene manifests—have explicit handling rather than falling through generic logic.

Registry entries can carry provenance metadata that links back to source files or upstream workspaces.

Sidecar Parsing

The readMetadata function (lines 179-204) parses .json sidecar files and extracts:

  • sourceWorkspacePath: Origin file in another workspace
  • manifestWorkspacePath: Containing scene/generation context
  • artifactId and versionId: Registry identifiers
  • provenance: Audit trail data

Each linked path undergoes validation through safeLinkedWorkspacePath (lines 59-77), which applies the same traversal protections to external references. Warnings accumulate for:

  • Missing sidecar files
  • Unsafe linked paths that fail validation
  • Version mismatches between sidecar and actual file

Entry Construction and Traversal

Building the Asset Entry

The buildEntry function (lines 225-250) assembles the final AssetLibraryEntry object:

interface AssetLibraryEntry {
  workspacePath: string;      // Normalized relative path
  absolutePath: string;       // Resolved sandboxed path
  name: string;
  extension: string;
  sizeBytes: number;
  modifiedAt: number;
  capability: AssetCapability;
  state: AssetState;
  openable: boolean;
  metadata?: AssetMetadata;
}

Filesystem Walking

collectFiles (lines 252-275) performs a constrained directory traversal of two allowed roots:

  • Workflows/: Source assets and work-in-progress files
  • Exports/: Generated outputs and final artifacts

It explicitly skips:

  • Hidden directories (.git, .modly)
  • Temporary folders (__temp__, .tmp)
  • Internal sidecar files (handled as metadata attachments, not standalone entries)

Public API Methods

Listing Assets

listWorkspaceAssetLibrary (lines 777-785) returns an AssetLibraryListResult containing all valid entries, pre-filtered to exclude unsupported or corrupted assets.

const result = await ipcRenderer.invoke('workspace:library:list');
// result.entries: AssetLibraryEntry[]
// result.warnings: ValidationWarning[]

Reading with Preview Generation

readWorkspaceAssetLibraryEntry (lines 801-808) builds a complete entry and delegates to previewEntry (lines 887-998) to generate renderer-ready payloads:

Preview Type Use Case
Text Shaders, JSON manifests, code
Binary Raw buffer for custom parsers
3D Model Three.js-compatible GLB/GLTF data

Opening Assets

openWorkspaceAssetLibraryEntry (lines 835-843) confirms the asset is openable (or that a valid sourceWorkspacePath override was provided) before returning the entry. This prevents UI states where non-interactive assets would attempt to load into editors.

IPC Registration and Channel Security

The registerWorkspaceAssetLibraryIpcHandlers function (lines 554-566) wires the service into ipcMain:

ipcMain.handle('workspace:library:list', listWorkspaceAssetLibrary);
ipcMain.handle('workspace:library:read', readWorkspaceAssetLibraryEntry);
ipcMain.handle('workspace:library:open', openWorkspaceAssetLibraryEntry);

All three handlers accept only the pre-defined payload shapes from src/shared/types/assetLibrary.ts, rejecting malformed messages at the serialization boundary.

Renderer-Side Usage

The frontend service at src/areas/generate/assetLibraryService.ts forwards calls through these IPC channels. UI components in src/areas/generate/assetLibraryUi.ts consume the resulting data for asset browsing and 3D preview panels.

// Fetch workspace assets
const assets = await ipcRenderer.invoke('workspace:library:list');

// Read specific asset with preview
const { entry, preview } = await ipcRenderer.invoke(
  'workspace:library:read',
  { workspacePath: 'Exports/character.glb' }
);

// Open for editing
const openResult = await ipcRenderer.invoke(
  'workspace:library:open',
  { workspacePath: 'Exports/character.glb' }
);

Summary

  • Strict sandboxing via assertSafeWorkspaceRelativePath and normalizeWorkspaceAssetPath prevents filesystem escape
  • Capability classification through classifyAssetLibraryCandidate enables type-aware UI rendering
  • Metadata-driven linking with safeLinkedWorkspacePath validates cross-workspace references
  • Three IPC channels—list, read, open—expose all functionality to the renderer
  • Preview generation in previewEntry bridges raw files to renderable formats

Frequently Asked Questions

How does Modly prevent directory traversal attacks in the artifact registry?

The service implements double validation: assertSafeWorkspaceRelativePath (lines 84-95) rejects traversal segments, encoded escapes, and absolute paths before normalizeWorkspaceAssetPath (lines 97-104) resolves against the workspace root. Even if validation were bypassed, the resolution step guarantees the final path stays within the sandbox.

What file types can the Modly artifact registry open directly?

Openability depends on capability classification in classifyAssetLibraryCandidate (lines 118-143). Mesh files (.glb, .gltf), rigged meshes with .rig.json sidecars, animation motions, and generated world manifests are openable. Landmark sidecars and internal metadata files return openable: false and display as read-only reference data.

How does the registry handle assets that originated in other workspaces?

The readMetadata function (lines 179-204) extracts sourceWorkspacePath from sidecar files, then safeLinkedWorkspacePath (lines 59-77) validates this external reference against the same traversal rules. The read and open handlers accept an optional sourceWorkspacePath override to resolve the canonical asset when a local copy is a derivative export.

Where are the core types for the artifact registry defined?

Shared type definitions—including AssetLibraryEntry, AssetCapability, AssetState, and IPC payload shapes—reside in src/shared/types/assetLibrary.ts. The main process implementation is in electron/main/artifact-registry-service.ts, with frontend service wrappers in src/areas/generate/assetLibraryService.ts.

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 →