Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
16 KiB
DSS Export/Import System - Complete Implementation Guide
Overview
The DSS (Design System Studio) Export/Import system enables complete project archival, distribution, and restoration with round-trip fidelity. Projects can be exported to versioned .dss archive files and imported back with full metadata, relationships, and audit information preserved.
Key Features:
- ✅ Round-trip fidelity (export → import = identical state)
- ✅ Complete metadata preservation (source attribution, deprecation, timestamps)
- ✅ Multiple import strategies (Replace, Merge, Fork)
- ✅ UUID-based smart merging with conflict detection
- ✅ Schema versioning with automatic migrations
- ✅ Referential integrity validation
- ✅ Backward compatible (no breaking changes)
Architecture Overview
Shadow UUID Strategy
Instead of replacing existing integer IDs, we introduce UUIDs as a transport-layer identity:
Database (Runtime): Archive Format (Transport):
┌──────────────────┐ ┌──────────────────┐
│ id (integer/str) │ │ UUID references │
│ projects │────────▶│ .dss archive │
│ components │ │ (ZIP) │
│ tokens │ │ │
└──────────────────┘ └──────────────────┘
(unchanged) (new, export-only)
Benefits:
- No database schema breaking changes
- Backward compatible with existing code
- Clean separation of export/import logic from runtime logic
- Supports distributed collaboration
Implementation Details
Phase 1: Model Extensions (UUID Fields)
All models now include optional UUID fields with auto-generation:
from dss.models.project import Project
from dss.models.component import Component
from dss.models.theme import DesignToken, Theme
# UUIDs are auto-generated if not provided
project = Project(
id="my-project", # Keep existing ID for runtime
uuid="...", # Auto-generated UUID
name="My Design System"
)
token = DesignToken(
uuid="...", # Auto-generated
name="primary",
value="#3B82F6"
)
component = Component(
uuid="...", # Auto-generated
name="Button"
)
Database Schema Changes:
- Added
uuid TEXT UNIQUEcolumns to:projects,components,styles - UUIDs nullable for backward compatibility
- Indexed for fast lookups
Phase 2: Export (Archive Creation)
Creates versioned .dss ZIP archives with complete project state:
project.dss (ZIP Archive)
├── manifest.json # Metadata, version, contents
├── config.json # Project configuration
├── tokens.json # All tokens with metadata
├── components.json # Components with variants
├── themes.json # Theme definitions
└── history/ # Future: audit logs
└── audit-trail.json
Example Export:
from pathlib import Path
from dss.export_import import DSSArchiveExporter
project = Project(...) # Your DSS project
exporter = DSSArchiveExporter(project)
archive_path = exporter.export_to_file(Path("my-design-system.dss"))
print(f"Exported to: {archive_path}")
# Output: Exported to: my-design-system.dss (2.3 MB)
Exported Token Format (W3C-compatible):
{
"tokens": {
"colors": {
"primary": {
"uuid": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"$value": "#3B82F6",
"$type": "color",
"$category": "color",
"$description": "Primary brand color",
"$source": "figma:abc123",
"$deprecated": false,
"$createdAt": "2025-01-15T10:00:00Z",
"$updatedAt": "2025-12-01T14:30:00Z"
}
}
}
}
Phase 3: Import (Archive Loading)
Loads .dss archives with three strategies:
3a. REPLACE Strategy (Backup Restore)
Complete project replacement - ideal for backup restoration and cloning:
from dss.export_import import DSSArchiveImporter
importer = DSSArchiveImporter(Path("backup.dss"))
# Analyze before importing (no modifications)
analysis = importer.analyze()
print(f"Valid: {analysis.is_valid}")
print(f"Errors: {[e.message for e in analysis.errors]}")
# Import with REPLACE (wipes all existing data)
imported_project = importer.import_replace()
Validation Pipeline:
- Archive integrity check (valid ZIP, required files present)
- Manifest validation (required fields, version format)
- Schema version compatibility (migrations if needed)
- Structural validation (JSON format, required keys)
- Referential integrity (all UUIDs resolve, no dangling references)
3b. MERGE Strategy (Smart Update)
UUID-based intelligent merging for team collaboration:
from dss.export_import import DSSArchiveImporter
from dss.export_import.merger import SmartMerger, ConflictResolutionMode
# Load imported project
importer = DSSArchiveImporter(Path("updated.dss"))
imported_project = importer.import_replace()
# Create merger
local_project = Project(...) # Your current project
merger = SmartMerger(local_project, imported_project)
# Analyze merge
analysis = merger.analyze_merge()
print(f"New tokens: {len(analysis.new_items['tokens'])}")
print(f"Updated: {len(analysis.updated_items['tokens'])}")
print(f"Conflicts: {len(analysis.conflicted_items)}")
# Perform merge with strategy
merged = merger.merge_with_strategy(
ConflictResolutionMode.OVERWRITE # Import wins
)
Merge Detection:
- New items: Exist in import, not in local → Add
- Updated items: Same UUID, same hash → Skip
- Updated items: Same UUID, different hash, not modified locally → Update
- Conflicts: Same UUID, different hash, modified both → Detect
Conflict Strategies:
OVERWRITE: Import version wins (timestamp-based guidance)KEEP_LOCAL: Keep local version (safest for local work)FORK: Create duplicate with new UUID (no data loss)
Example Conflict Resolution:
from dss.export_import.merger import ConflictItem
analysis = merger.analyze_merge()
for conflict in analysis.conflicted_items:
print(f"Conflict: {conflict.entity_name}")
print(f" Local updated: {conflict.local_updated_at}")
print(f" Imported updated: {conflict.imported_updated_at}")
print(f" Local is newer: {conflict.local_is_newer}")
print(f" Imported is newer: {conflict.imported_is_newer}")
# Apply strategy
if analysis.has_conflicts:
merged = merger.merge_with_strategy(
ConflictResolutionMode.MANUAL # Handled elsewhere
)
Phase 4: Schema Versioning & Migrations
Automatic schema evolution handling:
from dss.export_import.migrations import MigrationManager
# Current schema version
current = MigrationManager.get_latest_version()
print(f"Current schema: {current}") # "1.0.1"
# Automatic migration on import
archive_version = "1.0.0" # Old archive
target_version = current
if archive_version < target_version:
migrated_data = MigrationManager.migrate(
archive_data,
from_version=archive_version,
to_version=target_version
)
Version Compatibility:
- Old archives (v1.0.0) → Auto-migrated to latest
- Current archives (v1.0.1) → No migration needed
- Newer archives (v1.0.2) → Error: Please update DSS
Defining New Migrations:
from dss.export_import.migrations import SchemaMigration, MigrationManager
class MigrationV1_0_1_to_V1_0_2(SchemaMigration):
source_version = "1.0.1"
target_version = "1.0.2"
def up(self, data):
"""Upgrade v1.0.1 → v1.0.2"""
# Add new fields, transform structure, etc.
if 'components' in data:
for comp in data['components']:
if 'deprecationMessage' not in comp:
comp['deprecationMessage'] = ""
return data
def down(self, data):
"""Rollback v1.0.2 → v1.0.1"""
# Remove new fields
if 'components' in data:
for comp in data['components']:
comp.pop('deprecationMessage', None)
return data
# Register migration
MigrationManager.MIGRATIONS[("1.0.1", "1.0.2")] = MigrationV1_0_1_to_V1_0_2
MigrationManager.VERSIONS.append("1.0.2")
Usage Examples
1. Backup & Restore Workflow
from pathlib import Path
from datetime import datetime
from dss.export_import import DSSArchiveExporter, DSSArchiveImporter
# BACKUP
def backup_project(project, backup_dir="./backups"):
timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
backup_path = Path(backup_dir) / f"backup_{project.name}_{timestamp}.dss"
exporter = DSSArchiveExporter(project)
saved_path = exporter.export_to_file(backup_path)
print(f"✓ Backed up to {saved_path}")
return saved_path
# RESTORE
def restore_from_backup(backup_path):
importer = DSSArchiveImporter(backup_path)
# Validate before restoring
analysis = importer.analyze()
if not analysis.is_valid:
errors = "\n".join([e.message for e in analysis.errors])
raise ValueError(f"Cannot restore: {errors}")
# Restore
project = importer.import_replace()
print(f"✓ Restored project: {project.name}")
return project
# Usage
project = Project(...)
backup_path = backup_project(project)
restored = restore_from_backup(backup_path)
2. Project Export for Distribution
# Export complete project
exporter = DSSArchiveExporter(project)
exporter.export_to_file(Path("design-system-v2.0.dss"))
# Share with team, other projects, or documentation
# File contains everything needed to reconstruct the system
3. Collaborative Merging
from dss.export_import.merger import SmartMerger, ConflictResolutionMode
# Team member A has local version
local_project = Project(...)
# Team member B shares updated version
importer = DSSArchiveImporter(Path("shared-updates.dss"))
remote_updates = importer.import_replace()
# Merge intelligently
merger = SmartMerger(local_project, remote_updates)
analysis = merger.analyze_merge()
# Show merge summary to user
print(f"New tokens: {len(analysis.new_items['tokens'])}")
print(f"Updated: {len(analysis.updated_items['components'])}")
print(f"Conflicts to resolve: {len(analysis.conflicted_items)}")
# Apply merge
merged_project = merger.merge_with_strategy(
ConflictResolutionMode.KEEP_LOCAL # Prefer local changes
)
4. Archive Analysis Without Import
# Inspect archive before importing
importer = DSSArchiveImporter(Path("mysterious-update.dss"))
analysis = importer.analyze()
if analysis.is_valid:
print(f"Project: {analysis.project_name}")
print(f"Tokens: {analysis.content_summary['tokens']['count']}")
print(f"Components: {analysis.content_summary['components']['count']}")
print(f"Schema: {analysis.schema_version}")
print(f"Migration needed: {analysis.migration_needed}")
if analysis.migration_needed:
print(f"Will be upgraded from {analysis.schema_version} to {analysis.target_version}")
else:
for error in analysis.errors:
print(f"✗ [{error.stage}] {error.message}")
Database Integration
The export/import system integrates with the existing DSS database layer:
Adding UUIDs to Existing Projects
Existing projects need UUID generation. A migration utility handles this:
from dss.storage.database import get_connection
from uuid import uuid4
def backfill_uuids():
"""Generate UUIDs for all existing records"""
with get_connection() as conn:
cursor = conn.cursor()
# Projects
cursor.execute("SELECT id FROM projects WHERE uuid IS NULL")
for row in cursor.fetchall():
project_id = row[0]
new_uuid = str(uuid4())
conn.execute(
"UPDATE projects SET uuid = ? WHERE id = ?",
(new_uuid, project_id)
)
# Components
cursor.execute("SELECT id FROM components WHERE uuid IS NULL")
for row in cursor.fetchall():
comp_id = row[0]
new_uuid = str(uuid4())
conn.execute(
"UPDATE components SET uuid = ? WHERE id = ?",
(new_uuid, comp_id)
)
# Run once to initialize
backfill_uuids()
API Reference
DSSArchiveExporter
class DSSArchiveExporter:
def __init__(self, project: Project):
"""Initialize exporter with project"""
def export_to_file(self, output_path: Path) -> Path:
"""Export to .dss file, returns path"""
DSSArchiveImporter
class DSSArchiveImporter:
def __init__(self, archive_path: Path):
"""Initialize importer with archive path"""
def analyze(self) -> ImportAnalysis:
"""Analyze archive without importing"""
def import_replace(self) -> Project:
"""Import with REPLACE strategy"""
SmartMerger
class SmartMerger:
def __init__(self, local_project: Project, imported_project: Project):
"""Initialize merger"""
def analyze_merge(self) -> MergeAnalysis:
"""Analyze merge without modifying"""
def merge_with_strategy(
self,
conflict_handler: ConflictResolutionMode
) -> Project:
"""Perform merge with strategy"""
MigrationManager
class MigrationManager:
@classmethod
def migrate(
cls,
data: Dict,
from_version: str,
to_version: str
) -> Dict:
"""Apply migrations from source to target"""
@classmethod
def get_latest_version(cls) -> str:
"""Get latest schema version"""
File Structure
dss-mvp1/dss/
├── models/
│ ├── project.py # Project + uuid field
│ ├── component.py # Component + uuid field
│ └── theme.py # Theme + DesignToken with uuid
│
├── export_import/ # NEW PACKAGE
│ ├── __init__.py # Package exports
│ ├── exporter.py # Archive creation
│ ├── importer.py # Archive loading + validation
│ ├── merger.py # Smart merge logic
│ └── migrations.py # Schema versioning
│
└── storage/
└── database.py # Updated with uuid columns
Backward Compatibility
✅ No breaking changes
- Existing code continues to work unchanged
- UUIDs are optional (auto-generated if missing)
- Database schema is backward compatible (uuid columns nullable)
- Export/import is opt-in feature
- Runtime code doesn't use UUIDs (transport-layer only)
Security Considerations
- Archive Integrity: Validate before importing
- Referential Integrity: All UUID references checked
- Schema Validation: JSON schemas enforced
- Conflict Detection: No silent overwrites
- Audit Trail: Import operations logged
Performance Notes
- Export: O(n) where n = total tokens + components (single pass)
- Import: O(n) validation + O(m) for merge where m = local items
- Archive size: Gzipped, typically 10-50% of token count in KB
- Memory: Entire archive loaded in memory (can be optimized with streaming)
Future Enhancements
- Selective Export: Choose what to export (tokens only, components only, etc.)
- Streaming Import: Process large archives without full memory load
- Audit Trail Export: Include sync history and activity logs
- Figma Sync: Direct sync with Figma without manual export
- Cloud Storage: Native upload/download to cloud services
- Compression: Optional additional compression
- Encryption: Encrypted archives for sensitive projects
Troubleshooting
"Archive validation failed"
Check the detailed error messages in analysis.errors. Ensure:
- Archive is valid ZIP file
- manifest.json exists and is valid JSON
- All referenced files exist in archive
"Schema version too new"
Update DSS application to latest version. Archives can only be migrated forward, not backward.
"Referential integrity error"
Ensure all token/component references are valid. Check if:
- Referenced UUIDs exist in archive
- No circular dependencies
- All dependencies are included in export
"Merge conflicts detected"
Review conflicts in analysis.conflicted_items. Decide on resolution strategy:
OVERWRITE: Trust imported versionKEEP_LOCAL: Trust local versionFORK: Create separate copy of imported version
Support
For issues or questions:
- Check ImportAnalysis errors
- Review migration compatibility
- Validate archive structure
- Check referential integrity
Generated with DSS Export/Import System v1.0.0