2020from pyoaev .signatures .types import ExpectationType , InjectExecutionActions
2121
2222
23+ class ToolErrorInfo (BaseModel ):
24+ """Crash report. Non-zero exit code and a timestamp if the tool left one behind."""
25+
26+ model_config = ConfigDict (extra = "allow" )
27+
28+ exit_code : int = 0
29+ crash_timestamp : str | None = None
30+
31+
32+ class ToolTimeoutInfo (BaseModel ):
33+ """Timeout report. Whatever partial loot was rescued before the kill signal."""
34+
35+ model_config = ConfigDict (extra = "allow" )
36+
37+ partial_results : list [str ] = []
38+
39+
40+ class ToolOutput (BaseModel ):
41+ """Whatever the tool spat out: status, error info, timeout info, or injector extras."""
42+
43+ model_config = ConfigDict (extra = "allow" )
44+
45+ status : str | None = None
46+ error_info : ToolErrorInfo | None = None
47+ timeout_info : ToolTimeoutInfo | None = None
48+
49+
2350class SignatureValue (BaseModel ):
2451 """One signature observation: a type and the value it carries."""
2552
@@ -152,6 +179,25 @@ def execution_duration(self) -> float:
152179 except :
153180 return 0.0
154181
182+ def post_execution_udpate (self , tool_output : ToolOutput , now : datetime ) -> None :
183+ """
184+ Update execution-related metadata according to tool output and now timestamp
185+ """
186+ self .end_time = now
187+
188+ if tool_output .error_info and tool_output .error_info .exit_code != 0 :
189+ self .execution_status = "failed"
190+ if tool_output .error_info .crash_timestamp :
191+ self .end_time = tool_output .error_info .crash_timestamp
192+ elif tool_output .timeout_info :
193+ self .execution_status = "timeout"
194+ elif tool_output .status == "partial" :
195+ self .execution_status = "partial"
196+ else :
197+ self .execution_status = "success"
198+
199+ self .execution_action = "complete"
200+
155201
156202class SignatureCallbackPayload (BaseModel ):
157203 """Outer POST envelope validated by ``SignatureApiManager`` before wire transmission."""
@@ -188,13 +234,21 @@ def build_from_models(
188234 )
189235
190236
191- class PreExecutionSignature (BaseModel ):
192- """Pre-execution data dump. Field set varies by category: network, cloud."""
237+ class ExecutionSignature (BaseModel ):
238+ """
239+ Execution signature data. Field set varies by category: network, cloud. Plus outcome, end_time, and any partial results.
240+ """
193241
194242 model_config = ConfigDict (extra = "allow" )
195243
196244 # Timing always emitted at call time.
197- start_time : str | None = None
245+ start_time : str = Field (
246+ default_factory = lambda : datetime .now (timezone .utc ).strftime (
247+ "%Y-%m-%dT%H:%M:%SZ"
248+ )
249+ )
250+ end_time : str | None = None
251+ partial_results : list [str ] | None = None
198252
199253 # Network identity
200254 source_ipv4 : str | None = None
@@ -209,40 +263,15 @@ class PreExecutionSignature(BaseModel):
209263 cloud_region : str | None = None
210264 target_service : str | None = None
211265
266+ def post_execution_udpate (self , tool_output : ToolOutput , now : datetime ) -> None :
267+ """ """
268+ self .end_time = now .strftime ("%Y-%m-%dT%H:%M:%SZ" )
212269
213- class PostExecutionSignature (PreExecutionSignature ):
214- """Post-execution view: pre-execution fields plus outcome, end_time, and any partial results."""
215-
216- end_time : str | None = None
217- execution_status : str | None = None
218- partial_results : list [str ] | None = None
219-
220-
221- class ToolErrorInfo (BaseModel ):
222- """Crash report. Non-zero exit code and a timestamp if the tool left one behind."""
223-
224- model_config = ConfigDict (extra = "allow" )
225-
226- exit_code : int = 0
227- crash_timestamp : str | None = None
228-
270+ if tool_output .error_info and tool_output .error_info .crash_timestamp :
271+ self .end_time = tool_output .error_info .crash_timestamp
229272
230- class ToolTimeoutInfo (BaseModel ):
231- """Timeout report. Whatever partial loot was rescued before the kill signal."""
232-
233- model_config = ConfigDict (extra = "allow" )
234-
235- partial_results : list [str ] = []
236-
237-
238- class ToolOutput (BaseModel ):
239- """Whatever the tool spat out: status, error info, timeout info, or injector extras."""
240-
241- model_config = ConfigDict (extra = "allow" )
242-
243- status : str | None = None
244- error_info : ToolErrorInfo | None = None
245- timeout_info : ToolTimeoutInfo | None = None
273+ if tool_output .timeout_info and tool_output .timeout_info .partial_results :
274+ self .partial_results = tool_output .timeout_info .partial_results
246275
247276
248277class NetworkInjectorConfig (BaseModel ):
@@ -339,8 +368,7 @@ def build_network_configs(
339368 "TargetSignatures" ,
340369 "SignaturePayload" ,
341370 "SignatureCallbackPayload" ,
342- "PreExecutionSignature" ,
343- "PostExecutionSignature" ,
371+ "ExecutionSignature" ,
344372 "ToolErrorInfo" ,
345373 "ToolTimeoutInfo" ,
346374 "ToolOutput" ,
0 commit comments