> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Versioning Guide

> Workflow versioning provides complete change tracking, rollback capability, and an immutable audit trail for compliance. Every time you publish a workflow, a p…

## Overview

Workflow versioning provides complete change tracking, rollback capability, and an immutable audit trail for compliance. Every time you publish a workflow, a permanent snapshot is created that preserves the exact state of nodes, edges, and canvas viewport.

***

## Key Concepts

### Versions vs. Drafts

* **Draft Edits**: Changes made in the workflow editor are not versioned automatically
* **Publishing**: Creates an immutable version snapshot with an incremented version number
* **Version Numbers**: Sequential integers starting at 1: v1, v2, v3, etc.
* **Immutability**: Once published, versions cannot be edited or deleted

### Immutability

Workflow versions are **permanently immutable**:

* Cannot be edited after creation
* Cannot be deleted (preserves complete audit trail)
* Rollback creates a **new version** (doesn't modify the old one)
* All versions remain accessible forever

This ensures regulatory compliance and provides a complete history of workflow changes.

***

## Use Cases

### 1. Production Issue Recovery

Quickly rollback when workflow changes break production:

```typescript theme={null}
// User publishes v2 with bug
await createVersion({ notes: 'Added new approval step' });

// Production breaks - rollback to v1
await rollback({ 
  target_version: 1, 
  notes: 'Emergency rollback - approval node causing timeout' 
});

// Creates v3 (identical to v1) with rollback tag
```

### 2. Compliance Audit

Track who changed what and when for regulatory requirements:

* **Who**: `published_by` user ID links to profile
* **What**: Complete snapshot of workflow state
* **When**: `published_at` timestamp
* **Why**: Optional `notes` field for change descriptions

Auditors can see:

* Version history timeline
* Changes between versions (visual diff)
* Rollback events and reasons
* User attribution for each change

### 3. Debugging

Compare versions to understand what changed:

```typescript theme={null}
const diff = await compareVersions(2, 3);

console.log(diff.nodes.added);     // New nodes in v3
console.log(diff.nodes.removed);   // Deleted from v2
console.log(diff.nodes.modified);  // Changed configuration
console.log(diff.edges.added);     // New connections
console.log(diff.edges.removed);   // Disconnected paths
```

### 4. A/B Testing

Run different workflow versions and compare results:

```typescript theme={null}
// Deploy v2 to production
await createVersion({ 
  notes: 'Test new notification timing', 
  tags: ['production', 'experiment-a'] 
});

// Later: Deploy v3 with different timing
await createVersion({ 
  notes: 'Alternative notification timing', 
  tags: ['production', 'experiment-b'] 
});

// Compare execution results
// SELECT * FROM fw_workflow_executions WHERE workflow_version IN (2, 3)
```

### 5. Staged Rollouts

Use tags to manage deployment stages:

```typescript theme={null}
// Development
await createVersion({ tags: ['development', 'feature-xyz'] });

// Staging
await createVersion({ tags: ['staging', 'feature-xyz'] });

// Production
await createVersion({ tags: ['production', 'v2.1.0'] });
```

***

## API Reference

### useWorkflowVersions Hook

Complete workflow version management hook.

```typescript theme={null}
import { useWorkflowVersions } from '@/cores/fw/hooks/useWorkflowVersions';

const {
  versions,              // All versions (newest first)
  isLoading,            // Loading state
  error,                // Error state
  getVersion,           // Fetch specific version
  createVersion,        // Create new version
  isCreatingVersion,    // Creating state
  rollback,             // Rollback to version
  isRollingBack,        // Rolling back state
  compareVersions,      // Visual diff
} = useWorkflowVersions(ruleId);
```

#### Creating a Version

```typescript theme={null}
// Minimal
await createVersion({ notes: 'Bug fix' });

// With tags
await createVersion({ 
  notes: 'Added approval gates', 
  tags: ['production', 'v2.0'] 
});

// Returns: Version number (e.g., 3)
```

#### Rolling Back

```typescript theme={null}
await rollback({ 
  target_version: 2,
  notes: 'Rollback due to production issue #123'
});

// Creates new version (e.g., v4) identical to v2
// Tags rollback version automatically
```

#### Comparing Versions

```typescript theme={null}
const diff = await compareVersions(1, 3);

// Returns:
{
  versionA: { /* Version 1 data */ },
  versionB: { /* Version 3 data */ },
  diff: {
    nodes: {
      added: [/* Nodes added in v3 */],
      removed: [/* Nodes removed from v1 */],
      modified: [/* Nodes changed between versions */],
    },
    edges: {
      added: [/* Connections added in v3 */],
      removed: [/* Connections removed from v1 */],
    }
  }
}
```

#### Getting Specific Version

```typescript theme={null}
const version = await getVersion(2);

console.log(version.version);            // 2
console.log(version.published_by);       // User ID
console.log(version.published_at);       // ISO timestamp
console.log(version.workflow_snapshot);  // { nodes, edges, viewport }
console.log(version.notes);              // Change description
console.log(version.tags);               // ['production', 'v1.5']
```

***

## Database Schema

### fw\_workflow\_versions Table

```sql theme={null}
CREATE TABLE fw_workflow_versions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  organization_id UUID NOT NULL REFERENCES pf_organizations(id),
  rule_id UUID NOT NULL REFERENCES fw_automation_rules(id),
  version INTEGER NOT NULL,
  published_by UUID NOT NULL REFERENCES auth.users(id),
  published_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  workflow_snapshot JSONB NOT NULL,  -- { nodes, edges, viewport }
  notes TEXT,
  tags TEXT[],
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (rule_id, version)
);
```

**Snapshot Structure:**

```typescript theme={null}
interface WorkflowSnapshot {
  nodes: Array<{
    id: string;
    type: string;
    position: { x: number; y: number };
    data: Record<string, any>;
  }>;
  edges: Array<{
    id: string;
    source: string;
    target: string;
    sourceHandle?: string;
    targetHandle?: string;
  }>;
  viewport?: {
    x: number;
    y: number;
    zoom: number;
  };
}
```

### Execution Version Linking

The `fw_workflow_executions` table links each execution to the version used:

```sql theme={null}
CREATE TABLE fw_workflow_executions (
  id UUID PRIMARY KEY,
  rule_id UUID NOT NULL REFERENCES fw_automation_rules(id),
  workflow_version INTEGER,  -- Links to version used
  status TEXT NOT NULL,
  -- ... other fields
);
```

Query executions by version:

```sql theme={null}
SELECT * FROM fw_workflow_executions 
WHERE rule_id = 'rule-uuid' 
  AND workflow_version = 2;
```

***

## Best Practices

### 1. Publish Before Major Changes

Create a version before making risky changes:

```typescript theme={null}
// Before refactoring
await createVersion({ 
  notes: 'Pre-refactor checkpoint', 
  tags: ['checkpoint'] 
});

// Make changes...

// After testing
await createVersion({ 
  notes: 'Refactored error handling', 
  tags: ['refactor-complete'] 
});
```

### 2. Add Descriptive Notes

Help future maintainers understand changes:

```typescript theme={null}
// ❌ Bad
await createVersion({ notes: 'Changes' });

// ✅ Good
await createVersion({ 
  notes: 'Fixed timeout in approval node (15min → 30min) per ticket #456' 
});
```

### 3. Use Meaningful Tags

Organize versions with consistent tagging:

```typescript theme={null}
// Environment tags
tags: ['development']
tags: ['staging']
tags: ['production']

// Release tags
tags: ['v1.0.0', 'production']
tags: ['v1.0.1', 'hotfix']

// Feature tags
tags: ['feature-notifications', 'staging']

// Special markers
tags: ['rollback', 'emergency']
tags: ['checkpoint', 'pre-refactor']
```

### 4. Review Diff Before Rollback

Always compare versions before rolling back:

```typescript theme={null}
// 1. Compare versions
const diff = await compareVersions(currentVersion, targetVersion);

// 2. Review changes
console.log('Will remove:', diff.nodes.removed.length, 'nodes');
console.log('Will add:', diff.nodes.added.length, 'nodes');

// 3. Confirm and rollback
if (userConfirmed) {
  await rollback({ target_version: targetVersion });
}
```

### 5. Link Versions to Issues

Reference issue tracking systems in notes:

```typescript theme={null}
await createVersion({ 
  notes: 'Implemented multi-level approval (JIRA-1234)',
  tags: ['feature-approvals', 'sprint-23']
});
```

***

## Security & Compliance

### Immutability

Versions cannot be modified or deleted:

* **No UPDATE policy** on `fw_workflow_versions`
* **No DELETE policy** on `fw_workflow_versions`
* Even platform admins cannot alter versions

This ensures audit trail integrity for compliance.

### Multi-Tenant Isolation

Row-Level Security (RLS) ensures:

* Users can only see versions in their organization
* Cross-tenant version access is blocked
* Execution version links are organization-scoped

### Audit Trail

Every version captures:

* **Who**: User ID of publisher
* **When**: Timestamp of publication
* **What**: Complete workflow state
* **Why**: Optional notes explaining changes

***

## Troubleshooting

### Version Creation Fails

**Symptom**: `create_workflow_version()` returns error

**Causes:**

1. No workflow definition exists for the rule
2. User lacks organization access
3. Invalid rule\_id

**Solution:**

```typescript theme={null}
// Verify definition exists
const { data } = await supabase
  .from('fw_workflow_definitions')
  .select()
  .eq('rule_id', ruleId)
  .single();

if (!data) {
  console.error('No workflow definition found');
}
```

### Rollback Creates Wrong Version

**Symptom**: Rolled back version doesn't match target

**Cause**: Snapshot stored incorrectly

**Solution:**

```typescript theme={null}
// Verify target version snapshot
const { data: targetVersion } = await supabase
  .from('fw_workflow_versions')
  .select('workflow_snapshot')
  .eq('version', targetVersionNum)
  .single();

console.log('Target nodes:', targetVersion.workflow_snapshot.nodes);
```

### Version Comparison Incorrect

**Symptom**: Diff shows wrong changes

**Cause**: Node IDs changed between versions

**Solution**: Version comparison uses node IDs as identity. If you manually change node IDs, comparison will treat them as different nodes.

***

## Migration Guide

### Adding Versioning to Existing Workflows

If you have workflows created before versioning was implemented:

```typescript theme={null}
// For each existing workflow:
const { data: definition } = await supabase
  .from('fw_workflow_definitions')
  .select()
  .eq('rule_id', ruleId)
  .single();

if (definition) {
  // Create initial version (v1)
  await supabase.rpc('create_workflow_version', {
    p_rule_id: ruleId,
    p_published_by: currentUserId,
    p_notes: 'Initial version (migrated)',
    p_tags: ['migration', 'v1.0'],
  });
}
```

***

## Related Documentation

* [Workflow Builder Guide](/fw/workflow-builder-guide) - Visual editor usage
* [Workflow API Reference](/fw/workflow-api) - Complete API documentation
* [FW-07 Specification](https://github.com/Encore-OS/encoreos/blob/development/specs/fw/archive/FW-07-workflow-versioning.md) - Implementation details
