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

> Explore the Modly artifact registry service. Learn how IPC-driven asset management with path sandboxing and type classification secures your workspace assets.

- Repository: [lightningpixel/modly](https://github.com/lightningpixel/modly)
- Tags: deep-dive
- Published: 2026-08-20

---

**The Modly artifact registry service is a secure, IPC-driven layer in [`electron/main/artifact-registry-service.ts`](https://github.com/lightningpixel/modly/blob/main/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)

```typescript
// 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`](https://github.com/lightningpixel/modly/blob/main/.rig.json) sidecars):

| Pattern | Capability | Openable? |
|---------|-----------|-----------|
| `.glb` with no rig | `mesh` | Yes |
| `.glb` with [`.rig.json`](https://github.com/lightningpixel/modly/blob/main/.rig.json) | `rigged-mesh` | Yes |
| `.fbx` animation clip | `animation-motion` | Yes |
| [`_landmarks.json`](https://github.com/lightningpixel/modly/blob/main/_landmarks.json) sidecar | `landmark-data` | No |
| [`world.json`](https://github.com/lightningpixel/modly/blob/main/world.json) manifest | `generated-world` | Yes |

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

## Metadata Extraction and Link Safety

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

### Safe Link Validation

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:

```typescript
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.

```typescript
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`:

```typescript
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`](https://github.com/lightningpixel/modly/blob/main/src/shared/types/assetLibrary.ts), rejecting malformed messages at the serialization boundary.

## Renderer-Side Usage

The frontend service at [`src/areas/generate/assetLibraryService.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/generate/assetLibraryService.ts) forwards calls through these IPC channels. UI components in [`src/areas/generate/assetLibraryUi.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/generate/assetLibraryUi.ts) consume the resulting data for asset browsing and 3D preview panels.

```typescript
// 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`](https://github.com/lightningpixel/modly/blob/main/.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`](https://github.com/lightningpixel/modly/blob/main/src/shared/types/assetLibrary.ts). The main process implementation is in [`electron/main/artifact-registry-service.ts`](https://github.com/lightningpixel/modly/blob/main/electron/main/artifact-registry-service.ts), with frontend service wrappers in [`src/areas/generate/assetLibraryService.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/generate/assetLibraryService.ts).