1- import { parsePrincipal , serializePrincipal } from '@sim/auth/principal'
1+ import {
2+ parsePrincipal ,
3+ serializePrincipal ,
4+ type WorkflowExecutionPrincipal ,
5+ } from '@sim/auth/principal'
26import { normalizeStringArray } from '@/lib/core/utils/arrays'
37import { normalizeWorkflowVariables } from '@/lib/core/utils/records'
48import type { ExecutionMetadata , SerializableExecutionState } from '@/executor/execution/types'
59
10+ const EXECUTION_SNAPSHOT_VERSION = 1
11+ const LEGACY_PAUSE_SESSION_ID = 'legacy-paused-execution'
12+
13+ function requireLegacyMetadataString (
14+ metadata : Record < string , unknown > ,
15+ field : 'workflowId' | 'workspaceId'
16+ ) : string {
17+ const value = metadata [ field ]
18+ if ( typeof value !== 'string' || ! value . trim ( ) ) {
19+ throw new Error ( `Legacy execution snapshot metadata ${ field } must be a non-empty string` )
20+ }
21+ return value
22+ }
23+
24+ /** Restores only identity that the pre-principal snapshot format recorded unambiguously. */
25+ function parseLegacyPrincipal ( metadata : Record < string , unknown > ) : WorkflowExecutionPrincipal {
26+ const workflowId = requireLegacyMetadataString ( metadata , 'workflowId' )
27+ const workspaceId = requireLegacyMetadataString ( metadata , 'workspaceId' )
28+ if ( metadata . sessionUserId !== undefined ) {
29+ if ( typeof metadata . sessionUserId !== 'string' || ! metadata . sessionUserId . trim ( ) ) {
30+ throw new Error ( 'Legacy execution snapshot metadata sessionUserId must be a non-empty string' )
31+ }
32+ return {
33+ kind : 'session' ,
34+ userId : metadata . sessionUserId ,
35+ sessionId : LEGACY_PAUSE_SESSION_ID ,
36+ }
37+ }
38+ return { kind : 'system' , serviceId : 'internal' , workspaceId, workflowId }
39+ }
40+
641export class ExecutionSnapshot {
742 public readonly metadata : ExecutionMetadata
843 public readonly workflow : any
@@ -29,6 +64,7 @@ export class ExecutionSnapshot {
2964
3065 toJSON ( ) : string {
3166 return JSON . stringify ( {
67+ version : EXECUTION_SNAPSHOT_VERSION ,
3268 metadata : {
3369 ...this . metadata ,
3470 principal : serializePrincipal ( this . metadata . principal ) ,
@@ -51,12 +87,23 @@ export class ExecutionSnapshot {
5187 throw new Error ( 'Execution snapshot metadata must be an object' )
5288 }
5389 const serializedMetadata = parsed . metadata as Record < string , unknown >
54- if ( serializedMetadata . principal === undefined ) {
55- throw new Error ( 'Execution snapshot metadata is missing its principal' )
90+ let principal : WorkflowExecutionPrincipal
91+ if ( parsed . version === EXECUTION_SNAPSHOT_VERSION ) {
92+ if ( serializedMetadata . principal === undefined ) {
93+ throw new Error ( 'Execution snapshot metadata is missing its principal' )
94+ }
95+ principal = parsePrincipal ( serializedMetadata . principal )
96+ } else if ( parsed . version === undefined ) {
97+ if ( serializedMetadata . principal !== undefined ) {
98+ throw new Error ( 'Unversioned execution snapshots cannot contain a principal' )
99+ }
100+ principal = parseLegacyPrincipal ( serializedMetadata )
101+ } else {
102+ throw new Error ( `Unsupported execution snapshot version ${ String ( parsed . version ) } ` )
56103 }
57104 const metadata = {
58105 ...serializedMetadata ,
59- principal : parsePrincipal ( serializedMetadata . principal ) ,
106+ principal,
60107 } as ExecutionMetadata
61108 return new ExecutionSnapshot (
62109 metadata ,
0 commit comments