sys-scan-agent 5.0.3__py3-none-any.whl → 5.0.3.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sys_scan_agent/models/__init__.py +162 -1
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/METADATA +1 -1
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/RECORD +8 -9
- tests/test_graph_main.py +2 -1
- sys_scan_agent/models.py +0 -163
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/WHEEL +0 -0
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/entry_points.txt +0 -0
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/licenses/LICENSE +0 -0
- {sys_scan_agent-5.0.3.dist-info → sys_scan_agent-5.0.3.dev0.dist-info}/top_level.txt +0 -0
@@ -1 +1,162 @@
|
|
1
|
-
|
1
|
+
from __future__ import annotations
|
2
|
+
from typing import List, Dict, Optional, Any, Union
|
3
|
+
from pydantic import BaseModel, Field
|
4
|
+
import hashlib
|
5
|
+
|
6
|
+
# -----------------
|
7
|
+
# Core Report Schema (subset + extensions)
|
8
|
+
# -----------------
|
9
|
+
|
10
|
+
class Finding(BaseModel):
|
11
|
+
id: str
|
12
|
+
title: str
|
13
|
+
severity: str
|
14
|
+
# Legacy field name expected throughout enrichment pipeline. The C++ layer now emits
|
15
|
+
# base_severity_score instead; ingestion normalizes by copying that value into risk_score
|
16
|
+
# (and risk_total) if risk_score is absent. We retain risk_score as required so downstream
|
17
|
+
# code need not handle Optional[int].
|
18
|
+
risk_score: int
|
19
|
+
# Transitional visibility: surface base_severity_score if present in raw report (or if
|
20
|
+
# synthesized during normalization) for transparency / future migration to holistic risk.
|
21
|
+
base_severity_score: Optional[int] = None
|
22
|
+
description: Optional[str] = ""
|
23
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
24
|
+
operational_error: bool = False # if true, represents scanner operational issue, not security signal
|
25
|
+
# Extensions
|
26
|
+
category: Optional[str] = None
|
27
|
+
tags: List[str] = Field(default_factory=list)
|
28
|
+
risk_subscores: Optional[Dict[str, float]] = None # impact/exposure/anomaly/confidence
|
29
|
+
correlation_refs: List[str] = Field(default_factory=list)
|
30
|
+
baseline_status: Optional[str] = None # new|existing|unknown
|
31
|
+
severity_source: Optional[str] = None # raw|bumped|rule_engine
|
32
|
+
allowlist_reason: Optional[str] = None
|
33
|
+
probability_actionable: Optional[float] = None # calibrated probability (0-1)
|
34
|
+
graph_degree: Optional[int] = None # number of correlations referencing this finding
|
35
|
+
cluster_id: Optional[int] = None # correlation graph connected component id
|
36
|
+
rationale: Optional[list[str]] = None # explanations for risk
|
37
|
+
risk_total: Optional[int] = None # duplicate of risk_score as stable name for external consumption
|
38
|
+
host_role: Optional[str] = None # inferred host role classification (workstation|dev_workstation|bastion|lightweight_router|container_host)
|
39
|
+
host_role_rationale: Optional[List[str]] = None # signals used for role classification
|
40
|
+
metric_drift: Optional[dict] = None # when synthetic metric drift finding, carry metrics metadata
|
41
|
+
|
42
|
+
def identity_hash(self) -> str:
|
43
|
+
h = hashlib.sha256()
|
44
|
+
# Use stable core identity (scanner + id + title) stored externally
|
45
|
+
core = f"{self.id}\n{self.title}\n{self.severity}\n"
|
46
|
+
h.update(core.encode())
|
47
|
+
return h.hexdigest()
|
48
|
+
|
49
|
+
class ScannerResult(BaseModel):
|
50
|
+
scanner: str
|
51
|
+
finding_count: int
|
52
|
+
findings: List[Finding]
|
53
|
+
|
54
|
+
class Meta(BaseModel):
|
55
|
+
hostname: Optional[str] = None
|
56
|
+
tool_version: Optional[str] = None
|
57
|
+
json_schema_version: Optional[str] = None
|
58
|
+
# Extensions
|
59
|
+
host_id: Optional[str] = None
|
60
|
+
scan_id: Optional[str] = None
|
61
|
+
|
62
|
+
class Summary(BaseModel):
|
63
|
+
finding_count_total: Optional[int] = None
|
64
|
+
finding_count_emitted: Optional[int] = None
|
65
|
+
severity_counts: Dict[str, int] = Field(default_factory=dict)
|
66
|
+
|
67
|
+
class SummaryExtension(BaseModel):
|
68
|
+
total_risk_score: int
|
69
|
+
emitted_risk_score: Optional[int] = None
|
70
|
+
|
71
|
+
class Report(BaseModel):
|
72
|
+
meta: Meta
|
73
|
+
summary: Summary
|
74
|
+
results: List[ScannerResult]
|
75
|
+
collection_warnings: List[dict] = Field(default_factory=list)
|
76
|
+
scanner_errors: List[dict] = Field(default_factory=list)
|
77
|
+
summary_extension: SummaryExtension
|
78
|
+
|
79
|
+
# -----------------
|
80
|
+
# Correlation / Enrichment Models
|
81
|
+
# -----------------
|
82
|
+
|
83
|
+
class Correlation(BaseModel):
|
84
|
+
id: str
|
85
|
+
title: str
|
86
|
+
rationale: str
|
87
|
+
related_finding_ids: List[str]
|
88
|
+
risk_score_delta: int = 0
|
89
|
+
tags: List[str] = Field(default_factory=list)
|
90
|
+
severity: Optional[str] = None
|
91
|
+
predicate_hits: Optional[dict[str, list[str]]] = None # finding_id -> list of condition descriptors satisfied
|
92
|
+
|
93
|
+
class Reductions(BaseModel):
|
94
|
+
module_summary: Optional[dict] = None
|
95
|
+
suid_summary: Optional[dict] = None
|
96
|
+
network_summary: Optional[dict] = None
|
97
|
+
top_findings: List[dict] = Field(default_factory=list)
|
98
|
+
# Alias list for evaluation metrics (same content as top_findings) to express "top_risks" semantics
|
99
|
+
top_risks: Optional[List[dict]] = None
|
100
|
+
|
101
|
+
class MultiHostCorrelation(BaseModel):
|
102
|
+
type: str # e.g., module_propagation
|
103
|
+
key: str # module name
|
104
|
+
host_ids: List[str]
|
105
|
+
first_seen_recent: bool = True
|
106
|
+
rationale: Optional[str] = None
|
107
|
+
|
108
|
+
class Summaries(BaseModel):
|
109
|
+
executive_summary: Optional[str] = None
|
110
|
+
analyst: Optional[dict] = None
|
111
|
+
consistency_findings: Optional[list] = None # output of Prompt A
|
112
|
+
triage_summary: Optional[dict] = None # structured triage output (Prompt B)
|
113
|
+
action_narrative: Optional[str] = None # human narrative of actions (Prompt C)
|
114
|
+
metrics: Optional[dict] = None # token/latency metrics & alerts
|
115
|
+
causal_hypotheses: Optional[list[dict]] = None # experimental speculative root cause hypotheses
|
116
|
+
attack_coverage: Optional[dict] = None # ATT&CK technique coverage summary
|
117
|
+
|
118
|
+
class ActionItem(BaseModel):
|
119
|
+
priority: int
|
120
|
+
action: str
|
121
|
+
correlation_refs: List[str] = Field(default_factory=list)
|
122
|
+
|
123
|
+
class AgentWarning(BaseModel):
|
124
|
+
module: str
|
125
|
+
stage: str
|
126
|
+
error_type: str
|
127
|
+
message: str
|
128
|
+
severity: str = "warning" # warning|error|info
|
129
|
+
hint: Optional[str] = None
|
130
|
+
|
131
|
+
class FollowupResult(BaseModel):
|
132
|
+
finding_id: str
|
133
|
+
plan: List[str] = Field(default_factory=list)
|
134
|
+
results: dict = Field(default_factory=dict)
|
135
|
+
status: str = "executed" # executed|skipped|error
|
136
|
+
notes: Optional[str] = None
|
137
|
+
|
138
|
+
class EnrichedOutput(BaseModel):
|
139
|
+
version: str = "agent_mvp_1"
|
140
|
+
correlations: List[Correlation]
|
141
|
+
reductions: dict
|
142
|
+
summaries: Summaries
|
143
|
+
actions: List[ActionItem]
|
144
|
+
raw_reference: Optional[str] = None # sha256 of original report file
|
145
|
+
enriched_findings: Optional[List[Finding]] = None # flattened findings with subscores
|
146
|
+
correlation_graph: Optional[dict] = None # clusters & metrics
|
147
|
+
followups: Optional[List[FollowupResult]] = None
|
148
|
+
enrichment_results: Optional[dict] = None # aggregated follow-up verification outcomes
|
149
|
+
multi_host_correlation: Optional[List[MultiHostCorrelation]] = None
|
150
|
+
integrity: Optional[dict] = None # sha256 + signature verification status
|
151
|
+
|
152
|
+
class AgentState(BaseModel):
|
153
|
+
raw_report: Optional[dict] = None
|
154
|
+
report: Optional[Report] = None
|
155
|
+
correlations: List[Correlation] = Field(default_factory=list)
|
156
|
+
reductions: dict = Field(default_factory=dict)
|
157
|
+
summaries: Summaries = Field(default_factory=Summaries)
|
158
|
+
actions: List[ActionItem] = Field(default_factory=list)
|
159
|
+
followups: List[FollowupResult] = Field(default_factory=list)
|
160
|
+
enrichment_results: dict = Field(default_factory=dict)
|
161
|
+
multi_host_correlation: List[MultiHostCorrelation] = Field(default_factory=list)
|
162
|
+
agent_warnings: List[dict] = Field(default_factory=list)
|
@@ -37,7 +37,6 @@ sys_scan_agent/metrics.py,sha256=G8h8G3Kgrcee0kgQ37ihtu8iHkasXbXyywY5YQOIF54,409
|
|
37
37
|
sys_scan_agent/metrics_exporter.py,sha256=MBfpuxn077lEgIiKPJEzhz5qsZ21weEKPHXQCwIXJKU,8661
|
38
38
|
sys_scan_agent/metrics_node.py,sha256=F7OQ3yU06Lftjmm_pbzfDu6ybrRrAqN4gfyAy0xBIFQ,6752
|
39
39
|
sys_scan_agent/migration_v3.py,sha256=LTmzRtjQUwHfNtr-gpBdyCLQdiu_HjdU73oYqFVCIJQ,2190
|
40
|
-
sys_scan_agent/models.py,sha256=e_bD4sJ31lpNt8jgfFSNNznVwB8ZO4m9qVMNmofbitM,6890
|
41
40
|
sys_scan_agent/performance_baseline.py,sha256=btFtN943S2GahaHcTEJFrDJCnA-78XG0H6Gqf_q1I50,7520
|
42
41
|
sys_scan_agent/pipeline.py,sha256=c3xdk5-gPK-UKq3ahYZDsjGZ3IEBU8EtDAFtDOo1w2M,14395
|
43
42
|
sys_scan_agent/rarity_generate.py,sha256=BM2bgyUmNM_PhVIsCG7jFXTf3D8d5QQkohdnFbbl9t4,1851
|
@@ -68,10 +67,10 @@ sys_scan_agent/graph/routing.py,sha256=Tqs-F1QMAdCf9HecUvAQwZeD1X11HsvxB8uXZ_ZBf
|
|
68
67
|
sys_scan_agent/graph/rules.py,sha256=SIh4lxVaBAkYNkRLB4KFvk7jL4rkD3MrL0IverfzAzc,9641
|
69
68
|
sys_scan_agent/graph/summarization.py,sha256=cXc5Lh8-mBLy4PK_BHOchOAyT2OqdL52X2pBNoexuRc,14140
|
70
69
|
sys_scan_agent/graph/utils.py,sha256=oM5-USXt9oIplvhb_5l0eJdq4MEtORs6mzF4RTzUu3Y,13891
|
71
|
-
sys_scan_agent/models/__init__.py,sha256=
|
70
|
+
sys_scan_agent/models/__init__.py,sha256=wgylTYY2kP1k03CFg5s9Q2DS2slpHfhvP0kf_w6xU3E,6888
|
72
71
|
sys_scan_agent/models/mistral-security-scanner/adapter_config.json,sha256=MOx5bdifYA3m-aWPdxAIYnfluOJWJcMg3GYtSySPGkg,945
|
73
72
|
sys_scan_agent/models/mistral-security-scanner/tokenizer.json,sha256=PFz0QCNxT7ObBeceQl-Ne5KAX_c_eYiwg7jIfwv4c5M,17209961
|
74
|
-
sys_scan_agent-5.0.3.dist-info/licenses/LICENSE,sha256=VXRfqQBS6tVMaaDjs09EmMmLbC5Hb5yzhxdUgL0GHow,12135
|
73
|
+
sys_scan_agent-5.0.3.dev0.dist-info/licenses/LICENSE,sha256=VXRfqQBS6tVMaaDjs09EmMmLbC5Hb5yzhxdUgL0GHow,12135
|
75
74
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
76
75
|
tests/conftest.py,sha256=YzOXysZy-Sw1WCGdeHeINiE1jrSNMA_4AwLw-0sFFys,512
|
77
76
|
tests/test_advanced_router.py,sha256=GbE3PPDkgiKswr-VNTH9b3qhRG53ea2cVmFBCZQxYFY,1297
|
@@ -99,7 +98,7 @@ tests/test_fleet_report_schema.py,sha256=P3fH_BxVQoBfW9lDPLxLaf3EFTK9BvbJPsqOTaT
|
|
99
98
|
tests/test_graph.py,sha256=iU1JMf4OWCcwh1cWjaN-L3rM0DXocq03E1SBPpNXwYM,86256
|
100
99
|
tests/test_graph_analysis.py,sha256=D24NossWc1vi4HPiCKYjyf67TbSicIyvqZu3LwGGJP8,14107
|
101
100
|
tests/test_graph_cycle.py,sha256=vRktx0h2SX0PxirWC9L68nSLvCSt_YmhdjS-g-w9FJs,2617
|
102
|
-
tests/test_graph_main.py,sha256=
|
101
|
+
tests/test_graph_main.py,sha256=WTrXih5WiJcUYf3G82g7wn5E_GK-dw0QRR8sbFl1KPU,44062
|
103
102
|
tests/test_graph_scaffold_workflow.py,sha256=fD8_6K3qZO8wO60bfAp_a5_Z02bg3Q1H5GqDOhXR_ho,3597
|
104
103
|
tests/test_graph_utils.py,sha256=b4jnOiBGMb6GXFF2qerFOlHw7Z83b0PvnsCurCsX4Nw,25783
|
105
104
|
tests/test_graph_with_toolnode.py,sha256=UXwTA_YNOs8npGR9InX8p_NHmpWQPmXrE1iwDQ7VBsQ,14870
|
@@ -141,8 +140,8 @@ tests/test_tools_enhanced.py,sha256=rJK6Hczu2mp24gdqubI7fy_m6VfPpm6dwbaTHTMHW6M,
|
|
141
140
|
tests/test_utils.py,sha256=-iUT5p_a1R90QJndAJazYgO2xHZBjfErQnSKRIkHj54,7534
|
142
141
|
tests/test_workflow_equivalence.py,sha256=OyGkCHeYLaVs47FG1098o6fyn0TAtuwh12b7oM5uWwI,25127
|
143
142
|
tests/test_yaml_corruption.py,sha256=_5FLGIv7jppCDZncR_gwxDYTHjlxlErLjQD3vVO37AQ,2107
|
144
|
-
sys_scan_agent-5.0.3.dist-info/METADATA,sha256=
|
145
|
-
sys_scan_agent-5.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
146
|
-
sys_scan_agent-5.0.3.dist-info/entry_points.txt,sha256=7rmYGTp4NvfbpxCqWu7wrHCKd-2BEZfnlPJoxSDKokg,105
|
147
|
-
sys_scan_agent-5.0.3.dist-info/top_level.txt,sha256=3uTXqS-hAr46En_EzXhUkyBEZ6TrlSvUT_toOPE4Ero,48
|
148
|
-
sys_scan_agent-5.0.3.dist-info/RECORD,,
|
143
|
+
sys_scan_agent-5.0.3.dev0.dist-info/METADATA,sha256=CTD8JqrwdShPlGEtInUZb5UTOuQT62MWYvT0bUpHIzE,8542
|
144
|
+
sys_scan_agent-5.0.3.dev0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
145
|
+
sys_scan_agent-5.0.3.dev0.dist-info/entry_points.txt,sha256=7rmYGTp4NvfbpxCqWu7wrHCKd-2BEZfnlPJoxSDKokg,105
|
146
|
+
sys_scan_agent-5.0.3.dev0.dist-info/top_level.txt,sha256=3uTXqS-hAr46En_EzXhUkyBEZ6TrlSvUT_toOPE4Ero,48
|
147
|
+
sys_scan_agent-5.0.3.dev0.dist-info/RECORD,,
|
tests/test_graph_main.py
CHANGED
@@ -12,7 +12,8 @@ import os
|
|
12
12
|
import importlib.util
|
13
13
|
|
14
14
|
# Load the main graph.py module directly
|
15
|
-
|
15
|
+
graph_py_path = os.path.join(os.path.dirname(__file__), '..', 'sys_scan_agent', 'graph.py')
|
16
|
+
graph_spec = importlib.util.spec_from_file_location("graph_main", graph_py_path)
|
16
17
|
if graph_spec is None or graph_spec.loader is None:
|
17
18
|
raise ImportError("Could not load graph.py module")
|
18
19
|
graph_main = importlib.util.module_from_spec(graph_spec)
|
sys_scan_agent/models.py
DELETED
@@ -1,163 +0,0 @@
|
|
1
|
-
from __future__ import annotations
|
2
|
-
from typing import List, Dict, Optional, Any, Union
|
3
|
-
from pydantic import BaseModel, Field
|
4
|
-
import hashlib
|
5
|
-
|
6
|
-
# -----------------
|
7
|
-
# Core Report Schema (subset + extensions)
|
8
|
-
# -----------------
|
9
|
-
|
10
|
-
class Finding(BaseModel):
|
11
|
-
id: str
|
12
|
-
title: str
|
13
|
-
severity: str
|
14
|
-
# Legacy field name expected throughout enrichment pipeline. The C++ layer now emits
|
15
|
-
# base_severity_score instead; ingestion normalizes by copying that value into risk_score
|
16
|
-
# (and risk_total) if risk_score is absent. We retain risk_score as required so downstream
|
17
|
-
# code need not handle Optional[int].
|
18
|
-
risk_score: int
|
19
|
-
# Transitional visibility: surface base_severity_score if present in raw report (or if
|
20
|
-
# synthesized during normalization) for transparency / future migration to holistic risk.
|
21
|
-
base_severity_score: Optional[int] = None
|
22
|
-
description: Optional[str] = ""
|
23
|
-
metadata: Dict[str, Any] = Field(default_factory=dict)
|
24
|
-
operational_error: bool = False # if true, represents scanner operational issue, not security signal
|
25
|
-
# Extensions
|
26
|
-
category: Optional[str] = None
|
27
|
-
tags: List[str] = Field(default_factory=list)
|
28
|
-
risk_subscores: Optional[Dict[str, float]] = None # impact/exposure/anomaly/confidence
|
29
|
-
correlation_refs: List[str] = Field(default_factory=list)
|
30
|
-
baseline_status: Optional[str] = None # new|existing|unknown
|
31
|
-
severity_source: Optional[str] = None # raw|bumped|rule_engine
|
32
|
-
allowlist_reason: Optional[str] = None
|
33
|
-
probability_actionable: Optional[float] = None # calibrated probability (0-1)
|
34
|
-
graph_degree: Optional[int] = None # number of correlations referencing this finding
|
35
|
-
cluster_id: Optional[int] = None # correlation graph connected component id
|
36
|
-
rationale: Optional[list[str]] = None # explanations for risk
|
37
|
-
risk_total: Optional[int] = None # duplicate of risk_score as stable name for external consumption
|
38
|
-
host_role: Optional[str] = None # inferred host role classification (workstation|dev_workstation|bastion|lightweight_router|container_host)
|
39
|
-
host_role_rationale: Optional[List[str]] = None # signals used for role classification
|
40
|
-
metric_drift: Optional[dict] = None # when synthetic metric drift finding, carry metrics metadata
|
41
|
-
|
42
|
-
def identity_hash(self) -> str:
|
43
|
-
h = hashlib.sha256()
|
44
|
-
# Use stable core identity (scanner + id + title) stored externally
|
45
|
-
core = f"{self.id}\n{self.title}\n{self.severity}\n"
|
46
|
-
h.update(core.encode())
|
47
|
-
return h.hexdigest()
|
48
|
-
|
49
|
-
class ScannerResult(BaseModel):
|
50
|
-
scanner: str
|
51
|
-
finding_count: int
|
52
|
-
findings: List[Finding]
|
53
|
-
|
54
|
-
class Meta(BaseModel):
|
55
|
-
hostname: Optional[str] = None
|
56
|
-
tool_version: Optional[str] = None
|
57
|
-
json_schema_version: Optional[str] = None
|
58
|
-
# Extensions
|
59
|
-
host_id: Optional[str] = None
|
60
|
-
scan_id: Optional[str] = None
|
61
|
-
|
62
|
-
class Summary(BaseModel):
|
63
|
-
finding_count_total: Optional[int] = None
|
64
|
-
finding_count_emitted: Optional[int] = None
|
65
|
-
severity_counts: Dict[str, int] = Field(default_factory=dict)
|
66
|
-
|
67
|
-
class SummaryExtension(BaseModel):
|
68
|
-
total_risk_score: int
|
69
|
-
emitted_risk_score: Optional[int] = None
|
70
|
-
|
71
|
-
class Report(BaseModel):
|
72
|
-
meta: Meta
|
73
|
-
summary: Summary
|
74
|
-
results: List[ScannerResult]
|
75
|
-
collection_warnings: List[dict] = Field(default_factory=list)
|
76
|
-
scanner_errors: List[dict] = Field(default_factory=list)
|
77
|
-
summary_extension: SummaryExtension
|
78
|
-
|
79
|
-
# -----------------
|
80
|
-
# Correlation / Enrichment Models
|
81
|
-
# -----------------
|
82
|
-
|
83
|
-
class Correlation(BaseModel):
|
84
|
-
id: str
|
85
|
-
title: str
|
86
|
-
rationale: str
|
87
|
-
related_finding_ids: List[str]
|
88
|
-
risk_score_delta: int = 0
|
89
|
-
tags: List[str] = Field(default_factory=list)
|
90
|
-
severity: Optional[str] = None
|
91
|
-
predicate_hits: Optional[dict[str, list[str]]] = None # finding_id -> list of condition descriptors satisfied
|
92
|
-
|
93
|
-
class Reductions(BaseModel):
|
94
|
-
module_summary: Optional[dict] = None
|
95
|
-
suid_summary: Optional[dict] = None
|
96
|
-
network_summary: Optional[dict] = None
|
97
|
-
top_findings: List[dict] = Field(default_factory=list)
|
98
|
-
# Alias list for evaluation metrics (same content as top_findings) to express "top_risks" semantics
|
99
|
-
top_risks: Optional[List[dict]] = None
|
100
|
-
|
101
|
-
class MultiHostCorrelation(BaseModel):
|
102
|
-
type: str # e.g., module_propagation
|
103
|
-
key: str # module name
|
104
|
-
host_ids: List[str]
|
105
|
-
first_seen_recent: bool = True
|
106
|
-
rationale: Optional[str] = None
|
107
|
-
|
108
|
-
class Summaries(BaseModel):
|
109
|
-
executive_summary: Optional[str] = None
|
110
|
-
analyst: Optional[dict] = None
|
111
|
-
consistency_findings: Optional[list] = None # output of Prompt A
|
112
|
-
triage_summary: Optional[dict] = None # structured triage output (Prompt B)
|
113
|
-
action_narrative: Optional[str] = None # human narrative of actions (Prompt C)
|
114
|
-
metrics: Optional[dict] = None # token/latency metrics & alerts
|
115
|
-
causal_hypotheses: Optional[list[dict]] = None # experimental speculative root cause hypotheses
|
116
|
-
attack_coverage: Optional[dict] = None # ATT&CK technique coverage summary
|
117
|
-
|
118
|
-
class ActionItem(BaseModel):
|
119
|
-
priority: int
|
120
|
-
action: str
|
121
|
-
correlation_refs: List[str] = Field(default_factory=list)
|
122
|
-
|
123
|
-
class AgentWarning(BaseModel):
|
124
|
-
module: str
|
125
|
-
stage: str
|
126
|
-
error_type: str
|
127
|
-
message: str
|
128
|
-
severity: str = "warning" # warning|error|info
|
129
|
-
hint: Optional[str] = None
|
130
|
-
|
131
|
-
class FollowupResult(BaseModel):
|
132
|
-
finding_id: str
|
133
|
-
plan: List[str] = Field(default_factory=list)
|
134
|
-
results: dict = Field(default_factory=dict)
|
135
|
-
status: str = "executed" # executed|skipped|error
|
136
|
-
notes: Optional[str] = None
|
137
|
-
|
138
|
-
class EnrichedOutput(BaseModel):
|
139
|
-
version: str = "agent_mvp_1"
|
140
|
-
correlations: List[Correlation]
|
141
|
-
reductions: dict
|
142
|
-
summaries: Summaries
|
143
|
-
actions: List[ActionItem]
|
144
|
-
raw_reference: Optional[str] = None # sha256 of original report file
|
145
|
-
enriched_findings: Optional[List[Finding]] = None # flattened findings with subscores
|
146
|
-
correlation_graph: Optional[dict] = None # clusters & metrics
|
147
|
-
followups: Optional[List[FollowupResult]] = None
|
148
|
-
enrichment_results: Optional[dict] = None # aggregated follow-up verification outcomes
|
149
|
-
multi_host_correlation: Optional[List[MultiHostCorrelation]] = None
|
150
|
-
integrity: Optional[dict] = None # sha256 + signature verification status
|
151
|
-
|
152
|
-
class AgentState(BaseModel):
|
153
|
-
raw_report: Optional[dict] = None
|
154
|
-
report: Optional[Report] = None
|
155
|
-
correlations: List[Correlation] = Field(default_factory=list)
|
156
|
-
reductions: dict = Field(default_factory=dict)
|
157
|
-
summaries: Summaries = Field(default_factory=Summaries)
|
158
|
-
actions: List[ActionItem] = Field(default_factory=list)
|
159
|
-
followups: List[FollowupResult] = Field(default_factory=list)
|
160
|
-
enrichment_results: dict = Field(default_factory=dict)
|
161
|
-
multi_host_correlation: List[MultiHostCorrelation] = Field(default_factory=list)
|
162
|
-
agent_warnings: List[dict] = Field(default_factory=list)
|
163
|
-
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|