contrastapi 1.22.3__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.
- contrastapi/__init__.py +39 -0
- contrastapi/_transport.py +170 -0
- contrastapi/_version.py +1 -0
- contrastapi/client.py +171 -0
- contrastapi/exceptions.py +176 -0
- contrastapi/models.py +661 -0
- contrastapi/namespaces/__init__.py +0 -0
- contrastapi/namespaces/atlas.py +134 -0
- contrastapi/namespaces/cve.py +125 -0
- contrastapi/namespaces/d3fend.py +124 -0
- contrastapi/namespaces/domain.py +129 -0
- contrastapi/namespaces/intel.py +151 -0
- contrastapi/namespaces/ioc.py +61 -0
- contrastapi/namespaces/security.py +94 -0
- contrastapi/shortcuts.py +182 -0
- contrastapi-1.22.3.dist-info/METADATA +194 -0
- contrastapi-1.22.3.dist-info/RECORD +18 -0
- contrastapi-1.22.3.dist-info/WHEEL +4 -0
contrastapi/models.py
ADDED
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
"""Lightweight TypedDict response models — IDE autocomplete, zero runtime cost.
|
|
2
|
+
|
|
3
|
+
Every TypedDict mirrors the corresponding `app/schemas.py` Pydantic class on the
|
|
4
|
+
server. Field names are wire-exact (kept in sync via the v1.22.3 round-2 audit
|
|
5
|
+
against `app/schemas.py`). Drift here = silent KeyError downstream, so the rule
|
|
6
|
+
is: **if the server schema doesn't have it, the TypedDict doesn't either**.
|
|
7
|
+
|
|
8
|
+
Why TypedDict (not Pydantic)?
|
|
9
|
+
* No additional dependency beyond `httpx`.
|
|
10
|
+
* Zero validation overhead — server already validates on response.
|
|
11
|
+
* `total=False` everywhere — every key is optional from the SDK's perspective
|
|
12
|
+
so omitted fields (Pydantic `response_model_exclude_none=True`) don't
|
|
13
|
+
trigger spurious type errors.
|
|
14
|
+
|
|
15
|
+
Coverage strategy: top-level keys only. Nested complex fields (`kev`, `cvss`,
|
|
16
|
+
`reputation`, `verdict.falsifiable_fields`, `pivot_hint.params`, etc.) stay as
|
|
17
|
+
`dict[str, Any]` so server-side schema drift on internal subtrees doesn't
|
|
18
|
+
break IDE completion for SDK consumers.
|
|
19
|
+
|
|
20
|
+
For richer typing (full nested validation), use the server's `app.schemas`
|
|
21
|
+
Pydantic models directly — they remain the wire-contract source of truth.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
from typing import Any, TypedDict
|
|
27
|
+
|
|
28
|
+
# --- Cross-cutting shapes ---
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ErrorBody(TypedDict, total=False):
|
|
32
|
+
code: str
|
|
33
|
+
message: str
|
|
34
|
+
retry_after_seconds: int | None
|
|
35
|
+
upgrade_url: str | None
|
|
36
|
+
docs_url: str | None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ErrorEnvelope(TypedDict, total=False):
|
|
40
|
+
"""Wire-level error response (v1.22.2+)."""
|
|
41
|
+
|
|
42
|
+
error: ErrorBody
|
|
43
|
+
# Top-level back-compat extensions: hint, tier, limit, upgrade, field,
|
|
44
|
+
# received, suggestion, support, reset_in, error_code, docs.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Verdict(TypedDict, total=False):
|
|
48
|
+
deterministic: bool
|
|
49
|
+
falsifiable_fields: list[str]
|
|
50
|
+
sources_queried: list[str]
|
|
51
|
+
sources_unavailable: list[str]
|
|
52
|
+
completeness: str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class PivotHint(TypedDict, total=False):
|
|
56
|
+
tool: str
|
|
57
|
+
value: str
|
|
58
|
+
reason: str
|
|
59
|
+
params: dict[str, Any]
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# --- CVE / KEV / CWE / Exploit ---
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class CveResponse(TypedDict, total=False):
|
|
66
|
+
cve_id: str
|
|
67
|
+
summary: str
|
|
68
|
+
description: str
|
|
69
|
+
severity: str
|
|
70
|
+
cvss_v3: float
|
|
71
|
+
cvss_breakdown: dict[str, Any]
|
|
72
|
+
cwe_id: str
|
|
73
|
+
epss: dict[str, Any]
|
|
74
|
+
kev: dict[str, Any]
|
|
75
|
+
affected_products: list[dict[str, Any]]
|
|
76
|
+
total_products: int
|
|
77
|
+
published: str
|
|
78
|
+
modified: str
|
|
79
|
+
references: list[str]
|
|
80
|
+
total_references: int
|
|
81
|
+
patch_available: bool
|
|
82
|
+
patch_url: str
|
|
83
|
+
sources: list[str]
|
|
84
|
+
verdict: Verdict
|
|
85
|
+
next_calls: list[PivotHint]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class CveSearchResponse(TypedDict, total=False):
|
|
89
|
+
count: int
|
|
90
|
+
total: int
|
|
91
|
+
truncated: bool
|
|
92
|
+
offset: int
|
|
93
|
+
summary: str
|
|
94
|
+
results: list[dict[str, Any]]
|
|
95
|
+
query_echo: dict[str, Any]
|
|
96
|
+
next_offset: int | None
|
|
97
|
+
hint: dict[str, Any]
|
|
98
|
+
verdict: Verdict
|
|
99
|
+
next_calls: list[PivotHint]
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class KevDetailResponse(TypedDict, total=False):
|
|
103
|
+
cve_id: str
|
|
104
|
+
in_kev: bool
|
|
105
|
+
date_added: str
|
|
106
|
+
due_date: str
|
|
107
|
+
required_action: str
|
|
108
|
+
known_ransomware_use: bool
|
|
109
|
+
vendor_project: str
|
|
110
|
+
product: str
|
|
111
|
+
vulnerability_name: str
|
|
112
|
+
short_description: str
|
|
113
|
+
notes: str
|
|
114
|
+
cwes: list[str]
|
|
115
|
+
verdict: Verdict
|
|
116
|
+
next_calls: list[PivotHint]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class CweLookupResponse(TypedDict, total=False):
|
|
120
|
+
cwe_id: str
|
|
121
|
+
name: str
|
|
122
|
+
description: str
|
|
123
|
+
extended_description: str
|
|
124
|
+
abstract_type: str
|
|
125
|
+
status: str
|
|
126
|
+
likelihood: str
|
|
127
|
+
mitigations: list[str]
|
|
128
|
+
examples: list[str]
|
|
129
|
+
parent_cwe: str
|
|
130
|
+
child_cwes: list[str]
|
|
131
|
+
cve_count: int
|
|
132
|
+
total_mitigations: int | None
|
|
133
|
+
total_examples: int | None
|
|
134
|
+
updated_at: str
|
|
135
|
+
verdict: Verdict
|
|
136
|
+
next_calls: list[PivotHint]
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class ExploitResponse(TypedDict, total=False):
|
|
140
|
+
cve_id: str
|
|
141
|
+
exploits_found: int
|
|
142
|
+
sources: dict[str, Any]
|
|
143
|
+
has_public_exploit: bool
|
|
144
|
+
exploits: list[dict[str, Any]]
|
|
145
|
+
summary: str
|
|
146
|
+
verdict: Verdict
|
|
147
|
+
next_calls: list[PivotHint]
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# --- Bulk parity (v1.21.0+ unified status enum: ok/error/not_found/invalid_format) ---
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class BulkCveItem(TypedDict, total=False):
|
|
154
|
+
cve_id: str
|
|
155
|
+
status: str
|
|
156
|
+
cve: CveResponse | None
|
|
157
|
+
error: str
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class BulkCveResponse(TypedDict, total=False):
|
|
161
|
+
results: list[BulkCveItem]
|
|
162
|
+
total: int
|
|
163
|
+
successful: int
|
|
164
|
+
failed: int
|
|
165
|
+
timed_out: int
|
|
166
|
+
not_found: int
|
|
167
|
+
partial: bool
|
|
168
|
+
summary: str
|
|
169
|
+
verdict: Verdict
|
|
170
|
+
next_calls: list[PivotHint]
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class BulkIocItem(TypedDict, total=False):
|
|
174
|
+
indicator: str
|
|
175
|
+
status: str
|
|
176
|
+
ioc: dict[str, Any]
|
|
177
|
+
error: str
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class BulkIocResponse(TypedDict, total=False):
|
|
181
|
+
results: list[BulkIocItem]
|
|
182
|
+
total: int
|
|
183
|
+
successful: int
|
|
184
|
+
failed: int
|
|
185
|
+
timed_out: int
|
|
186
|
+
not_found: int
|
|
187
|
+
invalid: int
|
|
188
|
+
partial: bool
|
|
189
|
+
summary: str
|
|
190
|
+
verdict: Verdict
|
|
191
|
+
next_calls: list[PivotHint]
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class BulkAtlasTechniqueItem(TypedDict, total=False):
|
|
195
|
+
technique_id: str
|
|
196
|
+
status: str
|
|
197
|
+
technique: dict[str, Any]
|
|
198
|
+
error: str
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class BulkAtlasTechniqueResponse(TypedDict, total=False):
|
|
202
|
+
results: list[BulkAtlasTechniqueItem]
|
|
203
|
+
total: int
|
|
204
|
+
successful: int
|
|
205
|
+
failed: int
|
|
206
|
+
partial: bool
|
|
207
|
+
summary: str
|
|
208
|
+
verdict: Verdict
|
|
209
|
+
next_calls: list[PivotHint]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# --- IOC / Hash / Phishing / Password ---
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class IocResponse(TypedDict, total=False):
|
|
216
|
+
indicator: str
|
|
217
|
+
type: str # ip | domain | url | hash | unknown
|
|
218
|
+
threat_level: str # none | low | medium | high
|
|
219
|
+
sources: dict[str, Any]
|
|
220
|
+
summary: str
|
|
221
|
+
verdict: Verdict
|
|
222
|
+
next_calls: list[PivotHint]
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
class HashResponse(TypedDict, total=False):
|
|
226
|
+
hash: str
|
|
227
|
+
hash_type: str
|
|
228
|
+
found: bool
|
|
229
|
+
malware_family: str | None
|
|
230
|
+
file_type: str | None
|
|
231
|
+
file_size: int | None
|
|
232
|
+
first_seen: str | None
|
|
233
|
+
tags: list[str]
|
|
234
|
+
verdict: Verdict
|
|
235
|
+
next_calls: list[PivotHint]
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
class PhishingResponse(TypedDict, total=False):
|
|
239
|
+
url: str
|
|
240
|
+
host: str
|
|
241
|
+
is_malicious: bool
|
|
242
|
+
is_stale: bool
|
|
243
|
+
sources: dict[str, Any]
|
|
244
|
+
summary: str
|
|
245
|
+
verdict: Verdict
|
|
246
|
+
next_calls: list[PivotHint]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class PasswordResponse(TypedDict, total=False):
|
|
250
|
+
hash_prefix: str
|
|
251
|
+
found: bool
|
|
252
|
+
pwned_count: int
|
|
253
|
+
summary: str
|
|
254
|
+
verdict: Verdict
|
|
255
|
+
next_calls: list[PivotHint]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
# --- Domain ---
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class DomainReportResponse(TypedDict, total=False):
|
|
262
|
+
domain: str
|
|
263
|
+
dns: dict[str, Any]
|
|
264
|
+
reverse_dns: dict[str, Any]
|
|
265
|
+
whois: dict[str, Any]
|
|
266
|
+
ssl: dict[str, Any]
|
|
267
|
+
subdomains: dict[str, Any]
|
|
268
|
+
certificates: dict[str, Any]
|
|
269
|
+
email_security: dict[str, Any]
|
|
270
|
+
waf: dict[str, Any]
|
|
271
|
+
threat: dict[str, Any]
|
|
272
|
+
risk: dict[str, Any]
|
|
273
|
+
risk_score: int | None # DEPRECATED (Sunset 2026-09-01); use risk.score
|
|
274
|
+
reputation: dict[str, Any]
|
|
275
|
+
summary: str
|
|
276
|
+
verdict: Verdict
|
|
277
|
+
next_calls: list[PivotHint]
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
class DnsResponse(TypedDict, total=False):
|
|
281
|
+
domain: str
|
|
282
|
+
records: dict[str, Any]
|
|
283
|
+
summary: str
|
|
284
|
+
verdict: Verdict
|
|
285
|
+
next_calls: list[PivotHint]
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class WhoisResponse(TypedDict, total=False):
|
|
289
|
+
domain: str
|
|
290
|
+
whois: dict[str, Any]
|
|
291
|
+
summary: str
|
|
292
|
+
verdict: Verdict
|
|
293
|
+
next_calls: list[PivotHint]
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class SubdomainsResponse(TypedDict, total=False):
|
|
297
|
+
domain: str
|
|
298
|
+
count: int
|
|
299
|
+
subdomains: list[str]
|
|
300
|
+
summary: str
|
|
301
|
+
sources: list[str]
|
|
302
|
+
warnings: list[str]
|
|
303
|
+
found_via_wordlist: int
|
|
304
|
+
found_via_crtsh: int
|
|
305
|
+
verdict: Verdict
|
|
306
|
+
next_calls: list[PivotHint]
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class CertsResponse(TypedDict, total=False):
|
|
310
|
+
domain: str
|
|
311
|
+
total_certificates: int
|
|
312
|
+
certificates: list[dict[str, Any]]
|
|
313
|
+
summary: str
|
|
314
|
+
verdict: Verdict
|
|
315
|
+
next_calls: list[PivotHint]
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class SslResponse(TypedDict, total=False):
|
|
319
|
+
domain: str
|
|
320
|
+
valid: bool
|
|
321
|
+
cert_valid: bool
|
|
322
|
+
grade: str
|
|
323
|
+
validation_errors: list[str]
|
|
324
|
+
issuer: dict[str, Any]
|
|
325
|
+
subject: dict[str, Any]
|
|
326
|
+
san: list[str]
|
|
327
|
+
not_before: str
|
|
328
|
+
not_after: str
|
|
329
|
+
days_until_expiry: int
|
|
330
|
+
summary: str
|
|
331
|
+
verdict: Verdict
|
|
332
|
+
next_calls: list[PivotHint]
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
class TechResponse(TypedDict, total=False):
|
|
336
|
+
domain: str
|
|
337
|
+
technologies: list[dict[str, Any]]
|
|
338
|
+
categories: dict[str, list[str]]
|
|
339
|
+
count: int
|
|
340
|
+
summary: str
|
|
341
|
+
verdict: Verdict
|
|
342
|
+
next_calls: list[PivotHint]
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class ThreatResponse(TypedDict, total=False):
|
|
346
|
+
domain: str
|
|
347
|
+
urlhaus_status: str
|
|
348
|
+
urls_online: int
|
|
349
|
+
url_count: int
|
|
350
|
+
threat_types: list[str]
|
|
351
|
+
tags: list[str]
|
|
352
|
+
urls: list[dict[str, Any]]
|
|
353
|
+
summary: str
|
|
354
|
+
verdict: Verdict
|
|
355
|
+
next_calls: list[PivotHint]
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
class WaybackResponse(TypedDict, total=False):
|
|
359
|
+
domain: str
|
|
360
|
+
status: str # 'ok' | 'unavailable'
|
|
361
|
+
snapshots: list[dict[str, Any]]
|
|
362
|
+
total_snapshots: int
|
|
363
|
+
earliest: str
|
|
364
|
+
latest: str
|
|
365
|
+
warnings: list[str]
|
|
366
|
+
summary: str
|
|
367
|
+
verdict: Verdict
|
|
368
|
+
next_calls: list[PivotHint]
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class AuditResponse(TypedDict, total=False):
|
|
372
|
+
domain: str
|
|
373
|
+
report: DomainReportResponse | None
|
|
374
|
+
headers: dict[str, Any]
|
|
375
|
+
tech: TechResponse | None
|
|
376
|
+
summary: str
|
|
377
|
+
verdict: Verdict
|
|
378
|
+
next_calls: list[PivotHint]
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
class BulkDomainResponse(TypedDict, total=False):
|
|
382
|
+
results: list[dict[str, Any]]
|
|
383
|
+
total: int
|
|
384
|
+
successful: int
|
|
385
|
+
failed: int
|
|
386
|
+
timed_out: int
|
|
387
|
+
summary: str
|
|
388
|
+
verdict: Verdict
|
|
389
|
+
next_calls: list[PivotHint]
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
# --- IP / ASN / Threat report ---
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class IpLookupResponse(TypedDict, total=False):
|
|
396
|
+
ip: str
|
|
397
|
+
ptr: str | None
|
|
398
|
+
asn: int | None
|
|
399
|
+
asn_name: str | None
|
|
400
|
+
country: str | None
|
|
401
|
+
ports: list[int]
|
|
402
|
+
hostnames: list[str]
|
|
403
|
+
vulns: list[dict[str, Any]]
|
|
404
|
+
cpes: list[str]
|
|
405
|
+
tags: list[str]
|
|
406
|
+
reputation: dict[str, Any]
|
|
407
|
+
cloud_provider: str | None
|
|
408
|
+
is_datacenter: bool
|
|
409
|
+
tor_exit: bool
|
|
410
|
+
risk_score: int
|
|
411
|
+
severity_label: str # low | medium | high | critical
|
|
412
|
+
summary: str
|
|
413
|
+
verdict: Verdict
|
|
414
|
+
next_calls: list[PivotHint]
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
class AsnResponse(TypedDict, total=False):
|
|
418
|
+
target: str
|
|
419
|
+
resolved_ip: str | None
|
|
420
|
+
asn: int
|
|
421
|
+
asn_name: str
|
|
422
|
+
country: str | None
|
|
423
|
+
prefixes: list[str]
|
|
424
|
+
prefix_count: int
|
|
425
|
+
summary: str
|
|
426
|
+
verdict: Verdict
|
|
427
|
+
next_calls: list[PivotHint]
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
class ThreatReportResponse(TypedDict, total=False):
|
|
431
|
+
ip: str
|
|
432
|
+
enrichment: dict[str, Any]
|
|
433
|
+
abuseipdb: dict[str, Any]
|
|
434
|
+
shodan: dict[str, Any]
|
|
435
|
+
asn_info: dict[str, Any]
|
|
436
|
+
risk_score: int
|
|
437
|
+
severity_label: str
|
|
438
|
+
summary: str
|
|
439
|
+
verdict: Verdict
|
|
440
|
+
next_calls: list[PivotHint]
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
# --- Email / Phone / Username ---
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class EmailMxResponse(TypedDict, total=False):
|
|
447
|
+
domain: str
|
|
448
|
+
mx_records: list[dict[str, Any]]
|
|
449
|
+
mail_provider: str | None
|
|
450
|
+
email_security: dict[str, Any]
|
|
451
|
+
summary: str
|
|
452
|
+
verdict: Verdict
|
|
453
|
+
next_calls: list[PivotHint]
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
class DisposableResponse(TypedDict, total=False):
|
|
457
|
+
email: str
|
|
458
|
+
domain: str
|
|
459
|
+
disposable: bool
|
|
460
|
+
provider: str | None
|
|
461
|
+
summary: str
|
|
462
|
+
verdict: Verdict
|
|
463
|
+
next_calls: list[PivotHint]
|
|
464
|
+
|
|
465
|
+
|
|
466
|
+
class PhoneLookupResponse(TypedDict, total=False):
|
|
467
|
+
valid: bool
|
|
468
|
+
number: str
|
|
469
|
+
country: str | None
|
|
470
|
+
region: str | None
|
|
471
|
+
carrier: str | None
|
|
472
|
+
line_type: str | None
|
|
473
|
+
format: dict[str, Any]
|
|
474
|
+
summary: str
|
|
475
|
+
verdict: Verdict
|
|
476
|
+
next_calls: list[PivotHint]
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
class UsernameLookupResponse(TypedDict, total=False):
|
|
480
|
+
username: str
|
|
481
|
+
found_count: int
|
|
482
|
+
platforms: list[dict[str, Any]]
|
|
483
|
+
summary: str
|
|
484
|
+
verdict: Verdict
|
|
485
|
+
next_calls: list[PivotHint]
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
# --- ATLAS ---
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
class AtlasTechniqueResponse(TypedDict, total=False):
|
|
492
|
+
technique_id: str
|
|
493
|
+
name: str
|
|
494
|
+
description: str
|
|
495
|
+
tactics: list[str]
|
|
496
|
+
inherited_tactics: bool
|
|
497
|
+
maturity: str
|
|
498
|
+
attack_reference_id: str
|
|
499
|
+
attack_reference_url: str
|
|
500
|
+
subtechnique_of: str
|
|
501
|
+
created_date: str
|
|
502
|
+
modified_date: str
|
|
503
|
+
verdict: Verdict
|
|
504
|
+
next_calls: list[PivotHint]
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
class AtlasTechniqueListItem(TypedDict, total=False):
|
|
508
|
+
technique_id: str
|
|
509
|
+
name: str
|
|
510
|
+
description: str
|
|
511
|
+
tactics: list[str]
|
|
512
|
+
inherited_tactics: bool
|
|
513
|
+
maturity: str
|
|
514
|
+
attack_reference_id: str
|
|
515
|
+
subtechnique_of: str
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
class AtlasTechniqueSearchResponse(TypedDict, total=False):
|
|
519
|
+
query: dict[str, Any]
|
|
520
|
+
total: int
|
|
521
|
+
results: list[AtlasTechniqueListItem]
|
|
522
|
+
verdict: Verdict
|
|
523
|
+
next_calls: list[PivotHint]
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
class AtlasCaseStudyResponse(TypedDict, total=False):
|
|
527
|
+
case_study_id: str
|
|
528
|
+
name: str
|
|
529
|
+
description: str
|
|
530
|
+
techniques_used: list[str]
|
|
531
|
+
verdict: Verdict
|
|
532
|
+
next_calls: list[PivotHint]
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
class AtlasCaseStudySearchResponse(TypedDict, total=False):
|
|
536
|
+
query: dict[str, Any]
|
|
537
|
+
total: int
|
|
538
|
+
results: list[AtlasCaseStudyResponse]
|
|
539
|
+
verdict: Verdict
|
|
540
|
+
next_calls: list[PivotHint]
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
# --- D3FEND ---
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
class D3fendDefenseResponse(TypedDict, total=False):
|
|
547
|
+
defense_id: str
|
|
548
|
+
label: str
|
|
549
|
+
uri: str
|
|
550
|
+
parent_label: str
|
|
551
|
+
description: str
|
|
552
|
+
tactic: str # singular
|
|
553
|
+
artifact: str
|
|
554
|
+
attack_techniques: list[str]
|
|
555
|
+
verdict: Verdict
|
|
556
|
+
next_calls: list[PivotHint]
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
class D3fendDefenseListItem(TypedDict, total=False):
|
|
560
|
+
defense_id: str
|
|
561
|
+
label: str
|
|
562
|
+
uri: str
|
|
563
|
+
parent_label: str
|
|
564
|
+
tactic: str
|
|
565
|
+
artifact: str
|
|
566
|
+
|
|
567
|
+
|
|
568
|
+
class D3fendDefenseSearchResponse(TypedDict, total=False):
|
|
569
|
+
query: dict[str, Any]
|
|
570
|
+
total: int
|
|
571
|
+
results: list[D3fendDefenseListItem]
|
|
572
|
+
verdict: Verdict
|
|
573
|
+
next_calls: list[PivotHint]
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
class D3fendDefenseForAttackItem(TypedDict, total=False):
|
|
577
|
+
defense_id: str
|
|
578
|
+
label: str
|
|
579
|
+
uri: str
|
|
580
|
+
parent_label: str
|
|
581
|
+
tactic: str
|
|
582
|
+
artifact: str
|
|
583
|
+
attack_label: str
|
|
584
|
+
attack_tactic: str
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
class D3fendForAttackResponse(TypedDict, total=False):
|
|
588
|
+
attack_technique_id: str
|
|
589
|
+
total: int
|
|
590
|
+
truncated: bool
|
|
591
|
+
defenses: list[D3fendDefenseForAttackItem]
|
|
592
|
+
coverage_by_tactic: dict[str, int]
|
|
593
|
+
verdict: Verdict
|
|
594
|
+
next_calls: list[PivotHint]
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
class D3fendCoverageResponse(TypedDict, total=False):
|
|
598
|
+
queried_techniques: list[str]
|
|
599
|
+
coverage_by_tactic: dict[str, int]
|
|
600
|
+
defended_techniques: list[str]
|
|
601
|
+
undefended_techniques: list[str]
|
|
602
|
+
verdict: Verdict
|
|
603
|
+
next_calls: list[PivotHint]
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
# --- Code-security checks + scan ---
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
class CodeCheckResponse(TypedDict, total=False):
|
|
610
|
+
findings: list[dict[str, Any]]
|
|
611
|
+
total: int
|
|
612
|
+
by_severity: dict[str, int]
|
|
613
|
+
summary: str
|
|
614
|
+
verdict: Verdict
|
|
615
|
+
next_calls: list[PivotHint]
|
|
616
|
+
|
|
617
|
+
|
|
618
|
+
class CheckHeadersResponse(TypedDict, total=False):
|
|
619
|
+
findings: list[dict[str, Any]]
|
|
620
|
+
total: int
|
|
621
|
+
by_severity: dict[str, int]
|
|
622
|
+
summary: str
|
|
623
|
+
verdict: Verdict
|
|
624
|
+
next_calls: list[PivotHint]
|
|
625
|
+
|
|
626
|
+
|
|
627
|
+
class ScanHeadersResponse(TypedDict, total=False):
|
|
628
|
+
domain: str
|
|
629
|
+
status_code: int
|
|
630
|
+
url: str
|
|
631
|
+
score: int
|
|
632
|
+
grade: str
|
|
633
|
+
findings: list[dict[str, Any]]
|
|
634
|
+
headers: dict[str, str]
|
|
635
|
+
summary: str
|
|
636
|
+
verdict: Verdict
|
|
637
|
+
next_calls: list[PivotHint]
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
class DependenciesResponse(TypedDict, total=False):
|
|
641
|
+
findings: list[dict[str, Any]]
|
|
642
|
+
total: int
|
|
643
|
+
by_severity: dict[str, int]
|
|
644
|
+
summary: str
|
|
645
|
+
verdict: Verdict
|
|
646
|
+
next_calls: list[PivotHint]
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
# --- Meta ---
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
class StatusResponse(TypedDict, total=False):
|
|
653
|
+
status: str
|
|
654
|
+
version: str
|
|
655
|
+
uptime_seconds: int
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
class UsageResponse(TypedDict, total=False):
|
|
659
|
+
requests_remaining: int
|
|
660
|
+
window_seconds: int
|
|
661
|
+
tier: str
|
|
File without changes
|