@cryptotaxi247 / CoPilot / commits / 894461e5

Mitre (#449)

* Add endpoint to search for MITRE techniques in alerts and update response models * Add endpoint to fetch alerts for specific MITRE techniques and update response models * Add endpoints for MITRE software, references, and mitigations with response models * Add endpoint and models for listing MITRE ATT&CK groups * Add tactic mapping to MITRE techniques in alerts processing * Add endpoint to list all available Atomic Red Team tests and update response models * Enhance regex handling and normalization for path-based exclusions in VeloSigmaExclusionService * Add pagination support to MITRE technique alerts endpoint and response model * Implement pagination for MITRE techniques in alerts endpoint and update response model * Add pagination support to Atomic Tests endpoint and update response model * Update agent name resolution in VelociraptorSigmaService to use hostname from Agents table if available * Refactor path-based regex handling in VeloSigmaExclusionService for improved normalization and matching * Remove redundant comment on path-based regex handling in VeloSigmaExclusionService * dev build * back to main * Fix dependency declaration for Velociraptor Sigma alert creation route * Add provisioning function for Crowdstrike monitoring alerts * Add CrowdStrike monitoring alert provisioning and update alert descriptions * Add provisioning for Fortinet system monitoring alerts * Add provisioning for Fortinet UTM monitoring alerts * Add provisioning for Palo Alto monitoring alerts * chore: update frontend dependencies * feat: add mitre api/types * dev build * back to main * feat: add function to conditionally create alert tags if they do not exist * feat: update mitre api/types * feat: update mitre api/types * fix: update description field to be optional with default value in Stream model * fix: enable dependency verification for Velociraptor Sigma alert creation route * feat: add mitre pages * fix: improve MITRE techniques pagination and total count retrieval in alerts search * feat: update mitre page * feat: update mitre pagination * chore: update frontend dependencies * feat: update mitre techniques list * feat: update mitre techniques list * feat: add mitre technique card * feat: add mitre technique overview * feat: add full event payload as comment in Velociraptor Sigma alerts * feat: update mitre technique overview * feat: update mitre groups overview * feat: update markdown component * feat: await check_wazuh_manager_version in provision_wazuh_customer function * chore: update frontend dependencies * feat: improve Technique Details sidebar * refactor: mitre components * feat: add group, software components * feat: add mitigation, tactic components * feat: add technique details * refactor: removed mock data * lint * feat: add alerts list * feat: add alert details * refactor: improve filters * feat: add shufflepy dependency * feat: enhance migration process with current revision check and logging * feat: add Singul integration routes and services * chore: update frontend dependencies * feat: update mitre api * feat: add atomic tests * chore: update frontend dependencies --------- Co-authored-by: Davide Di Modica <webmaster.ddm@gmail.com>

taylor_socfortress committed May 29, 2025 at 08:06 UTC 894461e50d634cdc9862f61099577eaa325868f7
388 files changed +12628 -2642
.vscode/settings.json
+1
@@ -54,6 +54,7 @@
54 "scoutsuite",
55 "Shiki",
56 "shikijs",
57 + "SIEM",
58 "signin",
59 "Socfortress",
60 "sparkline",
backend/app/connectors/graylog/schema/events.py
+2 -2
@@ -34,7 +34,7 @@ class Conditions(BaseModel):
34
35
36 class SeriesItem(BaseModel):
37 - type: str
37 + type: Optional[str] = None
38 id: str
39 field: Optional[str] = None
40
@@ -48,7 +48,7 @@ class Config(BaseModel):
48 search_within_ms: Optional[int] = Field(None, description="The search window in milliseconds")
49 series: Optional[Union[str, List[SeriesItem]]] = Field(None, description="The series to be included in the config")
50 streams: Optional[List[str]] = Field(None, description="The streams to be included in the config")
51 - type: str = Field(..., description="The type of the config")
51 + type: Optional[str] = Field(None, description="The type of the config")
52
53
54 class NotificationSettings(BaseModel):
backend/app/connectors/graylog/schema/streams.py
+2 -1
@@ -2,6 +2,7 @@ from typing import List
2 from typing import Optional
3
4 from pydantic import BaseModel
5 +from pydantic import Field
6
7
8 class Rule(BaseModel):
@@ -18,7 +19,7 @@ class Stream(BaseModel):
19 content_pack: Optional[str]
20 created_at: str
21 creator_user_id: str
21 - description: str
22 + description: Optional[str] = Field('No description provided')
23 disabled: bool
24 id: str
25 index_set_id: str
backend/app/connectors/shuffle/routes/singul.py new
+28
@@ -0,0 +1,28 @@
1 +from fastapi import APIRouter
2 +from fastapi import Security
3 +from loguru import logger
4 +
5 +from app.auth.utils import AuthHandler
6 +from app.connectors.shuffle.schema.singul import SingulRequest
7 +from app.connectors.shuffle.services.singul import execute_singul
8 +
9 +shuffle_singul_router = APIRouter()
10 +
11 +
12 +@shuffle_singul_router.post(
13 + "/execute",
14 + description="Execute a Shuffle Integration.",
15 + dependencies=[Security(AuthHandler().require_any_scope("admin", "analyst"))],
16 +)
17 +async def execute_integration_route(request: SingulRequest):
18 + """
19 + Execute a workflow.
20 +
21 + Args:
22 + request (SingulRequest): The request object containing the workflow ID.
23 +
24 + Returns:
25 + dict: The response containing the execution ID.
26 + """
27 + logger.info("Executing Singul integration")
28 + return await execute_singul(request)
backend/app/connectors/shuffle/schema/singul.py new
+14
@@ -0,0 +1,14 @@
1 +from typing import Any
2 +from typing import Dict
3 +from typing import List
4 +from typing import Optional
5 +
6 +from fastapi import HTTPException
7 +from pydantic import BaseModel
8 +from pydantic import Field
9 +from pydantic import root_validator
10 +
11 +
12 +class SingulRequest(BaseModel):
13 + app: str = Field(..., description="The name of the application", example="outlook_office365")
14 +
backend/app/connectors/shuffle/services/singul.py new
+34
@@ -0,0 +1,34 @@
1 +from loguru import logger
2 +from shufflepy import Singul
3 +from app.connectors.shuffle.schema.singul import SingulRequest
4 +from app.connectors.shuffle.utils.universal import send_post_request
5 +
6 +singul = Singul(auth="TEMP", url="https://singul.io")
7 +
8 +async def execute_singul(
9 + request: SingulRequest,
10 +) -> dict:
11 + """
12 + Execute a Singul integration.
13 +
14 + Args:
15 + request (IntegrationRequest): The request object containing the workflow ID.
16 +
17 + Returns:
18 + dict: The response containing the execution ID.
19 + """
20 + logger.info("Executing Singul integration")
21 + response = singul.communication.send_message(
22 + app=request.app,
23 + fields=[
24 + {"key": "to", "value": "walton.taylor23@gmail.com"},
25 + {"key": "subject", "value": "Test Email from Singul"},
26 + {"key": "body", "value": "This is a test email sent from Singul."},
27 + ]
28 + )
29 + logger.info(f"Singul response: {response}")
30 + return {
31 + "executionId": response.get("id", "unknown"),
32 + "message": "Singul integration executed successfully",
33 + }
34 +
backend/app/connectors/wazuh_manager/routes/mitre.py
+312 -4
@@ -7,20 +7,148 @@ from fastapi import Path
7 from fastapi import Query
8 from fastapi import Security
9 from loguru import logger
10 +from fastapi import HTTPException
11
12 from app.auth.routes.auth import AuthHandler
13 from app.connectors.wazuh_manager.schema.mitre import AtomicRedTeamMarkdownResponse
13 -from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTacticsResponse
14 -from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTechniquesResponse
14 +from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTacticsResponse, AtomicTestsListResponse
15 +from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTechniquesResponse, MitreTechniquesInAlertsResponse, MitreTechniqueInAlert, MitreTechniqueAlertsResponse, WazuhMitreSoftwareResponse, WazuhMitreReferencesResponse, WazuhMitreMitigationsResponse, WazuhMitreGroupsResponse
16 +from app.connectors.wazuh_manager.services.mitre import get_alerts_by_mitre_id, get_mitre_references, get_mitre_groups
17 from app.connectors.wazuh_manager.services.mitre import AtomicRedTeamService
16 -from app.connectors.wazuh_manager.services.mitre import get_mitre_tactics
17 -from app.connectors.wazuh_manager.services.mitre import get_mitre_techniques
18 +from app.connectors.wazuh_manager.services.mitre import get_mitre_tactics, get_mitre_software, get_mitre_mitigations
19 +from app.connectors.wazuh_manager.services.mitre import get_mitre_techniques, search_mitre_techniques_in_alerts
20
21 # Initialize router and auth handler
22 wazuh_manager_mitre_router = APIRouter()
23 auth_handler = AuthHandler()
24
25
26 +@wazuh_manager_mitre_router.get(
27 + "/groups",
28 + response_model=WazuhMitreGroupsResponse,
29 + description="List MITRE ATT&CK groups",
30 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
31 +)
32 +async def list_mitre_groups(
33 + limit: Optional[int] = Query(None, description="Maximum number of items to return"),
34 + offset: Optional[int] = Query(None, description="First item to return"),
35 + select: Optional[List[str]] = Query(None, description="List of fields to return"),
36 + sort: Optional[str] = Query(None, description="Fields to sort by"),
37 + search: Optional[str] = Query(None, description="Text to search in fields"),
38 + q: Optional[str] = Query(None, description="Query to filter results"),
39 +):
40 + """
41 + List MITRE ATT&CK groups with optional filtering parameters.
42 +
43 + Args:
44 + limit: Maximum number of items to return
45 + offset: First item to return
46 + select: List of fields to return
47 + sort: Fields to sort by
48 + search: Text to search in fields
49 + q: Query to filter results
50 +
51 + Returns:
52 + WazuhMitreGroupsResponse: A list of MITRE ATT&CK groups matching the criteria.
53 + """
54 + return await get_mitre_groups(
55 + limit=limit, offset=offset, select=select, sort=sort, search=search, q=q
56 + )
57 +
58 +@wazuh_manager_mitre_router.get(
59 + "/mitigations",
60 + response_model=WazuhMitreMitigationsResponse,
61 + description="List MITRE ATT&CK mitigations",
62 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
63 +)
64 +async def list_mitre_mitigations(
65 + limit: Optional[int] = Query(None, description="Maximum number of items to return"),
66 + offset: Optional[int] = Query(None, description="First item to return"),
67 + select: Optional[List[str]] = Query(None, description="List of fields to return"),
68 + sort: Optional[str] = Query(None, description="Fields to sort by"),
69 + search: Optional[str] = Query(None, description="Text to search in fields"),
70 + q: Optional[str] = Query(None, description="Query to filter results"),
71 +):
72 + """
73 + List MITRE ATT&CK mitigations with optional filtering parameters.
74 +
75 + Args:
76 + limit: Maximum number of items to return
77 + offset: First item to return
78 + select: List of fields to return
79 + sort: Fields to sort by
80 + search: Text to search in fields
81 + q: Query to filter results
82 +
83 + Returns:
84 + WazuhMitreMitigationsResponse: A list of MITRE ATT&CK mitigations matching the criteria.
85 + """
86 + return await get_mitre_mitigations(
87 + limit=limit, offset=offset, select=select, sort=sort, search=search, q=q
88 + )
89 +
90 +@wazuh_manager_mitre_router.get(
91 + "/references",
92 + response_model=WazuhMitreReferencesResponse,
93 + description="List MITRE ATT&CK references",
94 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
95 +)
96 +async def list_mitre_references(
97 + limit: Optional[int] = Query(None, description="Maximum number of items to return"),
98 + offset: Optional[int] = Query(None, description="First item to return"),
99 + sort: Optional[str] = Query(None, description="Fields to sort by"),
100 + search: Optional[str] = Query(None, description="Text to search in fields"),
101 + q: Optional[str] = Query(None, description="Query to filter results"),
102 +):
103 + """
104 + List MITRE ATT&CK references with optional filtering parameters.
105 +
106 + Args:
107 + limit: Maximum number of items to return
108 + offset: First item to return
109 + sort: Fields to sort by
110 + search: Text to search in fields
111 + q: Query to filter results
112 +
113 + Returns:
114 + WazuhMitreReferencesResponse: A list of MITRE ATT&CK references matching the criteria.
115 + """
116 + return await get_mitre_references(
117 + limit=limit, offset=offset, sort=sort, search=search, q=q
118 + )
119 +
120 +@wazuh_manager_mitre_router.get(
121 + "/software",
122 + response_model=WazuhMitreSoftwareResponse,
123 + description="List MITRE ATT&CK software",
124 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
125 +)
126 +async def list_mitre_software(
127 + limit: Optional[int] = Query(None, description="Maximum number of items to return"),
128 + offset: Optional[int] = Query(None, description="First item to return"),
129 + select: Optional[List[str]] = Query(None, description="List of fields to return"),
130 + sort: Optional[str] = Query(None, description="Fields to sort by"),
131 + search: Optional[str] = Query(None, description="Text to search in fields"),
132 + q: Optional[str] = Query(None, description="Query to filter results"),
133 +):
134 + """
135 + List MITRE ATT&CK software with optional filtering parameters.
136 +
137 + Args:
138 + limit: Maximum number of items to return
139 + offset: First item to return
140 + select: List of fields to return
141 + sort: Fields to sort by
142 + search: Text to search in fields
143 + q: Query to filter results
144 +
145 + Returns:
146 + WazuhMitreSoftwareResponse: A list of MITRE ATT&CK software matching the criteria.
147 + """
148 + return await get_mitre_software(
149 + limit=limit, offset=offset, select=select, sort=sort, search=search, q=q
150 + )
151 +
152 @wazuh_manager_mitre_router.get(
153 "/tactics",
154 response_model=WazuhMitreTacticsResponse,
@@ -83,6 +211,59 @@ async def list_mitre_techniques(
211 return await get_mitre_techniques(limit=limit, offset=offset, select=select, sort=sort, search=search, q=q)
212
213
214 +@wazuh_manager_mitre_router.get(
215 + "/atomic-tests",
216 + response_model=AtomicTestsListResponse,
217 + description="List all available Atomic Red Team tests",
218 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
219 +)
220 +async def list_atomic_tests(
221 + size: int = Query(25, description="Maximum number of techniques to return per page"),
222 + page: int = Query(1, description="Page number for pagination", gt=0),
223 +):
224 + """
225 + List all available Atomic Red Team tests across all techniques.
226 +
227 + Args:
228 + size: Maximum number of techniques to return per page
229 + page: Page number for pagination
230 +
231 + Returns:
232 + AtomicTestsListResponse: A paginated list of techniques with Atomic Red Team tests.
233 + """
234 + logger.info(f"Request for list of all Atomic Red Team tests (page {page}, size {size})")
235 +
236 + try:
237 + # Get the list of all atomic tests
238 + result = await AtomicRedTeamService.list_all_atomic_tests()
239 +
240 + # Apply pagination to the results
241 + total_techniques = result["total_techniques"]
242 + all_tests = result["tests"]
243 +
244 + # Calculate total pages
245 + total_pages = (total_techniques + size - 1) // size if total_techniques > 0 else 1
246 +
247 + # Apply pagination
248 + start_idx = (page - 1) * size
249 + end_idx = start_idx + size
250 + paginated_tests = all_tests[start_idx:end_idx]
251 +
252 + return AtomicTestsListResponse(
253 + success=True,
254 + message=f"Found {total_techniques} techniques with {result.get('total_tests', 'many')} atomic tests (page {page} of {total_pages})",
255 + total_techniques=total_techniques,
256 + total_tests=result.get("total_tests"),
257 + tests=paginated_tests,
258 + last_updated=result["last_updated"],
259 + page=page,
260 + page_size=size,
261 + total_pages=total_pages
262 + )
263 + except Exception as e:
264 + logger.error(f"Error retrieving atomic tests: {str(e)}")
265 + raise HTTPException(status_code=500, detail=f"Error retrieving atomic tests: {str(e)}")
266 +
267 @wazuh_manager_mitre_router.get(
268 "/techniques/{technique_id}/atomic-tests",
269 response_model=AtomicRedTeamMarkdownResponse,
@@ -120,3 +301,130 @@ async def get_technique_atomic_tests(technique_id: str = Path(..., description="
301 technique_id=clean_technique_id,
302 markdown_content=markdown_content,
303 )
304 +
305 +@wazuh_manager_mitre_router.get(
306 + "/techniques/alerts",
307 + response_model=MitreTechniquesInAlertsResponse,
308 + description="Search for MITRE ATT&CK techniques in alerts",
309 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
310 +)
311 +async def list_mitre_techniques_in_alerts(
312 + time_range: str = Query("now-24h", description="Time range for the search (e.g., now-24h, now-7d)"),
313 + size: int = Query(25, description="Maximum number of techniques to return per page"),
314 + page: int = Query(1, description="Page number for pagination", gt=0),
315 + rule_level: Optional[int] = Query(None, description="Filter by rule level"),
316 + rule_group: Optional[str] = Query(None, description="Filter by rule group"),
317 + mitre_field: Optional[str] = Query(None, description="Override the field containing MITRE IDs"),
318 + index_pattern: str = Query("wazuh-*", description="Index pattern to search"),
319 +) -> MitreTechniquesInAlertsResponse:
320 + """Search for MITRE ATT&CK techniques in Wazuh alerts."""
321 + logger.info(f"Searching for MITRE techniques in alerts from {time_range} (page {page}, size {size})")
322 +
323 + # Calculate the offset based on page and size
324 + offset = (page - 1) * size
325 +
326 + # Build additional filters based on request parameters
327 + additional_filters = []
328 +
329 + if rule_level is not None:
330 + additional_filters.append({
331 + "match_phrase": {"rule_level": {"query": str(rule_level)}}
332 + })
333 +
334 + if rule_group is not None:
335 + additional_filters.append({
336 + "match_phrase": {"rule_groups": {"query": rule_group}}
337 + })
338 +
339 + # Execute the search with the specified parameters
340 + results = await search_mitre_techniques_in_alerts(
341 + time_range=time_range,
342 + size=size,
343 + offset=offset,
344 + additional_filters=additional_filters,
345 + index_pattern=index_pattern,
346 + mitre_field=mitre_field
347 + )
348 +
349 + # Get the total number of techniques (from all pages)
350 + total_techniques = results.get('total_techniques_count', results['techniques_count'])
351 +
352 + # Calculate total pages based on the total number of techniques
353 + total_pages = (total_techniques + size - 1) // size if total_techniques > 0 else 1
354 +
355 + return MitreTechniquesInAlertsResponse(
356 + success=True,
357 + message=f"Found {total_techniques} MITRE techniques in {results['total_alerts']} alerts (page {page} of {total_pages})",
358 + total_alerts=results['total_alerts'],
359 + techniques_count=total_techniques, # Use the total count for all pages
360 + techniques=results['techniques'], # Use current page techniques
361 + time_range=time_range,
362 + field_used=results.get('field_used', 'unknown'),
363 + page=page,
364 + page_size=size,
365 + total_pages=total_pages
366 + )
367 +
368 +
369 +@wazuh_manager_mitre_router.get(
370 + "/techniques/{technique_id}/alerts",
371 + response_model=MitreTechniqueAlertsResponse,
372 + description="Get alert documents for a specific MITRE ATT&CK technique",
373 + dependencies=[Security(auth_handler.require_any_scope("admin", "analyst"))],
374 +)
375 +async def get_mitre_technique_alerts(
376 + technique_id: str = Path(..., description="MITRE ATT&CK technique ID (e.g., T1047, 1047)"),
377 + time_range: str = Query("now-24h", description="Time range for the search (e.g., now-24h, now-7d)"),
378 + size: int = Query(25, description="Maximum number of alerts to return per page"),
379 + page: int = Query(1, description="Page number for pagination", gt=0),
380 + rule_level: Optional[int] = Query(None, description="Filter by rule level"),
381 + rule_group: Optional[str] = Query(None, description="Filter by rule group"),
382 + mitre_field: Optional[str] = Query(None, description="Override the field containing MITRE IDs"),
383 + index_pattern: str = Query("wazuh-*", description="Index pattern to search"),
384 +) -> MitreTechniqueAlertsResponse:
385 + """Get alert documents for a specific MITRE ATT&CK technique."""
386 + logger.info(f"Request for alerts related to MITRE technique {technique_id} from {time_range} (page {page}, size {size})")
387 +
388 + # Clean up technique ID if needed
389 + clean_technique_id = technique_id.strip()
390 +
391 + # Calculate the offset based on page and size
392 + offset = (page - 1) * size
393 +
394 + # Build additional filters based on request parameters
395 + additional_filters = []
396 +
397 + if rule_level is not None:
398 + additional_filters.append({
399 + "match_phrase": {"rule_level": {"query": str(rule_level)}}
400 + })
401 +
402 + if rule_group is not None:
403 + additional_filters.append({
404 + "match_phrase": {"rule_groups": {"query": rule_group}}
405 + })
406 +
407 + # Get the alerts
408 + results = await get_alerts_by_mitre_id(
409 + technique_id=clean_technique_id,
410 + time_range=time_range,
411 + size=size,
412 + offset=offset,
413 + additional_filters=additional_filters,
414 + index_pattern=index_pattern,
415 + mitre_field=mitre_field
416 + )
417 +
418 + return MitreTechniqueAlertsResponse(
419 + success=True,
420 + message=f"Found {results['total_alerts']} alerts for MITRE technique {clean_technique_id} (page {page} of {(results['total_alerts'] + size - 1) // size})",
421 + technique_id=results['technique_id'],
422 + technique_name=results['technique_name'],
423 + total_alerts=results['total_alerts'],
424 + alerts=results['alerts'],
425 + field_used=results.get('field_used', 'unknown'),
426 + time_range=time_range,
427 + page=page,
428 + page_size=size,
429 + total_pages=(results['total_alerts'] + size - 1) // size
430 + )
backend/app/connectors/wazuh_manager/schema/mitre.py
+172 -1
@@ -3,7 +3,7 @@ from typing import Dict
3 from typing import List
4 from typing import Optional
5
6 -from pydantic import BaseModel
6 +from pydantic import BaseModel, Field
7
8
9 class MitreTacticItem(BaseModel):
@@ -119,3 +119,174 @@ class AtomicRedTeamMarkdownResponse(BaseModel):
119 message: str
120 technique_id: str
121 markdown_content: Optional[str] = None
122 +
123 +
124 +class AtomicTestSummary(BaseModel):
125 + """Summary information about an Atomic Red Team test."""
126 + technique_id: str = Field(..., description="MITRE ATT&CK technique ID")
127 + technique_name: str = Field(..., description="MITRE ATT&CK technique name")
128 + test_count: int = Field(..., description="Number of atomic tests available for this technique")
129 + categories: List[str] = Field(default_factory=list, description="Categories/platforms the tests cover")
130 + has_prerequisites: bool = Field(False, description="Whether the tests have prerequisites")
131 +
132 +class AtomicTestsListResponse(BaseModel):
133 + """Response model for listing all available Atomic Red Team tests."""
134 + success: bool = Field(True, description="Whether the request was successful")
135 + message: str = Field(..., description="Response message")
136 + total_techniques: int = Field(..., description="Total number of techniques with atomic tests")
137 + total_tests: Optional[int] = Field(None, description="Total number of individual atomic tests")
138 + tests: List[AtomicTestSummary] = Field(..., description="List of techniques with atomic tests")
139 + last_updated: str = Field(..., description="When the test information was last updated")
140 + page: int = Field(1, description="Current page number")
141 + page_size: int = Field(..., description="Number of items per page")
142 + total_pages: int = Field(..., description="Total number of pages available")
143 +
144 +class MitreTechniqueInAlert(BaseModel):
145 + """Schema for a MITRE technique found in alerts."""
146 + technique_id: str = Field(..., description="MITRE ATT&CK technique ID")
147 + technique_name: str = Field(..., description="MITRE ATT&CK technique name")
148 + count: int = Field(..., description="Number of alerts containing this technique")
149 + last_seen: Optional[str] = Field(None, description="Last time this technique was seen in an alert")
150 + tactics: List[Dict[str, str]] = Field(default_factory=list, description="Associated tactics for this technique")
151 +
152 +
153 +class MitreTechniquesInAlertsResponse(BaseModel):
154 + """Response schema for MITRE techniques found in alerts."""
155 + success: bool = Field(True, description="Whether the request was successful")
156 + message: str = Field(..., description="Description of the response")
157 + total_alerts: int = Field(..., description="Total number of alerts matching the query")
158 + techniques_count: int = Field(..., description="Number of unique techniques found")
159 + techniques: List[MitreTechniqueInAlert] = Field(..., description="List of techniques with counts")
160 + time_range: str = Field(..., description="Time range used for the search")
161 + field_used: Optional[str] = Field(..., description="Field name used to extract MITRE techniques")
162 + page: int = Field(1, description="Current page number")
163 + page_size: int = Field(..., description="Number of items per page")
164 + total_pages: int = Field(..., description="Total number of pages available")
165 +
166 +
167 +class MitreTechniqueAlertsResponse(BaseModel):
168 + """Response schema for detailed alerts associated with a specific MITRE technique."""
169 + success: bool = Field(True, description="Whether the request was successful")
170 + message: str = Field(..., description="Description of the response")
171 + technique_id: str = Field(..., description="The MITRE technique ID that was searched for")
172 + technique_name: str = Field(..., description="The name of the MITRE technique")
173 + total_alerts: int = Field(..., description="Total number of alerts found")
174 + alerts: List[Dict] = Field(..., description="List of alert documents")
175 + field_used: Optional[str] = Field(..., description="Field name used to search for MITRE techniques")
176 + time_range: str = Field(..., description="Time range used for the search")
177 + page: int = Field(1, description="Current page number")
178 + page_size: int = Field(..., description="Number of items per page")
179 + total_pages: int = Field(..., description="Total number of pages available")
180 +
181 +
182 +class MitreSoftwareItem(BaseModel):
183 + """Represents a single MITRE ATT&CK software from Wazuh's API."""
184 +
185 + mitre_version: Optional[str] = None
186 + deprecated: int = 0
187 + description: str
188 + name: str
189 + id: str
190 + modified_time: str
191 + created_time: str
192 + groups: List[str] = []
193 + techniques: List[str] = []
194 + references: List[MitreReference] = []
195 + url: str
196 + source: str
197 + external_id: str
198 +
199 + # Additional fields that might be present
200 + platforms: Optional[List[str]] = None
201 + aliases: Optional[List[str]] = None
202 + type: Optional[str] = None # For distinguishing between malware, tool, etc.
203 +
204 + class Config:
205 + """Configuration for the model."""
206 + extra = "ignore" # Ignore extra fields from the API
207 +
208 +
209 +class WazuhMitreSoftwareResponse(BaseModel):
210 + """Response model for the MITRE software endpoint."""
211 +
212 + success: bool
213 + message: str
214 + results: List[MitreSoftwareItem] = []
215 +
216 +class MitreReferenceItem(BaseModel):
217 + """Represents a single MITRE ATT&CK reference from Wazuh's API."""
218 + url: str
219 + description: Optional[str] = None
220 + source: str
221 + id: Optional[str] = None # ID of the related technique, tactic, or software
222 + type: Optional[str] = None # Type of the item the reference belongs to (technique, tactic, etc.)
223 +
224 + class Config:
225 + """Configuration for the model."""
226 + extra = "ignore" # Ignore extra fields from the API
227 +
228 +class WazuhMitreReferencesResponse(BaseModel):
229 + """Response model for the MITRE references endpoint."""
230 + success: bool
231 + message: str
232 + results: List[MitreReferenceItem] = []
233 + total: int = 0
234 +
235 +class MitreMitigationItem(BaseModel):
236 + """Represents a single MITRE ATT&CK mitigation from Wazuh's API."""
237 + mitre_version: Optional[str] = None
238 + deprecated: int = 0
239 + description: str
240 + name: str
241 + id: str
242 + modified_time: str
243 + created_time: str
244 + techniques: List[str] = []
245 + references: List[MitreReference] = []
246 + url: str
247 + source: str
248 + external_id: str
249 +
250 + class Config:
251 + """Configuration for the model."""
252 + extra = "ignore" # Ignore extra fields from the API
253 +
254 +
255 +class WazuhMitreMitigationsResponse(BaseModel):
256 + """Response model for the MITRE mitigations endpoint."""
257 + success: bool
258 + message: str
259 + results: List[MitreMitigationItem] = []
260 + total: int = 0
261 +
262 +class MitreGroupItem(BaseModel):
263 + """Represents a single MITRE ATT&CK group from Wazuh's API."""
264 + mitre_version: Optional[str] = None
265 + deprecated: int = 0
266 + description: Optional[str] = None
267 + name: str
268 + id: str
269 + modified_time: str
270 + created_time: str
271 + software: List[str] = []
272 + techniques: List[str] = []
273 + references: List[MitreReference] = []
274 + url: str
275 + external_id: str
276 + source: str
277 +
278 + # Additional fields that might be present
279 + aliases: Optional[List[str]] = None
280 + country: Optional[str] = None
281 +
282 + class Config:
283 + """Configuration for the model."""
284 + extra = "ignore" # Ignore extra fields from the API
285 +
286 +
287 +class WazuhMitreGroupsResponse(BaseModel):
288 + """Response model for the MITRE groups endpoint."""
289 + success: bool
290 + message: str
291 + results: List[MitreGroupItem] = []
292 + total: int = 0
backend/app/connectors/wazuh_manager/services/mitre.py
+1067 -3
@@ -2,16 +2,24 @@ import time
2 from typing import Dict
3 from typing import List
4 from typing import Optional
5 -from typing import Tuple
6 -
5 +from typing import Tuple, Union
6 +from datetime import datetime
7 +import yaml
8 import aiohttp
9 +import asyncio
10 from fastapi import HTTPException
11 from loguru import logger
12 +import re
13 +import json
14 from pydantic import ValidationError
15
16 from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTacticsResponse
13 -from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTechniquesResponse
17 +from app.connectors.wazuh_manager.schema.mitre import WazuhMitreTechniquesResponse, WazuhMitreSoftwareResponse, WazuhMitreReferencesResponse, WazuhMitreMitigationsResponse, WazuhMitreGroupsResponse
18 from app.connectors.wazuh_manager.utils.universal import send_get_request
19 +from app.connectors.wazuh_indexer.utils.universal import (
20 + create_wazuh_indexer_client_async,
21 +)
22 +from elasticsearch7 import AsyncElasticsearch
23
24 # Constants for the Atomic Red Team GitHub repository
25 GITHUB_RAW_URL = "https://raw.githubusercontent.com/redcanaryco/atomic-red-team/refs/heads/master/atomics"
@@ -24,6 +32,198 @@ class AtomicRedTeamService:
32 # Cache to store the markdown content with timestamp
33 # Format: {technique_id: (markdown_content, timestamp)}
34 _cache: Dict[str, Tuple[str, float]] = {}
35 + _tests_cache: Dict[str, Tuple[List[Dict], float]] = {} # Cache for all tests
36 +
37 + @classmethod
38 + async def list_all_atomic_tests(cls) -> Dict:
39 + """
40 + Get a list of all available Atomic Red Team tests.
41 +
42 + Returns:
43 + Dict containing test information and metadata
44 + """
45 + # Check cache first
46 + if "all_tests" in cls._tests_cache:
47 + tests, timestamp = cls._tests_cache["all_tests"]
48 + if time.time() - timestamp < CACHE_EXPIRY:
49 + logger.debug("Returning cached list of all atomic tests")
50 + return {
51 + "total_techniques": len(tests),
52 + "tests": tests,
53 + "last_updated": datetime.fromtimestamp(timestamp).isoformat()
54 + }
55 +
56 + # Fetch the list of all techniques with atomic tests
57 + try:
58 + # First, try to fetch index.yaml which has metadata about all tests
59 + async with aiohttp.ClientSession() as session:
60 + url = "https://raw.githubusercontent.com/redcanaryco/atomic-red-team/refs/heads/master/atomics/Indexes/Indexes-Markdown/atomic-red-team-index.md"
61 + async with session.get(url) as response:
62 + if response.status == 200:
63 + return await cls._parse_atomic_index_markdown(await response.text())
64 +
65 + # If markdown index not available, try alternate approach
66 + logger.warning(f"Could not fetch atomic-red-team-index.md: {response.status}. Trying alternate method.")
67 + return await cls._fetch_techniques_from_atomics_folder()
68 + except Exception as e:
69 + logger.error(f"Error listing atomic tests: {str(e)}")
70 + raise HTTPException(status_code=500, detail=f"Error listing atomic tests: {str(e)}")
71 + @classmethod
72 + async def _parse_atomic_index_markdown(cls, content: str) -> Dict:
73 + """Parse the atomic-red-team-index.md file to extract test information."""
74 + techniques = []
75 + technique_pattern = r'\|\s*\[([^]]+)\]\([^)]+\)\s*\|\s*([T\d\.]+)\s*\|\s*(\d+)\s*\|'
76 +
77 + matches = re.findall(technique_pattern, content)
78 + total_tests = 0
79 +
80 + for name, technique_id, test_count in matches:
81 + try:
82 + count = int(test_count)
83 + total_tests += count
84 + techniques.append({
85 + "technique_id": technique_id,
86 + "technique_name": name,
87 + "test_count": count,
88 + "categories": [], # Would require additional requests to determine
89 + "has_prerequisites": False # Would require additional requests to determine
90 + })
91 + except ValueError:
92 + continue # Skip if test_count isn't a valid integer
93 +
94 + result = {
95 + "total_techniques": len(techniques),
96 + "total_tests": total_tests,
97 + "tests": techniques,
98 + "last_updated": datetime.utcnow().isoformat()
99 + }
100 +
101 + # Cache the result
102 + cls._tests_cache["all_tests"] = (techniques, time.time())
103 +
104 + return result
105 +
106 + @classmethod
107 + async def _fetch_techniques_from_atomics_folder(cls) -> Dict:
108 + """Fetch and parse techniques directly from the Atomic Red Team repository."""
109 + # This is a fallback method that fetches the techniques directly from the GitHub API
110 + try:
111 + async with aiohttp.ClientSession() as session:
112 + url = "https://api.github.com/repos/redcanaryco/atomic-red-team/contents/atomics"
113 + headers = {"Accept": "application/vnd.github.v3+json"}
114 +
115 + async with session.get(url, headers=headers) as response:
116 + if response.status != 200:
117 + logger.error(f"GitHub API error: {response.status}")
118 + raise HTTPException(status_code=response.status,
119 + detail="Could not access Atomic Red Team repository")
120 +
121 + folders = await response.json()
122 +
123 + # Filter to only include technique folders (T#### format)
124 + technique_folders = [f for f in folders if f["type"] == "dir" and f["name"].startswith("T")]
125 +
126 + techniques = []
127 + total_tests = 0
128 +
129 + # Process each technique folder (limit concurrent requests)
130 + semaphore = asyncio.Semaphore(5) # Limit to 5 concurrent requests
131 +
132 + async def process_technique(folder):
133 + nonlocal total_tests
134 + technique_id = folder["name"]
135 +
136 + async with semaphore:
137 + # Try to get the YAML file that contains test information
138 + yaml_url = f"{GITHUB_RAW_URL}/{technique_id}/{technique_id}.yaml"
139 + md_url = f"{GITHUB_RAW_URL}/{technique_id}/{technique_id}.md"
140 +
141 + # First try YAML for structured data
142 + async with session.get(yaml_url) as yaml_resp:
143 + if yaml_resp.status == 200:
144 + yaml_content = await yaml_resp.text()
145 + try:
146 + data = yaml.safe_load(yaml_content)
147 + test_count = len(data.get('atomic_tests', []))
148 + total_tests += test_count
149 + platforms = set()
150 + has_prereqs = False
151 +
152 + for test in data.get('atomic_tests', []):
153 + if test.get('supported_platforms'):
154 + platforms.update(test.get('supported_platforms', []))
155 + if test.get('dependencies'):
156 + has_prereqs = True
157 +
158 + return {
159 + "technique_id": technique_id,
160 + "technique_name": data.get('display_name', technique_id),
161 + "test_count": test_count,
162 + "categories": list(platforms),
163 + "has_prerequisites": has_prereqs
164 + }
165 + except Exception as e:
166 + logger.warning(f"Error parsing YAML for {technique_id}: {e}")
167 +
168 + # Fall back to MD file and extract basic info
169 + async with session.get(md_url) as md_resp:
170 + if md_resp.status == 200:
171 + md_content = await md_resp.text()
172 +
173 + # Extract name from markdown header
174 + name_match = re.search(r'# ([^\n]+)', md_content)
175 + name = name_match.group(1) if name_match else technique_id
176 +
177 + # Count atomic tests by headers
178 + test_headers = re.findall(r'## Atomic Test #\d+', md_content)
179 + test_count = len(test_headers)
180 + total_tests += test_count
181 +
182 + # Look for platform indicators
183 + platforms = []
184 + if 'windows' in md_content.lower():
185 + platforms.append('windows')
186 + if 'macos' in md_content.lower() or 'darwin' in md_content.lower():
187 + platforms.append('macos')
188 + if 'linux' in md_content.lower():
189 + platforms.append('linux')
190 +
191 + return {
192 + "technique_id": technique_id,
193 + "technique_name": name.replace(f"- {technique_id}", "").strip(),
194 + "test_count": test_count,
195 + "categories": platforms,
196 + "has_prerequisites": 'dependency' in md_content.lower() or 'dependencies' in md_content.lower()
197 + }
198 +
199 + # If both methods fail, return basic info
200 + return {
201 + "technique_id": technique_id,
202 + "technique_name": technique_id,
203 + "test_count": 0,
204 + "categories": [],
205 + "has_prerequisites": False
206 + }
207 +
208 + # Process all techniques concurrently but with rate limiting
209 + technique_tasks = [process_technique(folder) for folder in technique_folders]
210 + techniques = [t for t in await asyncio.gather(*technique_tasks) if t["test_count"] > 0]
211 +
212 + result = {
213 + "total_techniques": len(techniques),
214 + "total_tests": total_tests,
215 + "tests": techniques,
216 + "last_updated": datetime.utcnow().isoformat()
217 + }
218 +
219 + # Cache the result
220 + cls._tests_cache["all_tests"] = (techniques, time.time())
221 +
222 + return result
223 +
224 + except Exception as e:
225 + logger.error(f"Error fetching atomic tests from GitHub: {str(e)}")
226 + raise HTTPException(status_code=500, detail=f"Error listing atomic tests: {str(e)}")
227
228 @classmethod
229 async def get_technique_markdown(cls, technique_id: str) -> Optional[str]:
@@ -210,3 +410,867 @@ async def get_mitre_techniques(
410 except Exception as e:
411 logger.error(f"Error parsing Wazuh MITRE techniques response: {e}")
412 raise HTTPException(status_code=500, detail=f"Error processing MITRE data: {str(e)}")
413 +
414 +
415 +
416 +async def search_mitre_techniques_in_alerts(
417 + time_range: str = "now-24h",
418 + size: int = 1000,
419 + offset: int = 0,
420 + additional_filters: Optional[List[Dict]] = None,
421 + index_pattern: str = "wazuh-*",
422 + mitre_field: Optional[str] = None,
423 +) -> Dict[str, Union[int, List[Dict]]]:
424 + """
425 + Search for MITRE ATT&CK techniques in Wazuh alerts using the Wazuh Indexer.
426 + """
427 + logger.info(f"Searching for MITRE techniques in alerts from {time_range} to now")
428 +
429 + try:
430 + # First get technique data from Wazuh to build ID-name mapping as fallback
431 + technique_mapping = await _build_technique_id_name_mapping()
432 + logger.debug(f"Built technique mapping with {len(technique_mapping)} techniques")
433 +
434 + # Now get the tactic information for each technique
435 + technique_tactic_mapping = await _build_technique_tactic_mapping()
436 +
437 + # Log the number of entries in our mappings
438 + logger.info(f"Built technique mapping with {len(technique_mapping)} techniques")
439 + logger.info(f"Built technique-tactic mapping with {len(technique_tactic_mapping)} techniques")
440 +
441 + # If debugging is needed, log a few sample keys from the mapping
442 + if technique_tactic_mapping:
443 + sample_keys = list(technique_tactic_mapping.keys())[:5]
444 + logger.debug(f"Sample keys in technique_tactic_mapping: {sample_keys}")
445 +
446 + # Get Wazuh Indexer client
447 + client = await _get_wazuh_indexer_client()
448 +
449 + # Try multiple field paths that might contain MITRE IDs
450 + field_options = ["rule_mitre_id", "rule.mitre.id", "mitre.id"]
451 + if mitre_field:
452 + field_options.insert(0, mitre_field) # Prioritize user-specified field
453 +
454 + # Field options for technique names (corresponding to each ID field)
455 + name_field_options = ["rule_mitre_technique", "rule.mitre.technique", "mitre.technique"]
456 +
457 + results = None
458 + errors = []
459 +
460 + # Try each field option until we find one that works
461 + for i, field in enumerate(field_options):
462 + try:
463 + # Get the corresponding name field if available
464 + name_field = name_field_options[i] if i < len(name_field_options) else None
465 +
466 + logger.info(f"Trying MITRE search with field: {field} (name field: {name_field})")
467 +
468 + # First fetch all techniques to get the total count
469 + count_query = _build_mitre_search_query(
470 + time_range=time_range,
471 + size=10000, # Large size to get full count
472 + offset=0,
473 + additional_filters=additional_filters,
474 + index_pattern=index_pattern,
475 + mitre_field=field,
476 + name_field=name_field
477 + )
478 +
479 + # Set size to 0 to just get counts
480 + count_query["body"]["size"] = 0
481 +
482 + # Execute count query
483 + count_response = await client.search(**count_query)
484 +
485 + # If we get aggregations with buckets, we found the right field
486 + if (count_response.get("aggregations") and
487 + count_response["aggregations"].get("techniques") and
488 + count_response["aggregations"]["techniques"].get("buckets")):
489 +
490 + # Get total count of techniques
491 + total_techniques = len(count_response["aggregations"]["techniques"]["buckets"])
492 +
493 + # Now fetch just the requested page
494 + query = _build_mitre_search_query(
495 + time_range=time_range,
496 + size=size,
497 + offset=offset,
498 + additional_filters=additional_filters,
499 + index_pattern=index_pattern,
500 + mitre_field=field,
501 + name_field=name_field
502 + )
503 +
504 + # Log the query for debugging
505 + logger.debug(f"Executing query: {query}")
506 +
507 + # Execute the search
508 + response = await client.search(**query)
509 +
510 + # Process results with both ID and name field
511 + page_results = _process_mitre_search_results(
512 + response=response,
513 + mitre_field=field,
514 + technique_mapping=technique_mapping,
515 + name_field=name_field,
516 + technique_tactic_mapping=technique_tactic_mapping
517 + )
518 +
519 + # Update with the full count
520 + results = page_results
521 + results["total_techniques_count"] = total_techniques
522 +
523 + logger.info(f"Found {results['techniques_count']} MITRE techniques on this page, {total_techniques} total with field '{field}'")
524 + break
525 + else:
526 + logger.warning(f"No results found with field '{field}', trying next option")
527 +
528 + except Exception as e:
529 + logger.warning(f"Error with field '{field}': {str(e)}")
530 + errors.append(f"{field}: {str(e)}")
531 +
532 + # If no results found with any field, return empty results
533 + if not results:
534 + logger.warning(f"No MITRE techniques found with any field option. Errors: {errors}")
535 + return {
536 + "total_alerts": 0,
537 + "techniques_count": 0,
538 + "total_techniques_count": 0,
539 + "techniques": [],
540 + "field_used": None,
541 + "attempted_fields": field_options,
542 + "errors": errors
543 + }
544 +
545 + return results
546 +
547 + except Exception as e:
548 + error_message = f"Error searching MITRE techniques: {str(e)}"
549 + logger.exception(error_message)
550 + raise HTTPException(status_code=500, detail=error_message)
551 +
552 +
553 +async def _build_technique_id_name_mapping() -> Dict[str, str]:
554 + """
555 + Build a mapping of MITRE technique IDs to their names.
556 +
557 + Returns:
558 + Dict mapping technique IDs to technique names
559 + """
560 + try:
561 + # Fetch all techniques from Wazuh
562 + techniques_response = await get_mitre_techniques(limit=1000)
563 +
564 + # Create mapping from ID to name
565 + technique_mapping = {}
566 + if techniques_response and hasattr(techniques_response, 'success') and techniques_response.success:
567 + # Debug the response structure
568 + logger.debug(f"Techniques response type: {type(techniques_response)}")
569 +
570 + if hasattr(techniques_response, 'results'):
571 + techniques = techniques_response.results
572 + logger.debug(f"Got {len(techniques)} techniques, first item type: {type(techniques[0]) if techniques else 'None'}")
573 +
574 + for technique in techniques:
575 + # Check if it's a dictionary or an object with attributes
576 + if isinstance(technique, dict):
577 + technique_id = technique.get("id", "")
578 + technique_name = technique.get("name", technique_id)
579 + else:
580 + # Try direct attribute access for Pydantic models
581 + technique_id = getattr(technique, "id", "")
582 + technique_name = getattr(technique, "name", technique_id)
583 +
584 + if technique_id:
585 + technique_mapping[technique_id] = technique_name
586 +
587 + # Sometimes the ID might be referenced without the 'T' prefix
588 + if technique_id.startswith('T'):
589 + technique_mapping[technique_id[1:]] = technique_name
590 +
591 + logger.info(f"Built mapping for {len(technique_mapping)} MITRE techniques")
592 + return technique_mapping
593 +
594 + except Exception as e:
595 + logger.exception(f"Error building technique mapping: {str(e)}")
596 + return {} # Return empty mapping if error occurs
597 +
598 +async def _build_technique_tactic_mapping() -> Dict[str, List[Dict[str, str]]]:
599 + """
600 + Build a mapping of MITRE technique IDs to their associated tactics.
601 +
602 + Returns:
603 + Dict mapping technique IDs to lists of tactic information
604 + """
605 + try:
606 + # Fetch all techniques from Wazuh
607 + techniques_response = await get_mitre_techniques(limit=1000)
608 +
609 + # Create mapping from ID to tactics
610 + technique_tactic_mapping = {}
611 + if hasattr(techniques_response, 'success') and techniques_response.success:
612 + techniques = techniques_response.results
613 +
614 + # Get all tactics for name lookup
615 + tactics_response = await get_mitre_tactics(limit=1000)
616 + tactic_name_mapping = {}
617 +
618 + if hasattr(tactics_response, 'success') and tactics_response.success:
619 + for tactic in tactics_response.results:
620 + if isinstance(tactic, dict):
621 + tactic_id = tactic.get("id", "")
622 + tactic_name = tactic.get("name", "")
623 + short_name = tactic.get("short_name", "")
624 + else:
625 + tactic_id = getattr(tactic, "id", "")
626 + tactic_name = getattr(tactic, "name", "")
627 + short_name = getattr(tactic, "short_name", "")
628 +
629 + if tactic_id:
630 + tactic_name_mapping[tactic_id] = {
631 + "name": tactic_name,
632 + "short_name": short_name
633 + }
634 +
635 + logger.debug(f"Built tactic name mapping with {len(tactic_name_mapping)} tactics")
636 +
637 + # Map techniques to tactics with names
638 + for technique in techniques:
639 + if isinstance(technique, dict):
640 + technique_id = technique.get("id", "")
641 + technique_external_id = technique.get("external_id", "")
642 + tactic_ids = technique.get("tactics", [])
643 + else:
644 + technique_id = getattr(technique, "id", "")
645 + technique_external_id = getattr(technique, "external_id", "")
646 + tactic_ids = getattr(technique, "tactics", [])
647 +
648 + if technique_id:
649 + tactics = []
650 + for tactic_id in tactic_ids:
651 + tactic_info = {
652 + "id": tactic_id,
653 + "name": tactic_name_mapping.get(tactic_id, {}).get("name", "Unknown"),
654 + "short_name": tactic_name_mapping.get(tactic_id, {}).get("short_name", "")
655 + }
656 + tactics.append(tactic_info)
657 +
658 + # Store with multiple key formats for more robust matching
659 + if technique_external_id:
660 + # Store as "T1234"
661 + technique_tactic_mapping[technique_external_id] = tactics
662 + # Store as "1234" (without T prefix)
663 + if technique_external_id.startswith('T'):
664 + technique_tactic_mapping[technique_external_id[1:]] = tactics
665 +
666 + technique_tactic_mapping[technique_id] = tactics
667 +
668 + # Debug log some sample mappings
669 + sample_keys = list(technique_tactic_mapping.keys())[:5]
670 + logger.debug(f"Sample technique ID keys in mapping: {sample_keys}")
671 +
672 + logger.info(f"Built mapping for {len(technique_tactic_mapping)} techniques with tactics")
673 +
674 + return technique_tactic_mapping
675 + except Exception as e:
676 + logger.exception(f"Error building technique-tactic mapping: {str(e)}")
677 + return {}
678 +
679 +def _process_mitre_search_results(
680 + response: Dict,
681 + mitre_field: str,
682 + technique_mapping: Dict[str, str],
683 + name_field: Optional[str] = None,
684 + technique_tactic_mapping: Optional[Dict[str, List[Dict[str, str]]]] = None
685 +) -> Dict:
686 + """
687 + Process the Wazuh Indexer response to extract MITRE technique information.
688 + """
689 + # Validate response structure
690 + if not response or "aggregations" not in response or "techniques" not in response["aggregations"]:
691 + logger.warning("MITRE search response missing aggregations")
692 + return {"total_alerts": 0, "techniques_count": 0, "techniques": [], "field_used": mitre_field}
693 +
694 + # Extract the buckets from the aggregation
695 + techniques_buckets = response["aggregations"]["techniques"]["buckets"]
696 +
697 + # Debug: log a sample of the first few buckets
698 + if techniques_buckets:
699 + sample = techniques_buckets[:2]
700 + logger.debug(f"Sample buckets: {sample}")
701 +
702 + # Get the total count
703 + total_hits = (
704 + response["hits"]["total"]["value"]
705 + if isinstance(response["hits"]["total"], dict) and "value" in response["hits"]["total"]
706 + else response["hits"]["total"]
707 + )
708 +
709 + # Format the techniques data
710 + techniques = []
711 + for bucket in techniques_buckets:
712 + key = bucket["key"]
713 + if not key:
714 + continue
715 +
716 + # The key might be a single ID or a nested structure
717 + technique_ids = []
718 + if isinstance(key, list):
719 + # If key is already a list
720 + technique_ids.extend([tid for tid in key if tid])
721 + else:
722 + # If key is a string, might contain comma-separated values
723 + technique_ids.extend([tid.strip() for tid in str(key).split(",") if tid.strip()])
724 +
725 + for technique_id in technique_ids:
726 + # First try to get name from the document itself via sub-aggregation
727 + technique_name = "Unknown Technique"
728 +
729 + # Check if we have a name from sub-aggregation
730 + if name_field and "technique_name" in bucket and "buckets" in bucket["technique_name"]:
731 + name_buckets = bucket["technique_name"]["buckets"]
732 + if name_buckets and len(name_buckets) > 0 and name_buckets[0]["key"]:
733 + technique_name = name_buckets[0]["key"]
734 +
735 + # Get associated tactics for this technique
736 + tactics = []
737 + if technique_tactic_mapping:
738 + # Try exact match first
739 + if technique_id in technique_tactic_mapping:
740 + tactics = technique_tactic_mapping[technique_id]
741 + logger.debug(f"Found tactics for technique ID: {technique_id} (exact match)")
742 + # Try with 'T' prefix if it doesn't have one
743 + elif not technique_id.startswith('T') and f"T{technique_id}" in technique_tactic_mapping:
744 + tactics = technique_tactic_mapping[f"T{technique_id}"]
745 + logger.debug(f"Found tactics for technique ID: {technique_id} (added T prefix)")
746 + # Try without 'T' prefix if it has one
747 + elif technique_id.startswith('T') and technique_id[1:] in technique_tactic_mapping:
748 + tactics = technique_tactic_mapping[technique_id[1:]]
749 + logger.debug(f"Found tactics for technique ID: {technique_id} (removed T prefix)")
750 + else:
751 + # Log that we couldn't find tactics for this technique
752 + logger.debug(f"No tactics found for technique ID: {technique_id}")
753 +
754 + # If no name found, use our mapping as fallback
755 + if technique_name == "Unknown Technique":
756 + technique_name = technique_mapping.get(technique_id, "Unknown Technique")
757 +
758 + # Debug log if we're still getting "Unknown Technique"
759 + if technique_name == "Unknown Technique":
760 + logger.debug(f"Could not find name for technique {technique_id} in document or mapping")
761 +
762 + techniques.append({
763 + "technique_id": technique_id,
764 + "technique_name": technique_name,
765 + "count": bucket["doc_count"],
766 + "last_seen": datetime.utcnow().isoformat() + "Z",
767 + "tactics": tactics
768 + })
769 +
770 + # Add debugging information
771 + debug_info = {
772 + "technique_count_in_aggs": len(techniques_buckets),
773 + "mapping_size": len(technique_mapping),
774 + "tactic_mapping_size": len(technique_tactic_mapping) if technique_tactic_mapping else 0,
775 + "timestamp": datetime.utcnow().isoformat(),
776 + "sample_technique_ids": [t["technique_id"] for t in techniques[:3]] if techniques else []
777 + }
778 +
779 + # Compile the final result
780 + return {
781 + "total_alerts": total_hits,
782 + "techniques_count": len(techniques),
783 + "techniques": techniques,
784 + "field_used": mitre_field,
785 + "name_field_used": name_field,
786 + "debug_info": debug_info,
787 + }
788 +
789 +
790 +async def _get_wazuh_indexer_client() -> AsyncElasticsearch:
791 + """Get Wazuh Indexer client with error handling."""
792 + try:
793 + return await create_wazuh_indexer_client_async()
794 + except Exception as e:
795 + logger.error(f"Failed to create OpenSearch client: {str(e)}")
796 + raise HTTPException(
797 + status_code=503,
798 + detail=f"Unable to connect to Wazuh Indexer: {str(e)}"
799 + )
800 +
801 +
802 +def _build_mitre_search_query(
803 + time_range: str,
804 + size: int,
805 + offset: int,
806 + additional_filters: Optional[List[Dict]],
807 + index_pattern: str,
808 + mitre_field: str,
809 + name_field: Optional[str] = None,
810 +) -> Dict:
811 + """Build the Wazuh Indexer query for MITRE technique aggregation."""
812 + # Build the base filters
813 + query_filters = [
814 + {"match_all": {}},
815 + {"range": {"timestamp": {"from": time_range, "to": "now"}}}
816 + ]
817 +
818 + # Add filters for mitre field (required)
819 + query_filters.append({"exists": {"field": mitre_field}})
820 +
821 + # Add any additional filters provided
822 + if additional_filters:
823 + query_filters.extend(additional_filters)
824 +
825 + # Base query
826 + query = {
827 + "index": index_pattern,
828 + "body": {
829 + "size": 0,
830 + "from": offset,
831 + "query": {
832 + "bool": {
833 + "must": [],
834 + "filter": query_filters,
835 + "should": [],
836 + "must_not": []
837 + }
838 + },
839 + "aggs": {
840 + "techniques": {
841 + "terms": {
842 + "field": mitre_field,
843 + "size": size,
844 + "order": {"_count": "desc"}
845 + }
846 + }
847 + }
848 + }
849 + }
850 +
851 + # If we have a separate name field, add a sub-aggregation to collect technique names
852 + if name_field:
853 + # Add filter for name field (optional)
854 + query["body"]["aggs"]["techniques"]["aggs"] = {
855 + "technique_name": {
856 + "terms": {
857 + "field": name_field,
858 + "size": 1 # Just need the first/most common name
859 + }
860 + }
861 + }
862 +
863 + return query
864 +
865 +
866 +
867 +async def get_alerts_by_mitre_id(
868 + technique_id: str,
869 + time_range: str = "now-24h",
870 + size: int = 100,
871 + offset: int = 0,
872 + additional_filters: Optional[List[Dict]] = None,
873 + index_pattern: str = "wazuh-*",
874 + mitre_field: Optional[str] = None,
875 +) -> Dict[str, Union[str, int, List[Dict]]]:
876 + """
877 + Fetch alert documents associated with a specific MITRE ATT&CK technique ID.
878 +
879 + Args:
880 + technique_id: The MITRE technique ID to search for
881 + time_range: Time range for the search (e.g., "now-24h", "now-7d")
882 + size: Maximum number of alerts to return
883 + additional_filters: Additional filters to apply to the query
884 + index_pattern: OpenSearch index pattern to search
885 + mitre_field: Override the default field name containing MITRE IDs
886 +
887 + Returns:
888 + Dict containing results with technique info and alert documents
889 + """
890 + logger.info(f"Fetching alerts for MITRE technique {technique_id} from {time_range} to now")
891 +
892 + try:
893 + # Get technique name from mapping
894 + technique_mapping = await _build_technique_id_name_mapping()
895 +
896 + # Try matching with and without 'T' prefix
897 + technique_name = "Unknown Technique"
898 + if technique_id in technique_mapping:
899 + technique_name = technique_mapping[technique_id]
900 + elif technique_id.startswith('T') and technique_id[1:] in technique_mapping:
901 + technique_name = technique_mapping[technique_id[1:]]
902 + elif not technique_id.startswith('T') and f"T{technique_id}" in technique_mapping:
903 + technique_name = technique_mapping[f"T{technique_id}"]
904 +
905 + # Get OpenSearch client
906 + client = await _get_wazuh_indexer_client()
907 +
908 + # Try multiple field paths that might contain MITRE IDs
909 + field_options = ["rule_mitre_id", "rule.mitre.id", "mitre.id"]
910 + if mitre_field:
911 + field_options.insert(0, mitre_field) # Prioritize user-specified field
912 +
913 + results = None
914 + errors = []
915 +
916 + # Try each field option until we find one that works
917 + for field in field_options:
918 + try:
919 + logger.info(f"Trying to search alerts with field: {field}")
920 +
921 + # Build query
922 + query = _build_mitre_alerts_query(
923 + technique_id=technique_id,
924 + time_range=time_range,
925 + size=size,
926 + offset=offset,
927 + additional_filters=additional_filters,
928 + index_pattern=index_pattern,
929 + mitre_field=field
930 + )
931 +
932 + # Execute the search
933 + response = await client.search(**query)
934 +
935 + # Check if we got results
936 + if response.get("hits") and response["hits"].get("hits") and len(response["hits"]["hits"]) > 0:
937 + # Get the total hits
938 + total_hits = (
939 + response["hits"]["total"]["value"]
940 + if isinstance(response["hits"]["total"], dict) and "value" in response["hits"]["total"]
941 + else response["hits"]["total"]
942 + )
943 +
944 + # Extract the documents
945 + documents = [hit["_source"] for hit in response["hits"]["hits"]]
946 +
947 + results = {
948 + "technique_id": technique_id,
949 + "technique_name": technique_name,
950 + "total_alerts": total_hits,
951 + "alerts": documents,
952 + "field_used": field
953 + }
954 +
955 + logger.info(f"Found {len(documents)} of {total_hits} alerts for technique {technique_id} using field '{field}'")
956 + break
957 + else:
958 + logger.warning(f"No alerts found for technique {technique_id} with field '{field}'")
959 +
960 + except Exception as e:
961 + logger.warning(f"Error searching with field '{field}': {str(e)}")
962 + errors.append(f"{field}: {str(e)}")
963 +
964 + # If no results found with any field, return empty results
965 + if not results:
966 + logger.warning(f"No alerts found for technique {technique_id} with any field option")
967 + return {
968 + "technique_id": technique_id,
969 + "technique_name": technique_name,
970 + "total_alerts": 0,
971 + "alerts": [],
972 + "field_used": None,
973 + "errors": errors
974 + }
975 +
976 + return results
977 +
978 + except AsyncElasticsearch as oe:
979 + error_message = f"Wazuh Indexer error: {str(oe)}"
980 + logger.error(error_message)
981 + raise HTTPException(status_code=503, detail=error_message)
982 + except Exception as e:
983 + error_message = f"Error fetching alerts for MITRE technique {technique_id}: {str(e)}"
984 + logger.exception(error_message)
985 + raise HTTPException(status_code=500, detail=error_message)
986 +
987 +
988 +def _build_mitre_alerts_query(
989 + technique_id: str,
990 + time_range: str,
991 + size: int,
992 + offset: int,
993 + additional_filters: Optional[List[Dict]],
994 + index_pattern: str,
995 + mitre_field: str,
996 +) -> Dict:
997 + """Build the OpenSearch query to fetch alerts for a specific MITRE technique."""
998 + # Build the base filters
999 + query_filters = [
1000 + {"range": {"timestamp": {"from": time_range, "to": "now"}}}
1001 + ]
1002 +
1003 + # Add MITRE ID filter with support for array fields
1004 + query_filters.append({
1005 + "query_string": {
1006 + "query": f"{mitre_field}:\"{technique_id}\"",
1007 + "analyze_wildcard": True
1008 + }
1009 + })
1010 +
1011 + # Add any additional filters provided
1012 + if additional_filters:
1013 + query_filters.extend(additional_filters)
1014 +
1015 + # Base query
1016 + query = {
1017 + "index": index_pattern,
1018 + "body": {
1019 + "size": size,
1020 + "from": offset,
1021 + "query": {
1022 + "bool": {
1023 + "filter": query_filters
1024 + }
1025 + },
1026 + "_source": True,
1027 + "sort": [
1028 + {"timestamp": {"order": "desc"}}
1029 + ],
1030 + "track_total_hits": True
1031 + }
1032 + }
1033 +
1034 + return query
1035 +
1036 +
1037 +async def get_mitre_software(
1038 + limit: Optional[int] = None,
1039 + offset: Optional[int] = None,
1040 + select: Optional[List[str]] = None,
1041 + sort: Optional[str] = None,
1042 + search: Optional[str] = None,
1043 + q: Optional[str] = None,
1044 +) -> WazuhMitreSoftwareResponse:
1045 + """
1046 + Fetch MITRE ATT&CK software from Wazuh API.
1047 +
1048 + Args:
1049 + limit: Maximum number of items to return
1050 + offset: First item to return
1051 + select: List of fields to return
1052 + sort: Fields to sort by
1053 + search: Text to search in fields
1054 + q: Query to filter results
1055 +
1056 + Returns:
1057 + WazuhMitreSoftwareResponse: A list of all MITRE ATT&CK software.
1058 + """
1059 + # Build parameters dictionary, excluding None values
1060 + params = {"limit": limit, "offset": offset, "sort": sort, "search": search, "q": q}
1061 +
1062 + # Add select parameter if provided
1063 + if select:
1064 + params["select"] = ",".join(select)
1065 +
1066 + # Remove None values
1067 + params = {k: v for k, v in params.items() if v is not None}
1068 +
1069 + response = await send_get_request(endpoint="/mitre/software", params=params)
1070 +
1071 + logger.debug(f"Response from Wazuh MITRE software endpoint with params {params}")
1072 +
1073 + try:
1074 + # Extract data from response
1075 + if "data" in response and "data" in response["data"]:
1076 + wazuh_data = response["data"]["data"]
1077 + mitre_software = wazuh_data.get("affected_items", [])
1078 + total_items = wazuh_data.get("total_affected_items", len(mitre_software))
1079 +
1080 + logger.debug(f"Retrieved {len(mitre_software)} of {total_items} MITRE software from Wazuh")
1081 +
1082 + return WazuhMitreSoftwareResponse(
1083 + success=True,
1084 + message=f"Successfully retrieved {len(mitre_software)} MITRE software",
1085 + results=mitre_software,
1086 + )
1087 + else:
1088 + logger.error("Unexpected response structure from Wazuh API")
1089 + raise HTTPException(status_code=500, detail="Unexpected response structure from Wazuh API")
1090 +
1091 + except ValidationError as e:
1092 + logger.error(f"Validation error parsing Wazuh MITRE software response: {e}")
1093 + raise HTTPException(status_code=500, detail=f"Data validation error: {str(e)}")
1094 + except Exception as e:
1095 + logger.error(f"Error parsing Wazuh MITRE software response: {e}")
1096 + raise HTTPException(status_code=500, detail=f"Error processing MITRE data: {str(e)}")
1097 +
1098 +async def get_mitre_references(
1099 + limit: Optional[int] = None,
1100 + offset: Optional[int] = None,
1101 + sort: Optional[str] = None,
1102 + search: Optional[str] = None,
1103 + q: Optional[str] = None,
1104 +) -> WazuhMitreReferencesResponse:
1105 + """
1106 + Fetch MITRE ATT&CK references from Wazuh API.
1107 +
1108 + Args:
1109 + limit: Maximum number of items to return
1110 + offset: First item to return
1111 + sort: Fields to sort by
1112 + search: Text to search in fields
1113 + q: Query to filter results
1114 +
1115 + Returns:
1116 + WazuhMitreReferencesResponse: A list of all MITRE ATT&CK references.
1117 + """
1118 + # Build parameters dictionary, excluding None values
1119 + params = {"limit": limit, "offset": offset, "sort": sort, "search": search, "q": q}
1120 +
1121 + # Remove None values
1122 + params = {k: v for k, v in params.items() if v is not None}
1123 +
1124 + response = await send_get_request(endpoint="/mitre/references", params=params)
1125 +
1126 + logger.debug(f"Response from Wazuh MITRE references endpoint with params {params}")
1127 +
1128 + try:
1129 + # Extract data from response
1130 + if "data" in response and "data" in response["data"]:
1131 + wazuh_data = response["data"]["data"]
1132 + mitre_references = wazuh_data.get("affected_items", [])
1133 + total_items = wazuh_data.get("total_affected_items", len(mitre_references))
1134 +
1135 + logger.debug(f"Retrieved {len(mitre_references)} of {total_items} MITRE references from Wazuh")
1136 +
1137 + return WazuhMitreReferencesResponse(
1138 + success=True,
1139 + message=f"Successfully retrieved {len(mitre_references)} MITRE references",
1140 + results=mitre_references,
1141 + total=total_items
1142 + )
1143 + else:
1144 + logger.error("Unexpected response structure from Wazuh API")
1145 + raise HTTPException(status_code=500, detail="Unexpected response structure from Wazuh API")
1146 +
1147 + except ValidationError as e:
1148 + logger.error(f"Validation error parsing Wazuh MITRE references response: {e}")
1149 + raise HTTPException(status_code=500, detail=f"Data validation error: {str(e)}")
1150 + except Exception as e:
1151 + logger.error(f"Error parsing Wazuh MITRE references response: {e}")
1152 + raise HTTPException(status_code=500, detail=f"Error processing MITRE data: {str(e)}")
1153 +
1154 +async def get_mitre_mitigations(
1155 + limit: Optional[int] = None,
1156 + offset: Optional[int] = None,
1157 + select: Optional[List[str]] = None,
1158 + sort: Optional[str] = None,
1159 + search: Optional[str] = None,
1160 + q: Optional[str] = None,
1161 +) -> WazuhMitreMitigationsResponse:
1162 + """
1163 + Fetch MITRE ATT&CK mitigations from Wazuh API.
1164 +
1165 + Args:
1166 + limit: Maximum number of items to return
1167 + offset: First item to return
1168 + select: List of fields to return
1169 + sort: Fields to sort by
1170 + search: Text to search in fields
1171 + q: Query to filter results
1172 +
1173 + Returns:
1174 + WazuhMitreMitigationsResponse: A list of all MITRE ATT&CK mitigations.
1175 + """
1176 + # Build parameters dictionary, excluding None values
1177 + params = {"limit": limit, "offset": offset, "sort": sort, "search": search, "q": q}
1178 +
1179 + # Add select parameter if provided
1180 + if select:
1181 + params["select"] = ",".join(select)
1182 +
1183 + # Remove None values
1184 + params = {k: v for k, v in params.items() if v is not None}
1185 +
1186 + response = await send_get_request(endpoint="/mitre/mitigations", params=params)
1187 +
1188 + logger.debug(f"Response from Wazuh MITRE mitigations endpoint with params {params}")
1189 +
1190 + try:
1191 + # Extract data from response
1192 + if "data" in response and "data" in response["data"]:
1193 + wazuh_data = response["data"]["data"]
1194 + mitre_mitigations = wazuh_data.get("affected_items", [])
1195 + total_items = wazuh_data.get("total_affected_items", len(mitre_mitigations))
1196 +
1197 + logger.debug(f"Retrieved {len(mitre_mitigations)} of {total_items} MITRE mitigations from Wazuh")
1198 +
1199 + return WazuhMitreMitigationsResponse(
1200 + success=True,
1201 + message=f"Successfully retrieved {len(mitre_mitigations)} MITRE mitigations",
1202 + results=mitre_mitigations,
1203 + total=total_items
1204 + )
1205 + else:
1206 + logger.error("Unexpected response structure from Wazuh API")
1207 + raise HTTPException(status_code=500, detail="Unexpected response structure from Wazuh API")
1208 +
1209 + except ValidationError as e:
1210 + logger.error(f"Validation error parsing Wazuh MITRE mitigations response: {e}")
1211 + raise HTTPException(status_code=500, detail=f"Data validation error: {str(e)}")
1212 + except Exception as e:
1213 + logger.error(f"Error parsing Wazuh MITRE mitigations response: {e}")
1214 + raise HTTPException(status_code=500, detail=f"Error processing MITRE data: {str(e)}")
1215 +
1216 +async def get_mitre_groups(
1217 + limit: Optional[int] = None,
1218 + offset: Optional[int] = None,
1219 + select: Optional[List[str]] = None,
1220 + sort: Optional[str] = None,
1221 + search: Optional[str] = None,
1222 + q: Optional[str] = None,
1223 +) -> WazuhMitreGroupsResponse:
1224 + """
1225 + Fetch MITRE ATT&CK groups from Wazuh API.
1226 +
1227 + Args:
1228 + limit: Maximum number of items to return
1229 + offset: First item to return
1230 + select: List of fields to return
1231 + sort: Fields to sort by
1232 + search: Text to search in fields
1233 + q: Query to filter results
1234 +
1235 + Returns:
1236 + WazuhMitreGroupsResponse: A list of all MITRE ATT&CK groups.
1237 + """
1238 + # Build parameters dictionary, excluding None values
1239 + params = {"limit": limit, "offset": offset, "sort": sort, "search": search, "q": q}
1240 +
1241 + # Add select parameter if provided
1242 + if select:
1243 + params["select"] = ",".join(select)
1244 +
1245 + # Remove None values
1246 + params = {k: v for k, v in params.items() if v is not None}
1247 +
1248 + response = await send_get_request(endpoint="/mitre/groups", params=params)
1249 +
1250 + logger.debug(f"Response from Wazuh MITRE groups endpoint with params {params}")
1251 +
1252 + try:
1253 + # Extract data from response
1254 + if "data" in response and "data" in response["data"]:
1255 + wazuh_data = response["data"]["data"]
1256 + mitre_groups = wazuh_data.get("affected_items", [])
1257 + total_items = wazuh_data.get("total_affected_items", len(mitre_groups))
1258 +
1259 + logger.debug(f"Retrieved {len(mitre_groups)} of {total_items} MITRE groups from Wazuh")
1260 +
1261 + return WazuhMitreGroupsResponse(
1262 + success=True,
1263 + message=f"Successfully retrieved {len(mitre_groups)} MITRE groups",
1264 + results=mitre_groups,
1265 + total=total_items
1266 + )
1267 + else:
1268 + logger.error("Unexpected response structure from Wazuh API")
1269 + raise HTTPException(status_code=500, detail="Unexpected response structure from Wazuh API")
1270 +
1271 + except ValidationError as e:
1272 + logger.error(f"Validation error parsing Wazuh MITRE groups response: {e}")
1273 + raise HTTPException(status_code=500, detail=f"Data validation error: {str(e)}")
1274 + except Exception as e:
1275 + logger.error(f"Error parsing Wazuh MITRE groups response: {e}")
1276 + raise HTTPException(status_code=500, detail=f"Error processing MITRE data: {str(e)}")
backend/app/customer_provisioning/services/provision.py
+1 -1
@@ -108,7 +108,7 @@ async def provision_wazuh_customer(
108 )
109 ).datasource.uid
110 # ! CREATE THE VULNERABILITY DATASOURCE IF WAZUH VERSION 4.8.0 OR HIGHER ! #
111 - if check_wazuh_manager_version() is True:
111 + if await check_wazuh_manager_version() is True:
112 logger.info("Creating vulnerability datasource since Wazuh version is 4.8.0 or higher")
113 await create_vulnerability_datasource(
114 request=request,
backend/app/db/db_setup.py
+52
@@ -83,6 +83,30 @@ async def create_copilot_user_if_not_exists(db_url: str, db_user_name: str):
83 logger.info(f"An error occurred: {e}")
84
85
86 +# def apply_migrations():
87 +# """
88 +# Applies Alembic migrations to ensure the database schema is up to date.
89 +# """
90 +# logger.info("Applying migrations")
91 +
92 +# # Navigate up three levels from db_setup.py to the backend directory, then to the alembic directory
93 +# base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
94 +# alembic_directory = os.path.join(base_dir, "alembic")
95 +
96 +# logger.info(f"base_dir: {base_dir}")
97 +# logger.info(f"Alembic directory: {alembic_directory}")
98 +
99 +# alembic_cfg = Config(os.path.join(alembic_directory, "alembic.ini"))
100 +# alembic_cfg.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URI.replace("+aiomysql", "+pymysql"))
101 +# alembic_cfg.set_main_option("script_location", alembic_directory)
102 +
103 +# # Apply migrations to the latest revision
104 +# try:
105 +# command.upgrade(alembic_cfg, "head")
106 +# except Exception as e: # Catch any exception
107 +# logger.error(f"Error applying migrations: {e}")
108 +# raise e
109 +
110 def apply_migrations():
111 """
112 Applies Alembic migrations to ensure the database schema is up to date.
@@ -100,9 +124,37 @@ def apply_migrations():
124 alembic_cfg.set_main_option("sqlalchemy.url", SQLALCHEMY_DATABASE_URI.replace("+aiomysql", "+pymysql"))
125 alembic_cfg.set_main_option("script_location", alembic_directory)
126
127 + # Check current revision first
128 + logger.info("Checking current database revision...")
129 + try:
130 + from alembic.script import ScriptDirectory
131 + from sqlalchemy import create_engine
132 +
133 + # Get current revision
134 + engine = create_engine(SQLALCHEMY_DATABASE_URI.replace("+aiomysql", "+pymysql"))
135 + with engine.connect() as connection:
136 + from alembic.runtime.migration import MigrationContext
137 + context = MigrationContext.configure(connection)
138 + current_rev = context.get_current_revision()
139 + logger.info(f"Current database revision: {current_rev}")
140 +
141 + # Get head revision
142 + script = ScriptDirectory.from_config(alembic_cfg)
143 + head_rev = script.get_current_head()
144 + logger.info(f"Target head revision: {head_rev}")
145 +
146 + if current_rev == head_rev:
147 + logger.info("Database is already up to date!")
148 + return
149 +
150 + except Exception as e:
151 + logger.warning(f"Could not check current revision: {e}")
152 +
153 # Apply migrations to the latest revision
154 + logger.info("Starting migration upgrade...")
155 try:
156 command.upgrade(alembic_cfg, "head")
157 + logger.info("Migrations completed successfully!")
158 except Exception as e: # Catch any exception
159 logger.error(f"Error applying migrations: {e}")
160 raise e
backend/app/incidents/services/db_operations.py
+12
@@ -939,6 +939,18 @@ async def create_alert_tag(alert_tag: AlertTagCreate, db: AsyncSession) -> Alert
939 raise HTTPException(status_code=400, detail="Alert tag already exists")
940 return db_alert_tag
941
942 +async def add_alert_tag_if_not_exists(alert_tag: AlertTagCreate, db: AsyncSession) -> AlertTag:
943 + # Check if the tag already exists
944 + result = await db.execute(select(AlertTag).where(AlertTag.tag == alert_tag.tag))
945 + existing_tag = result.scalars().first()
946 +
947 + if existing_tag:
948 + logger.info(f"Tag {alert_tag.tag} already exists with ID {alert_tag.alert_id}")
949 + return None
950 +
951 + # If it doesn't exist, create a new one
952 + return await create_alert_tag(alert_tag, db)
953 +
954
955 async def delete_alert_tag(alert_id: int, tag_id: int, db: AsyncSession):
956 result = await db.execute(select(AlertTag).where(AlertTag.id == tag_id))
backend/app/incidents/services/velo_sigma.py
+251 -23
@@ -1,4 +1,5 @@
1 import re
2 +import json
3 from datetime import datetime
4 from datetime import timedelta
5 from typing import Any
@@ -29,7 +30,7 @@ from app.incidents.schema.velo_sigma import SysmonEvent
30 from app.incidents.schema.velo_sigma import VelociraptorSigmaAlert
31 from app.incidents.schema.velo_sigma import VelociraptorSigmaAlertResponse
32 from app.incidents.schema.velo_sigma import VeloSigmaExclusionCreate
32 -from app.incidents.services.db_operations import create_alert_tag
33 +from app.incidents.services.db_operations import create_alert_tag, add_alert_tag_if_not_exists
34 from app.incidents.services.db_operations import create_comment
35 from app.incidents.services.incident_alert import create_alert
36 from app.incidents.services.incident_alert import create_alert_full
@@ -161,23 +162,81 @@ class VeloSigmaExclusionService:
162 if field_value.startswith("regex:"):
163 # Remove the regex: prefix and try to match
164 regex_pattern = field_value[6:]
164 - try:
165 - if not re.search(regex_pattern, event_value, re.IGNORECASE):
166 - logger.debug(f"Regex pattern '{regex_pattern}' did not match '{event_value}'")
165 + # Special handling for path-based regex patterns
166 + if "path" in field_name.lower() or "file" in field_name.lower() or "\\" in regex_pattern or "/" in regex_pattern:
167 + try:
168 + # Normalize paths for comparison by converting all to lowercase and standardizing backslashes
169 + pattern = regex_pattern.lower().replace("\\\\", "\\")
170 + value = event_value.lower().replace("\\\\", "\\")
171 +
172 + # Remove the regex: prefix if present
173 + if pattern.startswith("regex:"):
174 + pattern = pattern[6:]
175 +
176 + # Handle escaped parentheses in Windows paths
177 + pattern = pattern.replace("\\(", "(").replace("\\)", ")")
178 +
179 + # Convert the wildcard pattern to proper regex format
180 + # Escape special regex characters except for the wildcards we want to keep
181 + pattern_parts = re.split(r'(\.\*)', pattern)
182 + regex_parts = []
183 +
184 + for i, part in enumerate(pattern_parts):
185 + if part == ".*":
186 + # Keep wildcards as-is
187 + regex_parts.append(part)
188 + else:
189 + # Escape regex special characters but keep path separators
190 + escaped = re.escape(part)
191 + regex_parts.append(escaped)
192 +
193 + pattern_regex = "".join(regex_parts)
194 +
195 + # Force matching the entire string
196 + pattern_regex = f"^{pattern_regex}$"
197 +
198 + logger.debug(f"Path regex check: Pattern='{pattern}' → Regex='{pattern_regex}' vs Value='{value}'")
199 +
200 + # Try the match
201 + match_result = re.search(pattern_regex, value, re.IGNORECASE)
202 + if match_result:
203 + logger.debug(f"Path regex match succeeded! Match: {match_result.group(0)}")
204 + return True
205 + else:
206 + logger.debug(f"Path regex match failed")
207 + return False
208 +
209 + except Exception as e:
210 + logger.error(f"Error in path regex matching: {str(e)}")
211 + return False
212 + else:
213 + # Standard regex for non-path values
214 + try:
215 + if not re.search(regex_pattern, event_value, re.IGNORECASE):
216 + logger.debug(f"Regex pattern '{regex_pattern}' did not match '{event_value}'")
217 + return False
218 + else:
219 + logger.debug(f"Regex pattern '{regex_pattern}' matched '{event_value}'")
220 + except re.error as e:
221 + logger.error(f"Invalid regex pattern in exclusion {exclusion.id}: {regex_pattern} - Error: {str(e)}")
222 return False
168 - else:
169 - logger.debug(f"Regex pattern '{regex_pattern}' matched '{event_value}'")
170 - except re.error:
171 - logger.error(f"Invalid regex pattern in exclusion {exclusion.id}: {regex_pattern}")
172 - return False
223 else:
224 # Case-insensitive path comparison for Windows paths
175 - if "path" in field_name.lower() or "file" in field_name.lower() or "\\" in field_value:
176 - norm_field_value = field_value.lower().replace("\\\\", "\\")
177 - norm_event_value = event_value.lower().replace("\\\\", "\\")
225 + if "path" in field_name.lower() or "file" in field_name.lower() or "\\" in field_value or "/" in field_value:
226 + # Log raw values for debugging
227 + logger.debug(f"Before normalization - Rule: '{field_value}', Event: '{event_value}'")
228 +
229 + # Use the path normalization helper
230 + norm_field_value = self._normalize_windows_path(field_value)
231 + norm_event_value = self._normalize_windows_path(event_value)
232 +
233 + logger.debug(f"After normalization - Rule: '{norm_field_value}', Event: '{norm_event_value}'")
234 +
235 if norm_field_value != norm_event_value:
236 logger.debug(f"Path mismatch: rule='{norm_field_value}' event='{norm_event_value}'")
237 return False
238 + else:
239 + logger.debug(f"Path match found for: {field_name}")
240 else:
241 # Standard case-insensitive match for other fields
242 if field_value.lower() != event_value.lower():
@@ -198,6 +257,63 @@ class VeloSigmaExclusionService:
257 logger.info(f"Alert matched exclusion rule '{exclusion.name}' (ID: {exclusion.id})")
258 return True
259
260 + def _normalize_windows_path(self, path: str, is_regex: bool = False) -> str:
261 + """
262 + Normalize Windows paths by converting all backslash variations to a consistent format.
263 +
264 + Args:
265 + path: The path string to normalize
266 + is_regex: Whether the path contains regex patterns that should be preserved
267 +
268 + Returns:
269 + Normalized path with consistent backslashes and formatting
270 + """
271 + if not path:
272 + return ""
273 +
274 + # Convert to lowercase for case-insensitive comparison
275 + normalized = path.lower()
276 +
277 + if is_regex:
278 + # Special handling for regex patterns
279 + # First, temporarily replace regex character classes with placeholders
280 + placeholders = {}
281 +
282 + # Find all character classes like [^\\] or [\\w] and preserve them
283 + char_class_pattern = r'(\[\^?[^\]]*\])'
284 + char_classes = re.finditer(char_class_pattern, normalized)
285 +
286 + for i, match in enumerate(char_classes):
287 + placeholder = f"__REGEX_PLACEHOLDER_{i}__"
288 + placeholders[placeholder] = match.group(0)
289 + normalized = normalized.replace(match.group(0), placeholder)
290 +
291 + # Use regex to replace any sequence of one or more backslashes with a single backslash
292 + # This handles \, \\, \\\, \\\\, etc.
293 + normalized = re.sub(r'\\+', r'\\', normalized)
294 +
295 + # Handle escaped special characters in paths
296 + normalized = normalized.replace("\\(", "(").replace("\\)", ")")
297 + normalized = normalized.replace("\\[", "[").replace("\\]", "]")
298 + normalized = normalized.replace("\\ ", " ")
299 +
300 + # Remove any trailing backslash
301 + if normalized.endswith("\\"):
302 + normalized = normalized[:-1]
303 +
304 + if is_regex:
305 + # Restore the regex character classes with their original content
306 + for placeholder, original in placeholders.items():
307 + normalized = normalized.replace(placeholder, original)
308 +
309 + # Log only in debug for excessive paths
310 + if path != normalized:
311 + path_preview = path[:20] + "..." if len(path) > 20 else path
312 + norm_preview = normalized[:20] + "..." if len(normalized) > 20 else normalized
313 + logger.debug(f"Path normalized: '{path_preview}' → '{norm_preview}'")
314 +
315 + return normalized
316 +
317 async def _update_exclusion_stats(self, exclusion_id: int) -> None:
318 """Update the statistics for an exclusion after it matches."""
319 try:
@@ -416,20 +532,46 @@ class VelociraptorSigmaService:
532 db=self.session,
533 )
534
535 + # Add the full event payload as a separate comment
536 + try:
537 + # Convert event to string if it's an object or dictionary
538 + event_payload = alert.event
539 + if not isinstance(event_payload, str):
540 + # Try to serialize using json
541 + try:
542 + event_payload = json.dumps(event_payload, default=lambda o: o.__dict__ if hasattr(o, "__dict__") else str(o), indent=2)
543 + except TypeError:
544 + # If JSON serialization fails, use string representation
545 + event_payload = str(event_payload)
546 +
547 + await create_comment(
548 + comment=CommentCreate(
549 + alert_id=result["alert_id"],
550 + comment=f"Full Event Payload:\n```\n{event_payload}\n```",
551 + user_name="admin",
552 + created_at=datetime.utcnow(),
553 + ),
554 + db=self.session,
555 + )
556 + logger.info(f"Added full event payload as comment to alert ID: {result['alert_id']}")
557 + except Exception as e:
558 + logger.error(f"Failed to add event payload as comment: {str(e)}")
559 + logger.exception(e)
560 +
561 # Add tags
420 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag=f"{alert.type}"), db=self.session)
421 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="velociraptor-direct"), db=self.session)
562 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag=f"{alert.type}"), db=self.session)
563 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="velociraptor-direct"), db=self.session)
564
565 # Add event-specific tags
566 if "Sysmon" in alert.channel:
425 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:sysmon"), db=self.session)
567 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:sysmon"), db=self.session)
568 elif "Defender" in alert.channel:
427 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:defender"), db=self.session)
569 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:defender"), db=self.session)
570 elif "PowerShell" in alert.channel:
429 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:powershell"), db=self.session)
571 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:powershell"), db=self.session)
572 else:
573 # Generic event type
432 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:generic"), db=self.session)
574 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag="event_type:generic"), db=self.session)
575
576 logger.info(f"Created fallback CoPilot alert with ID: {result['alert_id']} for customer {customer_code}")
577 result["success"] = True
@@ -526,9 +668,24 @@ class VelociraptorSigmaService:
668 source_process_id = getattr(event_data, "SourceProcessId", 0)
669 source_user = getattr(event_data, "SourceUser", "Unknown User")
670
671 + agent_name = alert.computer # Default to the computer name from the alert
672 +
673 + if alert.clientID:
674 + # Query the Agents table to find matching agent by velociraptor_id
675 + agent_query = select(Agents).where(Agents.velociraptor_id == alert.clientID)
676 + agent_result = await self.session.execute(agent_query)
677 + agent = agent_result.scalar_one_or_none()
678 +
679 + if agent and agent.hostname:
680 + logger.info(f"Found agent details {agent}")
681 + # ! SOMETIMES VELOCIRAPTOR AND WAZUH ENUMERATE DIFFERENT HOSTNAMES ! #
682 + # ! Due to this, we will use the agent.hostname as the asset name as this is what ! #
683 + # ! used in the Wazuh events.!#
684 + agent_name = agent.hostname
685 +
686 # Fetch corresponding Wazuh alert
687 wazuh_event = await self._fetch_wazuh_alert(
531 - agent_name=alert.computer,
688 + agent_name=agent_name,
689 event_record_id=event_record_id,
690 index_pattern=alert.index_pattern,
691 )
@@ -564,9 +721,24 @@ class VelociraptorSigmaService:
721 # Extract event record ID
722 event_record_id = str(parsed_event.System.EventRecordID)
723
724 + agent_name = alert.computer # Default to the computer name from the alert
725 +
726 + if alert.clientID:
727 + # Query the Agents table to find matching agent by velociraptor_id
728 + agent_query = select(Agents).where(Agents.velociraptor_id == alert.clientID)
729 + agent_result = await self.session.execute(agent_query)
730 + agent = agent_result.scalar_one_or_none()
731 +
732 + if agent and agent.hostname:
733 + logger.info(f"Found agent details {agent}")
734 + # ! SOMETIMES VELOCIRAPTOR AND WAZUH ENUMERATE DIFFERENT HOSTNAMES ! #
735 + # ! Due to this, we will use the agent.hostname as the asset name as this is what ! #
736 + # ! used in the Wazuh events.!#
737 + agent_name = agent.hostname
738 +
739 # Fetch corresponding Wazuh alert
740 wazuh_event = await self._fetch_wazuh_alert(
569 - agent_name=alert.computer,
741 + agent_name=agent_name,
742 event_record_id=event_record_id,
743 index_pattern=alert.index_pattern,
744 )
@@ -605,9 +777,24 @@ class VelociraptorSigmaService:
777 # Extract event record ID
778 event_record_id = str(parsed_event.System.EventRecordID)
779
780 + agent_name = alert.computer # Default to the computer name from the alert
781 +
782 + if alert.clientID:
783 + # Query the Agents table to find matching agent by velociraptor_id
784 + agent_query = select(Agents).where(Agents.velociraptor_id == alert.clientID)
785 + agent_result = await self.session.execute(agent_query)
786 + agent = agent_result.scalar_one_or_none()
787 +
788 + if agent and agent.hostname:
789 + logger.info(f"Found agent details {agent}")
790 + # ! SOMETIMES VELOCIRAPTOR AND WAZUH ENUMERATE DIFFERENT HOSTNAMES ! #
791 + # ! Due to this, we will use the agent.hostname as the asset name as this is what ! #
792 + # ! used in the Wazuh events.!#
793 + agent_name = agent.hostname
794 +
795 # Fetch corresponding Wazuh alert
796 wazuh_event = await self._fetch_wazuh_alert(
610 - agent_name=alert.computer,
797 + agent_name=agent_name,
798 event_record_id=event_record_id,
799 index_pattern=alert.index_pattern,
800 )
@@ -653,11 +840,26 @@ class VelociraptorSigmaService:
840 # Extract event record ID if available
841 event_record_id = str(getattr(parsed_event.System, "EventRecordID", "unknown"))
842
843 + agent_name = alert.computer # Default to the computer name from the alert
844 +
845 + if alert.clientID:
846 + # Query the Agents table to find matching agent by velociraptor_id
847 + agent_query = select(Agents).where(Agents.velociraptor_id == alert.clientID)
848 + agent_result = await self.session.execute(agent_query)
849 + agent = agent_result.scalar_one_or_none()
850 +
851 + if agent and agent.hostname:
852 + logger.info(f"Found agent details {agent}")
853 + # ! SOMETIMES VELOCIRAPTOR AND WAZUH ENUMERATE DIFFERENT HOSTNAMES ! #
854 + # ! Due to this, we will use the agent.hostname as the asset name as this is what ! #
855 + # ! used in the Wazuh events.!#
856 + agent_name = agent.hostname
857 +
858 # Try to fetch corresponding Wazuh alert if we have an event record ID
859 wazuh_event = None
860 if event_record_id != "unknown":
861 wazuh_event = await self._fetch_wazuh_alert(
660 - agent_name=alert.computer,
862 + agent_name=agent_name,
863 event_record_id=event_record_id,
864 index_pattern=alert.index_pattern,
865 )
@@ -735,8 +937,34 @@ class VelociraptorSigmaService:
937 db=self.session,
938 )
939
940 + # Add the full event payload as a separate comment
941 + try:
942 + # Convert event to string if it's an object or dictionary
943 + event_payload = alert.event
944 + if not isinstance(event_payload, str):
945 + # Try to serialize using json
946 + try:
947 + event_payload = json.dumps(event_payload, default=lambda o: o.__dict__ if hasattr(o, "__dict__") else str(o), indent=2)
948 + except TypeError:
949 + # If JSON serialization fails, use string representation
950 + event_payload = str(event_payload)
951 +
952 + await create_comment(
953 + comment=CommentCreate(
954 + alert_id=result["alert_id"],
955 + comment=f"Full Event Payload:\n```\n{event_payload}\n```",
956 + user_name="admin",
957 + created_at=datetime.utcnow(),
958 + ),
959 + db=self.session,
960 + )
961 + logger.info(f"Added full event payload as comment to alert ID: {result['alert_id']}")
962 + except Exception as e:
963 + logger.error(f"Failed to add event payload as comment: {str(e)}")
964 + logger.exception(e)
965 +
966 # Add a tag
739 - await create_alert_tag(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag=f"{alert.type}"), db=self.session)
967 + await add_alert_tag_if_not_exists(alert_tag=AlertTagCreate(alert_id=result["alert_id"], tag=f"{alert.type}"), db=self.session)
968
969 logger.info(f"Created CoPilot alert with ID: {result['alert_id']}")
970
backend/app/integrations/monitoring_alert/routes/provision.py
+29 -1
@@ -25,7 +25,7 @@ from app.integrations.monitoring_alert.schema.provision import (
25 from app.integrations.monitoring_alert.schema.provision import (
26 ProvisionWazuhMonitoringAlertResponse,
27 )
28 -from app.integrations.monitoring_alert.services.provision import provision_custom_alert
28 +from app.integrations.monitoring_alert.services.provision import provision_custom_alert, provision_crowdstrike_monitoring_alert, provision_fortinet_system_monitoring_alert, provision_fortinet_utm_monitoring_alert, provision_paloalto_monitoring_alert
29 from app.integrations.monitoring_alert.services.provision import (
30 provision_office365_exchange_online_alert,
31 )
@@ -120,6 +120,30 @@ async def invoke_provision_office365_threat_intel_alert(
120 # Provision the Office365 Threat Intel monitoring alert
121 await provision_office365_threat_intel_alert(request)
122
123 +async def invoke_provision_crowdstrike_monitoring_alert(
124 + request: ProvisionMonitoringAlertRequest,
125 +):
126 + # Provision the CrowdStrike monitoring alert
127 + await provision_crowdstrike_monitoring_alert(request)
128 +
129 +async def invoke_provision_fortinet_system_monitoring_alert(
130 + request: ProvisionMonitoringAlertRequest,
131 +):
132 + # Provision the Fortinet System monitoring alert
133 + await provision_fortinet_system_monitoring_alert(request)
134 +
135 +async def invoke_provision_fortinet_utm_monitoring_alert(
136 + request: ProvisionMonitoringAlertRequest,
137 +):
138 + # Provision the Fortinet UTM monitoring alert
139 + await provision_fortinet_utm_monitoring_alert(request)
140 +
141 +async def invoke_provision_paloalto_monitoring_alert(
142 + request: ProvisionMonitoringAlertRequest,
143 +):
144 + # Provision the Palo Alto monitoring alert
145 + await provision_paloalto_monitoring_alert(request)
146 +
147
148 async def invoke_provision_custom_monitoring_alert(
149 request: CustomMonitoringAlertProvisionModel,
@@ -134,6 +158,10 @@ PROVISION_FUNCTIONS = {
158 "SURICATA_ALERT_SEVERITY_1": invoke_provision_suricata_monitoring_alert,
159 "OFFICE365_EXCHANGE_ONLINE": invoke_provision_office365_exchange_online_alert,
160 "OFFICE365_THREAT_INTEL": invoke_provision_office365_threat_intel_alert,
161 + "CROWDSTRIKE_ALERT": invoke_provision_crowdstrike_monitoring_alert,
162 + "FORTINET_SYSTEM": invoke_provision_fortinet_system_monitoring_alert,
163 + "FORTINET_UTM": invoke_provision_fortinet_utm_monitoring_alert,
164 + "PALOALTO_ALERT": invoke_provision_paloalto_monitoring_alert,
165 "CUSTOM": invoke_provision_custom_monitoring_alert,
166 # Add more alert names and functions as needed
167 }
backend/app/integrations/monitoring_alert/schema/provision.py
+20
@@ -33,6 +33,26 @@ class AvailableMonitoringAlerts(str, Enum):
33 "alert that is created within CoPilot. Ensure that you have a pipeline rule that sets the "
34 "alert_severity field to 1 when the Office365 alert is detected."
35 )
36 + CROWDSTRIKE_ALERT = (
37 + "This alert monitors the CrowdStrike events. When an alert is detected, it triggers an "
38 + "alert that is created within CoPilot. Ensure that you have a pipeline rule that sets the "
39 + "alert_severity field to 1 when the CrowdStrike alert is detected."
40 + )
41 + FORTINET_SYSTEM = (
42 + "This alert monitors the Fortinet System events. When an alert is detected, it triggers an "
43 + "alert that is created within CoPilot. Ensure that you have a pipeline rule that sets the "
44 + "alert_severity field to 1 when the Fortinet alert is detected."
45 + )
46 + FORTINET_UTM = (
47 + "This alert monitors the Fortinet UTM events. When an alert is detected, it triggers an "
48 + "alert that is created within CoPilot. Ensure that you have a pipeline rule that sets the "
49 + "alert_severity field to 1 when the Fortinet alert is detected."
50 + )
51 + PALOALTO_ALERT = (
52 + "This alert monitors the PaloAlto events. When an alert is detected, it triggers an "
53 + "alert that is created within CoPilot. Ensure that you have a pipeline rule that sets the "
54 + "alert_severity field to 1 when the PaloAlto alert is detected."
55 + )
56
57
58 class AvailableMonitoringAlertsResponse(BaseModel):
backend/app/integrations/monitoring_alert/services/provision.py
+367
@@ -667,6 +667,373 @@ async def provision_office365_threat_intel_alert(
667 message="Office365 Threat Intel monitoring alerts provisioned successfully",
668 )
669
670 +async def provision_crowdstrike_monitoring_alert(
671 + request: ProvisionMonitoringAlertRequest,
672 +) -> ProvisionWazuhMonitoringAlertResponse:
673 + """
674 + Provisions Crowdstrike monitoring alerts.
675 +
676 + Returns:
677 + ProvisionWazuhMonitoringAlertResponse: The response indicating the success of provisioning the monitoring alerts.
678 + """
679 + #
680 + logger.info(
681 + f"Invoking provision_crowdstrike_monitoring_alert with request: {request.dict()}",
682 + )
683 + await provision_alert_definition(
684 + GraylogAlertProvisionModel(
685 + title="CROWDSTRIKE ALERT",
686 + description="Alert on Crowdstrike alerts",
687 + priority=2,
688 + config=GraylogAlertProvisionConfig(
689 + type="aggregation-v1",
690 + query="syslog_type:crowdstrike AND (syslog_level:Alert OR syslog_level:Warning)",
691 + query_parameters=[],
692 + streams=[],
693 + group_by=[],
694 + series=[],
695 + conditions={
696 + "expression": None,
697 + },
698 + search_within_ms=await convert_seconds_to_milliseconds(
699 + request.search_within_last,
700 + ),
701 + execute_every_ms=await convert_seconds_to_milliseconds(
702 + request.execute_every,
703 + ),
704 + event_limit=1000,
705 + ),
706 + field_spec={
707 + "ALERT_ID": GraylogAlertProvisionFieldSpecItem(
708 + data_type="string",
709 + providers=[
710 + GraylogAlertProvisionProvider(
711 + type="template-v1",
712 + template="${source._id}",
713 + require_values=True,
714 + ),
715 + ],
716 + ),
717 + "CUSTOMER_CODE": GraylogAlertProvisionFieldSpecItem(
718 + data_type="string",
719 + providers=[
720 + GraylogAlertProvisionProvider(
721 + type="template-v1",
722 + template="${source.syslog_customer}",
723 + require_values=True,
724 + ),
725 + ],
726 + ),
727 + "ALERT_SOURCE": GraylogAlertProvisionFieldSpecItem(
728 + data_type="string",
729 + providers=[
730 + GraylogAlertProvisionProvider(
731 + type="template-v1",
732 + template="CROWDSTRIKE",
733 + require_values=True,
734 + ),
735 + ],
736 + ),
737 + "COPILOT_ALERT_ID": GraylogAlertProvisionFieldSpecItem(
738 + data_type="string",
739 + providers=[
740 + GraylogAlertProvisionProvider(
741 + type="template-v1",
742 + template="NONE",
743 + require_values=True,
744 + ),
745 + ],
746 + ),
747 + },
748 + key_spec=[],
749 + notification_settings=GraylogAlertProvisionNotificationSettings(
750 + grace_period_ms=0,
751 + backlog_size=None,
752 + ),
753 + alert=True,
754 + ),
755 + )
756 +
757 + return ProvisionWazuhMonitoringAlertResponse(
758 + success=True,
759 + message="Crowdstrike monitoring alerts provisioned successfully",
760 + )
761 +
762 +async def provision_fortinet_system_monitoring_alert(
763 + request: ProvisionMonitoringAlertRequest,
764 +) -> ProvisionWazuhMonitoringAlertResponse:
765 + """
766 + Provisions Fortinet system monitoring alerts.
767 +
768 + Returns:
769 + ProvisionWazuhMonitoringAlertResponse: The response indicating the success of provisioning the monitoring alerts.
770 + """
771 + #
772 + logger.info(
773 + f"Invoking provision_fortinet_system_monitoring_alert with request: {request.dict()}",
774 + )
775 + await provision_alert_definition(
776 + GraylogAlertProvisionModel(
777 + title="FORTINET SYSTEM - CRITICAL EVENTS",
778 + description="FORTINET SYSTEM - CRITICAL EVENTS",
779 + priority=2,
780 + config=GraylogAlertProvisionConfig(
781 + type="aggregation-v1",
782 + query="syslog_type:fortinet AND subtype:system AND level:critical",
783 + query_parameters=[],
784 + streams=[],
785 + group_by=[],
786 + series=[],
787 + conditions={
788 + "expression": None,
789 + },
790 + search_within_ms=await convert_seconds_to_milliseconds(
791 + request.search_within_last,
792 + ),
793 + execute_every_ms=await convert_seconds_to_milliseconds(
794 + request.execute_every,
795 + ),
796 + event_limit=1000,
797 + ),
798 + field_spec={
799 + "ALERT_ID": GraylogAlertProvisionFieldSpecItem(
800 + data_type="string",
801 + providers=[
802 + GraylogAlertProvisionProvider(
803 + type="template-v1",
804 + template="${source._id}",
805 + require_values=True,
806 + ),
807 + ],
808 + ),
809 + "CUSTOMER_CODE": GraylogAlertProvisionFieldSpecItem(
810 + data_type="string",
811 + providers=[
812 + GraylogAlertProvisionProvider(
813 + type="template-v1",
814 + template="${source.syslog_customer}",
815 + require_values=True,
816 + ),
817 + ],
818 + ),
819 + "ALERT_SOURCE": GraylogAlertProvisionFieldSpecItem(
820 + data_type="string",
821 + providers=[
822 + GraylogAlertProvisionProvider(
823 + type="template-v1",
824 + template="FORTINET",
825 + require_values=True,
826 + ),
827 + ],
828 + ),
829 + "COPILOT_ALERT_ID": GraylogAlertProvisionFieldSpecItem(
830 + data_type="string",
831 + providers=[
832 + GraylogAlertProvisionProvider(
833 + type="template-v1",
834 + template="NONE",
835 + require_values=True,
836 + ),
837 + ],
838 + ),
839 + },
840 + key_spec=[],
841 + notification_settings=GraylogAlertProvisionNotificationSettings(
842 + grace_period_ms=0,
843 + backlog_size=None,
844 + ),
845 + alert=True,
846 + ),
847 + )
848 +
849 + return ProvisionWazuhMonitoringAlertResponse(
850 + success=True,
851 + message="Fortinet system monitoring alerts provisioned successfully",
852 + )
853 +
854 +async def provision_fortinet_utm_monitoring_alert(
855 + request: ProvisionMonitoringAlertRequest,
856 +) -> ProvisionWazuhMonitoringAlertResponse:
857 + """
858 + Provisions Fortinet UTM monitoring alerts.
859 +
860 + Returns:
861 + ProvisionWazuhMonitoringAlertResponse: The response indicating the success of provisioning the monitoring alerts.
862 + """
863 + #
864 + logger.info(
865 + f"Invoking provision_fortinet_utm_monitoring_alert with request: {request.dict()}",
866 + )
867 + await provision_alert_definition(
868 + GraylogAlertProvisionModel(
869 + title="FORTINET UTM - HIGH SEVERITY EVENTS",
870 + description="FORTINET UTM - HIGH SEVERITY EVENTS",
871 + priority=2,
872 + config=GraylogAlertProvisionConfig(
873 + type="aggregation-v1",
874 + query="syslog_type:fortinet AND type:utm AND (severity:high OR severity:critical) AND !action:dropped AND !action:clear_session",
875 + query_parameters=[],
876 + streams=[],
877 + group_by=[],
878 + series=[],
879 + conditions={
880 + "expression": None,
881 + },
882 + search_within_ms=await convert_seconds_to_milliseconds(
883 + request.search_within_last,
884 + ),
885 + execute_every_ms=await convert_seconds_to_milliseconds(
886 + request.execute_every,
887 + ),
888 + event_limit=1000,
889 + ),
890 + field_spec={
891 + "ALERT_ID": GraylogAlertProvisionFieldSpecItem(
892 + data_type="string",
893 + providers=[
894 + GraylogAlertProvisionProvider(
895 + type="template-v1",
896 + template="${source._id}",
897 + require_values=True,
898 + ),
899 + ],
900 + ),
901 + "CUSTOMER_CODE": GraylogAlertProvisionFieldSpecItem(
902 + data_type="string",
903 + providers=[
904 + GraylogAlertProvisionProvider(
905 + type="template-v1",
906 + template="${source.syslog_customer}",
907 + require_values=True,
908 + ),
909 + ],
910 + ),
911 + "ALERT_SOURCE": GraylogAlertProvisionFieldSpecItem(
912 + data_type="string",
913 + providers=[
914 + GraylogAlertProvisionProvider(
915 + type="template-v1",
916 + template="FORTINET",
917 + require_values=True,
918 + ),
919 + ],
920 + ),
921 + "COPILOT_ALERT_ID": GraylogAlertProvisionFieldSpecItem(
922 + data_type="string",
923 + providers=[
924 + GraylogAlertProvisionProvider(
925 + type="template-v1",
926 + template="NONE",
927 + require_values=True,
928 + ),
929 + ],
930 + ),
931 + },
932 + key_spec=[],
933 + notification_settings=GraylogAlertProvisionNotificationSettings(
934 + grace_period_ms=0,
935 + backlog_size=None,
936 + ),
937 + alert=True,
938 + ),
939 + )
940 +
941 + return ProvisionWazuhMonitoringAlertResponse(
942 + success=True,
943 + message="Fortinet UTM monitoring alerts provisioned successfully",
944 + )
945 +
946 +async def provision_paloalto_monitoring_alert(
947 + request: ProvisionMonitoringAlertRequest,
948 +) -> ProvisionWazuhMonitoringAlertResponse:
949 + """
950 + Provisions Palo Alto monitoring alerts.
951 +
952 + Returns:
953 + ProvisionWazuhMonitoringAlertResponse: The response indicating the success of provisioning the monitoring alerts.
954 + """
955 + #
956 + logger.info(
957 + f"Invoking provision_paloalto_monitoring_alert with request: {request.dict()}",
958 + )
959 + await provision_alert_definition(
960 + GraylogAlertProvisionModel(
961 + title="PALO ALTO - HIGH SEVERITY EVENTS",
962 + description="PALO ALTO - HIGH SEVERITY EVENTS",
963 + priority=2,
964 + config=GraylogAlertProvisionConfig(
965 + type="aggregation-v1",
966 + query="syslog_type:palo_alto AND event_log_name:THREAT AND (vendor_alert_severity:high OR vendor_alert_severity:critical) AND !vendor_event_action:drop",
967 + query_parameters=[],
968 + streams=[],
969 + group_by=[],
970 + series=[],
971 + conditions={
972 + "expression": None,
973 + },
974 + search_within_ms=await convert_seconds_to_milliseconds(
975 + request.search_within_last,
976 + ),
977 + execute_every_ms=await convert_seconds_to_milliseconds(
978 + request.execute_every,
979 + ),
980 + event_limit=1000,
981 + ),
982 + field_spec={
983 + "ALERT_ID": GraylogAlertProvisionFieldSpecItem(
984 + data_type="string",
985 + providers=[
986 + GraylogAlertProvisionProvider(
987 + type="template-v1",
988 + template="${source._id}",
989 + require_values=True,
990 + ),
991 + ],
992 + ),
993 + "CUSTOMER_CODE": GraylogAlertProvisionFieldSpecItem(
994 + data_type="string",
995 + providers=[
996 + GraylogAlertProvisionProvider(
997 + type="template-v1",
998 + template="${source.syslog_customer}",
999 + require_values=True,
1000 + ),
1001 + ],
1002 + ),
1003 + "ALERT_SOURCE": GraylogAlertProvisionFieldSpecItem(
1004 + data_type="string",
1005 + providers=[
1006 + GraylogAlertProvisionProvider(
1007 + type="template-v1",
1008 + template="PALOALTO",
1009 + require_values=True,
1010 + ),
1011 + ],
1012 + ),
1013 + "COPILOT_ALERT_ID": GraylogAlertProvisionFieldSpecItem(
1014 + data_type="string",
1015 + providers=[
1016 + GraylogAlertProvisionProvider(
1017 + type="template-v1",
1018 + template="NONE",
1019 + require_values=True,
1020 + ),
1021 + ],
1022 + ),
1023 + },
1024 + key_spec=[],
1025 + notification_settings=GraylogAlertProvisionNotificationSettings(
1026 + grace_period_ms=0,
1027 + backlog_size=None,
1028 + ),
1029 + alert=True,
1030 + ),
1031 + )
1032 +
1033 + return ProvisionWazuhMonitoringAlertResponse(
1034 + success=True,
1035 + message="Palo Alto monitoring alerts provisioned successfully",
1036 + )
1037
1038 async def provision_custom_alert(request: CustomMonitoringAlertProvisionModel) -> ProvisionWazuhMonitoringAlertResponse:
1039 """
backend/app/routers/shuffle.py
+7
@@ -2,6 +2,7 @@ from fastapi import APIRouter
2
3 from app.connectors.shuffle.routes.integrations import shuffle_integrations_router
4 from app.connectors.shuffle.routes.workflows import shuffle_workflows_router
5 +from app.connectors.shuffle.routes.singul import shuffle_singul_router
6
7 # Instantiate the APIRouter
8 router = APIRouter()
@@ -18,3 +19,9 @@ router.include_router(
19 prefix="/shuffle/integrations",
20 tags=["shuffle-integrations"],
21 )
22 +
23 +router.include_router(
24 + shuffle_singul_router,
25 + prefix="/shuffle/singul",
26 + tags=["shuffle-singul"],
27 +)
backend/requirements.txt
+1
@@ -155,6 +155,7 @@ starlette==0.27.0
155 stix==1.2.0.11
156 stix2==3.0.1
157 stix2-elevator==4.1.7
158 +shufflepy==0.1.6
159 stix2-patterns==2.0.0
160 stix2-validator==3.1.4
161 stixmarx==1.0.8
frontend/package.json
+35 -32
@@ -3,7 +3,7 @@
3 "type": "module",
4 "version": "1.0.0",
5 "private": true,
6 - "packageManager": "pnpm@10.9.0+sha512.0486e394640d3c1fb3c9d43d49cf92879ff74f8516959c235308f5a8f62e2e19528a65cdc2a3058f587cde71eba3d5b56327c8c33a97e4c4051ca48a10ca2d5f",
6 + "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977",
7 "engines": {
8 "node": ">=18.0.0"
9 },
@@ -38,15 +38,16 @@
38 "dependencies": {
39 "@ajoelp/json-to-formdata": "^1.5.0",
40 "@codemirror/commands": "^6.8.1",
41 - "@codemirror/lang-javascript": "^6.2.3",
41 + "@codemirror/lang-javascript": "^6.2.4",
42 "@codemirror/lang-xml": "^6.1.0",
43 "@codemirror/theme-one-dark": "^6.1.2",
44 "@f3ve/vue-markdown-it": "^0.2.3",
45 "@fontsource/jetbrains-mono": "^5.2.5",
46 - "@fontsource/lexend": "^5.2.6",
46 + "@fontsource/lexend": "^5.2.7",
47 "@fontsource/public-sans": "^5.2.5",
48 - "@shikijs/markdown-it": "^3.3.0",
49 - "@vueuse/core": "^13.1.0",
48 + "@shikijs/markdown-it": "^3.4.2",
49 + "@vueuse/core": "^13.3.0",
50 + "@vueuse/motion": "^3.0.3",
51 "axios": "^1.9.0",
52 "bytes": "^3.1.2",
53 "codemirror": "~6.0.1",
@@ -56,7 +57,7 @@
57 "echarts": "^5.6.0",
58 "file-saver": "^2.0.5",
59 "html-entities": "^2.6.0",
59 - "jose": "^6.0.10",
60 + "jose": "^6.0.11",
61 "js-md5": "^0.8.3",
62 "lodash": "^4.17.21",
63 "mitt": "^3.0.1",
@@ -64,16 +65,16 @@
65 "nanoid": "^5.1.5",
66 "password-validator": "^5.3.0",
67 "pinia": "^3.0.2",
67 - "pinia-plugin-persistedstate": "^4.2.0",
68 + "pinia-plugin-persistedstate": "^4.3.0",
69 "secure-ls": "^2.0.0",
69 - "shiki": "^3.3.0",
70 + "shiki": "^3.4.2",
71 "thememirror": "^2.0.1",
71 - "validator": "^13.15.0",
72 - "vue": "^3.5.13",
72 + "validator": "^13.15.15",
73 + "vue": "^3.5.15",
74 "vue-advanced-cropper": "^2.8.9",
75 "vue-codemirror": "^6.1.1",
76 "vue-highlight-words": "^3.0.1",
76 - "vue-i18n": "^11.1.3",
77 + "vue-i18n": "^11.1.5",
78 "vue-router": "^4.5.1",
79 "vue-sjv": "^0.0.6",
80 "vue3-apexcharts": "^1.8.0",
@@ -81,52 +82,54 @@
82 "vuedraggable": "^4.1.0"
83 },
84 "optionalDependencies": {
84 - "@rollup/rollup-linux-x64-gnu": "^4.40.0",
85 + "@rollup/rollup-linux-x64-gnu": "^4.41.1",
86 "treemate": "^0.3.11",
87 "vueuc": "^0.4.64"
88 },
89 "devDependencies": {
89 - "@antfu/eslint-config": "^4.12.0",
90 - "@clack/prompts": "^0.10.1",
91 - "@iconify/vue": "^4.3.0",
92 - "@tailwindcss/vite": "^4.1.4",
90 + "@antfu/eslint-config": "^4.13.2",
91 + "@clack/prompts": "^0.11.0",
92 + "@iconify/vue": "^5.0.0",
93 + "@tailwindcss/vite": "^4.1.7",
94 "@tsconfig/node20": "^20.1.5",
95 "@types/bytes": "^3.1.5",
96 "@types/file-saver": "^2.0.7",
97 "@types/fs-extra": "^11.0.4",
98 "@types/jsdom": "^21.1.7",
98 - "@types/lodash": "^4.17.16",
99 - "@types/node": "^22.15.2",
100 - "@types/validator": "^13.15.0",
101 - "@vitejs/plugin-vue": "^5.2.3",
102 - "@vitejs/plugin-vue-jsx": "^4.1.2",
99 + "@types/lodash": "^4.17.17",
100 + "@types/markdown-it": "^14.1.2",
101 + "@types/node": "^22.15.23",
102 + "@types/validator": "^13.15.1",
103 + "@vitejs/plugin-vue": "^5.2.4",
104 + "@vitejs/plugin-vue-jsx": "^4.2.0",
105 "@vue/test-utils": "^2.4.6",
106 "@vue/tsconfig": "^0.7.0",
105 - "cypress": "^14.3.2",
107 + "cypress": "^14.4.0",
108 "depcheck": "^1.4.7",
107 - "eslint": "^9.25.1",
109 + "eslint": "^9.27.0",
110 "flourite": "^1.3.0",
111 "fs-extra": "^11.3.0",
112 "jsdom": "^26.1.0",
111 - "npm-run-all2": "^7.0.2",
113 + "npm-run-all2": "^8.0.4",
114 "prettier": "^3.5.3",
115 "prettier-plugin-tailwindcss": "^0.6.11",
114 - "sass": "^1.87.0",
115 - "start-server-and-test": "^2.0.11",
116 - "tailwindcss": "^4.1.4",
117 - "taze": "^19.0.4",
118 - "type-fest": "^4.40.0",
116 + "sass": "^1.89.0",
117 + "start-server-and-test": "^2.0.12",
118 + "tailwindcss": "^4.1.7",
119 + "taze": "^19.1.0",
120 + "type-fest": "^4.41.0",
121 "typescript": "~5.8.3",
120 - "vite": "^6.3.3",
122 + "vite": "^6.3.5",
123 "vite-bundle-visualizer": "^1.2.1",
122 - "vite-plugin-vue-devtools": "^7.7.5",
124 + "vite-plugin-vue-devtools": "^7.7.6",
125 "vite-svg-loader": "^5.1.0",
124 - "vitest": "^3.1.2",
126 + "vitest": "^3.1.4",
127 "vue-tsc": "^2.2.10"
128 },
129 "pnpm": {
130 "onlyBuiltDependencies": [
131 "@parcel/watcher",
132 + "@tailwindcss/oxide",
133 "cypress",
134 "esbuild",
135 "unrs-resolver"
frontend/pnpm-lock.yaml
+1801 -1848
@@ -15,8 +15,8 @@ importers:
15 specifier: ^6.8.1
16 version: 6.8.1
17 '@codemirror/lang-javascript':
18 - specifier: ^6.2.3
19 - version: 6.2.3
18 + specifier: ^6.2.4
19 + version: 6.2.4
20 '@codemirror/lang-xml':
21 specifier: ^6.1.0
22 version: 6.1.0
@@ -25,25 +25,28 @@ importers:
25 version: 6.1.2
26 '@f3ve/vue-markdown-it':
27 specifier: ^0.2.3
28 - version: 0.2.3(vue@3.5.13(typescript@5.8.3))
28 + version: 0.2.3(vue@3.5.15(typescript@5.8.3))
29 '@fontsource/jetbrains-mono':
30 specifier: ^5.2.5
31 version: 5.2.5
32 '@fontsource/lexend':
33 - specifier: ^5.2.6
34 - version: 5.2.6
33 + specifier: ^5.2.7
34 + version: 5.2.7
35 '@fontsource/public-sans':
36 specifier: ^5.2.5
37 version: 5.2.5
38 '@shikijs/markdown-it':
39 - specifier: ^3.3.0
40 - version: 3.3.0
39 + specifier: ^3.4.2
40 + version: 3.4.2
41 '@vueuse/core':
42 - specifier: ^13.1.0
43 - version: 13.1.0(vue@3.5.13(typescript@5.8.3))
42 + specifier: ^13.3.0
43 + version: 13.3.0(vue@3.5.15(typescript@5.8.3))
44 + '@vueuse/motion':
45 + specifier: ^3.0.3
46 + version: 3.0.3(vue@3.5.15(typescript@5.8.3))
47 axios:
48 specifier: ^1.9.0
46 - version: 1.9.0(debug@4.4.0)
49 + version: 1.9.0(debug@4.4.1)
50 bytes:
51 specifier: ^3.1.2
52 version: 3.1.2
@@ -69,8 +72,8 @@ importers:
72 specifier: ^2.6.0
73 version: 2.6.0
74 jose:
72 - specifier: ^6.0.10
73 - version: 6.0.10
75 + specifier: ^6.0.11
76 + version: 6.0.11
77 js-md5:
78 specifier: ^0.8.3
79 version: 0.8.3
@@ -82,7 +85,7 @@ importers:
85 version: 3.0.1
86 naive-ui:
87 specifier: ^2.41.0
85 - version: 2.41.0(vue@3.5.13(typescript@5.8.3))
88 + version: 2.41.0(vue@3.5.15(typescript@5.8.3))
89 nanoid:
90 specifier: ^5.1.5
91 version: 5.1.5
@@ -91,65 +94,65 @@ importers:
94 version: 5.3.0
95 pinia:
96 specifier: ^3.0.2
94 - version: 3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))
97 + version: 3.0.2(typescript@5.8.3)(vue@3.5.15(typescript@5.8.3))
98 pinia-plugin-persistedstate:
96 - specifier: ^4.2.0
97 - version: 4.2.0(pinia@3.0.2(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3)))
99 + specifier: ^4.3.0
100 + version: 4.3.0(pinia@3.0.2(typescript@5.8.3)(vue@3.5.15(typescript@5.8.3)))
101 secure-ls:
102 specifier: ^2.0.0
103 version: 2.0.0
104 shiki:
102 - specifier: ^3.3.0
103 - version: 3.3.0
105 + specifier: ^3.4.2
106 + version: 3.4.2
107 thememirror:
108 specifier: ^2.0.1
106 - version: 2.0.1(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.5)
109 + version: 2.0.1(@codemirror/language@6.11.0)(@codemirror/state@6.5.2)(@codemirror/view@6.36.8)
110 validator:
108 - specifier: ^13.15.0
109 - version: 13.15.0
111 + specifier: ^13.15.15
112 + version: 13.15.15
113 vue:
111 - specifier: ^3.5.13
112 - version: 3.5.13(typescript@5.8.3)
114 + specifier: ^3.5.15
115 + version: 3.5.15(typescript@5.8.3)
116 vue-advanced-cropper:
117 specifier: ^2.8.9
115 - version: 2.8.9(vue@3.5.13(typescript@5.8.3))
118 + version: 2.8.9(vue@3.5.15(typescript@5.8.3))
119 vue-codemirror:
120 specifier: ^6.1.1
118 - version: 6.1.1(codemirror@6.0.1)(vue@3.5.13(typescript@5.8.3))
121 + version: 6.1.1(codemirror@6.0.1)(vue@3.5.15(typescript@5.8.3))
122 vue-highlight-words:
123 specifier: ^3.0.1
121 - version: 3.0.1(vue@3.5.13(typescript@5.8.3))
124 + version: 3.0.1(vue@3.5.15(typescript@5.8.3))
125 vue-i18n:
123 - specifier: ^11.1.3
124 - version: 11.1.3(vue@3.5.13(typescript@5.8.3))
126 + specifier: ^11.1.5
127 + version: 11.1.5(vue@3.5.15(typescript@5.8.3))
128 vue-router:
129 specifier: ^4.5.1
127 - version: 4.5.1(vue@3.5.13(typescript@5.8.3))
130 + version: 4.5.1(vue@3.5.15(typescript@5.8.3))
131 vue-sjv:
132 specifier: ^0.0.6
130 - version: 0.0.6(vue@3.5.13(typescript@5.8.3))
133 + version: 0.0.6(vue@3.5.15(typescript@5.8.3))
134 vue3-apexcharts:
135 specifier: ^1.8.0
133 - version: 1.8.0(apexcharts@4.5.0)(vue@3.5.13(typescript@5.8.3))
136 + version: 1.8.0(apexcharts@4.7.0)(vue@3.5.15(typescript@5.8.3))
137 vue3-marquee:
138 specifier: ^4.2.2
136 - version: 4.2.2(vue@3.5.13(typescript@5.8.3))
139 + version: 4.2.2(vue@3.5.15(typescript@5.8.3))
140 vuedraggable:
141 specifier: ^4.1.0
139 - version: 4.1.0(vue@3.5.13(typescript@5.8.3))
142 + version: 4.1.0(vue@3.5.15(typescript@5.8.3))
143 devDependencies:
144 '@antfu/eslint-config':
142 - specifier: ^4.12.0
143 - version: 4.12.0(@typescript-eslint/utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(@vue/compiler-sfc@3.5.13)(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))
145 + specifier: ^4.13.2
146 + version: 4.13.2(@vue/compiler-sfc@3.5.15)(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))
147 '@clack/prompts':
145 - specifier: ^0.10.1
146 - version: 0.10.1
148 + specifier: ^0.11.0
149 + version: 0.11.0
150 '@iconify/vue':
148 - specifier: ^4.3.0
149 - version: 4.3.0(vue@3.5.13(typescript@5.8.3))
151 + specifier: ^5.0.0
152 + version: 5.0.0(vue@3.5.15(typescript@5.8.3))
153 '@tailwindcss/vite':
151 - specifier: ^4.1.4
152 - version: 4.1.4(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))
154 + specifier: ^4.1.7
155 + version: 4.1.8(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))
156 '@tsconfig/node20':
157 specifier: ^20.1.5
158 version: 20.1.5
@@ -166,35 +169,38 @@ importers:
169 specifier: ^21.1.7
170 version: 21.1.7
171 '@types/lodash':
169 - specifier: ^4.17.16
170 - version: 4.17.16
172 + specifier: ^4.17.17
173 + version: 4.17.17
174 + '@types/markdown-it':
175 + specifier: ^14.1.2
176 + version: 14.1.2
177 '@types/node':
172 - specifier: ^22.15.2
173 - version: 22.15.2
178 + specifier: ^22.15.23
179 + version: 22.15.23
180 '@types/validator':
175 - specifier: ^13.15.0
176 - version: 13.15.0
181 + specifier: ^13.15.1
182 + version: 13.15.1
183 '@vitejs/plugin-vue':
178 - specifier: ^5.2.3
179 - version: 5.2.3(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))
184 + specifier: ^5.2.4
185 + version: 5.2.4(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))
186 '@vitejs/plugin-vue-jsx':
181 - specifier: ^4.1.2
182 - version: 4.1.2(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))
187 + specifier: ^4.2.0
188 + version: 4.2.0(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))
189 '@vue/test-utils':
190 specifier: ^2.4.6
191 version: 2.4.6
192 '@vue/tsconfig':
193 specifier: ^0.7.0
188 - version: 0.7.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))
194 + version: 0.7.0(typescript@5.8.3)(vue@3.5.15(typescript@5.8.3))
195 cypress:
190 - specifier: ^14.3.2
191 - version: 14.3.2
196 + specifier: ^14.4.0
197 + version: 14.4.0
198 depcheck:
199 specifier: ^1.4.7
200 version: 1.4.7
201 eslint:
196 - specifier: ^9.25.1
197 - version: 9.25.1(jiti@2.4.2)
202 + specifier: ^9.27.0
203 + version: 9.27.0(jiti@2.4.2)
204 flourite:
205 specifier: ^1.3.0
206 version: 1.3.0
@@ -205,8 +211,8 @@ importers:
211 specifier: ^26.1.0
212 version: 26.1.0
213 npm-run-all2:
208 - specifier: ^7.0.2
209 - version: 7.0.2
214 + specifier: ^8.0.4
215 + version: 8.0.4
216 prettier:
217 specifier: ^3.5.3
218 version: 3.5.3
@@ -214,51 +220,51 @@ importers:
220 specifier: ^0.6.11
221 version: 0.6.11(prettier@3.5.3)
222 sass:
217 - specifier: ^1.87.0
218 - version: 1.87.0
223 + specifier: ^1.89.0
224 + version: 1.89.0
225 start-server-and-test:
220 - specifier: ^2.0.11
221 - version: 2.0.11
226 + specifier: ^2.0.12
227 + version: 2.0.12
228 tailwindcss:
223 - specifier: ^4.1.4
224 - version: 4.1.4
229 + specifier: ^4.1.7
230 + version: 4.1.8
231 taze:
226 - specifier: ^19.0.4
227 - version: 19.0.4
232 + specifier: ^19.1.0
233 + version: 19.1.0
234 type-fest:
229 - specifier: ^4.40.0
230 - version: 4.40.0
235 + specifier: ^4.41.0
236 + version: 4.41.0
237 typescript:
238 specifier: ~5.8.3
239 version: 5.8.3
240 vite:
235 - specifier: ^6.3.3
236 - version: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
241 + specifier: ^6.3.5
242 + version: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
243 vite-bundle-visualizer:
244 specifier: ^1.2.1
239 - version: 1.2.1(rollup@4.39.0)
245 + version: 1.2.1(rollup@4.41.1)
246 vite-plugin-vue-devtools:
241 - specifier: ^7.7.5
242 - version: 7.7.5(rollup@4.39.0)(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))
247 + specifier: ^7.7.6
248 + version: 7.7.6(rollup@4.41.1)(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))
249 vite-svg-loader:
250 specifier: ^5.1.0
245 - version: 5.1.0(vue@3.5.13(typescript@5.8.3))
251 + version: 5.1.0(vue@3.5.15(typescript@5.8.3))
252 vitest:
247 - specifier: ^3.1.2
248 - version: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
253 + specifier: ^3.1.4
254 + version: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
255 vue-tsc:
256 specifier: ^2.2.10
257 version: 2.2.10(typescript@5.8.3)
258 optionalDependencies:
259 '@rollup/rollup-linux-x64-gnu':
254 - specifier: ^4.40.0
255 - version: 4.40.0
260 + specifier: ^4.41.1
261 + version: 4.41.1
262 treemate:
263 specifier: ^0.3.11
264 version: 0.3.11
265 vueuc:
266 specifier: ^0.4.64
261 - version: 0.4.64(vue@3.5.13(typescript@5.8.3))
267 + version: 0.4.64(vue@3.5.15(typescript@5.8.3))
268
269 packages:
270
@@ -269,8 +275,8 @@ packages:
275 resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
276 engines: {node: '>=6.0.0'}
277
272 - '@antfu/eslint-config@4.12.0':
273 - resolution: {integrity: sha512-8NszLFXu9/cwOP/qliYS3heD+9ZCouGgOWQmsXgDHLNkjC9IjI1yXBOp6Xs4EvwTKsSAZp3SVw382M8naqMQUg==}
278 + '@antfu/eslint-config@4.13.2':
279 + resolution: {integrity: sha512-F+IVIQUCfw6eW4H06c9a9USJ3UOnoBx4I0qsTL3kO6GcyJB6mwk+nawFf95DfHKT3fJKv58YPPz0XCmsY/w0XA==}
280 hasBin: true
281 peerDependencies:
282 '@eslint-react/eslint-plugin': ^1.38.4
@@ -318,116 +324,116 @@ packages:
324 svelte-eslint-parser:
325 optional: true
326
321 - '@antfu/install-pkg@1.0.0':
322 - resolution: {integrity: sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==}
327 + '@antfu/install-pkg@1.1.0':
328 + resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
329
324 - '@antfu/ni@24.3.0':
325 - resolution: {integrity: sha512-wBSav4mBxvHEW9RbdSo1SWLQ6MAlT0Dc423weC58yOWqW4OcMvtnNDdDrxOZeJ88fEIyPK93gDUWIelBxzSf8g==}
330 + '@antfu/ni@24.4.0':
331 + resolution: {integrity: sha512-ZjriRbGyWGSrBE1RY2qBIXyilejMWLDWh2Go2dqFottyiuOze36+BpPch2z2WnGEgEbzTBVPetMmQvt0xt+iww==}
332 hasBin: true
333
334 '@antfu/utils@0.7.10':
335 resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
336
331 - '@asamuzakjp/css-color@3.1.1':
332 - resolution: {integrity: sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==}
337 + '@asamuzakjp/css-color@3.2.0':
338 + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
339
334 - '@babel/code-frame@7.26.2':
335 - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
340 + '@babel/code-frame@7.27.1':
341 + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
342 engines: {node: '>=6.9.0'}
343
338 - '@babel/compat-data@7.26.8':
339 - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==}
344 + '@babel/compat-data@7.27.3':
345 + resolution: {integrity: sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==}
346 engines: {node: '>=6.9.0'}
347
342 - '@babel/core@7.26.10':
343 - resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==}
348 + '@babel/core@7.27.3':
349 + resolution: {integrity: sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==}
350 engines: {node: '>=6.9.0'}
351
346 - '@babel/generator@7.27.0':
347 - resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==}
352 + '@babel/generator@7.27.3':
353 + resolution: {integrity: sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==}
354 engines: {node: '>=6.9.0'}
355
350 - '@babel/helper-annotate-as-pure@7.25.9':
351 - resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==}
356 + '@babel/helper-annotate-as-pure@7.27.3':
357 + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==}
358 engines: {node: '>=6.9.0'}
359
354 - '@babel/helper-compilation-targets@7.27.0':
355 - resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==}
360 + '@babel/helper-compilation-targets@7.27.2':
361 + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
362 engines: {node: '>=6.9.0'}
363
358 - '@babel/helper-create-class-features-plugin@7.27.0':
359 - resolution: {integrity: sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==}
364 + '@babel/helper-create-class-features-plugin@7.27.1':
365 + resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==}
366 engines: {node: '>=6.9.0'}
367 peerDependencies:
368 '@babel/core': ^7.0.0
369
364 - '@babel/helper-member-expression-to-functions@7.25.9':
365 - resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==}
370 + '@babel/helper-member-expression-to-functions@7.27.1':
371 + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==}
372 engines: {node: '>=6.9.0'}
373
368 - '@babel/helper-module-imports@7.25.9':
369 - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
374 + '@babel/helper-module-imports@7.27.1':
375 + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
376 engines: {node: '>=6.9.0'}
377
372 - '@babel/helper-module-transforms@7.26.0':
373 - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
378 + '@babel/helper-module-transforms@7.27.3':
379 + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==}
380 engines: {node: '>=6.9.0'}
381 peerDependencies:
382 '@babel/core': ^7.0.0
383
378 - '@babel/helper-optimise-call-expression@7.25.9':
379 - resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==}
384 + '@babel/helper-optimise-call-expression@7.27.1':
385 + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==}
386 engines: {node: '>=6.9.0'}
387
382 - '@babel/helper-plugin-utils@7.26.5':
383 - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==}
388 + '@babel/helper-plugin-utils@7.27.1':
389 + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==}
390 engines: {node: '>=6.9.0'}
391
386 - '@babel/helper-replace-supers@7.26.5':
387 - resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==}
392 + '@babel/helper-replace-supers@7.27.1':
393 + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==}
394 engines: {node: '>=6.9.0'}
395 peerDependencies:
396 '@babel/core': ^7.0.0
397
392 - '@babel/helper-skip-transparent-expression-wrappers@7.25.9':
393 - resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==}
398 + '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
399 + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
400 engines: {node: '>=6.9.0'}
401
396 - '@babel/helper-string-parser@7.25.9':
397 - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
402 + '@babel/helper-string-parser@7.27.1':
403 + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
404 engines: {node: '>=6.9.0'}
405
400 - '@babel/helper-validator-identifier@7.25.9':
401 - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==}
406 + '@babel/helper-validator-identifier@7.27.1':
407 + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==}
408 engines: {node: '>=6.9.0'}
409
404 - '@babel/helper-validator-option@7.25.9':
405 - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
410 + '@babel/helper-validator-option@7.27.1':
411 + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
412 engines: {node: '>=6.9.0'}
413
408 - '@babel/helpers@7.27.0':
409 - resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==}
414 + '@babel/helpers@7.27.3':
415 + resolution: {integrity: sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==}
416 engines: {node: '>=6.9.0'}
417
412 - '@babel/parser@7.27.0':
413 - resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==}
418 + '@babel/parser@7.27.3':
419 + resolution: {integrity: sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==}
420 engines: {node: '>=6.0.0'}
421 hasBin: true
422
417 - '@babel/plugin-proposal-decorators@7.25.9':
418 - resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==}
423 + '@babel/plugin-proposal-decorators@7.27.1':
424 + resolution: {integrity: sha512-DTxe4LBPrtFdsWzgpmbBKevg3e9PBy+dXRt19kSbucbZvL2uqtdqwwpluL1jfxYE0wIDTFp1nTy/q6gNLsxXrg==}
425 engines: {node: '>=6.9.0'}
426 peerDependencies:
427 '@babel/core': ^7.0.0-0
428
423 - '@babel/plugin-syntax-decorators@7.25.9':
424 - resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==}
429 + '@babel/plugin-syntax-decorators@7.27.1':
430 + resolution: {integrity: sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==}
431 engines: {node: '>=6.9.0'}
432 peerDependencies:
433 '@babel/core': ^7.0.0-0
434
429 - '@babel/plugin-syntax-import-attributes@7.26.0':
430 - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==}
435 + '@babel/plugin-syntax-import-attributes@7.27.1':
436 + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==}
437 engines: {node: '>=6.9.0'}
438 peerDependencies:
439 '@babel/core': ^7.0.0-0
@@ -437,50 +443,56 @@ packages:
443 peerDependencies:
444 '@babel/core': ^7.0.0-0
445
440 - '@babel/plugin-syntax-jsx@7.25.9':
441 - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==}
446 + '@babel/plugin-syntax-jsx@7.27.1':
447 + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==}
448 engines: {node: '>=6.9.0'}
449 peerDependencies:
450 '@babel/core': ^7.0.0-0
451
446 - '@babel/plugin-syntax-typescript@7.25.9':
447 - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==}
452 + '@babel/plugin-syntax-typescript@7.27.1':
453 + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==}
454 engines: {node: '>=6.9.0'}
455 peerDependencies:
456 '@babel/core': ^7.0.0-0
457
452 - '@babel/plugin-transform-typescript@7.27.0':
453 - resolution: {integrity: sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==}
458 + '@babel/plugin-transform-typescript@7.27.1':
459 + resolution: {integrity: sha512-Q5sT5+O4QUebHdbwKedFBEwRLb02zJ7r4A5Gg2hUoLuU3FjdMcyqcywqUrLCaDsFCxzokf7u9kuy7qz51YUuAg==}
460 engines: {node: '>=6.9.0'}
461 peerDependencies:
462 '@babel/core': ^7.0.0-0
463
458 - '@babel/template@7.27.0':
459 - resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==}
464 + '@babel/template@7.27.2':
465 + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
466 engines: {node: '>=6.9.0'}
467
462 - '@babel/traverse@7.27.0':
463 - resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==}
468 + '@babel/traverse@7.27.3':
469 + resolution: {integrity: sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==}
470 engines: {node: '>=6.9.0'}
471
466 - '@babel/types@7.27.0':
467 - resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==}
472 + '@babel/types@7.27.3':
473 + resolution: {integrity: sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==}
474 engines: {node: '>=6.9.0'}
475
476 '@clack/core@0.4.2':
477 resolution: {integrity: sha512-NYQfcEy8MWIxrT5Fj8nIVchfRFA26yYKJcvBS7WlUIlw2OmQOY9DhGGXMovyI5J5PpxrCPGkgUi207EBrjpBvg==}
478
479 + '@clack/core@0.5.0':
480 + resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==}
481 +
482 '@clack/prompts@0.10.1':
483 resolution: {integrity: sha512-Q0T02vx8ZM9XSv9/Yde0jTmmBQufZhPJfYAg2XrrrxWWaZgq1rr8nU8Hv710BQ1dhoP8rtY7YUdpGej2Qza/cw==}
484
485 + '@clack/prompts@0.11.0':
486 + resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==}
487 +
488 '@codemirror/autocomplete@6.18.6':
489 resolution: {integrity: sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg==}
490
491 '@codemirror/commands@6.8.1':
492 resolution: {integrity: sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==}
493
482 - '@codemirror/lang-javascript@6.2.3':
483 - resolution: {integrity: sha512-8PR3vIWg7pSu7ur8A07pGiYHgy3hHj+mRYRCSG8q+mPIrl0F02rgpGv+DsQTHRTc30rydOsf5PZ7yjKFg2Ackw==}
494 + '@codemirror/lang-javascript@6.2.4':
495 + resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==}
496
497 '@codemirror/lang-xml@6.1.0':
498 resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==}
@@ -491,8 +503,8 @@ packages:
503 '@codemirror/lint@6.8.5':
504 resolution: {integrity: sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==}
505
494 - '@codemirror/search@6.5.10':
495 - resolution: {integrity: sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg==}
506 + '@codemirror/search@6.5.11':
507 + resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==}
508
509 '@codemirror/state@6.5.2':
510 resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==}
@@ -500,12 +512,8 @@ packages:
512 '@codemirror/theme-one-dark@6.1.2':
513 resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
514
503 - '@codemirror/view@6.36.5':
504 - resolution: {integrity: sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg==}
505 -
506 - '@colors/colors@1.5.0':
507 - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
508 - engines: {node: '>=0.1.90'}
515 + '@codemirror/view@6.36.8':
516 + resolution: {integrity: sha512-yoRo4f+FdnD01fFt4XpfpMCcCAo9QvZOtbrXExn4SqzH32YC6LgzqxfLZw/r6Ge65xyY03mK/UfUqrVw1gFiFg==}
517
518 '@css-render/plugin-bem@0.15.14':
519 resolution: {integrity: sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==}
@@ -521,28 +529,28 @@ packages:
529 resolution: {integrity: sha512-JqWH1vsgdGcw2RR6VliXXdA0/59LttzlU8UlRT/iUUsEeWfYq8I+K0yhihEUTTHLRm1EXvpsCx3083EU15ecsA==}
530 engines: {node: '>=18'}
531
524 - '@csstools/css-calc@2.1.2':
525 - resolution: {integrity: sha512-TklMyb3uBB28b5uQdxjReG4L80NxAqgrECqLZFQbyLekwwlcDDS8r3f07DKqeo8C4926Br0gf/ZDe17Zv4wIuw==}
532 + '@csstools/css-calc@2.1.4':
533 + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
534 engines: {node: '>=18'}
535 peerDependencies:
528 - '@csstools/css-parser-algorithms': ^3.0.4
529 - '@csstools/css-tokenizer': ^3.0.3
536 + '@csstools/css-parser-algorithms': ^3.0.5
537 + '@csstools/css-tokenizer': ^3.0.4
538
531 - '@csstools/css-color-parser@3.0.8':
532 - resolution: {integrity: sha512-pdwotQjCCnRPuNi06jFuP68cykU1f3ZWExLe/8MQ1LOs8Xq+fTkYgd+2V8mWUWMrOn9iS2HftPVaMZDaXzGbhQ==}
539 + '@csstools/css-color-parser@3.0.10':
540 + resolution: {integrity: sha512-TiJ5Ajr6WRd1r8HSiwJvZBiJOqtH86aHpUjq5aEKWHiII2Qfjqd/HCWKPOW8EP4vcspXbHnXrwIDlu5savQipg==}
541 engines: {node: '>=18'}
542 peerDependencies:
535 - '@csstools/css-parser-algorithms': ^3.0.4
536 - '@csstools/css-tokenizer': ^3.0.3
543 + '@csstools/css-parser-algorithms': ^3.0.5
544 + '@csstools/css-tokenizer': ^3.0.4
545
538 - '@csstools/css-parser-algorithms@3.0.4':
539 - resolution: {integrity: sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==}
546 + '@csstools/css-parser-algorithms@3.0.5':
547 + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
548 engines: {node: '>=18'}
549 peerDependencies:
542 - '@csstools/css-tokenizer': ^3.0.3
550 + '@csstools/css-tokenizer': ^3.0.4
551
544 - '@csstools/css-tokenizer@3.0.3':
545 - resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==}
552 + '@csstools/css-tokenizer@3.0.4':
553 + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
554 engines: {node: '>=18'}
555
556 '@cypress/request@3.0.8':
@@ -552,184 +560,180 @@ packages:
560 '@cypress/xvfb@1.2.4':
561 resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==}
562
555 - '@emnapi/core@1.4.0':
556 - resolution: {integrity: sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg==}
563 + '@emnapi/core@1.4.3':
564 + resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==}
565
558 - '@emnapi/runtime@1.4.0':
559 - resolution: {integrity: sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==}
566 + '@emnapi/runtime@1.4.3':
567 + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==}
568
561 - '@emnapi/wasi-threads@1.0.1':
562 - resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==}
569 + '@emnapi/wasi-threads@1.0.2':
570 + resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==}
571
572 '@emotion/hash@0.8.0':
573 resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
574
567 - '@es-joy/jsdoccomment@0.49.0':
568 - resolution: {integrity: sha512-xjZTSFgECpb9Ohuk5yMX5RhUEbfeQcuOp8IF60e+wyzWEF0M5xeSgqsfLtvPEX8BIyOX9saZqzuGPmZ8oWc+5Q==}
569 - engines: {node: '>=16'}
570 -
571 - '@es-joy/jsdoccomment@0.50.0':
572 - resolution: {integrity: sha512-+zZymuVLH6zVwXPtCAtC+bDymxmEwEqDftdAK+f407IF1bnX49anIxvBhCA1AqUIfD6egj1jM1vUnSuijjNyYg==}
575 + '@es-joy/jsdoccomment@0.50.2':
576 + resolution: {integrity: sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==}
577 engines: {node: '>=18'}
578
575 - '@esbuild/aix-ppc64@0.25.2':
576 - resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==}
579 + '@esbuild/aix-ppc64@0.25.5':
580 + resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==}
581 engines: {node: '>=18'}
582 cpu: [ppc64]
583 os: [aix]
584
581 - '@esbuild/android-arm64@0.25.2':
582 - resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==}
585 + '@esbuild/android-arm64@0.25.5':
586 + resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==}
587 engines: {node: '>=18'}
588 cpu: [arm64]
589 os: [android]
590
587 - '@esbuild/android-arm@0.25.2':
588 - resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==}
591 + '@esbuild/android-arm@0.25.5':
592 + resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==}
593 engines: {node: '>=18'}
594 cpu: [arm]
595 os: [android]
596
593 - '@esbuild/android-x64@0.25.2':
594 - resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==}
597 + '@esbuild/android-x64@0.25.5':
598 + resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==}
599 engines: {node: '>=18'}
600 cpu: [x64]
601 os: [android]
602
599 - '@esbuild/darwin-arm64@0.25.2':
600 - resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==}
603 + '@esbuild/darwin-arm64@0.25.5':
604 + resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==}
605 engines: {node: '>=18'}
606 cpu: [arm64]
607 os: [darwin]
608
605 - '@esbuild/darwin-x64@0.25.2':
606 - resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==}
609 + '@esbuild/darwin-x64@0.25.5':
610 + resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==}
611 engines: {node: '>=18'}
612 cpu: [x64]
613 os: [darwin]
614
611 - '@esbuild/freebsd-arm64@0.25.2':
612 - resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==}
615 + '@esbuild/freebsd-arm64@0.25.5':
616 + resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==}
617 engines: {node: '>=18'}
618 cpu: [arm64]
619 os: [freebsd]
620
617 - '@esbuild/freebsd-x64@0.25.2':
618 - resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==}
621 + '@esbuild/freebsd-x64@0.25.5':
622 + resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==}
623 engines: {node: '>=18'}
624 cpu: [x64]
625 os: [freebsd]
626
623 - '@esbuild/linux-arm64@0.25.2':
624 - resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==}
627 + '@esbuild/linux-arm64@0.25.5':
628 + resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==}
629 engines: {node: '>=18'}
630 cpu: [arm64]
631 os: [linux]
632
629 - '@esbuild/linux-arm@0.25.2':
630 - resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==}
633 + '@esbuild/linux-arm@0.25.5':
634 + resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==}
635 engines: {node: '>=18'}
636 cpu: [arm]
637 os: [linux]
638
635 - '@esbuild/linux-ia32@0.25.2':
636 - resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==}
639 + '@esbuild/linux-ia32@0.25.5':
640 + resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==}
641 engines: {node: '>=18'}
642 cpu: [ia32]
643 os: [linux]
644
641 - '@esbuild/linux-loong64@0.25.2':
642 - resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==}
645 + '@esbuild/linux-loong64@0.25.5':
646 + resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==}
647 engines: {node: '>=18'}
648 cpu: [loong64]
649 os: [linux]
650
647 - '@esbuild/linux-mips64el@0.25.2':
648 - resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==}
651 + '@esbuild/linux-mips64el@0.25.5':
652 + resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==}
653 engines: {node: '>=18'}
654 cpu: [mips64el]
655 os: [linux]
656
653 - '@esbuild/linux-ppc64@0.25.2':
654 - resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==}
657 + '@esbuild/linux-ppc64@0.25.5':
658 + resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==}
659 engines: {node: '>=18'}
660 cpu: [ppc64]
661 os: [linux]
662
659 - '@esbuild/linux-riscv64@0.25.2':
660 - resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==}
663 + '@esbuild/linux-riscv64@0.25.5':
664 + resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==}
665 engines: {node: '>=18'}
666 cpu: [riscv64]
667 os: [linux]
668
665 - '@esbuild/linux-s390x@0.25.2':
666 - resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==}
669 + '@esbuild/linux-s390x@0.25.5':
670 + resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==}
671 engines: {node: '>=18'}
672 cpu: [s390x]
673 os: [linux]
674
671 - '@esbuild/linux-x64@0.25.2':
672 - resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==}
675 + '@esbuild/linux-x64@0.25.5':
676 + resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==}
677 engines: {node: '>=18'}
678 cpu: [x64]
679 os: [linux]
680
677 - '@esbuild/netbsd-arm64@0.25.2':
678 - resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==}
681 + '@esbuild/netbsd-arm64@0.25.5':
682 + resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==}
683 engines: {node: '>=18'}
684 cpu: [arm64]
685 os: [netbsd]
686
683 - '@esbuild/netbsd-x64@0.25.2':
684 - resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==}
687 + '@esbuild/netbsd-x64@0.25.5':
688 + resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==}
689 engines: {node: '>=18'}
690 cpu: [x64]
691 os: [netbsd]
692
689 - '@esbuild/openbsd-arm64@0.25.2':
690 - resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==}
693 + '@esbuild/openbsd-arm64@0.25.5':
694 + resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==}
695 engines: {node: '>=18'}
696 cpu: [arm64]
697 os: [openbsd]
698
695 - '@esbuild/openbsd-x64@0.25.2':
696 - resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==}
699 + '@esbuild/openbsd-x64@0.25.5':
700 + resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==}
701 engines: {node: '>=18'}
702 cpu: [x64]
703 os: [openbsd]
704
701 - '@esbuild/sunos-x64@0.25.2':
702 - resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==}
705 + '@esbuild/sunos-x64@0.25.5':
706 + resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==}
707 engines: {node: '>=18'}
708 cpu: [x64]
709 os: [sunos]
710
707 - '@esbuild/win32-arm64@0.25.2':
708 - resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==}
711 + '@esbuild/win32-arm64@0.25.5':
712 + resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==}
713 engines: {node: '>=18'}
714 cpu: [arm64]
715 os: [win32]
716
713 - '@esbuild/win32-ia32@0.25.2':
714 - resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==}
717 + '@esbuild/win32-ia32@0.25.5':
718 + resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==}
719 engines: {node: '>=18'}
720 cpu: [ia32]
721 os: [win32]
722
719 - '@esbuild/win32-x64@0.25.2':
720 - resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==}
723 + '@esbuild/win32-x64@0.25.5':
724 + resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==}
725 engines: {node: '>=18'}
726 cpu: [x64]
727 os: [win32]
728
725 - '@eslint-community/eslint-plugin-eslint-comments@4.4.1':
726 - resolution: {integrity: sha512-lb/Z/MzbTf7CaVYM9WCFNQZ4L1yi3ev2fsFPF99h31ljhSEyUoyEsKsNWiU+qD1glbYTDJdqgyaLKtyTkkqtuQ==}
729 + '@eslint-community/eslint-plugin-eslint-comments@4.5.0':
730 + resolution: {integrity: sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg==}
731 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
732 peerDependencies:
733 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
734
731 - '@eslint-community/eslint-utils@4.5.1':
732 - resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==}
735 + '@eslint-community/eslint-utils@4.7.0':
736 + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==}
737 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
738 peerDependencies:
739 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@@ -738,8 +742,8 @@ packages:
742 resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
743 engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
744
741 - '@eslint/compat@1.2.8':
742 - resolution: {integrity: sha512-LqCYHdWL/QqKIJuZ/ucMAv8d4luKGs4oCPgpt8mWztQAtPrHfXKQ/XAUc8ljCHAfJCn6SvkpTcGt5Tsh8saowA==}
745 + '@eslint/compat@1.2.9':
746 + resolution: {integrity: sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==}
747 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
748 peerDependencies:
749 eslint: ^9.10.0
@@ -751,8 +755,8 @@ packages:
755 resolution: {integrity: sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==}
756 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
757
754 - '@eslint/config-helpers@0.2.1':
755 - resolution: {integrity: sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==}
758 + '@eslint/config-helpers@0.2.2':
759 + resolution: {integrity: sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==}
760 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
761
762 '@eslint/core@0.10.0':
@@ -763,16 +767,20 @@ packages:
767 resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==}
768 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
769
770 + '@eslint/core@0.14.0':
771 + resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==}
772 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
773 +
774 '@eslint/eslintrc@3.3.1':
775 resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
776 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
777
770 - '@eslint/js@9.25.1':
771 - resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==}
778 + '@eslint/js@9.27.0':
779 + resolution: {integrity: sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==}
780 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
781
774 - '@eslint/markdown@6.3.0':
775 - resolution: {integrity: sha512-8rj7wmuP5hwXZ0HWoad+WL9nftpN373bCCQz9QL6sA+clZiz7et8Pk0yDAKeo//xLlPONKQ6wCpjkOHCLkbYUw==}
782 + '@eslint/markdown@6.4.0':
783 + resolution: {integrity: sha512-J07rR8uBSNFJ9iliNINrchilpkmCihPmTVotpThUeKEn5G8aBBZnkjNBy/zovhJA5LBk1vWU9UDlhqKSc/dViQ==}
784 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
785
786 '@eslint/object-schema@2.1.6':
@@ -783,6 +791,10 @@ packages:
791 resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==}
792 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
793
794 + '@eslint/plugin-kit@0.3.1':
795 + resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==}
796 + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
797 +
798 '@f3ve/vue-markdown-it@0.2.3':
799 resolution: {integrity: sha512-v0VNd7wb55kwsUUy3n6DLI9+0FYSG0PrCTD3bWuSRo6WS3OHD5wghh/aHzebVdsVkSBXfVpiEUlMA3DrxLs7Lw==}
800 peerDependencies:
@@ -791,8 +803,8 @@ packages:
803 '@fontsource/jetbrains-mono@5.2.5':
804 resolution: {integrity: sha512-TPZ9b/uq38RMdrlZZkl0RwN8Ju9JxuqMETrw76pUQFbGtE1QbwQaNsLlnUrACNNBNbd0NZRXiJJSkC8ajPgbew==}
805
794 - '@fontsource/lexend@5.2.6':
795 - resolution: {integrity: sha512-SVRBO8I5T1iiX031yZuJDSEmKi+Yyqz7E8rTyNzl0zafbTXncQ7diuePsPH1acpGV57zLuuK7+8oey0+G7hxtA==}
806 + '@fontsource/lexend@5.2.7':
807 + resolution: {integrity: sha512-LvhJCaFlpR3/5msAzvIGJqVlvcVIN/Je9niM+pCFUazGeeb0ygOu0TlyAAJCi1TpN3te6tVqnDVMW+1fSFNQ9w==}
808
809 '@fontsource/public-sans@5.2.5':
810 resolution: {integrity: sha512-WSRBuKX8dwHxc35s/Q1arB7vkGL2A9YHB93gRP9OTu/nYgat0CBHfsAOUSDehBnREHa0rYZvWDDS08w5qPoWvg==}
@@ -819,34 +831,38 @@ packages:
831 resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
832 engines: {node: '>=18.18'}
833
822 - '@humanwhocodes/retry@0.4.2':
823 - resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==}
834 + '@humanwhocodes/retry@0.4.3':
835 + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
836 engines: {node: '>=18.18'}
837
838 '@iconify/types@2.0.0':
839 resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
840
829 - '@iconify/vue@4.3.0':
830 - resolution: {integrity: sha512-Xq0h6zMrHBbrW8jXJ9fISi+x8oDQllg5hTDkDuxnWiskJ63rpJu9CvJshj8VniHVTbsxCg9fVoPAaNp3RQI5OQ==}
841 + '@iconify/vue@5.0.0':
842 + resolution: {integrity: sha512-C+KuEWIF5nSBrobFJhT//JS87OZ++QDORB6f2q2Wm6fl2mueSTpFBeBsveK0KW9hWiZ4mNiPjsh6Zs4jjdROSg==}
843 peerDependencies:
844 vue: '>=3'
845
834 - '@intlify/core-base@11.1.3':
835 - resolution: {integrity: sha512-cMuHunYO7LE80azTitcvEbs1KJmtd6g7I5pxlApV3Jo547zdO3h31/0uXpqHc+Y3RKt1wo2y68RGSx77Z1klyA==}
846 + '@intlify/core-base@11.1.5':
847 + resolution: {integrity: sha512-xGRkISwV/2Trqb8yVQevlHm5roaQqy+75qwUzEQrviaQF0o4c5VDhjBW7WEGEoKFx09HSgq7NkvK/DAyuerTDg==}
848 engines: {node: '>= 16'}
849
838 - '@intlify/message-compiler@11.1.3':
839 - resolution: {integrity: sha512-7rbqqpo2f5+tIcwZTAG/Ooy9C8NDVwfDkvSeDPWUPQW+Dyzfw2o9H103N5lKBxO7wxX9dgCDjQ8Umz73uYw3hw==}
850 + '@intlify/message-compiler@11.1.5':
851 + resolution: {integrity: sha512-YLSBbjD7qUdShe3ZAat9Hnf9E8FRpN6qmNFD/x5Xg5JVXjsks0kJ90Zj6aAuyoppJQA/YJdWZ8/bB7k3dg2TjQ==}
852 engines: {node: '>= 16'}
853
842 - '@intlify/shared@11.1.3':
843 - resolution: {integrity: sha512-pTFBgqa/99JRA2H1qfyqv97MKWJrYngXBA/I0elZcYxvJgcCw3mApAoPW3mJ7vx3j+Ti0FyKUFZ4hWxdjKaxvA==}
854 + '@intlify/shared@11.1.5':
855 + resolution: {integrity: sha512-+I4vRzHm38VjLr/CAciEPJhGYFzWWW4HMTm+6H3WqknXLh0ozNX9oC8ogMUwTSXYR/wGUb1/lTpNziiCH5MybQ==}
856 engines: {node: '>= 16'}
857
858 '@isaacs/cliui@8.0.2':
859 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
860 engines: {node: '>=12'}
861
862 + '@isaacs/fs-minipass@4.0.1':
863 + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
864 + engines: {node: '>=18.0.0'}
865 +
866 '@jridgewell/gen-mapping@0.3.8':
867 resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
868 engines: {node: '>=6.0.0'}
@@ -874,8 +890,8 @@ packages:
890 '@lezer/highlight@1.2.1':
891 resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==}
892
877 - '@lezer/javascript@1.4.21':
878 - resolution: {integrity: sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==}
893 + '@lezer/javascript@1.5.1':
894 + resolution: {integrity: sha512-ATOImjeVJuvgm3JQ/bpo2Tmv55HSScE2MTPnKRMRIPx2cLhHGyX2VnqpHhtIV1tVzIjZDbcWQm+NCTF40ggZVw==}
895
896 '@lezer/lr@1.4.2':
897 resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==}
@@ -886,8 +902,8 @@ packages:
902 '@marijn/find-cluster-break@1.0.2':
903 resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
904
889 - '@napi-rs/wasm-runtime@0.2.9':
890 - resolution: {integrity: sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==}
905 + '@napi-rs/wasm-runtime@0.2.10':
906 + resolution: {integrity: sha512-bCsCyeZEwVErsGmyPNSzwfwFn4OdxBj0mmv6hOFucB/k81Ojdu68RbZdxYsRQUPc9l6SU5F/cG+bXgWs3oUgsQ==}
907
908 '@nodelib/fs.scandir@2.1.5':
909 resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
@@ -901,8 +917,8 @@ packages:
917 resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
918 engines: {node: '>= 8'}
919
904 - '@nuxt/kit@3.16.2':
905 - resolution: {integrity: sha512-K1SAUo2vweTfudKZzjKsZ5YJoxPLTspR5qz5+G61xtZreLpsdpDYfBseqsIAl5VFLJuszeRpWQ01jP9LfQ6Ksw==}
920 + '@nuxt/kit@3.17.4':
921 + resolution: {integrity: sha512-l+hY8sy2XFfg3PigZj+PTu6+KIJzmbACTRimn1ew/gtCz+F38f6KTF4sMRTN5CUxiB8TRENgEonASmkAWfpO9Q==}
922 engines: {node: '>=18.12.0'}
923
924 '@one-ini/wasm@0.1.1':
@@ -994,25 +1010,20 @@ packages:
1010 resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
1011 engines: {node: '>=14'}
1012
997 - '@pkgr/core@0.1.2':
998 - resolution: {integrity: sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==}
999 - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
1000 -
1001 - '@pkgr/core@0.2.0':
1002 - resolution: {integrity: sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==}
1003 - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
1004 -
1013 '@pkgr/core@0.2.4':
1014 resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==}
1015 engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
1016
1009 - '@polka/url@1.0.0-next.28':
1010 - resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==}
1017 + '@polka/url@1.0.0-next.29':
1018 + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
1019
1012 - '@quansync/fs@0.1.2':
1013 - resolution: {integrity: sha512-ezIadUb1aFhwJLd++WVqVpi9rnlX8vnd4ju7saPhwLHJN1mJgOv0puePTGV+FbtSnWtwoHDT8lAm4kagDZmpCg==}
1020 + '@quansync/fs@0.1.3':
1021 + resolution: {integrity: sha512-G0OnZbMWEs5LhDyqy2UL17vGhSVHkQIfVojMtEWVenvj0V5S84VBgy86kJIuNsGDp2p7sTKlpSIpBUWdC35OKg==}
1022 engines: {node: '>=20.0.0'}
1023
1024 + '@rolldown/pluginutils@1.0.0-beta.10':
1025 + resolution: {integrity: sha512-FeISF1RUTod5Kvt3yUXByrAPk5EfDWo/1BPv1ARBZ07weqx888SziPuWS6HUJU0YroGyQURjdIrkjWJP2zBFDQ==}
1026 +
1027 '@rollup/pluginutils@5.1.4':
1028 resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
1029 engines: {node: '>=14.0.0'}
@@ -1022,139 +1033,134 @@ packages:
1033 rollup:
1034 optional: true
1035
1025 - '@rollup/rollup-android-arm-eabi@4.39.0':
1026 - resolution: {integrity: sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==}
1036 + '@rollup/rollup-android-arm-eabi@4.41.1':
1037 + resolution: {integrity: sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==}
1038 cpu: [arm]
1039 os: [android]
1040
1030 - '@rollup/rollup-android-arm64@4.39.0':
1031 - resolution: {integrity: sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==}
1041 + '@rollup/rollup-android-arm64@4.41.1':
1042 + resolution: {integrity: sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==}
1043 cpu: [arm64]
1044 os: [android]
1045
1035 - '@rollup/rollup-darwin-arm64@4.39.0':
1036 - resolution: {integrity: sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==}
1046 + '@rollup/rollup-darwin-arm64@4.41.1':
1047 + resolution: {integrity: sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==}
1048 cpu: [arm64]
1049 os: [darwin]
1050
1040 - '@rollup/rollup-darwin-x64@4.39.0':
1041 - resolution: {integrity: sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==}
1051 + '@rollup/rollup-darwin-x64@4.41.1':
1052 + resolution: {integrity: sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==}
1053 cpu: [x64]
1054 os: [darwin]
1055
1045 - '@rollup/rollup-freebsd-arm64@4.39.0':
1046 - resolution: {integrity: sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==}
1056 + '@rollup/rollup-freebsd-arm64@4.41.1':
1057 + resolution: {integrity: sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==}
1058 cpu: [arm64]
1059 os: [freebsd]
1060
1050 - '@rollup/rollup-freebsd-x64@4.39.0':
1051 - resolution: {integrity: sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==}
1061 + '@rollup/rollup-freebsd-x64@4.41.1':
1062 + resolution: {integrity: sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==}
1063 cpu: [x64]
1064 os: [freebsd]
1065
1055 - '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
1056 - resolution: {integrity: sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==}
1066 + '@rollup/rollup-linux-arm-gnueabihf@4.41.1':
1067 + resolution: {integrity: sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==}
1068 cpu: [arm]
1069 os: [linux]
1070
1060 - '@rollup/rollup-linux-arm-musleabihf@4.39.0':
1061 - resolution: {integrity: sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==}
1071 + '@rollup/rollup-linux-arm-musleabihf@4.41.1':
1072 + resolution: {integrity: sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==}
1073 cpu: [arm]
1074 os: [linux]
1075
1065 - '@rollup/rollup-linux-arm64-gnu@4.39.0':
1066 - resolution: {integrity: sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==}
1076 + '@rollup/rollup-linux-arm64-gnu@4.41.1':
1077 + resolution: {integrity: sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==}
1078 cpu: [arm64]
1079 os: [linux]
1080
1070 - '@rollup/rollup-linux-arm64-musl@4.39.0':
1071 - resolution: {integrity: sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==}
1081 + '@rollup/rollup-linux-arm64-musl@4.41.1':
1082 + resolution: {integrity: sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==}
1083 cpu: [arm64]
1084 os: [linux]
1085
1075 - '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
1076 - resolution: {integrity: sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==}
1086 + '@rollup/rollup-linux-loongarch64-gnu@4.41.1':
1087 + resolution: {integrity: sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==}
1088 cpu: [loong64]
1089 os: [linux]
1090
1080 - '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
1081 - resolution: {integrity: sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==}
1091 + '@rollup/rollup-linux-powerpc64le-gnu@4.41.1':
1092 + resolution: {integrity: sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==}
1093 cpu: [ppc64]
1094 os: [linux]
1095
1085 - '@rollup/rollup-linux-riscv64-gnu@4.39.0':
1086 - resolution: {integrity: sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==}
1096 + '@rollup/rollup-linux-riscv64-gnu@4.41.1':
1097 + resolution: {integrity: sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==}
1098 cpu: [riscv64]
1099 os: [linux]
1100
1090 - '@rollup/rollup-linux-riscv64-musl@4.39.0':
1091 - resolution: {integrity: sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==}
1101 + '@rollup/rollup-linux-riscv64-musl@4.41.1':
1102 + resolution: {integrity: sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==}
1103 cpu: [riscv64]
1104 os: [linux]
1105
1095 - '@rollup/rollup-linux-s390x-gnu@4.39.0':
1096 - resolution: {integrity: sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==}
1106 + '@rollup/rollup-linux-s390x-gnu@4.41.1':
1107 + resolution: {integrity: sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==}
1108 cpu: [s390x]
1109 os: [linux]
1110
1100 - '@rollup/rollup-linux-x64-gnu@4.39.0':
1101 - resolution: {integrity: sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==}
1111 + '@rollup/rollup-linux-x64-gnu@4.41.1':
1112 + resolution: {integrity: sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==}
1113 cpu: [x64]
1114 os: [linux]
1115
1105 - '@rollup/rollup-linux-x64-gnu@4.40.0':
1106 - resolution: {integrity: sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==}
1116 + '@rollup/rollup-linux-x64-musl@4.41.1':
1117 + resolution: {integrity: sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==}
1118 cpu: [x64]
1119 os: [linux]
1120
1110 - '@rollup/rollup-linux-x64-musl@4.39.0':
1111 - resolution: {integrity: sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==}
1112 - cpu: [x64]
1113 - os: [linux]
1114 -
1115 - '@rollup/rollup-win32-arm64-msvc@4.39.0':
1116 - resolution: {integrity: sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==}
1121 + '@rollup/rollup-win32-arm64-msvc@4.41.1':
1122 + resolution: {integrity: sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==}
1123 cpu: [arm64]
1124 os: [win32]
1125
1120 - '@rollup/rollup-win32-ia32-msvc@4.39.0':
1121 - resolution: {integrity: sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==}
1126 + '@rollup/rollup-win32-ia32-msvc@4.41.1':
1127 + resolution: {integrity: sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==}
1128 cpu: [ia32]
1129 os: [win32]
1130
1125 - '@rollup/rollup-win32-x64-msvc@4.39.0':
1126 - resolution: {integrity: sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==}
1131 + '@rollup/rollup-win32-x64-msvc@4.41.1':
1132 + resolution: {integrity: sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==}
1133 cpu: [x64]
1134 os: [win32]
1135
1136 '@sec-ant/readable-stream@0.4.1':
1137 resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
1138
1133 - '@shikijs/core@3.3.0':
1134 - resolution: {integrity: sha512-CovkFL2WVaHk6PCrwv6ctlmD4SS1qtIfN8yEyDXDYWh4ONvomdM9MaFw20qHuqJOcb8/xrkqoWQRJ//X10phOQ==}
1139 + '@shikijs/core@3.4.2':
1140 + resolution: {integrity: sha512-AG8vnSi1W2pbgR2B911EfGqtLE9c4hQBYkv/x7Z+Kt0VxhgQKcW7UNDVYsu9YxwV6u+OJrvdJrMq6DNWoBjihQ==}
1141
1136 - '@shikijs/engine-javascript@3.3.0':
1137 - resolution: {integrity: sha512-XlhnFGv0glq7pfsoN0KyBCz9FJU678LZdQ2LqlIdAj6JKsg5xpYKay3DkazXWExp3DTJJK9rMOuGzU2911pg7Q==}
1142 + '@shikijs/engine-javascript@3.4.2':
1143 + resolution: {integrity: sha512-1/adJbSMBOkpScCE/SB6XkjJU17ANln3Wky7lOmrnpl+zBdQ1qXUJg2GXTYVHRq+2j3hd1DesmElTXYDgtfSOQ==}
1144
1139 - '@shikijs/engine-oniguruma@3.3.0':
1140 - resolution: {integrity: sha512-l0vIw+GxeNU7uGnsu6B+Crpeqf+WTQ2Va71cHb5ZYWEVEPdfYwY5kXwYqRJwHrxz9WH+pjSpXQz+TJgAsrkA5A==}
1145 + '@shikijs/engine-oniguruma@3.4.2':
1146 + resolution: {integrity: sha512-zcZKMnNndgRa3ORja6Iemsr3DrLtkX3cAF7lTJkdMB6v9alhlBsX9uNiCpqofNrXOvpA3h6lHcLJxgCIhVOU5Q==}
1147
1142 - '@shikijs/langs@3.3.0':
1143 - resolution: {integrity: sha512-zt6Kf/7XpBQKSI9eqku+arLkAcDQ3NHJO6zFjiChI8w0Oz6Jjjay7pToottjQGjSDCFk++R85643WbyINcuL+g==}
1148 + '@shikijs/langs@3.4.2':
1149 + resolution: {integrity: sha512-H6azIAM+OXD98yztIfs/KH5H4PU39t+SREhmM8LaNXyUrqj2mx+zVkr8MWYqjceSjDw9I1jawm1WdFqU806rMA==}
1150
1145 - '@shikijs/markdown-it@3.3.0':
1146 - resolution: {integrity: sha512-8cBI+tmDwIOAL+mSI3nU0rhyyvf4Qy3WoPIyZXVnRm1UJNyybxK+h+b0Zwa58UylBGXlw/eMLhKaYVztlgvkYw==}
1151 + '@shikijs/markdown-it@3.4.2':
1152 + resolution: {integrity: sha512-koJ4Mm5HcTJw2v5X9RFEfbc/4pho+p2co5xNtLSQNNWaCZWSTB7WDxZS+OYX6OkQ1HUgxu7WK/1mxtfiKCPVbw==}
1153 peerDependencies:
1154 markdown-it-async: ^2.2.0
1155 peerDependenciesMeta:
1156 markdown-it-async:
1157 optional: true
1158
1153 - '@shikijs/themes@3.3.0':
1154 - resolution: {integrity: sha512-tXeCvLXBnqq34B0YZUEaAD1lD4lmN6TOHAhnHacj4Owh7Ptb/rf5XCDeROZt2rEOk5yuka3OOW2zLqClV7/SOg==}
1159 + '@shikijs/themes@3.4.2':
1160 + resolution: {integrity: sha512-qAEuAQh+brd8Jyej2UDDf+b4V2g1Rm8aBIdvt32XhDPrHvDkEnpb7Kzc9hSuHUxz0Iuflmq7elaDuQAP9bHIhg==}
1161
1156 - '@shikijs/types@3.3.0':
1157 - resolution: {integrity: sha512-KPCGnHG6k06QG/2pnYGbFtFvpVJmC3uIpXrAiPrawETifujPBv0Se2oUxm5qYgjCvGJS9InKvjytOdN+bGuX+Q==}
1162 + '@shikijs/types@3.4.2':
1163 + resolution: {integrity: sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg==}
1164
1165 '@shikijs/vscode-textmate@10.0.2':
1166 resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
@@ -1168,16 +1174,12 @@ packages:
1174 '@sideway/pinpoint@2.0.0':
1175 resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
1176
1171 - '@sindresorhus/merge-streams@2.3.0':
1172 - resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
1173 - engines: {node: '>=18'}
1174 -
1177 '@sindresorhus/merge-streams@4.0.0':
1178 resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
1179 engines: {node: '>=18'}
1180
1179 - '@stylistic/eslint-plugin@4.2.0':
1180 - resolution: {integrity: sha512-8hXezgz7jexGHdo5WN6JBEIPHCSFyyU4vgbxevu4YLVS5vl+sxqAAGyXSzfNDyR6xMNSH5H1x67nsXcYMOHtZA==}
1181 + '@stylistic/eslint-plugin@4.4.0':
1182 + resolution: {integrity: sha512-bIh/d9X+OQLCAMdhHtps+frvyjvAM4B1YlSJzcEEhl7wXLIqPar3ngn9DrHhkBOrTA/z9J0bUMtctAspe0dxdQ==}
1183 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1184 peerDependencies:
1185 eslint: '>=9.0.0'
@@ -1201,71 +1203,71 @@ packages:
1203 '@svgdotjs/svg.js': ^3.2.4
1204 '@svgdotjs/svg.select.js': ^4.0.1
1205
1204 - '@svgdotjs/svg.select.js@4.0.2':
1205 - resolution: {integrity: sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==}
1206 + '@svgdotjs/svg.select.js@4.0.3':
1207 + resolution: {integrity: sha512-qkMgso1sd2hXKd1FZ1weO7ANq12sNmQJeGDjs46QwDVsxSRcHmvWKL2NDF7Yimpwf3sl5esOLkPqtV2bQ3v/Jg==}
1208 engines: {node: '>= 14.18'}
1209 peerDependencies:
1210 '@svgdotjs/svg.js': ^3.2.4
1211
1210 - '@tailwindcss/node@4.1.4':
1211 - resolution: {integrity: sha512-MT5118zaiO6x6hNA04OWInuAiP1YISXql8Z+/Y8iisV5nuhM8VXlyhRuqc2PEviPszcXI66W44bCIk500Oolhw==}
1212 + '@tailwindcss/node@4.1.8':
1213 + resolution: {integrity: sha512-OWwBsbC9BFAJelmnNcrKuf+bka2ZxCE2A4Ft53Tkg4uoiE67r/PMEYwCsourC26E+kmxfwE0hVzMdxqeW+xu7Q==}
1214
1213 - '@tailwindcss/oxide-android-arm64@4.1.4':
1214 - resolution: {integrity: sha512-xMMAe/SaCN/vHfQYui3fqaBDEXMu22BVwQ33veLc8ep+DNy7CWN52L+TTG9y1K397w9nkzv+Mw+mZWISiqhmlA==}
1215 + '@tailwindcss/oxide-android-arm64@4.1.8':
1216 + resolution: {integrity: sha512-Fbz7qni62uKYceWYvUjRqhGfZKwhZDQhlrJKGtnZfuNtHFqa8wmr+Wn74CTWERiW2hn3mN5gTpOoxWKk0jRxjg==}
1217 engines: {node: '>= 10'}
1218 cpu: [arm64]
1219 os: [android]
1220
1219 - '@tailwindcss/oxide-darwin-arm64@4.1.4':
1220 - resolution: {integrity: sha512-JGRj0SYFuDuAGilWFBlshcexev2hOKfNkoX+0QTksKYq2zgF9VY/vVMq9m8IObYnLna0Xlg+ytCi2FN2rOL0Sg==}
1221 + '@tailwindcss/oxide-darwin-arm64@4.1.8':
1222 + resolution: {integrity: sha512-RdRvedGsT0vwVVDztvyXhKpsU2ark/BjgG0huo4+2BluxdXo8NDgzl77qh0T1nUxmM11eXwR8jA39ibvSTbi7A==}
1223 engines: {node: '>= 10'}
1224 cpu: [arm64]
1225 os: [darwin]
1226
1225 - '@tailwindcss/oxide-darwin-x64@4.1.4':
1226 - resolution: {integrity: sha512-sdDeLNvs3cYeWsEJ4H1DvjOzaGios4QbBTNLVLVs0XQ0V95bffT3+scptzYGPMjm7xv4+qMhCDrkHwhnUySEzA==}
1227 + '@tailwindcss/oxide-darwin-x64@4.1.8':
1228 + resolution: {integrity: sha512-t6PgxjEMLp5Ovf7uMb2OFmb3kqzVTPPakWpBIFzppk4JE4ix0yEtbtSjPbU8+PZETpaYMtXvss2Sdkx8Vs4XRw==}
1229 engines: {node: '>= 10'}
1230 cpu: [x64]
1231 os: [darwin]
1232
1231 - '@tailwindcss/oxide-freebsd-x64@4.1.4':
1232 - resolution: {integrity: sha512-VHxAqxqdghM83HslPhRsNhHo91McsxRJaEnShJOMu8mHmEj9Ig7ToHJtDukkuLWLzLboh2XSjq/0zO6wgvykNA==}
1233 + '@tailwindcss/oxide-freebsd-x64@4.1.8':
1234 + resolution: {integrity: sha512-g8C8eGEyhHTqwPStSwZNSrOlyx0bhK/V/+zX0Y+n7DoRUzyS8eMbVshVOLJTDDC+Qn9IJnilYbIKzpB9n4aBsg==}
1235 engines: {node: '>= 10'}
1236 cpu: [x64]
1237 os: [freebsd]
1238
1237 - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.4':
1238 - resolution: {integrity: sha512-OTU/m/eV4gQKxy9r5acuesqaymyeSCnsx1cFto/I1WhPmi5HDxX1nkzb8KYBiwkHIGg7CTfo/AcGzoXAJBxLfg==}
1239 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8':
1240 + resolution: {integrity: sha512-Jmzr3FA4S2tHhaC6yCjac3rGf7hG9R6Gf2z9i9JFcuyy0u79HfQsh/thifbYTF2ic82KJovKKkIB6Z9TdNhCXQ==}
1241 engines: {node: '>= 10'}
1242 cpu: [arm]
1243 os: [linux]
1244
1243 - '@tailwindcss/oxide-linux-arm64-gnu@4.1.4':
1244 - resolution: {integrity: sha512-hKlLNvbmUC6z5g/J4H+Zx7f7w15whSVImokLPmP6ff1QqTVE+TxUM9PGuNsjHvkvlHUtGTdDnOvGNSEUiXI1Ww==}
1245 + '@tailwindcss/oxide-linux-arm64-gnu@4.1.8':
1246 + resolution: {integrity: sha512-qq7jXtO1+UEtCmCeBBIRDrPFIVI4ilEQ97qgBGdwXAARrUqSn/L9fUrkb1XP/mvVtoVeR2bt/0L77xx53bPZ/Q==}
1247 engines: {node: '>= 10'}
1248 cpu: [arm64]
1249 os: [linux]
1250
1249 - '@tailwindcss/oxide-linux-arm64-musl@4.1.4':
1250 - resolution: {integrity: sha512-X3As2xhtgPTY/m5edUtddmZ8rCruvBvtxYLMw9OsZdH01L2gS2icsHRwxdU0dMItNfVmrBezueXZCHxVeeb7Aw==}
1251 + '@tailwindcss/oxide-linux-arm64-musl@4.1.8':
1252 + resolution: {integrity: sha512-O6b8QesPbJCRshsNApsOIpzKt3ztG35gfX9tEf4arD7mwNinsoCKxkj8TgEE0YRjmjtO3r9FlJnT/ENd9EVefQ==}
1253 engines: {node: '>= 10'}
1254 cpu: [arm64]
1255 os: [linux]
1256
1255 - '@tailwindcss/oxide-linux-x64-gnu@4.1.4':
1256 - resolution: {integrity: sha512-2VG4DqhGaDSmYIu6C4ua2vSLXnJsb/C9liej7TuSO04NK+JJJgJucDUgmX6sn7Gw3Cs5ZJ9ZLrnI0QRDOjLfNQ==}
1257 + '@tailwindcss/oxide-linux-x64-gnu@4.1.8':
1258 + resolution: {integrity: sha512-32iEXX/pXwikshNOGnERAFwFSfiltmijMIAbUhnNyjFr3tmWmMJWQKU2vNcFX0DACSXJ3ZWcSkzNbaKTdngH6g==}
1259 engines: {node: '>= 10'}
1260 cpu: [x64]
1261 os: [linux]
1262
1261 - '@tailwindcss/oxide-linux-x64-musl@4.1.4':
1262 - resolution: {integrity: sha512-v+mxVgH2kmur/X5Mdrz9m7TsoVjbdYQT0b4Z+dr+I4RvreCNXyCFELZL/DO0M1RsidZTrm6O1eMnV6zlgEzTMQ==}
1263 + '@tailwindcss/oxide-linux-x64-musl@4.1.8':
1264 + resolution: {integrity: sha512-s+VSSD+TfZeMEsCaFaHTaY5YNj3Dri8rST09gMvYQKwPphacRG7wbuQ5ZJMIJXN/puxPcg/nU+ucvWguPpvBDg==}
1265 engines: {node: '>= 10'}
1266 cpu: [x64]
1267 os: [linux]
1268
1267 - '@tailwindcss/oxide-wasm32-wasi@4.1.4':
1268 - resolution: {integrity: sha512-2TLe9ir+9esCf6Wm+lLWTMbgklIjiF0pbmDnwmhR9MksVOq+e8aP3TSsXySnBDDvTTVd/vKu1aNttEGj3P6l8Q==}
1269 + '@tailwindcss/oxide-wasm32-wasi@4.1.8':
1270 + resolution: {integrity: sha512-CXBPVFkpDjM67sS1psWohZ6g/2/cd+cq56vPxK4JeawelxwK4YECgl9Y9TjkE2qfF+9/s1tHHJqrC4SS6cVvSg==}
1271 engines: {node: '>=14.0.0'}
1272 cpu: [wasm32]
1273 bundledDependencies:
@@ -1276,24 +1278,24 @@ packages:
1278 - '@emnapi/wasi-threads'
1279 - tslib
1280
1279 - '@tailwindcss/oxide-win32-arm64-msvc@4.1.4':
1280 - resolution: {integrity: sha512-VlnhfilPlO0ltxW9/BgfLI5547PYzqBMPIzRrk4W7uupgCt8z6Trw/tAj6QUtF2om+1MH281Pg+HHUJoLesmng==}
1281 + '@tailwindcss/oxide-win32-arm64-msvc@4.1.8':
1282 + resolution: {integrity: sha512-7GmYk1n28teDHUjPlIx4Z6Z4hHEgvP5ZW2QS9ygnDAdI/myh3HTHjDqtSqgu1BpRoI4OiLx+fThAyA1JePoENA==}
1283 engines: {node: '>= 10'}
1284 cpu: [arm64]
1285 os: [win32]
1286
1285 - '@tailwindcss/oxide-win32-x64-msvc@4.1.4':
1286 - resolution: {integrity: sha512-+7S63t5zhYjslUGb8NcgLpFXD+Kq1F/zt5Xv5qTv7HaFTG/DHyHD9GA6ieNAxhgyA4IcKa/zy7Xx4Oad2/wuhw==}
1287 + '@tailwindcss/oxide-win32-x64-msvc@4.1.8':
1288 + resolution: {integrity: sha512-fou+U20j+Jl0EHwK92spoWISON2OBnCazIc038Xj2TdweYV33ZRkS9nwqiUi2d/Wba5xg5UoHfvynnb/UB49cQ==}
1289 engines: {node: '>= 10'}
1290 cpu: [x64]
1291 os: [win32]
1292
1291 - '@tailwindcss/oxide@4.1.4':
1292 - resolution: {integrity: sha512-p5wOpXyOJx7mKh5MXh5oKk+kqcz8T+bA3z/5VWWeQwFrmuBItGwz8Y2CHk/sJ+dNb9B0nYFfn0rj/cKHZyjahQ==}
1293 + '@tailwindcss/oxide@4.1.8':
1294 + resolution: {integrity: sha512-d7qvv9PsM5N3VNKhwVUhpK6r4h9wtLkJ6lz9ZY9aeZgrUWk1Z8VPyqyDT9MZlem7GTGseRQHkeB1j3tC7W1P+A==}
1295 engines: {node: '>= 10'}
1296
1295 - '@tailwindcss/vite@4.1.4':
1296 - resolution: {integrity: sha512-4UQeMrONbvrsXKXXp/uxmdEN5JIJ9RkH7YVzs6AMxC/KC1+Np7WZBaNIco7TEjlkthqxZbt8pU/ipD+hKjm80A==}
1297 + '@tailwindcss/vite@4.1.8':
1298 + resolution: {integrity: sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A==}
1299 peerDependencies:
1300 vite: ^5.2.0 || ^6
1301
@@ -1313,12 +1315,6 @@ packages:
1315 '@types/debug@4.1.12':
1316 resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
1317
1316 - '@types/doctrine@0.0.9':
1317 - resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==}
1318 -
1319 - '@types/eslint@9.6.1':
1320 - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
1321 -
1318 '@types/estree@1.0.7':
1319 resolution: {integrity: sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==}
1320
@@ -1343,26 +1339,32 @@ packages:
1339 '@types/katex@0.16.7':
1340 resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
1341
1342 + '@types/linkify-it@5.0.0':
1343 + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
1344 +
1345 '@types/lodash-es@4.17.12':
1346 resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
1347
1349 - '@types/lodash@4.17.16':
1350 - resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
1348 + '@types/lodash@4.17.17':
1349 + resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==}
1350 +
1351 + '@types/markdown-it@14.1.2':
1352 + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
1353
1354 '@types/mdast@4.0.4':
1355 resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
1356
1357 + '@types/mdurl@2.0.0':
1358 + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
1359 +
1360 '@types/minimatch@3.0.5':
1361 resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==}
1362
1363 '@types/ms@2.1.0':
1364 resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
1365
1361 - '@types/node@22.15.2':
1362 - resolution: {integrity: sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==}
1363 -
1364 - '@types/normalize-package-data@2.4.4':
1365 - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
1366 + '@types/node@22.15.23':
1367 + resolution: {integrity: sha512-7Ec1zaFPF4RJ0eXu1YT/xgiebqwqoJz8rYPDi/O2BcZ++Wpt0Kq9cl0eg6NN6bYbPnR67ZLo7St5Q3UK0SnARw==}
1368
1369 '@types/parse-json@4.0.2':
1370 resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
@@ -1379,8 +1381,8 @@ packages:
1381 '@types/unist@3.0.3':
1382 resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
1383
1382 - '@types/validator@13.15.0':
1383 - resolution: {integrity: sha512-nh7nrWhLr6CBq9ldtw0wx+z9wKnnv/uTVLA9g/3/TcOYxbpOSZE+MhKPmWqU+K0NvThjhv12uD8MuqijB0WzEA==}
1384 + '@types/validator@13.15.1':
1385 + resolution: {integrity: sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==}
1386
1387 '@types/web-bluetooth@0.0.21':
1388 resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
@@ -1388,179 +1390,168 @@ packages:
1390 '@types/yauzl@2.10.3':
1391 resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
1392
1391 - '@typescript-eslint/eslint-plugin@8.30.1':
1392 - resolution: {integrity: sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==}
1393 + '@typescript-eslint/eslint-plugin@8.33.0':
1394 + resolution: {integrity: sha512-CACyQuqSHt7ma3Ns601xykeBK/rDeZa3w6IS6UtMQbixO5DWy+8TilKkviGDH6jtWCo8FGRKEK5cLLkPvEammQ==}
1395 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1396 peerDependencies:
1395 - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0
1397 + '@typescript-eslint/parser': ^8.33.0
1398 eslint: ^8.57.0 || ^9.0.0
1399 typescript: '>=4.8.4 <5.9.0'
1400
1399 - '@typescript-eslint/parser@8.30.1':
1400 - resolution: {integrity: sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==}
1401 + '@typescript-eslint/parser@8.33.0':
1402 + resolution: {integrity: sha512-JaehZvf6m0yqYp34+RVnihBAChkqeH+tqqhS0GuX1qgPpwLvmTPheKEs6OeCK6hVJgXZHJ2vbjnC9j119auStQ==}
1403 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1404 peerDependencies:
1405 eslint: ^8.57.0 || ^9.0.0
1406 typescript: '>=4.8.4 <5.9.0'
1407
1406 - '@typescript-eslint/scope-manager@8.29.0':
1407 - resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==}
1408 + '@typescript-eslint/project-service@8.33.0':
1409 + resolution: {integrity: sha512-d1hz0u9l6N+u/gcrk6s6gYdl7/+pp8yHheRTqP6X5hVDKALEaTn8WfGiit7G511yueBEL3OpOEpD+3/MBdoN+A==}
1410 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1411
1410 - '@typescript-eslint/scope-manager@8.30.1':
1411 - resolution: {integrity: sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==}
1412 + '@typescript-eslint/scope-manager@8.33.0':
1413 + resolution: {integrity: sha512-LMi/oqrzpqxyO72ltP+dBSP6V0xiUb4saY7WLtxSfiNEBI8m321LLVFU9/QDJxjDQG9/tjSqKz/E3380TEqSTw==}
1414 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1415
1414 - '@typescript-eslint/type-utils@8.30.1':
1415 - resolution: {integrity: sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==}
1416 + '@typescript-eslint/tsconfig-utils@8.33.0':
1417 + resolution: {integrity: sha512-sTkETlbqhEoiFmGr1gsdq5HyVbSOF0145SYDJ/EQmXHtKViCaGvnyLqWFFHtEXoS0J1yU8Wyou2UGmgW88fEug==}
1418 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1419 peerDependencies:
1418 - eslint: ^8.57.0 || ^9.0.0
1420 typescript: '>=4.8.4 <5.9.0'
1421
1421 - '@typescript-eslint/types@8.29.0':
1422 - resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==}
1423 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1424 -
1425 - '@typescript-eslint/types@8.30.1':
1426 - resolution: {integrity: sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==}
1427 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1428 -
1429 - '@typescript-eslint/typescript-estree@8.29.0':
1430 - resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==}
1422 + '@typescript-eslint/type-utils@8.33.0':
1423 + resolution: {integrity: sha512-lScnHNCBqL1QayuSrWeqAL5GmqNdVUQAAMTaCwdYEdWfIrSrOGzyLGRCHXcCixa5NK6i5l0AfSO2oBSjCjf4XQ==}
1424 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1425 peerDependencies:
1426 + eslint: ^8.57.0 || ^9.0.0
1427 typescript: '>=4.8.4 <5.9.0'
1428
1435 - '@typescript-eslint/typescript-estree@8.30.1':
1436 - resolution: {integrity: sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==}
1429 + '@typescript-eslint/types@8.33.0':
1430 + resolution: {integrity: sha512-DKuXOKpM5IDT1FA2g9x9x1Ug81YuKrzf4mYX8FAVSNu5Wo/LELHWQyM1pQaDkI42bX15PWl0vNPt1uGiIFUOpg==}
1431 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1438 - peerDependencies:
1439 - typescript: '>=4.8.4 <5.9.0'
1432
1441 - '@typescript-eslint/utils@8.29.0':
1442 - resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==}
1433 + '@typescript-eslint/typescript-estree@8.33.0':
1434 + resolution: {integrity: sha512-vegY4FQoB6jL97Tu/lWRsAiUUp8qJTqzAmENH2k59SJhw0Th1oszb9Idq/FyyONLuNqT1OADJPXfyUNOR8SzAQ==}
1435 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1436 peerDependencies:
1445 - eslint: ^8.57.0 || ^9.0.0
1437 typescript: '>=4.8.4 <5.9.0'
1438
1448 - '@typescript-eslint/utils@8.30.1':
1449 - resolution: {integrity: sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==}
1439 + '@typescript-eslint/utils@8.33.0':
1440 + resolution: {integrity: sha512-lPFuQaLA9aSNa7D5u2EpRiqdAUhzShwGg/nhpBlc4GR6kcTABttCuyjFs8BcEZ8VWrjCBof/bePhP3Q3fS+Yrw==}
1441 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1442 peerDependencies:
1443 eslint: ^8.57.0 || ^9.0.0
1444 typescript: '>=4.8.4 <5.9.0'
1445
1455 - '@typescript-eslint/visitor-keys@8.29.0':
1456 - resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==}
1457 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1458 -
1459 - '@typescript-eslint/visitor-keys@8.30.1':
1460 - resolution: {integrity: sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==}
1446 + '@typescript-eslint/visitor-keys@8.33.0':
1447 + resolution: {integrity: sha512-7RW7CMYoskiz5OOGAWjJFxgb7c5UNjTG292gYhWeOAcFmYCtVCSqjqSBj5zMhxbXo2JOW95YYrUWJfU0zrpaGQ==}
1448 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1449
1450 '@ungap/structured-clone@1.3.0':
1451 resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
1452
1466 - '@unrs/resolver-binding-darwin-arm64@1.6.3':
1467 - resolution: {integrity: sha512-+BbDAtwT4AVUyGIfC6SimaA6Mi/tEJCf5OYV5XQg7WIOW0vyD15aVgDLvsQscIZxgz42xB6DDqR7Kv6NBQJrEg==}
1453 + '@unrs/resolver-binding-darwin-arm64@1.7.5':
1454 + resolution: {integrity: sha512-efMrMFYcAY+Bg3TjHS9TIxyLW7DCkbmWyaePXA/FTuNNgzUgM9ffBoeA+4g90DjHMUuGyIcM4+96w1RoxNP3Tw==}
1455 cpu: [arm64]
1456 os: [darwin]
1457
1471 - '@unrs/resolver-binding-darwin-x64@1.6.3':
1472 - resolution: {integrity: sha512-q6qMXI8wT0u0GUns/L26kYHdX2du4yEhwxrXjPj/egvysI8XqcTyjnbWQm3NSJPw0Un2wvKPh0WuoTSJEZgbqw==}
1458 + '@unrs/resolver-binding-darwin-x64@1.7.5':
1459 + resolution: {integrity: sha512-K5Usy9LwmeLohtZGOC0IxhybYluGMrtBP/l73jVNKvuk240KmblE6lphSbydrocvEZEVfTfLmba8UeoSUfnh4A==}
1460 cpu: [x64]
1461 os: [darwin]
1462
1476 - '@unrs/resolver-binding-freebsd-x64@1.6.3':
1477 - resolution: {integrity: sha512-/7xs7QNNW17VZrFBf+2C95G72rA5c0YGtR18pvWrzM2tVPLrTsKnLl32hi3CG7F6cwwYRy7h61BIkMHh7qaZkw==}
1463 + '@unrs/resolver-binding-freebsd-x64@1.7.5':
1464 + resolution: {integrity: sha512-4vur1vMwq/hOkruiR24shuatm56jZo098x8ETchIewX8RbSwyTqHjnnJZ1WTLX2Vkg9hgy4RQqFpLnrL6Xp/hQ==}
1465 cpu: [x64]
1466 os: [freebsd]
1467
1481 - '@unrs/resolver-binding-linux-arm-gnueabihf@1.6.3':
1482 - resolution: {integrity: sha512-2xv5cUQCt+eYuq5tPF4AHStpzE8i8qdYnhitpvDv9vxzOZ5a0sdzgA8WHYgFe15dP469YOSivenMMdpuRcgE9Q==}
1468 + '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.5':
1469 + resolution: {integrity: sha512-/hD8IHDjlTUb1/ePHavsaHYRF8lMDh+14TXHmxC8cwqrBVoHIzGZV66z2VjBDpDUtmAutptOhfKBpRLv0O0ywA==}
1470 cpu: [arm]
1471 os: [linux]
1472
1486 - '@unrs/resolver-binding-linux-arm-musleabihf@1.6.3':
1487 - resolution: {integrity: sha512-4KaZxKIeFt/jAOD/zuBOLb5yyZk/XG9FKf5IXpDP21NcYxeus/os6w+NCK7wjSJKbOpHZhwfkAYLkfujkAOFkw==}
1473 + '@unrs/resolver-binding-linux-arm-musleabihf@1.7.5':
1474 + resolution: {integrity: sha512-UPrkyN5ziuT+uRATrwabvl8JZNMt1T/fN96bZVnK3E34lQLbku99biFEUHZgXh0knJzoSoAKWfyMyyrcv4Dqfg==}
1475 cpu: [arm]
1476 os: [linux]
1477
1491 - '@unrs/resolver-binding-linux-arm64-gnu@1.6.3':
1492 - resolution: {integrity: sha512-dJoZsZoWwvfS+khk0jkX6KnLL1T2vbRfsxinOR3PghpRKmMTnasEVAxmrXLQFNKqVKZV/mU7gHzWhiBMhbq3bw==}
1478 + '@unrs/resolver-binding-linux-arm64-gnu@1.7.5':
1479 + resolution: {integrity: sha512-btpXWiZystUjfNviOWjf7gwjak0h1dSrzjDGn4b8OkSIMw3Gp4yYtOMZRXxUtaaZRdnOQHqRh9+39PyK6LXQbQ==}
1480 cpu: [arm64]
1481 os: [linux]
1482
1496 - '@unrs/resolver-binding-linux-arm64-musl@1.6.3':
1497 - resolution: {integrity: sha512-2Y6JcAY9e557rD6O53Zmeblrfu48vQfl5CrrKjt0/2J1Op/pKX3WI8TOh0gs5T4qX9uJDqdte11SNUssckdfUA==}
1483 + '@unrs/resolver-binding-linux-arm64-musl@1.7.5':
1484 + resolution: {integrity: sha512-fzTDlm/RWRgHomLSabeV+/iKkAld+kUQaBJ2h0OveaV6+ZmZqEbdG9WDCe8U3/dax49mlPwZIvEnMZujzTPWCg==}
1485 cpu: [arm64]
1486 os: [linux]
1487
1501 - '@unrs/resolver-binding-linux-ppc64-gnu@1.6.3':
1502 - resolution: {integrity: sha512-kvcEe+j0De/DEfTNkte2xtmwSL4/GMesArcqmSgRqoOaGknUYY3whJ/3GygYKNMe82vvao4PaQkBlCrxhi88wQ==}
1488 + '@unrs/resolver-binding-linux-ppc64-gnu@1.7.5':
1489 + resolution: {integrity: sha512-i+9usBSko2DyFvB7iimhfDtIk9tWhg4sKh7kZC8JGfGMdhYWZ8a40VvgE/Xj8iDsX6ngVRsIsgsNCU9jPx86zw==}
1490 cpu: [ppc64]
1491 os: [linux]
1492
1506 - '@unrs/resolver-binding-linux-riscv64-gnu@1.6.3':
1507 - resolution: {integrity: sha512-fruY8swKre2H0J96h8HE+kN3iUnDR3VDd2wxBn4BxDw+5g7GOHBz5x1533l9mqAqHI4b2dMBECI4RtQdMOiBeQ==}
1493 + '@unrs/resolver-binding-linux-riscv64-gnu@1.7.5':
1494 + resolution: {integrity: sha512-gpdNeCckfTMOWyZ+AjB0KpgHE2aCCoGtKDSocKwU9RkfWpeVvpcokey5l1A68WXCDE33sonekbe8Wm4+E0z7VQ==}
1495 + cpu: [riscv64]
1496 + os: [linux]
1497 +
1498 + '@unrs/resolver-binding-linux-riscv64-musl@1.7.5':
1499 + resolution: {integrity: sha512-avni2nC47b0ZBCXL3lg6I3z9lyP1kKVYZXIyIsA/pcTra+Uuq0RgeWeEBc8IJ6DjGrpft7gWyyekrYK58VomGQ==}
1500 cpu: [riscv64]
1501 os: [linux]
1502
1511 - '@unrs/resolver-binding-linux-s390x-gnu@1.6.3':
1512 - resolution: {integrity: sha512-1w0eaSxm9e69TEj9eArZDPQ7mL2VL6Bb4AXeLOdQoe5SNQpZaL6RlwGm7ss9xErwC7c9Hvob/ZZF7i8xYT55zg==}
1503 + '@unrs/resolver-binding-linux-s390x-gnu@1.7.5':
1504 + resolution: {integrity: sha512-GLv1+kVnVluyG8KRIl176jIoExlhgl3ASZz+VGyQpv5EwD5FqOtZHFzsRJA3xXNQlnHj3iMO4SA/HX4dc6iOvA==}
1505 cpu: [s390x]
1506 os: [linux]
1507
1516 - '@unrs/resolver-binding-linux-x64-gnu@1.6.3':
1517 - resolution: {integrity: sha512-ymUqs8AQyHTQQ50aN7EcMV47gKh5yKg8a0+SWSuDZEl6eGEOKn590D/iMDydS5KoWbMTy6/pBipS4vsPUEjYVw==}
1508 + '@unrs/resolver-binding-linux-x64-gnu@1.7.5':
1509 + resolution: {integrity: sha512-frsoBmP2ww2axFqZvIexnDF5UuO0exCZjrchM7uvPbNzZCaU+B43r6Y3ywEFsXXH6MbZNpw10Ntuwb9N0orfcg==}
1510 cpu: [x64]
1511 os: [linux]
1512
1521 - '@unrs/resolver-binding-linux-x64-musl@1.6.3':
1522 - resolution: {integrity: sha512-LSfz1cguLZD+c00aTVbtrqX1x1sIR38M2lLYW3CZTGfippkg56Hf8kejHPA8H26OwB71c9/W78BCbgcdnEW+jQ==}
1513 + '@unrs/resolver-binding-linux-x64-musl@1.7.5':
1514 + resolution: {integrity: sha512-kdI20RI0k+XcA+vuW6KB/EJbzUvRfo8PsKy2DFlX1fhTVsEXaf21nkU9C3NdTwlTkl9YvvLGNTKoJDH7yn7K8w==}
1515 cpu: [x64]
1516 os: [linux]
1517
1526 - '@unrs/resolver-binding-wasm32-wasi@1.6.3':
1527 - resolution: {integrity: sha512-gehKZDmNDS2QTxefwPBLi0RJgOQ0dIoD/osCcNboDb3+ZKcbSMBaF3+4R5vj+XdV0QBdZg3vXwdwZswfEkQOcA==}
1518 + '@unrs/resolver-binding-wasm32-wasi@1.7.5':
1519 + resolution: {integrity: sha512-6F+PAhfsokXDtLihQzomvVK0rYzSP/qkgJg4+R4RaCmE3pwFspLeyUi1Wd11hwP4FQQn5/5Yw9jraUMQpMPWCg==}
1520 engines: {node: '>=14.0.0'}
1521 cpu: [wasm32]
1522
1531 - '@unrs/resolver-binding-win32-arm64-msvc@1.6.3':
1532 - resolution: {integrity: sha512-CzTmpDxwkoYl69stmlJzcVWITQEC6Vs8ASMZMEMbFO+q1Dw0GtpRjAA6X76zGcLOADDwzugx1vpT6YXarrhpTA==}
1523 + '@unrs/resolver-binding-win32-arm64-msvc@1.7.5':
1524 + resolution: {integrity: sha512-rZ1SRHK95gOqy7hQBcG2sxKMoKFRFAl8f+cGYayA3RRNidkY86uNsXZiWDGgIuelYXSudvAd9RElDib/Lkx7pQ==}
1525 cpu: [arm64]
1526 os: [win32]
1527
1536 - '@unrs/resolver-binding-win32-ia32-msvc@1.6.3':
1537 - resolution: {integrity: sha512-j+n1gWkfu4Q/octUHXU1p1IOrh+B27vpA7ec81RB6nXCml5u7F0B7SrCZU+HqajxjVqgEQEYOcRCb1yzfwfsWw==}
1528 + '@unrs/resolver-binding-win32-ia32-msvc@1.7.5':
1529 + resolution: {integrity: sha512-49JiW5JickDuC/VqSBlbZTqwX8sJBGBfodU/v4+vM8Eig63JOAK7bOtG8M8kxXRrkJIGhumba4cTf4QcWbMRcg==}
1530 cpu: [ia32]
1531 os: [win32]
1532
1541 - '@unrs/resolver-binding-win32-x64-msvc@1.6.3':
1542 - resolution: {integrity: sha512-n33drkd84G5Mu2BkUGawZXmm+IFPuRv7GpODfwEBs/CzZq2+BIZyAZmb03H9IgNbd7xaohZbtZ4/9Gb0xo5ssw==}
1533 + '@unrs/resolver-binding-win32-x64-msvc@1.7.5':
1534 + resolution: {integrity: sha512-69JcsNlbafX/FsafXswKb5M+jPXC9IRcNVz5SqEKH9+PA5jmJ6+fFyjFX1pipBRADGn+EuPhCeDcQl+CAxP+2g==}
1535 cpu: [x64]
1536 os: [win32]
1537
1546 - '@vitejs/plugin-vue-jsx@4.1.2':
1547 - resolution: {integrity: sha512-4Rk0GdE0QCdsIkuMmWeg11gmM4x8UmTnZR/LWPm7QJ7+BsK4tq08udrN0isrrWqz5heFy9HLV/7bOLgFS8hUjA==}
1538 + '@vitejs/plugin-vue-jsx@4.2.0':
1539 + resolution: {integrity: sha512-DSTrmrdLp+0LDNF77fqrKfx7X0ErRbOcUAgJL/HbSesqQwoUvUQ4uYQqaex+rovqgGcoPqVk+AwUh3v9CuiYIw==}
1540 engines: {node: ^18.0.0 || >=20.0.0}
1541 peerDependencies:
1542 vite: ^5.0.0 || ^6.0.0
1543 vue: ^3.0.0
1544
1553 - '@vitejs/plugin-vue@5.2.3':
1554 - resolution: {integrity: sha512-IYSLEQj4LgZZuoVpdSUCw3dIynTWQgPlaRP6iAvMle4My0HdYwr5g5wQAfwOeHQBmYwEkqF70nRpSilr6PoUDg==}
1545 + '@vitejs/plugin-vue@5.2.4':
1546 + resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==}
1547 engines: {node: ^18.0.0 || >=20.0.0}
1548 peerDependencies:
1549 vite: ^5.0.0 || ^6.0.0
1550 vue: ^3.2.25
1551
1560 - '@vitest/eslint-plugin@1.1.43':
1561 - resolution: {integrity: sha512-OLoUMO67Yg+kr7E6SjF5+Qvl2f6uNJ7ImQYnXT8WgnPiZE41ZQBsnzn70jehXrhFVadphHs2smk+yl0TFKLV5Q==}
1552 + '@vitest/eslint-plugin@1.2.1':
1553 + resolution: {integrity: sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==}
1554 peerDependencies:
1563 - '@typescript-eslint/utils': '>= 8.24.0'
1555 eslint: '>= 8.57.0'
1556 typescript: '>= 5.0.0'
1557 vitest: '*'
@@ -1570,11 +1561,11 @@ packages:
1561 vitest:
1562 optional: true
1563
1573 - '@vitest/expect@3.1.2':
1574 - resolution: {integrity: sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==}
1564 + '@vitest/expect@3.1.4':
1565 + resolution: {integrity: sha512-xkD/ljeliyaClDYqHPNCiJ0plY5YIcM0OlRiZizLhlPmpXWpxnGMyTZXOHFhFeG7w9P5PBeL4IdtJ/HeQwTbQA==}
1566
1576 - '@vitest/mocker@3.1.2':
1577 - resolution: {integrity: sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==}
1567 + '@vitest/mocker@3.1.4':
1568 + resolution: {integrity: sha512-8IJ3CvwtSw/EFXqWFL8aCMu+YyYXG2WUSrQbViOZkWTKTVicVwZ/YiEZDSqD00kX+v/+W+OnxhNWoeVKorHygA==}
1569 peerDependencies:
1570 msw: ^2.4.9
1571 vite: ^5.0.0 || ^6.0.0
@@ -1584,29 +1575,29 @@ packages:
1575 vite:
1576 optional: true
1577
1587 - '@vitest/pretty-format@3.1.2':
1588 - resolution: {integrity: sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==}
1578 + '@vitest/pretty-format@3.1.4':
1579 + resolution: {integrity: sha512-cqv9H9GvAEoTaoq+cYqUTCGscUjKqlJZC7PRwY5FMySVj5J+xOm1KQcCiYHJOEzOKRUhLH4R2pTwvFlWCEScsg==}
1580
1590 - '@vitest/runner@3.1.2':
1591 - resolution: {integrity: sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==}
1581 + '@vitest/runner@3.1.4':
1582 + resolution: {integrity: sha512-djTeF1/vt985I/wpKVFBMWUlk/I7mb5hmD5oP8K9ACRmVXgKTae3TUOtXAEBfslNKPzUQvnKhNd34nnRSYgLNQ==}
1583
1593 - '@vitest/snapshot@3.1.2':
1594 - resolution: {integrity: sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==}
1584 + '@vitest/snapshot@3.1.4':
1585 + resolution: {integrity: sha512-JPHf68DvuO7vilmvwdPr9TS0SuuIzHvxeaCkxYcCD4jTk67XwL45ZhEHFKIuCm8CYstgI6LZ4XbwD6ANrwMpFg==}
1586
1596 - '@vitest/spy@3.1.2':
1597 - resolution: {integrity: sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==}
1587 + '@vitest/spy@3.1.4':
1588 + resolution: {integrity: sha512-Xg1bXhu+vtPXIodYN369M86K8shGLouNjoVI78g8iAq2rFoHFdajNvJJ5A/9bPMFcfQqdaCpOgWKEoMQg/s0Yg==}
1589
1599 - '@vitest/utils@3.1.2':
1600 - resolution: {integrity: sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==}
1590 + '@vitest/utils@3.1.4':
1591 + resolution: {integrity: sha512-yriMuO1cfFhmiGc8ataN51+9ooHRuURdfAZfwFd3usWynjzpLslZdYnRegTv32qdgtJTsj15FoeZe2g15fY1gg==}
1592
1602 - '@volar/language-core@2.4.12':
1603 - resolution: {integrity: sha512-RLrFdXEaQBWfSnYGVxvR2WrO6Bub0unkdHYIdC31HzIEqATIuuhRRzYu76iGPZ6OtA4Au1SnW0ZwIqPP217YhA==}
1593 + '@volar/language-core@2.4.14':
1594 + resolution: {integrity: sha512-X6beusV0DvuVseaOEy7GoagS4rYHgDHnTrdOj5jeUb49fW5ceQyP9Ej5rBhqgz2wJggl+2fDbbojq1XKaxDi6w==}
1595
1605 - '@volar/source-map@2.4.12':
1606 - resolution: {integrity: sha512-bUFIKvn2U0AWojOaqf63ER0N/iHIBYZPpNGogfLPQ68F5Eet6FnLlyho7BS0y2HJ1jFhSif7AcuTx1TqsCzRzw==}
1596 + '@volar/source-map@2.4.14':
1597 + resolution: {integrity: sha512-5TeKKMh7Sfxo8021cJfmBzcjfY1SsXsPMMjMvjY7ivesdnybqqS+GxGAoXHAOUawQTwtdUxgP65Im+dEmvWtYQ==}
1598
1608 - '@volar/typescript@2.4.12':
1609 - resolution: {integrity: sha512-HJB73OTJDgPc80K30wxi3if4fSsZZAOScbj2fcicMuOPoOkcf9NNAINb33o+DzhBdF9xTKC1gnPmIRDous5S0g==}
1599 + '@volar/typescript@2.4.14':
1600 + resolution: {integrity: sha512-p8Z6f/bZM3/HyCdRNFZOEEzts51uV8WHeN8Tnfnm2EBv6FDB2TQLzfVx7aJvnl8ofKAOnS64B2O8bImBFaauRw==}
1601
1602 '@vue/babel-helper-vue-transform-on@1.4.0':
1603 resolution: {integrity: sha512-mCokbouEQ/ocRce/FpKCRItGo+013tHg7tixg3DUNS+6bmIchPt66012kBMm476vyEIJPafrvOf4E5OYj3shSw==}
@@ -1624,17 +1615,17 @@ packages:
1615 peerDependencies:
1616 '@babel/core': ^7.0.0-0
1617
1627 - '@vue/compiler-core@3.5.13':
1628 - resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==}
1618 + '@vue/compiler-core@3.5.15':
1619 + resolution: {integrity: sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw==}
1620
1630 - '@vue/compiler-dom@3.5.13':
1631 - resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==}
1621 + '@vue/compiler-dom@3.5.15':
1622 + resolution: {integrity: sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA==}
1623
1633 - '@vue/compiler-sfc@3.5.13':
1634 - resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==}
1624 + '@vue/compiler-sfc@3.5.15':
1625 + resolution: {integrity: sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ==}
1626
1636 - '@vue/compiler-ssr@3.5.13':
1637 - resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==}
1627 + '@vue/compiler-ssr@3.5.15':
1628 + resolution: {integrity: sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg==}
1629
1630 '@vue/compiler-vue2@2.7.16':
1631 resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==}
@@ -1642,25 +1633,19 @@ packages:
1633 '@vue/devtools-api@6.6.4':
1634 resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==}
1635
1645 - '@vue/devtools-api@7.7.2':
1646 - resolution: {integrity: sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==}
1636 + '@vue/devtools-api@7.7.6':
1637 + resolution: {integrity: sha512-b2Xx0KvXZObePpXPYHvBRRJLDQn5nhKjXh7vUhMEtWxz1AYNFOVIsh5+HLP8xDGL7sy+Q7hXeUxPHB/KgbtsPw==}
1638
1648 - '@vue/devtools-core@7.7.5':
1649 - resolution: {integrity: sha512-ElKr0NDor57gVaT+gMQ8kcVP4uFGqHcxuuQndW/rPwh6aHWvEcUL3sxL8cEk+e1Rdt28kS88erpsiIMO6hEENQ==}
1639 + '@vue/devtools-core@7.7.6':
1640 + resolution: {integrity: sha512-ghVX3zjKPtSHu94Xs03giRIeIWlb9M+gvDRVpIZ/cRIxKHdW6HE/sm1PT3rUYS3aV92CazirT93ne+7IOvGUWg==}
1641 peerDependencies:
1642 vue: ^3.0.0
1643
1653 - '@vue/devtools-kit@7.7.2':
1654 - resolution: {integrity: sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==}
1655 -
1656 - '@vue/devtools-kit@7.7.5':
1657 - resolution: {integrity: sha512-S9VAVJYVAe4RPx2JZb9ZTEi0lqTySz2CBeF0wHT5D3dkTLnT9yMMGegKNl4b2EIELwLSkcI9bl2qp0/jW+upqA==}
1644 + '@vue/devtools-kit@7.7.6':
1645 + resolution: {integrity: sha512-geu7ds7tem2Y7Wz+WgbnbZ6T5eadOvozHZ23Atk/8tksHMFOFylKi1xgGlQlVn0wlkEf4hu+vd5ctj1G4kFtwA==}
1646
1659 - '@vue/devtools-shared@7.7.2':
1660 - resolution: {integrity: sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==}
1661 -
1662 - '@vue/devtools-shared@7.7.5':
1663 - resolution: {integrity: sha512-QBjG72RfpM0DKtpns2RZOxBltO226kOAls9e4Lri6YxS2gWTgL0H+wj1R2K76lxxIeOrqo4+2Ty6RQnzv+WSTQ==}
1647 + '@vue/devtools-shared@7.7.6':
1648 + resolution: {integrity: sha512-yFEgJZ/WblEsojQQceuyK6FzpFDx4kqrz2ohInxNj5/DnhoX023upTv4OD6lNPLAA5LLkbwPVb10o/7b+Y4FVA==}
1649
1650 '@vue/language-core@2.2.10':
1651 resolution: {integrity: sha512-+yNoYx6XIKuAO8Mqh1vGytu8jkFEOH5C8iOv3i8Z/65A7x9iAOXA97Q+PqZ3nlm2lxf5rOJuIGI/wDtx/riNYw==}
@@ -1670,22 +1655,22 @@ packages:
1655 typescript:
1656 optional: true
1657
1673 - '@vue/reactivity@3.5.13':
1674 - resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==}
1658 + '@vue/reactivity@3.5.15':
1659 + resolution: {integrity: sha512-GaA5VUm30YWobCwpvcs9nvFKf27EdSLKDo2jA0IXzGS344oNpFNbEQ9z+Pp5ESDaxyS8FcH0vFN/XSe95BZtHQ==}
1660
1676 - '@vue/runtime-core@3.5.13':
1677 - resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==}
1661 + '@vue/runtime-core@3.5.15':
1662 + resolution: {integrity: sha512-CZAlIOQ93nj0OPpWWOx4+QDLCMzBNY85IQR4Voe6vIID149yF8g9WQaWnw042f/6JfvLttK7dnyWlC1EVCRK8Q==}
1663
1679 - '@vue/runtime-dom@3.5.13':
1680 - resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==}
1664 + '@vue/runtime-dom@3.5.15':
1665 + resolution: {integrity: sha512-wFplHKzKO/v998up2iCW3RN9TNUeDMhdBcNYZgs5LOokHntrB48dyuZHspcahKZczKKh3v6i164gapMPxBTKNw==}
1666
1682 - '@vue/server-renderer@3.5.13':
1683 - resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==}
1667 + '@vue/server-renderer@3.5.15':
1668 + resolution: {integrity: sha512-Gehc693kVTYkLt6QSYEjGvqvdK2zZ/gf/D5zkgmvBdeB30dNnVZS8yY7+IlBmHRd1rR/zwaqeu06Ij04ZxBscg==}
1669 peerDependencies:
1685 - vue: 3.5.13
1670 + vue: 3.5.15
1671
1687 - '@vue/shared@3.5.13':
1688 - resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==}
1672 + '@vue/shared@3.5.15':
1673 + resolution: {integrity: sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA==}
1674
1675 '@vue/test-utils@2.4.6':
1676 resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==}
@@ -1701,16 +1686,21 @@ packages:
1686 vue:
1687 optional: true
1688
1704 - '@vueuse/core@13.1.0':
1705 - resolution: {integrity: sha512-PAauvdRXZvTWXtGLg8cPUFjiZEddTqmogdwYpnn60t08AA5a8Q4hZokBnpTOnVNqySlFlTcRYIC8OqreV4hv3Q==}
1689 + '@vueuse/core@13.3.0':
1690 + resolution: {integrity: sha512-uYRz5oEfebHCoRhK4moXFM3NSCd5vu2XMLOq/Riz5FdqZMy2RvBtazdtL3gEcmDyqkztDe9ZP/zymObMIbiYSg==}
1691 peerDependencies:
1692 vue: ^3.5.0
1693
1709 - '@vueuse/metadata@13.1.0':
1710 - resolution: {integrity: sha512-+TDd7/a78jale5YbHX9KHW3cEDav1lz1JptwDvep2zSG8XjCsVE+9mHIzjTOaPbHUAk5XiE4jXLz51/tS+aKQw==}
1694 + '@vueuse/metadata@13.3.0':
1695 + resolution: {integrity: sha512-42IzJIOYCKIb0Yjv1JfaKpx8JlCiTmtCWrPxt7Ja6Wzoq0h79+YVXmBV03N966KEmDEESTbp5R/qO3AB5BDnGw==}
1696
1712 - '@vueuse/shared@13.1.0':
1713 - resolution: {integrity: sha512-IVS/qRRjhPTZ6C2/AM3jieqXACGwFZwWTdw5sNTSKk2m/ZpkuuN+ri+WCVUP8TqaKwJYt/KuMwmXspMAw8E6ew==}
1697 + '@vueuse/motion@3.0.3':
1698 + resolution: {integrity: sha512-4B+ITsxCI9cojikvrpaJcLXyq0spj3sdlzXjzesWdMRd99hhtFI6OJ/1JsqwtF73YooLe0hUn/xDR6qCtmn5GQ==}
1699 + peerDependencies:
1700 + vue: '>=3.0.0'
1701 +
1702 + '@vueuse/shared@13.3.0':
1703 + resolution: {integrity: sha512-L1QKsF0Eg9tiZSFXTgodYnu0Rsa2P0En2LuLrIs/jgrkyiDuJSsPZK+tx+wU0mMsYHUYEjNsuE41uqqkuR8VhA==}
1704 peerDependencies:
1705 vue: ^3.5.0
1706
@@ -1769,12 +1759,12 @@ packages:
1759 resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==}
1760 engines: {node: '>=12'}
1761
1772 - ansis@3.17.0:
1773 - resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==}
1762 + ansis@4.0.0:
1763 + resolution: {integrity: sha512-P8nrHI1EyW9OfBt1X7hMSwGN2vwRuqHSKJAT1gbLWZRzDa24oHjYwGHvEgHeBepupzk878yS/HBZ0NMPYtbolw==}
1764 engines: {node: '>=14'}
1765
1776 - apexcharts@4.5.0:
1777 - resolution: {integrity: sha512-E7ZkrVqPNBUWy/Rmg8DEIqHNBmElzICE/oxOX5Ekvs2ICQUOK/VkEkMH09JGJu+O/EA0NL31hxlmF+wrwrSLaQ==}
1766 + apexcharts@4.7.0:
1767 + resolution: {integrity: sha512-iZSrrBGvVlL+nt2B1NpqfDuBZ9jX61X9I2+XV0hlYXHtTwhwLTHDKGXjNXAgFBDLuvSYCB/rq2nPWVPRv2DrGA==}
1768
1769 arch@2.2.0:
1770 resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
@@ -1850,9 +1840,6 @@ packages:
1840 bcrypt-pbkdf@1.0.2:
1841 resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
1842
1853 - birpc@0.2.19:
1854 - resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==}
1855 -
1843 birpc@2.3.0:
1844 resolution: {integrity: sha512-ijbtkn/F3Pvzb6jHypHRyve2QApOCZDR25D/VnkY2G/lBNcXCTsnsCxgY4k4PkVB7zfwzYbY3O9Lcqe3xufS5g==}
1845
@@ -1875,8 +1862,8 @@ packages:
1862 resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
1863 engines: {node: '>=8'}
1864
1878 - browserslist@4.24.4:
1879 - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
1865 + browserslist@4.24.5:
1866 + resolution: {integrity: sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==}
1867 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
1868 hasBin: true
1869
@@ -1898,8 +1885,8 @@ packages:
1885 resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
1886 engines: {node: '>= 0.8'}
1887
1901 - c12@3.0.3:
1902 - resolution: {integrity: sha512-uC3MacKBb0Z15o5QWCHvHWj5Zv34pGQj9P+iXKSpTuSGFS0KKhUWf4t9AJ+gWjYOdmWCPEGpEzm8sS0iqbpo1w==}
1888 + c12@3.0.4:
1889 + resolution: {integrity: sha512-t5FaZTYbbCtvxuZq9xxIruYydrAGsJ+8UdP0pZzMiK2xl/gNiSOy0OxhLzHUEEb0m1QXYqfzfvyIFEmz/g9lqg==}
1890 peerDependencies:
1891 magicast: ^0.3.5
1892 peerDependenciesMeta:
@@ -1933,8 +1920,8 @@ packages:
1920 resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
1921 engines: {node: '>=10'}
1922
1936 - caniuse-lite@1.0.30001709:
1937 - resolution: {integrity: sha512-NgL3vUTnDrPCZ3zTahp4fsugQ4dc7EKTSzwQDPEel6DMoMnfH2jhry9n2Zm8onbSR+f/QtKHFOA+iAQu4kbtWA==}
1923 + caniuse-lite@1.0.30001718:
1924 + resolution: {integrity: sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==}
1925
1926 caseless@0.12.0:
1927 resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==}
@@ -1971,6 +1958,10 @@ packages:
1958 resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
1959 engines: {node: '>= 14.16.0'}
1960
1961 + chownr@3.0.0:
1962 + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
1963 + engines: {node: '>=18'}
1964 +
1965 ci-info@4.2.0:
1966 resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==}
1967 engines: {node: '>=8'}
@@ -1993,8 +1984,8 @@ packages:
1984 resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
1985 engines: {node: '>=8'}
1986
1996 - cli-table3@0.6.5:
1997 - resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
1987 + cli-table3@0.6.1:
1988 + resolution: {integrity: sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==}
1989 engines: {node: 10.* || >= 12.*}
1990
1991 cli-truncate@2.1.0:
@@ -2024,6 +2015,10 @@ packages:
2015 colorette@2.0.20:
2016 resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
2017
2018 + colors@1.4.0:
2019 + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==}
2020 + engines: {node: '>=0.1.90'}
2021 +
2022 combined-stream@1.0.8:
2023 resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
2024 engines: {node: '>= 0.8'}
@@ -2074,8 +2069,8 @@ packages:
2069 resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==}
2070 engines: {node: '>=12.13'}
2071
2077 - core-js-compat@3.41.0:
2078 - resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==}
2072 + core-js-compat@3.42.0:
2073 + resolution: {integrity: sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==}
2074
2075 core-util-is@1.0.2:
2076 resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
@@ -2121,8 +2116,8 @@ packages:
2116 resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==}
2117 engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'}
2118
2124 - cssstyle@4.3.0:
2125 - resolution: {integrity: sha512-6r0NiY0xizYqfBvWp1G7WXJ06/bZyrk7Dc6PHql82C/pKGUTKu4yAX4Y8JPamb1ob9nBKuxWzCGTRuGwU3yxJQ==}
2119 + cssstyle@4.3.1:
2120 + resolution: {integrity: sha512-ZgW+Jgdd7i52AaLYCriF8Mxqft0gD/R9i9wi6RWBhs1pqdPEzPjym7rvRKi397WmQFf3SlyUsszhw+VVCbx79Q==}
2121 engines: {node: '>=18'}
2122
2123 csstype@3.0.11:
@@ -2131,8 +2126,8 @@ packages:
2126 csstype@3.1.3:
2127 resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
2128
2134 - cypress@14.3.2:
2135 - resolution: {integrity: sha512-n+yGD2ZFFKgy7I3YtVpZ7BcFYrrDMcKj713eOZdtxPttpBjCyw/R8dLlFSsJPouneGN7A/HOSRyPJ5+3/gKDoA==}
2129 + cypress@14.4.0:
2130 + resolution: {integrity: sha512-/I59Fqxo7fqdiDi3IM2QKA65gZ7+PVejXg404/I8ZSq+NOnrmw+2pnMUJzpoNyg7KABcEBmgpkfAqhV98p7wJA==}
2131 engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
2132 hasBin: true
2133
@@ -2169,8 +2164,8 @@ packages:
2164 supports-color:
2165 optional: true
2166
2172 - debug@4.4.0:
2173 - resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
2167 + debug@4.4.1:
2168 + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
2169 engines: {node: '>=6.0'}
2170 peerDependencies:
2171 supports-color: '*'
@@ -2241,8 +2236,8 @@ packages:
2236 engines: {node: '>=0.10'}
2237 hasBin: true
2238
2244 - detect-libc@2.0.3:
2245 - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
2239 + detect-libc@2.0.4:
2240 + resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
2241 engines: {node: '>=8'}
2242
2243 detect-touch-device@1.1.6:
@@ -2251,10 +2246,6 @@ packages:
2246 devlop@1.1.0:
2247 resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
2248
2254 - doctrine@3.0.0:
2255 - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
2256 - engines: {node: '>=6.0.0'}
2257 -
2249 dom-serializer@2.0.0:
2250 resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
2251
@@ -2268,8 +2259,8 @@ packages:
2259 domutils@3.2.2:
2260 resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
2261
2271 - dotenv@16.4.7:
2272 - resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
2262 + dotenv@16.5.0:
2263 + resolution: {integrity: sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==}
2264 engines: {node: '>=12'}
2265
2266 dunder-proto@1.0.1:
@@ -2296,11 +2287,8 @@ packages:
2287 engines: {node: '>=14'}
2288 hasBin: true
2289
2299 - electron-to-chromium@1.5.130:
2300 - resolution: {integrity: sha512-Ou2u7L9j2XLZbhqzyX0jWDj6gA8D3jIfVzt4rikLf3cGBa0VdReuFimBKS9tQJA4+XpeCxj1NoWlfBXzbMa9IA==}
2301 -
2302 - emoji-regex-xs@1.0.0:
2303 - resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
2290 + electron-to-chromium@1.5.159:
2291 + resolution: {integrity: sha512-CEvHptWAMV5p6GJ0Lq8aheyvVbfzVrv5mmidu1D3pidoVNkB3tTBsTMVtPJ+rzRK5oV229mCLz9Zj/hNvU8GBA==}
2292
2293 emoji-regex@8.0.0:
2294 resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -2323,6 +2311,10 @@ packages:
2311 resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
2312 engines: {node: '>=0.12'}
2313
2314 + entities@6.0.0:
2315 + resolution: {integrity: sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==}
2316 + engines: {node: '>=0.12'}
2317 +
2318 error-ex@1.3.2:
2319 resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
2320
@@ -2340,8 +2332,8 @@ packages:
2332 resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
2333 engines: {node: '>= 0.4'}
2334
2343 - es-module-lexer@1.6.0:
2344 - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==}
2335 + es-module-lexer@1.7.0:
2336 + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
2337
2338 es-object-atoms@1.1.1:
2339 resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
@@ -2351,8 +2343,8 @@ packages:
2343 resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
2344 engines: {node: '>= 0.4'}
2345
2354 - esbuild@0.25.2:
2355 - resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==}
2346 + esbuild@0.25.5:
2347 + resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==}
2348 engines: {node: '>=18'}
2349 hasBin: true
2350
@@ -2389,8 +2381,17 @@ packages:
2381 peerDependencies:
2382 eslint: ^9.5.0
2383
2392 - eslint-flat-config-utils@2.0.1:
2393 - resolution: {integrity: sha512-brf0eAgQ6JlKj3bKfOTuuI7VcCZvi8ZCD1MMTVoEvS/d38j8cByZViLFALH/36+eqB17ukmfmKq3bWzGvizejA==}
2384 + eslint-flat-config-utils@2.1.0:
2385 + resolution: {integrity: sha512-6fjOJ9tS0k28ketkUcQ+kKptB4dBZY2VijMZ9rGn8Cwnn1SH0cZBoPXT8AHBFHxmHcLFQK9zbELDinZ2Mr1rng==}
2386 +
2387 + eslint-import-context@0.1.6:
2388 + resolution: {integrity: sha512-/e2ZNPDLCrU8niIy0pddcvXuoO2YrKjf3NAIX+60mHJBT4yv7mqCqvVdyCW2E720e25e4S/1OSVef4U6efGLFg==}
2389 + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
2390 + peerDependencies:
2391 + unrs-resolver: ^1.0.0
2392 + peerDependenciesMeta:
2393 + unrs-resolver:
2394 + optional: true
2395
2396 eslint-import-resolver-node@0.3.9:
2397 resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
@@ -2416,8 +2417,8 @@ packages:
2417 peerDependencies:
2418 eslint: '*'
2419
2419 - eslint-plugin-command@3.2.0:
2420 - resolution: {integrity: sha512-PSDOB9k7Wd57pp4HD/l3C1D93pKX8/wQo0kWDI4q6/UpgrfMTyNsavklipgiZqbXl1+VBABY1buCcQE5LDpg5g==}
2420 + eslint-plugin-command@3.2.1:
2421 + resolution: {integrity: sha512-PcpzWe8dvAPaBobxE9zgz1w94fO4JYvzciDzw6thlUb9Uqf5e2/gJz97itOGxvdq+mFeudi71m1OGFgvWmb93w==}
2422 peerDependencies:
2423 eslint: '*'
2424
@@ -2427,26 +2428,26 @@ packages:
2428 peerDependencies:
2429 eslint: '>=8'
2430
2430 - eslint-plugin-import-x@4.10.6:
2431 - resolution: {integrity: sha512-sWIaoezWK7kuPA7u29ULsO8WzlYYC8uivaipsazyHiZDykjNsuPtwRsYZIK2luqc5wppwXOop8iFdW7xffo/Xw==}
2431 + eslint-plugin-import-x@4.13.3:
2432 + resolution: {integrity: sha512-CDewJDEeYQhm94KGCDYiuwU1SdaWc/vh+SziSKkF7kichAqAFnQYtSYUvSwSBbiBjYLxV5uUxocxxQobRI9YXA==}
2433 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2434 peerDependencies:
2435 eslint: ^8.57.0 || ^9.0.0
2436
2436 - eslint-plugin-jsdoc@50.6.9:
2437 - resolution: {integrity: sha512-7/nHu3FWD4QRG8tCVqcv+BfFtctUtEDWc29oeDXB4bwmDM2/r1ndl14AG/2DUntdqH7qmpvdemJKwb3R97/QEw==}
2437 + eslint-plugin-jsdoc@50.6.17:
2438 + resolution: {integrity: sha512-hq+VQylhd12l8qjexyriDsejZhqiP33WgMTy2AmaGZ9+MrMWVqPECsM87GPxgHfQn0zw+YTuhqjUfk1f+q67aQ==}
2439 engines: {node: '>=18'}
2440 peerDependencies:
2441 eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
2442
2442 - eslint-plugin-jsonc@2.20.0:
2443 - resolution: {integrity: sha512-FRgCn9Hzk5eKboCbVMrr9QrhM0eO4G+WKH8IFXoaeqhM/2kuWzbStJn4kkr0VWL8J5H8RYZF+Aoam1vlBaZVkw==}
2443 + eslint-plugin-jsonc@2.20.1:
2444 + resolution: {integrity: sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng==}
2445 engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
2446 peerDependencies:
2447 eslint: '>=6.0.0'
2448
2448 - eslint-plugin-n@17.17.0:
2449 - resolution: {integrity: sha512-2VvPK7Mo73z1rDFb6pTvkH6kFibAmnTubFq5l83vePxu0WiY1s0LOtj2WHb6Sa40R3w4mnh8GFYbHBQyMlotKw==}
2449 + eslint-plugin-n@17.18.0:
2450 + resolution: {integrity: sha512-hvZ/HusueqTJ7VDLoCpjN0hx4N4+jHIWTXD4TMLHy9F23XkDagR9v+xQWRWR57yY55GPF8NnD4ox9iGTxirY8A==}
2451 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2452 peerDependencies:
2453 eslint: '>=8.23.0'
@@ -2455,8 +2456,8 @@ packages:
2456 resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==}
2457 engines: {node: '>=5.0.0'}
2458
2458 - eslint-plugin-perfectionist@4.11.0:
2459 - resolution: {integrity: sha512-5s+ehXydnLPQpLDj5mJ0CnYj2fQe6v6gKA3tS+FZVBLzwMOh8skH+l+1Gni08rG0SdEcNhJyjQp/mEkDYK8czw==}
2459 + eslint-plugin-perfectionist@4.13.0:
2460 + resolution: {integrity: sha512-dsPwXwV7IrG26PJ+h1crQ1f5kxay/gQAU0NJnbVTQc91l5Mz9kPjyIZ7fXgie+QSgi8a+0TwGbfaJx+GIhzuoQ==}
2461 engines: {node: ^18.0.0 || >=20.0.0}
2462 peerDependencies:
2463 eslint: '>=8.45.0'
@@ -2478,8 +2479,8 @@ packages:
2479 peerDependencies:
2480 eslint: '>=6.0.0'
2481
2481 - eslint-plugin-unicorn@58.0.0:
2482 - resolution: {integrity: sha512-fc3iaxCm9chBWOHPVjn+Czb/wHS0D2Mko7wkOdobqo9R2bbFObc4LyZaLTNy0mhZOP84nKkLhTUQxlLOZ7EjKw==}
2482 + eslint-plugin-unicorn@59.0.1:
2483 + resolution: {integrity: sha512-EtNXYuWPUmkgSU2E7Ttn57LbRREQesIP1BiLn7OZLKodopKfDXfBUkC/0j6mpw2JExwf43Uf3qLSvrSvppgy8Q==}
2484 engines: {node: ^18.20.0 || ^20.10.0 || >=21.0.0}
2485 peerDependencies:
2486 eslint: '>=9.22.0'
@@ -2493,15 +2494,15 @@ packages:
2494 '@typescript-eslint/eslint-plugin':
2495 optional: true
2496
2496 - eslint-plugin-vue@10.0.0:
2497 - resolution: {integrity: sha512-XKckedtajqwmaX6u1VnECmZ6xJt+YvlmMzBPZd+/sI3ub2lpYZyFnsyWo7c3nMOQKJQudeyk1lw/JxdgeKT64w==}
2497 + eslint-plugin-vue@10.1.0:
2498 + resolution: {integrity: sha512-/VTiJ1eSfNLw6lvG9ENySbGmcVvz6wZ9nA7ZqXlLBY2RkaF15iViYKxglWiIch12KiLAj0j1iXPYU6W4wTROFA==}
2499 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2500 peerDependencies:
2501 eslint: ^8.57.0 || ^9.0.0
2502 vue-eslint-parser: ^10.0.0
2503
2503 - eslint-plugin-yml@1.17.0:
2504 - resolution: {integrity: sha512-Q3LXFRnNpGYAK/PM0BY1Xs0IY1xTLfM0kC986nNQkx1l8tOGz+YS50N6wXkAJkrBpeUN9OxEMB7QJ+9MTDAqIQ==}
2504 + eslint-plugin-yml@1.18.0:
2505 + resolution: {integrity: sha512-9NtbhHRN2NJa/s3uHchO3qVVZw0vyOIvWlXWGaKCr/6l3Go62wsvJK5byiI6ZoYztDsow4GnS69BZD3GnqH3hA==}
2506 engines: {node: ^14.17.0 || >=16.0.0}
2507 peerDependencies:
2508 eslint: '>=6.0.0'
@@ -2524,8 +2525,8 @@ packages:
2525 resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
2526 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2527
2527 - eslint@9.25.1:
2528 - resolution: {integrity: sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==}
2528 + eslint@9.27.0:
2529 + resolution: {integrity: sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==}
2530 engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2531 hasBin: true
2532 peerDependencies:
@@ -2586,8 +2587,8 @@ packages:
2587 resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
2588 engines: {node: '>=10'}
2589
2589 - execa@9.5.2:
2590 - resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==}
2590 + execa@9.6.0:
2591 + resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==}
2592 engines: {node: ^18.19.0 || >=20.5.0}
2593
2594 executable@4.1.1:
@@ -2602,8 +2603,8 @@ packages:
2603 resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
2604 engines: {node: '>=12.0.0'}
2605
2605 - exsolve@1.0.4:
2606 - resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==}
2606 + exsolve@1.0.5:
2607 + resolution: {integrity: sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==}
2608
2609 extend@3.0.2:
2610 resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@@ -2633,19 +2634,14 @@ packages:
2634 fastq@1.19.1:
2635 resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
2636
2637 + fault@2.0.1:
2638 + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
2639 +
2640 fd-slicer@1.1.0:
2641 resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
2642
2639 - fdir@6.4.3:
2640 - resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==}
2641 - peerDependencies:
2642 - picomatch: ^3 || ^4
2643 - peerDependenciesMeta:
2644 - picomatch:
2645 - optional: true
2646 -
2647 - fdir@6.4.4:
2648 - resolution: {integrity: sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==}
2643 + fdir@6.4.5:
2644 + resolution: {integrity: sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==}
2645 peerDependencies:
2646 picomatch: ^3 || ^4
2647 peerDependenciesMeta:
@@ -2714,6 +2710,13 @@ packages:
2710 resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==}
2711 engines: {node: '>= 6'}
2712
2713 + format@0.2.2:
2714 + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
2715 + engines: {node: '>=0.4.x'}
2716 +
2717 + framesync@6.1.2:
2718 + resolution: {integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==}
2719 +
2720 from@0.1.7:
2721 resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
2722
@@ -2764,8 +2767,8 @@ packages:
2767 resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
2768 engines: {node: '>=18'}
2769
2767 - get-tsconfig@4.10.0:
2768 - resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
2770 + get-tsconfig@4.10.1:
2771 + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
2772
2773 getos@3.2.1:
2774 resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==}
@@ -2813,12 +2816,8 @@ packages:
2816 resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==}
2817 engines: {node: '>=18'}
2818
2816 - globals@16.0.0:
2817 - resolution: {integrity: sha512-iInW14XItCXET01CQFqudPOWP2jYMl7T+QRQT+UNcR/iQncN/F0UNpgd76iFkBPgNQb4+X3LV9tLJYzwh+Gl3A==}
2818 - engines: {node: '>=18'}
2819 -
2820 - globby@14.1.0:
2821 - resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
2819 + globals@16.2.0:
2820 + resolution: {integrity: sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==}
2821 engines: {node: '>=18'}
2822
2823 gopd@1.2.0:
@@ -2857,6 +2856,9 @@ packages:
2856 resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
2857 hasBin: true
2858
2859 + hey-listen@1.0.8:
2860 + resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
2861 +
2862 highlight-words-core@1.2.3:
2863 resolution: {integrity: sha512-m1O9HW3/GNHxzSIXWw1wCNXXsgLlxrP0OI6+ycGUhiUHkikqW3OrwVHz+lxeNBe5yqLESdIcj8PowHQ2zLvUvQ==}
2864
@@ -2871,10 +2873,6 @@ packages:
2873 hookable@5.5.3:
2874 resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
2875
2874 - hosted-git-info@7.0.2:
2875 - resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
2876 - engines: {node: ^16.14.0 || >=18.0.0}
2877 -
2876 html-encoding-sniffer@4.0.0:
2877 resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
2878 engines: {node: '>=18'}
@@ -2920,12 +2918,12 @@ packages:
2918 resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
2919 engines: {node: '>= 4'}
2920
2923 - ignore@7.0.3:
2924 - resolution: {integrity: sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==}
2921 + ignore@7.0.4:
2922 + resolution: {integrity: sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==}
2923 engines: {node: '>= 4'}
2924
2927 - immutable@5.1.1:
2928 - resolution: {integrity: sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==}
2925 + immutable@5.1.2:
2926 + resolution: {integrity: sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==}
2927
2928 import-fresh@3.3.1:
2929 resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -2950,10 +2948,6 @@ packages:
2948 resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
2949 engines: {node: '>=12'}
2950
2953 - index-to-position@1.0.0:
2954 - resolution: {integrity: sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA==}
2955 - engines: {node: '>=18'}
2956 -
2951 ini@1.3.8:
2952 resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
2953
@@ -3073,8 +3067,8 @@ packages:
3067 joi@17.13.3:
3068 resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
3069
3076 - jose@6.0.10:
3077 - resolution: {integrity: sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw==}
3070 + jose@6.0.11:
3071 + resolution: {integrity: sha512-QxG7EaliDARm1O1S8BGakqncGT9s25bKL1WSf6/oa17Tkqwi8D2ZNglqCF+DsYF88/rV66Q/Q2mFAy697E1DUg==}
3072
3073 js-beautify@1.15.4:
3074 resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==}
@@ -3187,68 +3181,68 @@ packages:
3181 resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
3182 engines: {node: '>= 0.8.0'}
3183
3190 - lightningcss-darwin-arm64@1.29.2:
3191 - resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
3184 + lightningcss-darwin-arm64@1.30.1:
3185 + resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
3186 engines: {node: '>= 12.0.0'}
3187 cpu: [arm64]
3188 os: [darwin]
3189
3196 - lightningcss-darwin-x64@1.29.2:
3197 - resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==}
3190 + lightningcss-darwin-x64@1.30.1:
3191 + resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
3192 engines: {node: '>= 12.0.0'}
3193 cpu: [x64]
3194 os: [darwin]
3195
3202 - lightningcss-freebsd-x64@1.29.2:
3203 - resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==}
3196 + lightningcss-freebsd-x64@1.30.1:
3197 + resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
3198 engines: {node: '>= 12.0.0'}
3199 cpu: [x64]
3200 os: [freebsd]
3201
3208 - lightningcss-linux-arm-gnueabihf@1.29.2:
3209 - resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==}
3202 + lightningcss-linux-arm-gnueabihf@1.30.1:
3203 + resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
3204 engines: {node: '>= 12.0.0'}
3205 cpu: [arm]
3206 os: [linux]
3207
3214 - lightningcss-linux-arm64-gnu@1.29.2:
3215 - resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==}
3208 + lightningcss-linux-arm64-gnu@1.30.1:
3209 + resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
3210 engines: {node: '>= 12.0.0'}
3211 cpu: [arm64]
3212 os: [linux]
3213
3220 - lightningcss-linux-arm64-musl@1.29.2:
3221 - resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==}
3214 + lightningcss-linux-arm64-musl@1.30.1:
3215 + resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
3216 engines: {node: '>= 12.0.0'}
3217 cpu: [arm64]
3218 os: [linux]
3219
3226 - lightningcss-linux-x64-gnu@1.29.2:
3227 - resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==}
3220 + lightningcss-linux-x64-gnu@1.30.1:
3221 + resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
3222 engines: {node: '>= 12.0.0'}
3223 cpu: [x64]
3224 os: [linux]
3225
3232 - lightningcss-linux-x64-musl@1.29.2:
3233 - resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==}
3226 + lightningcss-linux-x64-musl@1.30.1:
3227 + resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
3228 engines: {node: '>= 12.0.0'}
3229 cpu: [x64]
3230 os: [linux]
3231
3238 - lightningcss-win32-arm64-msvc@1.29.2:
3239 - resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==}
3232 + lightningcss-win32-arm64-msvc@1.30.1:
3233 + resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
3234 engines: {node: '>= 12.0.0'}
3235 cpu: [arm64]
3236 os: [win32]
3237
3244 - lightningcss-win32-x64-msvc@1.29.2:
3245 - resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==}
3238 + lightningcss-win32-x64-msvc@1.30.1:
3239 + resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
3240 engines: {node: '>= 12.0.0'}
3241 cpu: [x64]
3242 os: [win32]
3243
3250 - lightningcss@1.29.2:
3251 - resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
3244 + lightningcss@1.30.1:
3245 + resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
3246 engines: {node: '>= 12.0.0'}
3247
3248 lines-and-columns@1.2.4:
@@ -3333,6 +3327,9 @@ packages:
3327 mdast-util-from-markdown@2.0.2:
3328 resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==}
3329
3330 + mdast-util-frontmatter@2.0.1:
3331 + resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==}
3332 +
3333 mdast-util-gfm-autolink-literal@2.0.1:
3334 resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
3335
@@ -3386,6 +3383,9 @@ packages:
3383 micromark-core-commonmark@2.0.3:
3384 resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
3385
3386 + micromark-extension-frontmatter@2.0.0:
3387 + resolution: {integrity: sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==}
3388 +
3389 micromark-extension-gfm-autolink-literal@2.1.0:
3390 resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
3391
@@ -3517,9 +3517,18 @@ packages:
3517 resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
3518 engines: {node: '>=16 || 14 >=14.17'}
3519
3520 + minizlib@3.0.2:
3521 + resolution: {integrity: sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==}
3522 + engines: {node: '>= 18'}
3523 +
3524 mitt@3.0.1:
3525 resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
3526
3527 + mkdirp@3.0.1:
3528 + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==}
3529 + engines: {node: '>=10'}
3530 + hasBin: true
3531 +
3532 mlly@1.7.4:
3533 resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
3534
@@ -3552,8 +3561,8 @@ packages:
3561 engines: {node: ^18 || >=20}
3562 hasBin: true
3563
3555 - napi-postinstall@0.1.5:
3556 - resolution: {integrity: sha512-HI5bHONOUYqV+FJvueOSgjRxHTLB25a3xIv59ugAxFe7xRNbW96hyYbMbsKzl+QvFV9mN/SrtHwiU+vYhMwA7Q==}
3564 + napi-postinstall@0.2.4:
3565 + resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==}
3566 engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
3567 hasBin: true
3568
@@ -3578,17 +3587,13 @@ packages:
3587 engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
3588 hasBin: true
3589
3581 - normalize-package-data@6.0.2:
3582 - resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==}
3583 - engines: {node: ^16.14.0 || >=18.0.0}
3584 -
3590 npm-normalize-package-bin@4.0.0:
3591 resolution: {integrity: sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==}
3592 engines: {node: ^18.17.0 || >=20.5.0}
3593
3589 - npm-run-all2@7.0.2:
3590 - resolution: {integrity: sha512-7tXR+r9hzRNOPNTvXegM+QzCuMjzUIIq66VDunL6j60O4RrExx32XUhlrS7UK4VcdGw5/Wxzb3kfNcFix9JKDA==}
3591 - engines: {node: ^18.17.0 || >=20.5.0, npm: '>= 9'}
3594 + npm-run-all2@8.0.4:
3595 + resolution: {integrity: sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==}
3596 + engines: {node: ^20.5.0 || >=22.0.0, npm: '>= 10'}
3597 hasBin: true
3598
3599 npm-run-path@4.0.1:
@@ -3631,14 +3636,14 @@ packages:
3636 resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
3637 engines: {node: '>=18'}
3638
3634 - oniguruma-parser@0.11.2:
3635 - resolution: {integrity: sha512-F7Ld4oDZJCI5/wCZ8AOffQbqjSzIRpKH7I/iuSs1SkhZeCj0wS6PMZ4W6VA16TWHrAo0Y9bBKEJOe7tvwcTXnw==}
3639 + oniguruma-parser@0.12.1:
3640 + resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
3641
3637 - oniguruma-to-es@4.2.0:
3638 - resolution: {integrity: sha512-MDPs6KSOLS0tKQ7joqg44dRIRZUyotfTy0r+7oEEs6VwWWP0+E2PPDYWMFN0aqOjRyWHBYq7RfKw9GQk2S2z5g==}
3642 + oniguruma-to-es@4.3.3:
3643 + resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==}
3644
3640 - open@10.1.0:
3641 - resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==}
3645 + open@10.1.2:
3646 + resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==}
3647 engines: {node: '>=18'}
3648
3649 open@8.4.2:
@@ -3667,11 +3672,8 @@ packages:
3672 package-json-from-dist@1.0.1:
3673 resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
3674
3670 - package-manager-detector@0.2.11:
3671 - resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==}
3672 -
3673 - package-manager-detector@1.1.0:
3674 - resolution: {integrity: sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==}
3675 + package-manager-detector@1.3.0:
3676 + resolution: {integrity: sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==}
3677
3678 parent-module@1.0.1:
3679 resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
@@ -3681,18 +3683,13 @@ packages:
3683 resolution: {integrity: sha512-RmVuCHWsfu0QPNW+mraxh/xjQVw/lhUCUru8Zni3Ctq3AoMhpDTq0OVdKS6iesd6Kqb7viCV3isAL43dciOSog==}
3684 engines: {node: '>=14'}
3685
3684 - parse-imports@2.2.1:
3685 - resolution: {integrity: sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==}
3686 - engines: {node: '>= 18'}
3686 + parse-imports-exports@0.2.4:
3687 + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==}
3688
3689 parse-json@5.2.0:
3690 resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
3691 engines: {node: '>=8'}
3692
3692 - parse-json@8.2.0:
3693 - resolution: {integrity: sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ==}
3694 - engines: {node: '>=18'}
3695 -
3693 parse-ms@4.0.0:
3694 resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==}
3695 engines: {node: '>=18'}
@@ -3701,8 +3698,11 @@ packages:
3698 resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
3699 engines: {node: '>=0.10.0'}
3700
3704 - parse5@7.2.1:
3705 - resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
3701 + parse-statements@1.0.11:
3702 + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==}
3703 +
3704 + parse5@7.3.0:
3705 + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
3706
3707 password-validator@5.3.0:
3708 resolution: {integrity: sha512-Q+bSEM5pjokZqzWGoQaoylkeWeH4+9uMYlVImiPD0EOJClQ2RPBhrJ5h0OjhMKtwOmu5rRcLaTZo5Gk9RBl0ig==}
@@ -3734,10 +3734,6 @@ packages:
3734 resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
3735 engines: {node: '>=8'}
3736
3737 - path-type@6.0.0:
3738 - resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==}
3739 - engines: {node: '>=18'}
3740 -
3737 pathe@2.0.3:
3738 resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
3739
@@ -3777,11 +3773,11 @@ packages:
3773 resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
3774 engines: {node: '>=0.10.0'}
3775
3780 - pinia-plugin-persistedstate@4.2.0:
3781 - resolution: {integrity: sha512-3buhA7ac+ssbOIx3VRCC8oHkoFwhDM9oHRCjo7nj+O8WUqnW+jRqh7eYT5eS/DNa3H28zp3dYf/nd/Vc8zj8eQ==}
3776 + pinia-plugin-persistedstate@4.3.0:
3777 + resolution: {integrity: sha512-x9wxpHj6iFDj5ITQJ3rj6+KesEqyRk/vqcE3WE+VGfetleV9Zufqwa9qJ6AkA5wmRSQEp7BTA1us/MDVTRHFFw==}
3778 peerDependencies:
3783 - '@pinia/nuxt': '>=0.9.0'
3784 - pinia: '>=2.3.0'
3779 + '@pinia/nuxt': '>=0.10.0'
3780 + pinia: '>=3.0.0'
3781 peerDependenciesMeta:
3782 '@pinia/nuxt':
3783 optional: true
@@ -3813,6 +3809,9 @@ packages:
3809 pnpm-workspace-yaml@0.3.1:
3810 resolution: {integrity: sha512-3nW5RLmREmZ8Pm8MbPsO2RM+99RRjYd25ynj3NV0cFsN7CcEl4sDFzgoFmSyduFwxFQ2Qbu3y2UdCh6HlyUOeA==}
3811
3812 + popmotion@11.0.5:
3813 + resolution: {integrity: sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==}
3814 +
3815 postcss-selector-parser@6.1.2:
3816 resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
3817 engines: {node: '>=4'}
@@ -3897,8 +3896,8 @@ packages:
3896 resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
3897 engines: {node: '>= 0.6.0'}
3898
3900 - property-information@7.0.0:
3901 - resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==}
3899 + property-information@7.1.0:
3900 + resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
3901
3902 proto-list@1.2.4:
3903 resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
@@ -3942,14 +3941,6 @@ packages:
3941 resolution: {integrity: sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==}
3942 engines: {node: ^18.17.0 || >=20.5.0}
3943
3945 - read-package-up@11.0.0:
3946 - resolution: {integrity: sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==}
3947 - engines: {node: '>=18'}
3948 -
3949 - read-pkg@9.0.1:
3950 - resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==}
3951 - engines: {node: '>=18'}
3952 -
3944 readdirp@3.6.0:
3945 resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
3946 engines: {node: '>=8.10.0'}
@@ -4041,8 +4032,8 @@ packages:
4032 rollup:
4033 optional: true
4034
4044 - rollup@4.39.0:
4045 - resolution: {integrity: sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==}
4035 + rollup@4.41.1:
4036 + resolution: {integrity: sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==}
4037 engines: {node: '>=18.0.0', npm: '>=8.0.0'}
4038 hasBin: true
4039
@@ -4065,8 +4056,8 @@ packages:
4056 safer-buffer@2.1.2:
4057 resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
4058
4068 - sass@1.87.0:
4069 - resolution: {integrity: sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==}
4059 + sass@1.89.0:
4060 + resolution: {integrity: sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==}
4061 engines: {node: '>=14.0.0'}
4062 hasBin: true
4063
@@ -4095,8 +4086,8 @@ packages:
4086 resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
4087 hasBin: true
4088
4098 - semver@7.7.1:
4099 - resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
4089 + semver@7.7.2:
4090 + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
4091 engines: {node: '>=10'}
4092 hasBin: true
4093
@@ -4112,8 +4103,8 @@ packages:
4103 resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==}
4104 engines: {node: '>= 0.4'}
4105
4115 - shiki@3.3.0:
4116 - resolution: {integrity: sha512-j0Z1tG5vlOFGW8JVj0Cpuatzvshes7VJy5ncDmmMaYcmnGW0Js1N81TOW98ivTFNZfKRn9uwEg/aIm638o368g==}
4106 + shiki@3.4.2:
4107 + resolution: {integrity: sha512-wuxzZzQG8kvZndD7nustrNFIKYJ1jJoWIPaBpVe2+KHSvtzMi4SBjOxrigs8qeqce/l3U0cwiC+VAkLKSunHQQ==}
4108
4109 side-channel-list@1.0.0:
4110 resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
@@ -4148,13 +4139,6 @@ packages:
4139 sisteransi@1.0.5:
4140 resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
4141
4151 - slash@5.1.0:
4152 - resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
4153 - engines: {node: '>=14.16'}
4154 -
4155 - slashes@3.0.12:
4156 - resolution: {integrity: sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==}
4157 -
4142 slice-ansi@3.0.0:
4143 resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
4144 engines: {node: '>=8'}
@@ -4177,15 +4161,9 @@ packages:
4161 space-separated-tokens@2.0.2:
4162 resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
4163
4180 - spdx-correct@3.2.0:
4181 - resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
4182 -
4164 spdx-exceptions@2.5.0:
4165 resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
4166
4186 - spdx-expression-parse@3.0.1:
4187 - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
4188 -
4167 spdx-expression-parse@4.0.0:
4168 resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==}
4169
@@ -4213,14 +4191,11 @@ packages:
4191 stackback@0.0.2:
4192 resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
4193
4216 - start-server-and-test@2.0.11:
4217 - resolution: {integrity: sha512-TN39gLzPhHAflxyOkE/oMfQGj+pj3JgF6qVicFH/JrXt7xXktidKXwqfRga+ve7lVA8+RgPZVc25VrEPRScaDw==}
4194 + start-server-and-test@2.0.12:
4195 + resolution: {integrity: sha512-U6QiS5qsz+DN5RfJJrkAXdooxMDnLZ+n5nR8kaX//ZH19SilF6b58Z3zM9zTfrNIkJepzauHo4RceSgvgUSX9w==}
4196 engines: {node: '>=16'}
4197 hasBin: true
4198
4221 - std-env@3.8.1:
4222 - resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==}
4223 -
4199 std-env@3.9.0:
4200 resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
4201
@@ -4268,6 +4243,9 @@ packages:
4243 style-mod@4.1.2:
4244 resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
4245
4246 + style-value-types@5.1.2:
4247 + resolution: {integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==}
4248 +
4249 superjson@2.2.2:
4250 resolution: {integrity: sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==}
4251 engines: {node: '>=16'}
@@ -4292,23 +4270,23 @@ packages:
4270 symbol-tree@3.2.4:
4271 resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
4272
4295 - synckit@0.10.3:
4296 - resolution: {integrity: sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==}
4297 - engines: {node: ^14.18.0 || >=16.0.0}
4298 -
4299 - synckit@0.9.2:
4300 - resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==}
4273 + synckit@0.11.6:
4274 + resolution: {integrity: sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==}
4275 engines: {node: ^14.18.0 || >=16.0.0}
4276
4303 - tailwindcss@4.1.4:
4304 - resolution: {integrity: sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==}
4277 + tailwindcss@4.1.8:
4278 + resolution: {integrity: sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og==}
4279
4306 - tapable@2.2.1:
4307 - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
4280 + tapable@2.2.2:
4281 + resolution: {integrity: sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==}
4282 engines: {node: '>=6'}
4283
4310 - taze@19.0.4:
4311 - resolution: {integrity: sha512-bviyNotzqcIWpVBCC4QYVb2yupzKyUDGQi2m/8GERdiPaudVMtgAqaE98+x0cDDaByYRMJCyhQWM04ikUL6+kQ==}
4284 + tar@7.4.3:
4285 + resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
4286 + engines: {node: '>=18'}
4287 +
4288 + taze@19.1.0:
4289 + resolution: {integrity: sha512-MDN2WZb7TgsIvtFxqsLJ4GYy9dTDG5Dea/ZfPHrG98Cy7UH1EFIOzH+zDjnoP38ImuBbxZy1Zl8AbiwOZpYMUQ==}
4290 hasBin: true
4291
4292 thememirror@2.0.1:
@@ -4333,12 +4311,8 @@ packages:
4311 tinyexec@1.0.1:
4312 resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==}
4313
4336 - tinyglobby@0.2.12:
4337 - resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==}
4338 - engines: {node: '>=12.0.0'}
4339 -
4340 - tinyglobby@0.2.13:
4341 - resolution: {integrity: sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==}
4314 + tinyglobby@0.2.14:
4315 + resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==}
4316 engines: {node: '>=12.0.0'}
4317
4318 tinypool@1.0.2:
@@ -4353,11 +4327,11 @@ packages:
4327 resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
4328 engines: {node: '>=14.0.0'}
4329
4356 - tldts-core@6.1.85:
4357 - resolution: {integrity: sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==}
4330 + tldts-core@6.1.86:
4331 + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==}
4332
4359 - tldts@6.1.85:
4360 - resolution: {integrity: sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==}
4333 + tldts@6.1.86:
4334 + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==}
4335 hasBin: true
4336
4337 tmp@0.2.3:
@@ -4380,8 +4354,8 @@ packages:
4354 resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==}
4355 engines: {node: '>=16'}
4356
4383 - tr46@5.1.0:
4384 - resolution: {integrity: sha512-IUWnUK7ADYR5Sl1fZlO1INDUhVhatWl7BtJWsIhwJ0UAK7ilzzIa8uIqOO/aYVWHZPJkKbEL+362wrzoeRF7bw==}
4357 + tr46@5.1.1:
4358 + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
4359 engines: {node: '>=18'}
4360
4361 tree-kill@1.2.2:
@@ -4403,6 +4377,9 @@ packages:
4377 tslib@2.3.0:
4378 resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
4379
4380 + tslib@2.4.0:
4381 + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
4382 +
4383 tslib@2.8.1:
4384 resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
4385
@@ -4420,8 +4397,8 @@ packages:
4397 resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
4398 engines: {node: '>=10'}
4399
4423 - type-fest@4.40.0:
4424 - resolution: {integrity: sha512-ABHZ2/tS2JkvH1PEjxFDTUWC8dB5OsIGZP4IFLhR293GqT5Y5qB1WwL2kMPYhQW9DVgVD8Hd7I8gjwPIf5GFkw==}
4400 + type-fest@4.41.0:
4401 + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
4402 engines: {node: '>=16'}
4403
4404 typescript@5.8.3:
@@ -4432,11 +4409,11 @@ packages:
4409 uc.micro@2.1.0:
4410 resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
4411
4435 - ufo@1.5.4:
4436 - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
4412 + ufo@1.6.1:
4413 + resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
4414
4438 - unconfig@7.3.1:
4439 - resolution: {integrity: sha512-LH5WL+un92tGAzWS87k7LkAfwpMdm7V0IXG2FxEjZz/QxiIW5J5LkcrKQThj0aRz6+h/lFmKI9EUXmK/T0bcrw==}
4415 + unconfig@7.3.2:
4416 + resolution: {integrity: sha512-nqG5NNL2wFVGZ0NA/aCFw0oJ2pxSf1lwg4Z5ill8wd7K4KX/rQbHlwbh+bjctXL5Ly1xtzHenHGOK0b+lG6JVg==}
4417
4418 unctx@2.4.1:
4419 resolution: {integrity: sha512-AbaYw0Nm4mK4qjhns67C+kgxR2YWiwlDBPzxrN8h8C6VtAdCgditAY5Dezu3IJy4XVqAnbrXt9oQJvsn3fyozg==}
@@ -4444,16 +4421,12 @@ packages:
4421 undici-types@6.21.0:
4422 resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
4423
4447 - unicorn-magic@0.1.0:
4448 - resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
4449 - engines: {node: '>=18'}
4450 -
4424 unicorn-magic@0.3.0:
4425 resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==}
4426 engines: {node: '>=18'}
4427
4455 - unimport@4.1.3:
4456 - resolution: {integrity: sha512-H+IVJ7rAkE3b+oC8rSJ2FsPaVsweeMC8eKZc+C6Mz7+hxDF45AnrY/tVCNRBvzMwWNcJEV67WdAVcal27iMjOw==}
4428 + unimport@5.0.1:
4429 + resolution: {integrity: sha512-1YWzPj6wYhtwHE+9LxRlyqP4DiRrhGfJxdtH475im8ktyZXO3jHj/3PZ97zDdvkYoovFdi0K4SKl3a7l92v3sQ==}
4430 engines: {node: '>=18.12.0'}
4431
4432 unist-util-is@6.0.0:
@@ -4479,12 +4452,12 @@ packages:
4452 resolution: {integrity: sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA==}
4453 engines: {node: '>=18.12.0'}
4454
4482 - unplugin@2.2.2:
4483 - resolution: {integrity: sha512-Qp+iiD+qCRnUek+nDoYvtWX7tfnYyXsrOnJ452FRTgOyKmTM7TUJ3l+PLPJOOWPTUyKISKp4isC5JJPSXUjGgw==}
4455 + unplugin@2.3.5:
4456 + resolution: {integrity: sha512-RyWSb5AHmGtjjNQ6gIlA67sHOsWpsbWpwDokLwTcejVdOjEkJZh7QKu14J00gDDVSh8kGH4KYC/TNBceXFZhtw==}
4457 engines: {node: '>=18.12.0'}
4458
4486 - unrs-resolver@1.6.3:
4487 - resolution: {integrity: sha512-mYNIMmxlDcaepmUTNrBu2tEB/bRkLBUeAhke8XOnXYqSu/9dUk4cdFiJG1N4d5Q7Fii+9MpgavkxJpnXPqNhHw==}
4459 + unrs-resolver@1.7.5:
4460 + resolution: {integrity: sha512-DnuJxogme0dCRIdH+yIwpaNLWfff9DqcpfDh4J8qca17rOnu6e3AfNzB8mnUzjv7EgayXQkwnt1A2vT8BM9ZHA==}
4461
4462 untildify@4.0.0:
4463 resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==}
@@ -4510,11 +4483,8 @@ packages:
4483 resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
4484 hasBin: true
4485
4513 - validate-npm-package-license@3.0.4:
4514 - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
4515 -
4516 - validator@13.15.0:
4517 - resolution: {integrity: sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==}
4486 + validator@13.15.15:
4487 + resolution: {integrity: sha512-BgWVbCI72aIQy937xbawcs+hrVaN/CZ2UwutgaJ36hGqRrLNM+f5LUT/YPRbo8IV/ASeFzXszezV+y2+rq3l8A==}
4488 engines: {node: '>= 0.10'}
4489
4490 vdirs@0.1.8:
@@ -4542,8 +4512,8 @@ packages:
4512 peerDependencies:
4513 vite: ^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0
4514
4545 - vite-node@3.1.2:
4546 - resolution: {integrity: sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==}
4515 + vite-node@3.1.4:
4516 + resolution: {integrity: sha512-6enNwYnpyDo4hEgytbmc6mYWHXDHYEn0D1/rw4Q+tnHUGtKTJsn8T1YkX6Q18wI5LCrS8CTYlBaiCqxOy2kvUA==}
4517 engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
4518 hasBin: true
4519
@@ -4557,8 +4527,8 @@ packages:
4527 '@nuxt/kit':
4528 optional: true
4529
4560 - vite-plugin-vue-devtools@7.7.5:
4561 - resolution: {integrity: sha512-cSlQYI1E+8d0qubBg70suTBbXMFbTHLn7vLPYUPK9GjNNJ0nw+Yks0ZLOAp7/+PjmqSpN5fK1taor6HeAjKb1g==}
4530 + vite-plugin-vue-devtools@7.7.6:
4531 + resolution: {integrity: sha512-L7nPVM5a7lgit/Z+36iwoqHOaP3wxqVi1UvaDJwGCfblS9Y6vNqf32ILlzJVH9c47aHu90BhDXeZc+rgzHRHcw==}
4532 engines: {node: '>=v14.21.3'}
4533 peerDependencies:
4534 vite: ^3.1.0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0
@@ -4573,8 +4543,8 @@ packages:
4543 peerDependencies:
4544 vue: '>=3.2.13'
4545
4576 - vite@6.3.3:
4577 - resolution: {integrity: sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==}
4546 + vite@6.3.5:
4547 + resolution: {integrity: sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==}
4548 engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
4549 hasBin: true
4550 peerDependencies:
@@ -4613,16 +4583,16 @@ packages:
4583 yaml:
4584 optional: true
4585
4616 - vitest@3.1.2:
4617 - resolution: {integrity: sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==}
4586 + vitest@3.1.4:
4587 + resolution: {integrity: sha512-Ta56rT7uWxCSJXlBtKgIlApJnT6e6IGmTYxYcmxjJ4ujuZDI59GUQgVDObXXJujOmPDBYXHK1qmaGtneu6TNIQ==}
4588 engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
4589 hasBin: true
4590 peerDependencies:
4591 '@edge-runtime/vm': '*'
4592 '@types/debug': ^4.1.12
4593 '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
4624 - '@vitest/browser': 3.1.2
4625 - '@vitest/ui': 3.1.2
4594 + '@vitest/browser': 3.1.4
4595 + '@vitest/ui': 3.1.4
4596 happy-dom: '*'
4597 jsdom: '*'
4598 peerDependenciesMeta:
@@ -4661,8 +4631,8 @@ packages:
4631 codemirror: 6.x
4632 vue: 3.x
4633
4664 - vue-component-type-helpers@2.2.8:
4665 - resolution: {integrity: sha512-4bjIsC284coDO9om4HPA62M7wfsTvcmZyzdfR0aUlFXqq4tXxM1APyXpNVxPC8QazKw9OhmZNHBVDA6ODaZsrA==}
4634 + vue-component-type-helpers@2.2.10:
4635 + resolution: {integrity: sha512-iDUO7uQK+Sab2tYuiP9D1oLujCWlhHELHMgV/cB13cuGbG4qwkLHvtfWb6FzvxrIOPDnU0oHsz2MlQjhYDeaHA==}
4636
4637 vue-eslint-parser@10.1.3:
4638 resolution: {integrity: sha512-dbCBnd2e02dYWsXoqX5yKUZlOt+ExIpq7hmHKPb5ZqKcjf++Eo0hMseFTZMLKThrUk61m+Uv6A2YSBve6ZvuDQ==}
@@ -4675,8 +4645,8 @@ packages:
4645 peerDependencies:
4646 vue: ^3.0.0
4647
4678 - vue-i18n@11.1.3:
4679 - resolution: {integrity: sha512-Pcylh9z9S5+CJAqgbRZ3EKxFIBIrtY5YUppU722GIT65+Nukm0TCqiQegZnNLCZkXGthxe0cpqj0AoM51H+6Gw==}
4648 + vue-i18n@11.1.5:
4649 + resolution: {integrity: sha512-XCwuaEA5AF97g1frvH/EI1zI9uo1XKTf2/OCFgts7NvUWRsjlgeHPrkJV+a3gpzai2pC4quZ4AnOHFO8QK9hsg==}
4650 engines: {node: '>= 16'}
4651 peerDependencies:
4652 vue: ^3.0.0
@@ -4709,8 +4679,8 @@ packages:
4679 peerDependencies:
4680 vue: ^3.2
4681
4712 - vue@3.5.13:
4713 - resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==}
4682 + vue@3.5.15:
4683 + resolution: {integrity: sha512-aD9zK4rB43JAMK/5BmS4LdPiEp8Fdh8P1Ve/XNuMF5YRf78fCyPE6FUbQwcaWQ5oZ1R2CD9NKE0FFOVpMR7gEQ==}
4684 peerDependencies:
4685 typescript: '*'
4686 peerDependenciesMeta:
@@ -4796,8 +4766,8 @@ packages:
4766 wrappy@1.0.2:
4767 resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
4768
4799 - ws@8.18.1:
4800 - resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==}
4769 + ws@8.18.2:
4770 + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
4771 engines: {node: '>=10.0.0'}
4772 peerDependencies:
4773 bufferutil: ^4.0.1
@@ -4826,6 +4796,10 @@ packages:
4796 yallist@3.1.1:
4797 resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
4798
4799 + yallist@5.0.0:
4800 + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
4801 + engines: {node: '>=18'}
4802 +
4803 yaml-eslint-parser@1.3.0:
4804 resolution: {integrity: sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA==}
4805 engines: {node: ^14.17.0 || >=16.0.0}
@@ -4834,9 +4808,9 @@ packages:
4808 resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
4809 engines: {node: '>= 6'}
4810
4837 - yaml@2.7.1:
4838 - resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
4839 - engines: {node: '>= 14'}
4811 + yaml@2.8.0:
4812 + resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
4813 + engines: {node: '>= 14.6'}
4814 hasBin: true
4815
4816 yargs-parser@20.2.9:
@@ -4883,312 +4857,322 @@ snapshots:
4857 '@jridgewell/gen-mapping': 0.3.8
4858 '@jridgewell/trace-mapping': 0.3.25
4859
4886 - '@antfu/eslint-config@4.12.0(@typescript-eslint/utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(@vue/compiler-sfc@3.5.13)(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))':
4860 + '@antfu/eslint-config@4.13.2(@vue/compiler-sfc@3.5.15)(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))':
4861 dependencies:
4888 - '@antfu/install-pkg': 1.0.0
4862 + '@antfu/install-pkg': 1.1.0
4863 '@clack/prompts': 0.10.1
4890 - '@eslint-community/eslint-plugin-eslint-comments': 4.4.1(eslint@9.25.1(jiti@2.4.2))
4891 - '@eslint/markdown': 6.3.0
4892 - '@stylistic/eslint-plugin': 4.2.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
4893 - '@typescript-eslint/eslint-plugin': 8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
4894 - '@typescript-eslint/parser': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
4895 - '@vitest/eslint-plugin': 1.1.43(@typescript-eslint/utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))
4896 - ansis: 3.17.0
4864 + '@eslint-community/eslint-plugin-eslint-comments': 4.5.0(eslint@9.27.0(jiti@2.4.2))
4865 + '@eslint/markdown': 6.4.0
4866 + '@stylistic/eslint-plugin': 4.4.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
4867 + '@typescript-eslint/eslint-plugin': 8.33.0(@typescript-eslint/parser@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
4868 + '@typescript-eslint/parser': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
4869 + '@vitest/eslint-plugin': 1.2.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))
4870 + ansis: 4.0.0
4871 cac: 6.7.14
4898 - eslint: 9.25.1(jiti@2.4.2)
4899 - eslint-config-flat-gitignore: 2.1.0(eslint@9.25.1(jiti@2.4.2))
4900 - eslint-flat-config-utils: 2.0.1
4901 - eslint-merge-processors: 2.0.0(eslint@9.25.1(jiti@2.4.2))
4902 - eslint-plugin-antfu: 3.1.1(eslint@9.25.1(jiti@2.4.2))
4903 - eslint-plugin-command: 3.2.0(eslint@9.25.1(jiti@2.4.2))
4904 - eslint-plugin-import-x: 4.10.6(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
4905 - eslint-plugin-jsdoc: 50.6.9(eslint@9.25.1(jiti@2.4.2))
4906 - eslint-plugin-jsonc: 2.20.0(eslint@9.25.1(jiti@2.4.2))
4907 - eslint-plugin-n: 17.17.0(eslint@9.25.1(jiti@2.4.2))
4872 + eslint: 9.27.0(jiti@2.4.2)
4873 + eslint-config-flat-gitignore: 2.1.0(eslint@9.27.0(jiti@2.4.2))
4874 + eslint-flat-config-utils: 2.1.0
4875 + eslint-merge-processors: 2.0.0(eslint@9.27.0(jiti@2.4.2))
4876 + eslint-plugin-antfu: 3.1.1(eslint@9.27.0(jiti@2.4.2))
4877 + eslint-plugin-command: 3.2.1(eslint@9.27.0(jiti@2.4.2))
4878 + eslint-plugin-import-x: 4.13.3(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
4879 + eslint-plugin-jsdoc: 50.6.17(eslint@9.27.0(jiti@2.4.2))
4880 + eslint-plugin-jsonc: 2.20.1(eslint@9.27.0(jiti@2.4.2))
4881 + eslint-plugin-n: 17.18.0(eslint@9.27.0(jiti@2.4.2))
4882 eslint-plugin-no-only-tests: 3.3.0
4909 - eslint-plugin-perfectionist: 4.11.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
4910 - eslint-plugin-pnpm: 0.3.1(eslint@9.25.1(jiti@2.4.2))
4911 - eslint-plugin-regexp: 2.7.0(eslint@9.25.1(jiti@2.4.2))
4912 - eslint-plugin-toml: 0.12.0(eslint@9.25.1(jiti@2.4.2))
4913 - eslint-plugin-unicorn: 58.0.0(eslint@9.25.1(jiti@2.4.2))
4914 - eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))
4915 - eslint-plugin-vue: 10.0.0(eslint@9.25.1(jiti@2.4.2))(vue-eslint-parser@10.1.3(eslint@9.25.1(jiti@2.4.2)))
4916 - eslint-plugin-yml: 1.17.0(eslint@9.25.1(jiti@2.4.2))
4917 - eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.13)(eslint@9.25.1(jiti@2.4.2))
4918 - globals: 16.0.0
4883 + eslint-plugin-perfectionist: 4.13.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
4884 + eslint-plugin-pnpm: 0.3.1(eslint@9.27.0(jiti@2.4.2))
4885 + eslint-plugin-regexp: 2.7.0(eslint@9.27.0(jiti@2.4.2))
4886 + eslint-plugin-toml: 0.12.0(eslint@9.27.0(jiti@2.4.2))
4887 + eslint-plugin-unicorn: 59.0.1(eslint@9.27.0(jiti@2.4.2))
4888 + eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.33.0(@typescript-eslint/parser@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))
4889 + eslint-plugin-vue: 10.1.0(eslint@9.27.0(jiti@2.4.2))(vue-eslint-parser@10.1.3(eslint@9.27.0(jiti@2.4.2)))
4890 + eslint-plugin-yml: 1.18.0(eslint@9.27.0(jiti@2.4.2))
4891 + eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.15)(eslint@9.27.0(jiti@2.4.2))
4892 + globals: 16.2.0
4893 jsonc-eslint-parser: 2.4.0
4894 local-pkg: 1.1.1
4895 parse-gitignore: 2.0.0
4896 toml-eslint-parser: 0.10.0
4923 - vue-eslint-parser: 10.1.3(eslint@9.25.1(jiti@2.4.2))
4897 + vue-eslint-parser: 10.1.3(eslint@9.27.0(jiti@2.4.2))
4898 yaml-eslint-parser: 1.3.0
4899 transitivePeerDependencies:
4900 - '@eslint/json'
4927 - - '@typescript-eslint/utils'
4901 - '@vue/compiler-sfc'
4902 - supports-color
4903 - typescript
4904 - vitest
4905
4933 - '@antfu/install-pkg@1.0.0':
4906 + '@antfu/install-pkg@1.1.0':
4907 dependencies:
4935 - package-manager-detector: 0.2.11
4936 - tinyexec: 0.3.2
4908 + package-manager-detector: 1.3.0
4909 + tinyexec: 1.0.1
4910
4938 - '@antfu/ni@24.3.0':
4911 + '@antfu/ni@24.4.0':
4912 dependencies:
4940 - ansis: 3.17.0
4913 + ansis: 4.0.0
4914 fzf: 0.5.2
4942 - package-manager-detector: 1.1.0
4915 + package-manager-detector: 1.3.0
4916 tinyexec: 1.0.1
4917
4918 '@antfu/utils@0.7.10': {}
4919
4947 - '@asamuzakjp/css-color@3.1.1':
4920 + '@asamuzakjp/css-color@3.2.0':
4921 dependencies:
4949 - '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
4950 - '@csstools/css-color-parser': 3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
4951 - '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
4952 - '@csstools/css-tokenizer': 3.0.3
4922 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
4923 + '@csstools/css-color-parser': 3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
4924 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
4925 + '@csstools/css-tokenizer': 3.0.4
4926 lru-cache: 10.4.3
4927
4955 - '@babel/code-frame@7.26.2':
4928 + '@babel/code-frame@7.27.1':
4929 dependencies:
4957 - '@babel/helper-validator-identifier': 7.25.9
4930 + '@babel/helper-validator-identifier': 7.27.1
4931 js-tokens: 4.0.0
4932 picocolors: 1.1.1
4933
4961 - '@babel/compat-data@7.26.8': {}
4934 + '@babel/compat-data@7.27.3': {}
4935
4963 - '@babel/core@7.26.10':
4936 + '@babel/core@7.27.3':
4937 dependencies:
4938 '@ampproject/remapping': 2.3.0
4966 - '@babel/code-frame': 7.26.2
4967 - '@babel/generator': 7.27.0
4968 - '@babel/helper-compilation-targets': 7.27.0
4969 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10)
4970 - '@babel/helpers': 7.27.0
4971 - '@babel/parser': 7.27.0
4972 - '@babel/template': 7.27.0
4973 - '@babel/traverse': 7.27.0
4974 - '@babel/types': 7.27.0
4939 + '@babel/code-frame': 7.27.1
4940 + '@babel/generator': 7.27.3
4941 + '@babel/helper-compilation-targets': 7.27.2
4942 + '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.3)
4943 + '@babel/helpers': 7.27.3
4944 + '@babel/parser': 7.27.3
4945 + '@babel/template': 7.27.2
4946 + '@babel/traverse': 7.27.3
4947 + '@babel/types': 7.27.3
4948 convert-source-map: 2.0.0
4976 - debug: 4.4.0(supports-color@8.1.1)
4949 + debug: 4.4.1(supports-color@8.1.1)
4950 gensync: 1.0.0-beta.2
4951 json5: 2.2.3
4952 semver: 6.3.1
4953 transitivePeerDependencies:
4954 - supports-color
4955
4983 - '@babel/generator@7.27.0':
4956 + '@babel/generator@7.27.3':
4957 dependencies:
4985 - '@babel/parser': 7.27.0
4986 - '@babel/types': 7.27.0
4958 + '@babel/parser': 7.27.3
4959 + '@babel/types': 7.27.3
4960 '@jridgewell/gen-mapping': 0.3.8
4961 '@jridgewell/trace-mapping': 0.3.25
4962 jsesc: 3.1.0
4963
4991 - '@babel/helper-annotate-as-pure@7.25.9':
4964 + '@babel/helper-annotate-as-pure@7.27.3':
4965 dependencies:
4993 - '@babel/types': 7.27.0
4966 + '@babel/types': 7.27.3
4967
4995 - '@babel/helper-compilation-targets@7.27.0':
4968 + '@babel/helper-compilation-targets@7.27.2':
4969 dependencies:
4997 - '@babel/compat-data': 7.26.8
4998 - '@babel/helper-validator-option': 7.25.9
4999 - browserslist: 4.24.4
4970 + '@babel/compat-data': 7.27.3
4971 + '@babel/helper-validator-option': 7.27.1
4972 + browserslist: 4.24.5
4973 lru-cache: 5.1.1
4974 semver: 6.3.1
4975
5003 - '@babel/helper-create-class-features-plugin@7.27.0(@babel/core@7.26.10)':
4976 + '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.27.3)':
4977 dependencies:
5005 - '@babel/core': 7.26.10
5006 - '@babel/helper-annotate-as-pure': 7.25.9
5007 - '@babel/helper-member-expression-to-functions': 7.25.9
5008 - '@babel/helper-optimise-call-expression': 7.25.9
5009 - '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.10)
5010 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
5011 - '@babel/traverse': 7.27.0
4978 + '@babel/core': 7.27.3
4979 + '@babel/helper-annotate-as-pure': 7.27.3
4980 + '@babel/helper-member-expression-to-functions': 7.27.1
4981 + '@babel/helper-optimise-call-expression': 7.27.1
4982 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.27.3)
4983 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
4984 + '@babel/traverse': 7.27.3
4985 semver: 6.3.1
4986 transitivePeerDependencies:
4987 - supports-color
4988
5016 - '@babel/helper-member-expression-to-functions@7.25.9':
4989 + '@babel/helper-member-expression-to-functions@7.27.1':
4990 dependencies:
5018 - '@babel/traverse': 7.27.0
5019 - '@babel/types': 7.27.0
4991 + '@babel/traverse': 7.27.3
4992 + '@babel/types': 7.27.3
4993 transitivePeerDependencies:
4994 - supports-color
4995
5023 - '@babel/helper-module-imports@7.25.9':
4996 + '@babel/helper-module-imports@7.27.1':
4997 dependencies:
5025 - '@babel/traverse': 7.27.0
5026 - '@babel/types': 7.27.0
4998 + '@babel/traverse': 7.27.3
4999 + '@babel/types': 7.27.3
5000 transitivePeerDependencies:
5001 - supports-color
5002
5030 - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)':
5003 + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.3)':
5004 dependencies:
5032 - '@babel/core': 7.26.10
5033 - '@babel/helper-module-imports': 7.25.9
5034 - '@babel/helper-validator-identifier': 7.25.9
5035 - '@babel/traverse': 7.27.0
5005 + '@babel/core': 7.27.3
5006 + '@babel/helper-module-imports': 7.27.1
5007 + '@babel/helper-validator-identifier': 7.27.1
5008 + '@babel/traverse': 7.27.3
5009 transitivePeerDependencies:
5010 - supports-color
5011
5039 - '@babel/helper-optimise-call-expression@7.25.9':
5012 + '@babel/helper-optimise-call-expression@7.27.1':
5013 dependencies:
5041 - '@babel/types': 7.27.0
5014 + '@babel/types': 7.27.3
5015
5043 - '@babel/helper-plugin-utils@7.26.5': {}
5016 + '@babel/helper-plugin-utils@7.27.1': {}
5017
5045 - '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.10)':
5018 + '@babel/helper-replace-supers@7.27.1(@babel/core@7.27.3)':
5019 dependencies:
5047 - '@babel/core': 7.26.10
5048 - '@babel/helper-member-expression-to-functions': 7.25.9
5049 - '@babel/helper-optimise-call-expression': 7.25.9
5050 - '@babel/traverse': 7.27.0
5020 + '@babel/core': 7.27.3
5021 + '@babel/helper-member-expression-to-functions': 7.27.1
5022 + '@babel/helper-optimise-call-expression': 7.27.1
5023 + '@babel/traverse': 7.27.3
5024 transitivePeerDependencies:
5025 - supports-color
5026
5054 - '@babel/helper-skip-transparent-expression-wrappers@7.25.9':
5027 + '@babel/helper-skip-transparent-expression-wrappers@7.27.1':
5028 dependencies:
5056 - '@babel/traverse': 7.27.0
5057 - '@babel/types': 7.27.0
5029 + '@babel/traverse': 7.27.3
5030 + '@babel/types': 7.27.3
5031 transitivePeerDependencies:
5032 - supports-color
5033
5061 - '@babel/helper-string-parser@7.25.9': {}
5034 + '@babel/helper-string-parser@7.27.1': {}
5035
5063 - '@babel/helper-validator-identifier@7.25.9': {}
5036 + '@babel/helper-validator-identifier@7.27.1': {}
5037
5065 - '@babel/helper-validator-option@7.25.9': {}
5038 + '@babel/helper-validator-option@7.27.1': {}
5039
5067 - '@babel/helpers@7.27.0':
5040 + '@babel/helpers@7.27.3':
5041 dependencies:
5069 - '@babel/template': 7.27.0
5070 - '@babel/types': 7.27.0
5042 + '@babel/template': 7.27.2
5043 + '@babel/types': 7.27.3
5044
5072 - '@babel/parser@7.27.0':
5045 + '@babel/parser@7.27.3':
5046 dependencies:
5074 - '@babel/types': 7.27.0
5047 + '@babel/types': 7.27.3
5048
5076 - '@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.10)':
5049 + '@babel/plugin-proposal-decorators@7.27.1(@babel/core@7.27.3)':
5050 dependencies:
5078 - '@babel/core': 7.26.10
5079 - '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10)
5080 - '@babel/helper-plugin-utils': 7.26.5
5081 - '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.10)
5051 + '@babel/core': 7.27.3
5052 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.3)
5053 + '@babel/helper-plugin-utils': 7.27.1
5054 + '@babel/plugin-syntax-decorators': 7.27.1(@babel/core@7.27.3)
5055 transitivePeerDependencies:
5056 - supports-color
5057
5085 - '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.10)':
5058 + '@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.27.3)':
5059 dependencies:
5087 - '@babel/core': 7.26.10
5088 - '@babel/helper-plugin-utils': 7.26.5
5060 + '@babel/core': 7.27.3
5061 + '@babel/helper-plugin-utils': 7.27.1
5062
5090 - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)':
5063 + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.3)':
5064 dependencies:
5092 - '@babel/core': 7.26.10
5093 - '@babel/helper-plugin-utils': 7.26.5
5065 + '@babel/core': 7.27.3
5066 + '@babel/helper-plugin-utils': 7.27.1
5067
5095 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)':
5068 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.3)':
5069 dependencies:
5097 - '@babel/core': 7.26.10
5098 - '@babel/helper-plugin-utils': 7.26.5
5070 + '@babel/core': 7.27.3
5071 + '@babel/helper-plugin-utils': 7.27.1
5072
5100 - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)':
5073 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.3)':
5074 dependencies:
5102 - '@babel/core': 7.26.10
5103 - '@babel/helper-plugin-utils': 7.26.5
5075 + '@babel/core': 7.27.3
5076 + '@babel/helper-plugin-utils': 7.27.1
5077
5105 - '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)':
5078 + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.3)':
5079 dependencies:
5107 - '@babel/core': 7.26.10
5108 - '@babel/helper-plugin-utils': 7.26.5
5080 + '@babel/core': 7.27.3
5081 + '@babel/helper-plugin-utils': 7.27.1
5082
5110 - '@babel/plugin-transform-typescript@7.27.0(@babel/core@7.26.10)':
5083 + '@babel/plugin-transform-typescript@7.27.1(@babel/core@7.27.3)':
5084 dependencies:
5112 - '@babel/core': 7.26.10
5113 - '@babel/helper-annotate-as-pure': 7.25.9
5114 - '@babel/helper-create-class-features-plugin': 7.27.0(@babel/core@7.26.10)
5115 - '@babel/helper-plugin-utils': 7.26.5
5116 - '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
5117 - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10)
5085 + '@babel/core': 7.27.3
5086 + '@babel/helper-annotate-as-pure': 7.27.3
5087 + '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.27.3)
5088 + '@babel/helper-plugin-utils': 7.27.1
5089 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1
5090 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.3)
5091 transitivePeerDependencies:
5092 - supports-color
5093
5121 - '@babel/template@7.27.0':
5094 + '@babel/template@7.27.2':
5095 dependencies:
5123 - '@babel/code-frame': 7.26.2
5124 - '@babel/parser': 7.27.0
5125 - '@babel/types': 7.27.0
5096 + '@babel/code-frame': 7.27.1
5097 + '@babel/parser': 7.27.3
5098 + '@babel/types': 7.27.3
5099
5127 - '@babel/traverse@7.27.0':
5100 + '@babel/traverse@7.27.3':
5101 dependencies:
5129 - '@babel/code-frame': 7.26.2
5130 - '@babel/generator': 7.27.0
5131 - '@babel/parser': 7.27.0
5132 - '@babel/template': 7.27.0
5133 - '@babel/types': 7.27.0
5134 - debug: 4.4.0(supports-color@8.1.1)
5102 + '@babel/code-frame': 7.27.1
5103 + '@babel/generator': 7.27.3
5104 + '@babel/parser': 7.27.3
5105 + '@babel/template': 7.27.2
5106 + '@babel/types': 7.27.3
5107 + debug: 4.4.1(supports-color@8.1.1)
5108 globals: 11.12.0
5109 transitivePeerDependencies:
5110 - supports-color
5111
5139 - '@babel/types@7.27.0':
5112 + '@babel/types@7.27.3':
5113 dependencies:
5141 - '@babel/helper-string-parser': 7.25.9
5142 - '@babel/helper-validator-identifier': 7.25.9
5114 + '@babel/helper-string-parser': 7.27.1
5115 + '@babel/helper-validator-identifier': 7.27.1
5116
5117 '@clack/core@0.4.2':
5118 dependencies:
5119 picocolors: 1.1.1
5120 sisteransi: 1.0.5
5121
5122 + '@clack/core@0.5.0':
5123 + dependencies:
5124 + picocolors: 1.1.1
5125 + sisteransi: 1.0.5
5126 +
5127 '@clack/prompts@0.10.1':
5128 dependencies:
5129 '@clack/core': 0.4.2
5130 picocolors: 1.1.1
5131 sisteransi: 1.0.5
5132
5133 + '@clack/prompts@0.11.0':
5134 + dependencies:
5135 + '@clack/core': 0.5.0
5136 + picocolors: 1.1.1
5137 + sisteransi: 1.0.5
5138 +
5139 '@codemirror/autocomplete@6.18.6':
5140 dependencies:
5141 '@codemirror/language': 6.11.0
5142 '@codemirror/state': 6.5.2
5159 - '@codemirror/view': 6.36.5
5143 + '@codemirror/view': 6.36.8
5144 '@lezer/common': 1.2.3
5145
5146 '@codemirror/commands@6.8.1':
5147 dependencies:
5148 '@codemirror/language': 6.11.0
5149 '@codemirror/state': 6.5.2
5166 - '@codemirror/view': 6.36.5
5150 + '@codemirror/view': 6.36.8
5151 '@lezer/common': 1.2.3
5152
5169 - '@codemirror/lang-javascript@6.2.3':
5153 + '@codemirror/lang-javascript@6.2.4':
5154 dependencies:
5155 '@codemirror/autocomplete': 6.18.6
5156 '@codemirror/language': 6.11.0
5157 '@codemirror/lint': 6.8.5
5158 '@codemirror/state': 6.5.2
5175 - '@codemirror/view': 6.36.5
5159 + '@codemirror/view': 6.36.8
5160 '@lezer/common': 1.2.3
5177 - '@lezer/javascript': 1.4.21
5161 + '@lezer/javascript': 1.5.1
5162
5163 '@codemirror/lang-xml@6.1.0':
5164 dependencies:
5165 '@codemirror/autocomplete': 6.18.6
5166 '@codemirror/language': 6.11.0
5167 '@codemirror/state': 6.5.2
5184 - '@codemirror/view': 6.36.5
5168 + '@codemirror/view': 6.36.8
5169 '@lezer/common': 1.2.3
5170 '@lezer/xml': 1.0.6
5171
5172 '@codemirror/language@6.11.0':
5173 dependencies:
5174 '@codemirror/state': 6.5.2
5191 - '@codemirror/view': 6.36.5
5175 + '@codemirror/view': 6.36.8
5176 '@lezer/common': 1.2.3
5177 '@lezer/highlight': 1.2.1
5178 '@lezer/lr': 1.4.2
@@ -5197,13 +5181,13 @@ snapshots:
5181 '@codemirror/lint@6.8.5':
5182 dependencies:
5183 '@codemirror/state': 6.5.2
5200 - '@codemirror/view': 6.36.5
5184 + '@codemirror/view': 6.36.8
5185 crelt: 1.0.6
5186
5203 - '@codemirror/search@6.5.10':
5187 + '@codemirror/search@6.5.11':
5188 dependencies:
5189 '@codemirror/state': 6.5.2
5206 - '@codemirror/view': 6.36.5
5190 + '@codemirror/view': 6.36.8
5191 crelt: 1.0.6
5192
5193 '@codemirror/state@6.5.2':
@@ -5214,45 +5198,42 @@ snapshots:
5198 dependencies:
5199 '@codemirror/language': 6.11.0
5200 '@codemirror/state': 6.5.2
5217 - '@codemirror/view': 6.36.5
5201 + '@codemirror/view': 6.36.8
5202 '@lezer/highlight': 1.2.1
5203
5220 - '@codemirror/view@6.36.5':
5204 + '@codemirror/view@6.36.8':
5205 dependencies:
5206 '@codemirror/state': 6.5.2
5207 style-mod: 4.1.2
5208 w3c-keyname: 2.2.8
5209
5226 - '@colors/colors@1.5.0':
5227 - optional: true
5228 -
5210 '@css-render/plugin-bem@0.15.14(css-render@0.15.14)':
5211 dependencies:
5212 css-render: 0.15.14
5213
5233 - '@css-render/vue3-ssr@0.15.14(vue@3.5.13(typescript@5.8.3))':
5214 + '@css-render/vue3-ssr@0.15.14(vue@3.5.15(typescript@5.8.3))':
5215 dependencies:
5235 - vue: 3.5.13(typescript@5.8.3)
5216 + vue: 3.5.15(typescript@5.8.3)
5217
5218 '@csstools/color-helpers@5.0.2': {}
5219
5239 - '@csstools/css-calc@2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)':
5220 + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
5221 dependencies:
5241 - '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
5242 - '@csstools/css-tokenizer': 3.0.3
5222 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
5223 + '@csstools/css-tokenizer': 3.0.4
5224
5244 - '@csstools/css-color-parser@3.0.8(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)':
5225 + '@csstools/css-color-parser@3.0.10(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
5226 dependencies:
5227 '@csstools/color-helpers': 5.0.2
5247 - '@csstools/css-calc': 2.1.2(@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3))(@csstools/css-tokenizer@3.0.3)
5248 - '@csstools/css-parser-algorithms': 3.0.4(@csstools/css-tokenizer@3.0.3)
5249 - '@csstools/css-tokenizer': 3.0.3
5228 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
5229 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
5230 + '@csstools/css-tokenizer': 3.0.4
5231
5251 - '@csstools/css-parser-algorithms@3.0.4(@csstools/css-tokenizer@3.0.3)':
5232 + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
5233 dependencies:
5253 - '@csstools/css-tokenizer': 3.0.3
5234 + '@csstools/css-tokenizer': 3.0.4
5235
5255 - '@csstools/css-tokenizer@3.0.3': {}
5236 + '@csstools/css-tokenizer@3.0.4': {}
5237
5238 '@cypress/request@3.0.8':
5239 dependencies:
@@ -5282,140 +5263,133 @@ snapshots:
5263 transitivePeerDependencies:
5264 - supports-color
5265
5285 - '@emnapi/core@1.4.0':
5266 + '@emnapi/core@1.4.3':
5267 dependencies:
5287 - '@emnapi/wasi-threads': 1.0.1
5268 + '@emnapi/wasi-threads': 1.0.2
5269 tslib: 2.8.1
5270 optional: true
5271
5291 - '@emnapi/runtime@1.4.0':
5272 + '@emnapi/runtime@1.4.3':
5273 dependencies:
5274 tslib: 2.8.1
5275 optional: true
5276
5296 - '@emnapi/wasi-threads@1.0.1':
5277 + '@emnapi/wasi-threads@1.0.2':
5278 dependencies:
5279 tslib: 2.8.1
5280 optional: true
5281
5282 '@emotion/hash@0.8.0': {}
5283
5303 - '@es-joy/jsdoccomment@0.49.0':
5304 - dependencies:
5305 - comment-parser: 1.4.1
5306 - esquery: 1.6.0
5307 - jsdoc-type-pratt-parser: 4.1.0
5308 -
5309 - '@es-joy/jsdoccomment@0.50.0':
5284 + '@es-joy/jsdoccomment@0.50.2':
5285 dependencies:
5311 - '@types/eslint': 9.6.1
5286 '@types/estree': 1.0.7
5313 - '@typescript-eslint/types': 8.29.0
5287 + '@typescript-eslint/types': 8.33.0
5288 comment-parser: 1.4.1
5289 esquery: 1.6.0
5290 jsdoc-type-pratt-parser: 4.1.0
5291
5318 - '@esbuild/aix-ppc64@0.25.2':
5292 + '@esbuild/aix-ppc64@0.25.5':
5293 optional: true
5294
5321 - '@esbuild/android-arm64@0.25.2':
5295 + '@esbuild/android-arm64@0.25.5':
5296 optional: true
5297
5324 - '@esbuild/android-arm@0.25.2':
5298 + '@esbuild/android-arm@0.25.5':
5299 optional: true
5300
5327 - '@esbuild/android-x64@0.25.2':
5301 + '@esbuild/android-x64@0.25.5':
5302 optional: true
5303
5330 - '@esbuild/darwin-arm64@0.25.2':
5304 + '@esbuild/darwin-arm64@0.25.5':
5305 optional: true
5306
5333 - '@esbuild/darwin-x64@0.25.2':
5307 + '@esbuild/darwin-x64@0.25.5':
5308 optional: true
5309
5336 - '@esbuild/freebsd-arm64@0.25.2':
5310 + '@esbuild/freebsd-arm64@0.25.5':
5311 optional: true
5312
5339 - '@esbuild/freebsd-x64@0.25.2':
5313 + '@esbuild/freebsd-x64@0.25.5':
5314 optional: true
5315
5342 - '@esbuild/linux-arm64@0.25.2':
5316 + '@esbuild/linux-arm64@0.25.5':
5317 optional: true
5318
5345 - '@esbuild/linux-arm@0.25.2':
5319 + '@esbuild/linux-arm@0.25.5':
5320 optional: true
5321
5348 - '@esbuild/linux-ia32@0.25.2':
5322 + '@esbuild/linux-ia32@0.25.5':
5323 optional: true
5324
5351 - '@esbuild/linux-loong64@0.25.2':
5325 + '@esbuild/linux-loong64@0.25.5':
5326 optional: true
5327
5354 - '@esbuild/linux-mips64el@0.25.2':
5328 + '@esbuild/linux-mips64el@0.25.5':
5329 optional: true
5330
5357 - '@esbuild/linux-ppc64@0.25.2':
5331 + '@esbuild/linux-ppc64@0.25.5':
5332 optional: true
5333
5360 - '@esbuild/linux-riscv64@0.25.2':
5334 + '@esbuild/linux-riscv64@0.25.5':
5335 optional: true
5336
5363 - '@esbuild/linux-s390x@0.25.2':
5337 + '@esbuild/linux-s390x@0.25.5':
5338 optional: true
5339
5366 - '@esbuild/linux-x64@0.25.2':
5340 + '@esbuild/linux-x64@0.25.5':
5341 optional: true
5342
5369 - '@esbuild/netbsd-arm64@0.25.2':
5343 + '@esbuild/netbsd-arm64@0.25.5':
5344 optional: true
5345
5372 - '@esbuild/netbsd-x64@0.25.2':
5346 + '@esbuild/netbsd-x64@0.25.5':
5347 optional: true
5348
5375 - '@esbuild/openbsd-arm64@0.25.2':
5349 + '@esbuild/openbsd-arm64@0.25.5':
5350 optional: true
5351
5378 - '@esbuild/openbsd-x64@0.25.2':
5352 + '@esbuild/openbsd-x64@0.25.5':
5353 optional: true
5354
5381 - '@esbuild/sunos-x64@0.25.2':
5355 + '@esbuild/sunos-x64@0.25.5':
5356 optional: true
5357
5384 - '@esbuild/win32-arm64@0.25.2':
5358 + '@esbuild/win32-arm64@0.25.5':
5359 optional: true
5360
5387 - '@esbuild/win32-ia32@0.25.2':
5361 + '@esbuild/win32-ia32@0.25.5':
5362 optional: true
5363
5390 - '@esbuild/win32-x64@0.25.2':
5364 + '@esbuild/win32-x64@0.25.5':
5365 optional: true
5366
5393 - '@eslint-community/eslint-plugin-eslint-comments@4.4.1(eslint@9.25.1(jiti@2.4.2))':
5367 + '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.27.0(jiti@2.4.2))':
5368 dependencies:
5369 escape-string-regexp: 4.0.0
5396 - eslint: 9.25.1(jiti@2.4.2)
5370 + eslint: 9.27.0(jiti@2.4.2)
5371 ignore: 5.3.2
5372
5399 - '@eslint-community/eslint-utils@4.5.1(eslint@9.25.1(jiti@2.4.2))':
5373 + '@eslint-community/eslint-utils@4.7.0(eslint@9.27.0(jiti@2.4.2))':
5374 dependencies:
5401 - eslint: 9.25.1(jiti@2.4.2)
5375 + eslint: 9.27.0(jiti@2.4.2)
5376 eslint-visitor-keys: 3.4.3
5377
5378 '@eslint-community/regexpp@4.12.1': {}
5379
5406 - '@eslint/compat@1.2.8(eslint@9.25.1(jiti@2.4.2))':
5380 + '@eslint/compat@1.2.9(eslint@9.27.0(jiti@2.4.2))':
5381 optionalDependencies:
5408 - eslint: 9.25.1(jiti@2.4.2)
5382 + eslint: 9.27.0(jiti@2.4.2)
5383
5384 '@eslint/config-array@0.20.0':
5385 dependencies:
5386 '@eslint/object-schema': 2.1.6
5413 - debug: 4.4.0(supports-color@8.1.1)
5387 + debug: 4.4.1(supports-color@8.1.1)
5388 minimatch: 3.1.2
5389 transitivePeerDependencies:
5390 - supports-color
5391
5418 - '@eslint/config-helpers@0.2.1': {}
5392 + '@eslint/config-helpers@0.2.2': {}
5393
5394 '@eslint/core@0.10.0':
5395 dependencies:
@@ -5425,10 +5399,14 @@ snapshots:
5399 dependencies:
5400 '@types/json-schema': 7.0.15
5401
5402 + '@eslint/core@0.14.0':
5403 + dependencies:
5404 + '@types/json-schema': 7.0.15
5405 +
5406 '@eslint/eslintrc@3.3.1':
5407 dependencies:
5408 ajv: 6.12.6
5431 - debug: 4.4.0(supports-color@8.1.1)
5409 + debug: 4.4.1(supports-color@8.1.1)
5410 espree: 10.3.0
5411 globals: 14.0.0
5412 ignore: 5.3.2
@@ -5439,14 +5417,16 @@ snapshots:
5417 transitivePeerDependencies:
5418 - supports-color
5419
5442 - '@eslint/js@9.25.1': {}
5420 + '@eslint/js@9.27.0': {}
5421
5444 - '@eslint/markdown@6.3.0':
5422 + '@eslint/markdown@6.4.0':
5423 dependencies:
5424 '@eslint/core': 0.10.0
5425 '@eslint/plugin-kit': 0.2.8
5426 mdast-util-from-markdown: 2.0.2
5427 + mdast-util-frontmatter: 2.0.1
5428 mdast-util-gfm: 3.1.0
5429 + micromark-extension-frontmatter: 2.0.0
5430 micromark-extension-gfm: 3.0.0
5431 transitivePeerDependencies:
5432 - supports-color
@@ -5458,14 +5438,19 @@ snapshots:
5438 '@eslint/core': 0.13.0
5439 levn: 0.4.1
5440
5461 - '@f3ve/vue-markdown-it@0.2.3(vue@3.5.13(typescript@5.8.3))':
5441 + '@eslint/plugin-kit@0.3.1':
5442 + dependencies:
5443 + '@eslint/core': 0.14.0
5444 + levn: 0.4.1
5445 +
5446 + '@f3ve/vue-markdown-it@0.2.3(vue@3.5.15(typescript@5.8.3))':
5447 dependencies:
5448 markdown-it: 14.1.0
5464 - vue: 3.5.13(typescript@5.8.3)
5449 + vue: 3.5.15(typescript@5.8.3)
5450
5451 '@fontsource/jetbrains-mono@5.2.5': {}
5452
5468 - '@fontsource/lexend@5.2.6': {}
5453 + '@fontsource/lexend@5.2.7': {}
5454
5455 '@fontsource/public-sans@5.2.5': {}
5456
@@ -5486,26 +5471,26 @@ snapshots:
5471
5472 '@humanwhocodes/retry@0.3.1': {}
5473
5489 - '@humanwhocodes/retry@0.4.2': {}
5474 + '@humanwhocodes/retry@0.4.3': {}
5475
5476 '@iconify/types@2.0.0': {}
5477
5493 - '@iconify/vue@4.3.0(vue@3.5.13(typescript@5.8.3))':
5478 + '@iconify/vue@5.0.0(vue@3.5.15(typescript@5.8.3))':
5479 dependencies:
5480 '@iconify/types': 2.0.0
5496 - vue: 3.5.13(typescript@5.8.3)
5481 + vue: 3.5.15(typescript@5.8.3)
5482
5498 - '@intlify/core-base@11.1.3':
5483 + '@intlify/core-base@11.1.5':
5484 dependencies:
5500 - '@intlify/message-compiler': 11.1.3
5501 - '@intlify/shared': 11.1.3
5485 + '@intlify/message-compiler': 11.1.5
5486 + '@intlify/shared': 11.1.5
5487
5503 - '@intlify/message-compiler@11.1.3':
5488 + '@intlify/message-compiler@11.1.5':
5489 dependencies:
5505 - '@intlify/shared': 11.1.3
5490 + '@intlify/shared': 11.1.5
5491 source-map-js: 1.2.1
5492
5508 - '@intlify/shared@11.1.3': {}
5493 + '@intlify/shared@11.1.5': {}
5494
5495 '@isaacs/cliui@8.0.2':
5496 dependencies:
@@ -5516,6 +5501,10 @@ snapshots:
5501 wrap-ansi: 8.1.0
5502 wrap-ansi-cjs: wrap-ansi@7.0.0
5503
5504 + '@isaacs/fs-minipass@4.0.1':
5505 + dependencies:
5506 + minipass: 7.1.2
5507 +
5508 '@jridgewell/gen-mapping@0.3.8':
5509 dependencies:
5510 '@jridgewell/set-array': 1.2.1
@@ -5541,7 +5530,7 @@ snapshots:
5530 dependencies:
5531 '@lezer/common': 1.2.3
5532
5544 - '@lezer/javascript@1.4.21':
5533 + '@lezer/javascript@1.5.1':
5534 dependencies:
5535 '@lezer/common': 1.2.3
5536 '@lezer/highlight': 1.2.1
@@ -5559,10 +5548,10 @@ snapshots:
5548
5549 '@marijn/find-cluster-break@1.0.2': {}
5550
5562 - '@napi-rs/wasm-runtime@0.2.9':
5551 + '@napi-rs/wasm-runtime@0.2.10':
5552 dependencies:
5564 - '@emnapi/core': 1.4.0
5565 - '@emnapi/runtime': 1.4.0
5553 + '@emnapi/core': 1.4.3
5554 + '@emnapi/runtime': 1.4.3
5555 '@tybys/wasm-util': 0.9.0
5556 optional: true
5557
@@ -5578,16 +5567,15 @@ snapshots:
5567 '@nodelib/fs.scandir': 2.1.5
5568 fastq: 1.19.1
5569
5581 - '@nuxt/kit@3.16.2':
5570 + '@nuxt/kit@3.17.4':
5571 dependencies:
5583 - c12: 3.0.3
5572 + c12: 3.0.4
5573 consola: 3.4.2
5574 defu: 6.1.4
5575 destr: 2.0.5
5576 errx: 0.1.0
5588 - exsolve: 1.0.4
5589 - globby: 14.1.0
5590 - ignore: 7.0.3
5577 + exsolve: 1.0.5
5578 + ignore: 7.0.4
5579 jiti: 2.4.2
5580 klona: 2.0.6
5581 knitwork: 1.2.0
@@ -5596,11 +5584,12 @@ snapshots:
5584 pathe: 2.0.3
5585 pkg-types: 2.1.0
5586 scule: 1.3.0
5599 - semver: 7.7.1
5600 - std-env: 3.8.1
5601 - ufo: 1.5.4
5587 + semver: 7.7.2
5588 + std-env: 3.9.0
5589 + tinyglobby: 0.2.14
5590 + ufo: 1.6.1
5591 unctx: 2.4.1
5603 - unimport: 4.1.3
5592 + unimport: 5.0.1
5593 untyped: 2.0.0
5594 transitivePeerDependencies:
5595 - magicast
@@ -5671,123 +5660,118 @@ snapshots:
5660 '@pkgjs/parseargs@0.11.0':
5661 optional: true
5662
5674 - '@pkgr/core@0.1.2': {}
5675 -
5676 - '@pkgr/core@0.2.0': {}
5677 -
5663 '@pkgr/core@0.2.4': {}
5664
5680 - '@polka/url@1.0.0-next.28': {}
5665 + '@polka/url@1.0.0-next.29': {}
5666
5682 - '@quansync/fs@0.1.2':
5667 + '@quansync/fs@0.1.3':
5668 dependencies:
5669 quansync: 0.2.10
5670
5686 - '@rollup/pluginutils@5.1.4(rollup@4.39.0)':
5671 + '@rolldown/pluginutils@1.0.0-beta.10': {}
5672 +
5673 + '@rollup/pluginutils@5.1.4(rollup@4.41.1)':
5674 dependencies:
5675 '@types/estree': 1.0.7
5676 estree-walker: 2.0.2
5677 picomatch: 4.0.2
5678 optionalDependencies:
5692 - rollup: 4.39.0
5693 -
5694 - '@rollup/rollup-android-arm-eabi@4.39.0':
5695 - optional: true
5679 + rollup: 4.41.1
5680
5697 - '@rollup/rollup-android-arm64@4.39.0':
5681 + '@rollup/rollup-android-arm-eabi@4.41.1':
5682 optional: true
5683
5700 - '@rollup/rollup-darwin-arm64@4.39.0':
5684 + '@rollup/rollup-android-arm64@4.41.1':
5685 optional: true
5686
5703 - '@rollup/rollup-darwin-x64@4.39.0':
5687 + '@rollup/rollup-darwin-arm64@4.41.1':
5688 optional: true
5689
5706 - '@rollup/rollup-freebsd-arm64@4.39.0':
5690 + '@rollup/rollup-darwin-x64@4.41.1':
5691 optional: true
5692
5709 - '@rollup/rollup-freebsd-x64@4.39.0':
5693 + '@rollup/rollup-freebsd-arm64@4.41.1':
5694 optional: true
5695
5712 - '@rollup/rollup-linux-arm-gnueabihf@4.39.0':
5696 + '@rollup/rollup-freebsd-x64@4.41.1':
5697 optional: true
5698
5715 - '@rollup/rollup-linux-arm-musleabihf@4.39.0':
5699 + '@rollup/rollup-linux-arm-gnueabihf@4.41.1':
5700 optional: true
5701
5718 - '@rollup/rollup-linux-arm64-gnu@4.39.0':
5702 + '@rollup/rollup-linux-arm-musleabihf@4.41.1':
5703 optional: true
5704
5721 - '@rollup/rollup-linux-arm64-musl@4.39.0':
5705 + '@rollup/rollup-linux-arm64-gnu@4.41.1':
5706 optional: true
5707
5724 - '@rollup/rollup-linux-loongarch64-gnu@4.39.0':
5708 + '@rollup/rollup-linux-arm64-musl@4.41.1':
5709 optional: true
5710
5727 - '@rollup/rollup-linux-powerpc64le-gnu@4.39.0':
5711 + '@rollup/rollup-linux-loongarch64-gnu@4.41.1':
5712 optional: true
5713
5730 - '@rollup/rollup-linux-riscv64-gnu@4.39.0':
5714 + '@rollup/rollup-linux-powerpc64le-gnu@4.41.1':
5715 optional: true
5716
5733 - '@rollup/rollup-linux-riscv64-musl@4.39.0':
5717 + '@rollup/rollup-linux-riscv64-gnu@4.41.1':
5718 optional: true
5719
5736 - '@rollup/rollup-linux-s390x-gnu@4.39.0':
5720 + '@rollup/rollup-linux-riscv64-musl@4.41.1':
5721 optional: true
5722
5739 - '@rollup/rollup-linux-x64-gnu@4.39.0':
5723 + '@rollup/rollup-linux-s390x-gnu@4.41.1':
5724 optional: true
5725
5742 - '@rollup/rollup-linux-x64-gnu@4.40.0':
5726 + '@rollup/rollup-linux-x64-gnu@4.41.1':
5727 optional: true
5728
5745 - '@rollup/rollup-linux-x64-musl@4.39.0':
5729 + '@rollup/rollup-linux-x64-musl@4.41.1':
5730 optional: true
5731
5748 - '@rollup/rollup-win32-arm64-msvc@4.39.0':
5732 + '@rollup/rollup-win32-arm64-msvc@4.41.1':
5733 optional: true
5734
5751 - '@rollup/rollup-win32-ia32-msvc@4.39.0':
5735 + '@rollup/rollup-win32-ia32-msvc@4.41.1':
5736 optional: true
5737
5754 - '@rollup/rollup-win32-x64-msvc@4.39.0':
5738 + '@rollup/rollup-win32-x64-msvc@4.41.1':
5739 optional: true
5740
5741 '@sec-ant/readable-stream@0.4.1': {}
5742
5759 - '@shikijs/core@3.3.0':
5743 + '@shikijs/core@3.4.2':
5744 dependencies:
5761 - '@shikijs/types': 3.3.0
5745 + '@shikijs/types': 3.4.2
5746 '@shikijs/vscode-textmate': 10.0.2
5747 '@types/hast': 3.0.4
5748 hast-util-to-html: 9.0.5
5749
5766 - '@shikijs/engine-javascript@3.3.0':
5750 + '@shikijs/engine-javascript@3.4.2':
5751 dependencies:
5768 - '@shikijs/types': 3.3.0
5752 + '@shikijs/types': 3.4.2
5753 '@shikijs/vscode-textmate': 10.0.2
5770 - oniguruma-to-es: 4.2.0
5754 + oniguruma-to-es: 4.3.3
5755
5772 - '@shikijs/engine-oniguruma@3.3.0':
5756 + '@shikijs/engine-oniguruma@3.4.2':
5757 dependencies:
5774 - '@shikijs/types': 3.3.0
5758 + '@shikijs/types': 3.4.2
5759 '@shikijs/vscode-textmate': 10.0.2
5760
5777 - '@shikijs/langs@3.3.0':
5761 + '@shikijs/langs@3.4.2':
5762 dependencies:
5779 - '@shikijs/types': 3.3.0
5763 + '@shikijs/types': 3.4.2
5764
5781 - '@shikijs/markdown-it@3.3.0':
5765 + '@shikijs/markdown-it@3.4.2':
5766 dependencies:
5767 markdown-it: 14.1.0
5784 - shiki: 3.3.0
5768 + shiki: 3.4.2
5769
5786 - '@shikijs/themes@3.3.0':
5770 + '@shikijs/themes@3.4.2':
5771 dependencies:
5788 - '@shikijs/types': 3.3.0
5772 + '@shikijs/types': 3.4.2
5773
5790 - '@shikijs/types@3.3.0':
5774 + '@shikijs/types@3.4.2':
5775 dependencies:
5776 '@shikijs/vscode-textmate': 10.0.2
5777 '@types/hast': 3.0.4
@@ -5802,14 +5786,12 @@ snapshots:
5786
5787 '@sideway/pinpoint@2.0.0': {}
5788
5805 - '@sindresorhus/merge-streams@2.3.0': {}
5806 -
5789 '@sindresorhus/merge-streams@4.0.0': {}
5790
5809 - '@stylistic/eslint-plugin@4.2.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
5791 + '@stylistic/eslint-plugin@4.4.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
5792 dependencies:
5811 - '@typescript-eslint/utils': 8.29.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
5812 - eslint: 9.25.1(jiti@2.4.2)
5793 + '@typescript-eslint/utils': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
5794 + eslint: 9.27.0(jiti@2.4.2)
5795 eslint-visitor-keys: 4.2.0
5796 espree: 10.3.0
5797 estraverse: 5.3.0
@@ -5828,79 +5810,85 @@ snapshots:
5810
5811 '@svgdotjs/svg.js@3.2.4': {}
5812
5831 - '@svgdotjs/svg.resize.js@2.0.5(@svgdotjs/svg.js@3.2.4)(@svgdotjs/svg.select.js@4.0.2(@svgdotjs/svg.js@3.2.4))':
5813 + '@svgdotjs/svg.resize.js@2.0.5(@svgdotjs/svg.js@3.2.4)(@svgdotjs/svg.select.js@4.0.3(@svgdotjs/svg.js@3.2.4))':
5814 dependencies:
5815 '@svgdotjs/svg.js': 3.2.4
5834 - '@svgdotjs/svg.select.js': 4.0.2(@svgdotjs/svg.js@3.2.4)
5816 + '@svgdotjs/svg.select.js': 4.0.3(@svgdotjs/svg.js@3.2.4)
5817
5836 - '@svgdotjs/svg.select.js@4.0.2(@svgdotjs/svg.js@3.2.4)':
5818 + '@svgdotjs/svg.select.js@4.0.3(@svgdotjs/svg.js@3.2.4)':
5819 dependencies:
5820 '@svgdotjs/svg.js': 3.2.4
5821
5840 - '@tailwindcss/node@4.1.4':
5822 + '@tailwindcss/node@4.1.8':
5823 dependencies:
5824 + '@ampproject/remapping': 2.3.0
5825 enhanced-resolve: 5.18.1
5826 jiti: 2.4.2
5844 - lightningcss: 1.29.2
5845 - tailwindcss: 4.1.4
5827 + lightningcss: 1.30.1
5828 + magic-string: 0.30.17
5829 + source-map-js: 1.2.1
5830 + tailwindcss: 4.1.8
5831
5847 - '@tailwindcss/oxide-android-arm64@4.1.4':
5832 + '@tailwindcss/oxide-android-arm64@4.1.8':
5833 optional: true
5834
5850 - '@tailwindcss/oxide-darwin-arm64@4.1.4':
5835 + '@tailwindcss/oxide-darwin-arm64@4.1.8':
5836 optional: true
5837
5853 - '@tailwindcss/oxide-darwin-x64@4.1.4':
5838 + '@tailwindcss/oxide-darwin-x64@4.1.8':
5839 optional: true
5840
5856 - '@tailwindcss/oxide-freebsd-x64@4.1.4':
5841 + '@tailwindcss/oxide-freebsd-x64@4.1.8':
5842 optional: true
5843
5859 - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.4':
5844 + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.8':
5845 optional: true
5846
5862 - '@tailwindcss/oxide-linux-arm64-gnu@4.1.4':
5847 + '@tailwindcss/oxide-linux-arm64-gnu@4.1.8':
5848 optional: true
5849
5865 - '@tailwindcss/oxide-linux-arm64-musl@4.1.4':
5850 + '@tailwindcss/oxide-linux-arm64-musl@4.1.8':
5851 optional: true
5852
5868 - '@tailwindcss/oxide-linux-x64-gnu@4.1.4':
5853 + '@tailwindcss/oxide-linux-x64-gnu@4.1.8':
5854 optional: true
5855
5871 - '@tailwindcss/oxide-linux-x64-musl@4.1.4':
5856 + '@tailwindcss/oxide-linux-x64-musl@4.1.8':
5857 optional: true
5858
5874 - '@tailwindcss/oxide-wasm32-wasi@4.1.4':
5859 + '@tailwindcss/oxide-wasm32-wasi@4.1.8':
5860 optional: true
5861
5877 - '@tailwindcss/oxide-win32-arm64-msvc@4.1.4':
5862 + '@tailwindcss/oxide-win32-arm64-msvc@4.1.8':
5863 optional: true
5864
5880 - '@tailwindcss/oxide-win32-x64-msvc@4.1.4':
5865 + '@tailwindcss/oxide-win32-x64-msvc@4.1.8':
5866 optional: true
5867
5883 - '@tailwindcss/oxide@4.1.4':
5868 + '@tailwindcss/oxide@4.1.8':
5869 + dependencies:
5870 + detect-libc: 2.0.4
5871 + tar: 7.4.3
5872 optionalDependencies:
5885 - '@tailwindcss/oxide-android-arm64': 4.1.4
5886 - '@tailwindcss/oxide-darwin-arm64': 4.1.4
5887 - '@tailwindcss/oxide-darwin-x64': 4.1.4
5888 - '@tailwindcss/oxide-freebsd-x64': 4.1.4
5889 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.4
5890 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.4
5891 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.4
5892 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.4
5893 - '@tailwindcss/oxide-linux-x64-musl': 4.1.4
5894 - '@tailwindcss/oxide-wasm32-wasi': 4.1.4
5895 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.4
5896 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.4
5897 -
5898 - '@tailwindcss/vite@4.1.4(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))':
5899 - dependencies:
5900 - '@tailwindcss/node': 4.1.4
5901 - '@tailwindcss/oxide': 4.1.4
5902 - tailwindcss: 4.1.4
5903 - vite: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
5873 + '@tailwindcss/oxide-android-arm64': 4.1.8
5874 + '@tailwindcss/oxide-darwin-arm64': 4.1.8
5875 + '@tailwindcss/oxide-darwin-x64': 4.1.8
5876 + '@tailwindcss/oxide-freebsd-x64': 4.1.8
5877 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.8
5878 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.8
5879 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.8
5880 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.8
5881 + '@tailwindcss/oxide-linux-x64-musl': 4.1.8
5882 + '@tailwindcss/oxide-wasm32-wasi': 4.1.8
5883 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.8
5884 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.8
5885 +
5886 + '@tailwindcss/vite@4.1.8(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))':
5887 + dependencies:
5888 + '@tailwindcss/node': 4.1.8
5889 + '@tailwindcss/oxide': 4.1.8
5890 + tailwindcss: 4.1.8
5891 + vite: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
5892
5893 '@trysound/sax@0.2.0': {}
5894
@@ -5917,13 +5905,6 @@ snapshots:
5905 dependencies:
5906 '@types/ms': 2.1.0
5907
5920 - '@types/doctrine@0.0.9': {}
5921 -
5922 - '@types/eslint@9.6.1':
5923 - dependencies:
5924 - '@types/estree': 1.0.7
5925 - '@types/json-schema': 7.0.15
5926 -
5908 '@types/estree@1.0.7': {}
5909
5910 '@types/file-saver@2.0.7': {}
@@ -5931,7 +5912,7 @@ snapshots:
5912 '@types/fs-extra@11.0.4':
5913 dependencies:
5914 '@types/jsonfile': 6.1.4
5934 - '@types/node': 22.15.2
5915 + '@types/node': 22.15.23
5916
5917 '@types/hast@3.0.4':
5918 dependencies:
@@ -5939,38 +5920,45 @@ snapshots:
5920
5921 '@types/jsdom@21.1.7':
5922 dependencies:
5942 - '@types/node': 22.15.2
5923 + '@types/node': 22.15.23
5924 '@types/tough-cookie': 4.0.5
5944 - parse5: 7.2.1
5925 + parse5: 7.3.0
5926
5927 '@types/json-schema@7.0.15': {}
5928
5929 '@types/jsonfile@6.1.4':
5930 dependencies:
5950 - '@types/node': 22.15.2
5931 + '@types/node': 22.15.23
5932
5933 '@types/katex@0.16.7': {}
5934
5935 + '@types/linkify-it@5.0.0': {}
5936 +
5937 '@types/lodash-es@4.17.12':
5938 dependencies:
5956 - '@types/lodash': 4.17.16
5939 + '@types/lodash': 4.17.17
5940
5958 - '@types/lodash@4.17.16': {}
5941 + '@types/lodash@4.17.17': {}
5942 +
5943 + '@types/markdown-it@14.1.2':
5944 + dependencies:
5945 + '@types/linkify-it': 5.0.0
5946 + '@types/mdurl': 2.0.0
5947
5948 '@types/mdast@4.0.4':
5949 dependencies:
5950 '@types/unist': 3.0.3
5951
5952 + '@types/mdurl@2.0.0': {}
5953 +
5954 '@types/minimatch@3.0.5': {}
5955
5956 '@types/ms@2.1.0': {}
5957
5968 - '@types/node@22.15.2':
5958 + '@types/node@22.15.23':
5959 dependencies:
5960 undici-types: 6.21.0
5961
5972 - '@types/normalize-package-data@2.4.4': {}
5973 -
5962 '@types/parse-json@4.0.2': {}
5963
5964 '@types/sinonjs__fake-timers@8.1.1': {}
@@ -5981,314 +5969,298 @@ snapshots:
5969
5970 '@types/unist@3.0.3': {}
5971
5984 - '@types/validator@13.15.0': {}
5972 + '@types/validator@13.15.1': {}
5973
5974 '@types/web-bluetooth@0.0.21': {}
5975
5976 '@types/yauzl@2.10.3':
5977 dependencies:
5990 - '@types/node': 22.15.2
5978 + '@types/node': 22.15.23
5979 optional: true
5980
5993 - '@typescript-eslint/eslint-plugin@8.30.1(@typescript-eslint/parser@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
5981 + '@typescript-eslint/eslint-plugin@8.33.0(@typescript-eslint/parser@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
5982 dependencies:
5983 '@eslint-community/regexpp': 4.12.1
5996 - '@typescript-eslint/parser': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
5997 - '@typescript-eslint/scope-manager': 8.30.1
5998 - '@typescript-eslint/type-utils': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
5999 - '@typescript-eslint/utils': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
6000 - '@typescript-eslint/visitor-keys': 8.30.1
6001 - eslint: 9.25.1(jiti@2.4.2)
5984 + '@typescript-eslint/parser': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
5985 + '@typescript-eslint/scope-manager': 8.33.0
5986 + '@typescript-eslint/type-utils': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
5987 + '@typescript-eslint/utils': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
5988 + '@typescript-eslint/visitor-keys': 8.33.0
5989 + eslint: 9.27.0(jiti@2.4.2)
5990 graphemer: 1.4.0
6003 - ignore: 5.3.2
5991 + ignore: 7.0.4
5992 natural-compare: 1.4.0
5993 ts-api-utils: 2.1.0(typescript@5.8.3)
5994 typescript: 5.8.3
5995 transitivePeerDependencies:
5996 - supports-color
5997
6010 - '@typescript-eslint/parser@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
5998 + '@typescript-eslint/parser@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
5999 dependencies:
6012 - '@typescript-eslint/scope-manager': 8.30.1
6013 - '@typescript-eslint/types': 8.30.1
6014 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
6015 - '@typescript-eslint/visitor-keys': 8.30.1
6016 - debug: 4.4.0(supports-color@8.1.1)
6017 - eslint: 9.25.1(jiti@2.4.2)
6000 + '@typescript-eslint/scope-manager': 8.33.0
6001 + '@typescript-eslint/types': 8.33.0
6002 + '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3)
6003 + '@typescript-eslint/visitor-keys': 8.33.0
6004 + debug: 4.4.1(supports-color@8.1.1)
6005 + eslint: 9.27.0(jiti@2.4.2)
6006 typescript: 5.8.3
6007 transitivePeerDependencies:
6008 - supports-color
6009
6022 - '@typescript-eslint/scope-manager@8.29.0':
6010 + '@typescript-eslint/project-service@8.33.0(typescript@5.8.3)':
6011 dependencies:
6024 - '@typescript-eslint/types': 8.29.0
6025 - '@typescript-eslint/visitor-keys': 8.29.0
6012 + '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.8.3)
6013 + '@typescript-eslint/types': 8.33.0
6014 + debug: 4.4.1(supports-color@8.1.1)
6015 + transitivePeerDependencies:
6016 + - supports-color
6017 + - typescript
6018
6027 - '@typescript-eslint/scope-manager@8.30.1':
6019 + '@typescript-eslint/scope-manager@8.33.0':
6020 dependencies:
6029 - '@typescript-eslint/types': 8.30.1
6030 - '@typescript-eslint/visitor-keys': 8.30.1
6021 + '@typescript-eslint/types': 8.33.0
6022 + '@typescript-eslint/visitor-keys': 8.33.0
6023
6032 - '@typescript-eslint/type-utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
6024 + '@typescript-eslint/tsconfig-utils@8.33.0(typescript@5.8.3)':
6025 dependencies:
6034 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
6035 - '@typescript-eslint/utils': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
6036 - debug: 4.4.0(supports-color@8.1.1)
6037 - eslint: 9.25.1(jiti@2.4.2)
6038 - ts-api-utils: 2.1.0(typescript@5.8.3)
6026 typescript: 5.8.3
6040 - transitivePeerDependencies:
6041 - - supports-color
6042 -
6043 - '@typescript-eslint/types@8.29.0': {}
6044 -
6045 - '@typescript-eslint/types@8.30.1': {}
6027
6047 - '@typescript-eslint/typescript-estree@8.29.0(typescript@5.8.3)':
6028 + '@typescript-eslint/type-utils@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
6029 dependencies:
6049 - '@typescript-eslint/types': 8.29.0
6050 - '@typescript-eslint/visitor-keys': 8.29.0
6051 - debug: 4.4.0(supports-color@8.1.1)
6052 - fast-glob: 3.3.3
6053 - is-glob: 4.0.3
6054 - minimatch: 9.0.5
6055 - semver: 7.7.1
6030 + '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3)
6031 + '@typescript-eslint/utils': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
6032 + debug: 4.4.1(supports-color@8.1.1)
6033 + eslint: 9.27.0(jiti@2.4.2)
6034 ts-api-utils: 2.1.0(typescript@5.8.3)
6035 typescript: 5.8.3
6036 transitivePeerDependencies:
6037 - supports-color
6038
6061 - '@typescript-eslint/typescript-estree@8.30.1(typescript@5.8.3)':
6039 + '@typescript-eslint/types@8.33.0': {}
6040 +
6041 + '@typescript-eslint/typescript-estree@8.33.0(typescript@5.8.3)':
6042 dependencies:
6063 - '@typescript-eslint/types': 8.30.1
6064 - '@typescript-eslint/visitor-keys': 8.30.1
6065 - debug: 4.4.0(supports-color@8.1.1)
6043 + '@typescript-eslint/project-service': 8.33.0(typescript@5.8.3)
6044 + '@typescript-eslint/tsconfig-utils': 8.33.0(typescript@5.8.3)
6045 + '@typescript-eslint/types': 8.33.0
6046 + '@typescript-eslint/visitor-keys': 8.33.0
6047 + debug: 4.4.1(supports-color@8.1.1)
6048 fast-glob: 3.3.3
6049 is-glob: 4.0.3
6050 minimatch: 9.0.5
6069 - semver: 7.7.1
6051 + semver: 7.7.2
6052 ts-api-utils: 2.1.0(typescript@5.8.3)
6053 typescript: 5.8.3
6054 transitivePeerDependencies:
6055 - supports-color
6056
6075 - '@typescript-eslint/utils@8.29.0(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
6057 + '@typescript-eslint/utils@8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)':
6058 dependencies:
6077 - '@eslint-community/eslint-utils': 4.5.1(eslint@9.25.1(jiti@2.4.2))
6078 - '@typescript-eslint/scope-manager': 8.29.0
6079 - '@typescript-eslint/types': 8.29.0
6080 - '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.8.3)
6081 - eslint: 9.25.1(jiti@2.4.2)
6059 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.27.0(jiti@2.4.2))
6060 + '@typescript-eslint/scope-manager': 8.33.0
6061 + '@typescript-eslint/types': 8.33.0
6062 + '@typescript-eslint/typescript-estree': 8.33.0(typescript@5.8.3)
6063 + eslint: 9.27.0(jiti@2.4.2)
6064 typescript: 5.8.3
6065 transitivePeerDependencies:
6066 - supports-color
6067
6086 - '@typescript-eslint/utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)':
6068 + '@typescript-eslint/visitor-keys@8.33.0':
6069 dependencies:
6088 - '@eslint-community/eslint-utils': 4.5.1(eslint@9.25.1(jiti@2.4.2))
6089 - '@typescript-eslint/scope-manager': 8.30.1
6090 - '@typescript-eslint/types': 8.30.1
6091 - '@typescript-eslint/typescript-estree': 8.30.1(typescript@5.8.3)
6092 - eslint: 9.25.1(jiti@2.4.2)
6093 - typescript: 5.8.3
6094 - transitivePeerDependencies:
6095 - - supports-color
6096 -
6097 - '@typescript-eslint/visitor-keys@8.29.0':
6098 - dependencies:
6099 - '@typescript-eslint/types': 8.29.0
6100 - eslint-visitor-keys: 4.2.0
6101 -
6102 - '@typescript-eslint/visitor-keys@8.30.1':
6103 - dependencies:
6104 - '@typescript-eslint/types': 8.30.1
6070 + '@typescript-eslint/types': 8.33.0
6071 eslint-visitor-keys: 4.2.0
6072
6073 '@ungap/structured-clone@1.3.0': {}
6074
6109 - '@unrs/resolver-binding-darwin-arm64@1.6.3':
6075 + '@unrs/resolver-binding-darwin-arm64@1.7.5':
6076 optional: true
6077
6112 - '@unrs/resolver-binding-darwin-x64@1.6.3':
6078 + '@unrs/resolver-binding-darwin-x64@1.7.5':
6079 optional: true
6080
6115 - '@unrs/resolver-binding-freebsd-x64@1.6.3':
6081 + '@unrs/resolver-binding-freebsd-x64@1.7.5':
6082 optional: true
6083
6118 - '@unrs/resolver-binding-linux-arm-gnueabihf@1.6.3':
6084 + '@unrs/resolver-binding-linux-arm-gnueabihf@1.7.5':
6085 optional: true
6086
6121 - '@unrs/resolver-binding-linux-arm-musleabihf@1.6.3':
6087 + '@unrs/resolver-binding-linux-arm-musleabihf@1.7.5':
6088 optional: true
6089
6124 - '@unrs/resolver-binding-linux-arm64-gnu@1.6.3':
6090 + '@unrs/resolver-binding-linux-arm64-gnu@1.7.5':
6091 optional: true
6092
6127 - '@unrs/resolver-binding-linux-arm64-musl@1.6.3':
6093 + '@unrs/resolver-binding-linux-arm64-musl@1.7.5':
6094 optional: true
6095
6130 - '@unrs/resolver-binding-linux-ppc64-gnu@1.6.3':
6096 + '@unrs/resolver-binding-linux-ppc64-gnu@1.7.5':
6097 optional: true
6098
6133 - '@unrs/resolver-binding-linux-riscv64-gnu@1.6.3':
6099 + '@unrs/resolver-binding-linux-riscv64-gnu@1.7.5':
6100 optional: true
6101
6136 - '@unrs/resolver-binding-linux-s390x-gnu@1.6.3':
6102 + '@unrs/resolver-binding-linux-riscv64-musl@1.7.5':
6103 optional: true
6104
6139 - '@unrs/resolver-binding-linux-x64-gnu@1.6.3':
6105 + '@unrs/resolver-binding-linux-s390x-gnu@1.7.5':
6106 optional: true
6107
6142 - '@unrs/resolver-binding-linux-x64-musl@1.6.3':
6108 + '@unrs/resolver-binding-linux-x64-gnu@1.7.5':
6109 optional: true
6110
6145 - '@unrs/resolver-binding-wasm32-wasi@1.6.3':
6111 + '@unrs/resolver-binding-linux-x64-musl@1.7.5':
6112 + optional: true
6113 +
6114 + '@unrs/resolver-binding-wasm32-wasi@1.7.5':
6115 dependencies:
6147 - '@napi-rs/wasm-runtime': 0.2.9
6116 + '@napi-rs/wasm-runtime': 0.2.10
6117 optional: true
6118
6150 - '@unrs/resolver-binding-win32-arm64-msvc@1.6.3':
6119 + '@unrs/resolver-binding-win32-arm64-msvc@1.7.5':
6120 optional: true
6121
6153 - '@unrs/resolver-binding-win32-ia32-msvc@1.6.3':
6122 + '@unrs/resolver-binding-win32-ia32-msvc@1.7.5':
6123 optional: true
6124
6156 - '@unrs/resolver-binding-win32-x64-msvc@1.6.3':
6125 + '@unrs/resolver-binding-win32-x64-msvc@1.7.5':
6126 optional: true
6127
6159 - '@vitejs/plugin-vue-jsx@4.1.2(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))':
6128 + '@vitejs/plugin-vue-jsx@4.2.0(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))':
6129 dependencies:
6161 - '@babel/core': 7.26.10
6162 - '@babel/plugin-transform-typescript': 7.27.0(@babel/core@7.26.10)
6163 - '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.26.10)
6164 - vite: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
6165 - vue: 3.5.13(typescript@5.8.3)
6130 + '@babel/core': 7.27.3
6131 + '@babel/plugin-transform-typescript': 7.27.1(@babel/core@7.27.3)
6132 + '@rolldown/pluginutils': 1.0.0-beta.10
6133 + '@vue/babel-plugin-jsx': 1.4.0(@babel/core@7.27.3)
6134 + vite: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
6135 + vue: 3.5.15(typescript@5.8.3)
6136 transitivePeerDependencies:
6137 - supports-color
6138
6169 - '@vitejs/plugin-vue@5.2.3(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))':
6139 + '@vitejs/plugin-vue@5.2.4(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))':
6140 dependencies:
6171 - vite: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
6172 - vue: 3.5.13(typescript@5.8.3)
6141 + vite: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
6142 + vue: 3.5.15(typescript@5.8.3)
6143
6174 - '@vitest/eslint-plugin@1.1.43(@typescript-eslint/utils@8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3))(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))':
6144 + '@vitest/eslint-plugin@1.2.1(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))':
6145 dependencies:
6176 - '@typescript-eslint/utils': 8.30.1(eslint@9.25.1(jiti@2.4.2))(typescript@5.8.3)
6177 - eslint: 9.25.1(jiti@2.4.2)
6146 + '@typescript-eslint/utils': 8.33.0(eslint@9.27.0(jiti@2.4.2))(typescript@5.8.3)
6147 + eslint: 9.27.0(jiti@2.4.2)
6148 optionalDependencies:
6149 typescript: 5.8.3
6180 - vitest: 3.1.2(@types/debug@4.1.12)(@types/node@22.15.2)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
6150 + vitest: 3.1.4(@types/debug@4.1.12)(@types/node@22.15.23)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
6151 + transitivePeerDependencies:
6152 + - supports-color
6153
6182 - '@vitest/expect@3.1.2':
6154 + '@vitest/expect@3.1.4':
6155 dependencies:
6184 - '@vitest/spy': 3.1.2
6185 - '@vitest/utils': 3.1.2
6156 + '@vitest/spy': 3.1.4
6157 + '@vitest/utils': 3.1.4
6158 chai: 5.2.0
6159 tinyrainbow: 2.0.0
6160
6189 - '@vitest/mocker@3.1.2(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))':
6161 + '@vitest/mocker@3.1.4(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))':
6162 dependencies:
6191 - '@vitest/spy': 3.1.2
6163 + '@vitest/spy': 3.1.4
6164 estree-walker: 3.0.3
6165 magic-string: 0.30.17
6166 optionalDependencies:
6195 - vite: 6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1)
6167 + vite: 6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0)
6168
6197 - '@vitest/pretty-format@3.1.2':
6169 + '@vitest/pretty-format@3.1.4':
6170 dependencies:
6171 tinyrainbow: 2.0.0
6172
6201 - '@vitest/runner@3.1.2':
6173 + '@vitest/runner@3.1.4':
6174 dependencies:
6203 - '@vitest/utils': 3.1.2
6175 + '@vitest/utils': 3.1.4
6176 pathe: 2.0.3
6177
6206 - '@vitest/snapshot@3.1.2':
6178 + '@vitest/snapshot@3.1.4':
6179 dependencies:
6208 - '@vitest/pretty-format': 3.1.2
6180 + '@vitest/pretty-format': 3.1.4
6181 magic-string: 0.30.17
6182 pathe: 2.0.3
6183
6212 - '@vitest/spy@3.1.2':
6184 + '@vitest/spy@3.1.4':
6185 dependencies:
6186 tinyspy: 3.0.2
6187
6216 - '@vitest/utils@3.1.2':
6188 + '@vitest/utils@3.1.4':
6189 dependencies:
6218 - '@vitest/pretty-format': 3.1.2
6190 + '@vitest/pretty-format': 3.1.4
6191 loupe: 3.1.3
6192 tinyrainbow: 2.0.0
6193
6222 - '@volar/language-core@2.4.12':
6194 + '@volar/language-core@2.4.14':
6195 dependencies:
6224 - '@volar/source-map': 2.4.12
6196 + '@volar/source-map': 2.4.14
6197
6226 - '@volar/source-map@2.4.12': {}
6198 + '@volar/source-map@2.4.14': {}
6199
6228 - '@volar/typescript@2.4.12':
6200 + '@volar/typescript@2.4.14':
6201 dependencies:
6230 - '@volar/language-core': 2.4.12
6202 + '@volar/language-core': 2.4.14
6203 path-browserify: 1.0.1
6204 vscode-uri: 3.1.0
6205
6206 '@vue/babel-helper-vue-transform-on@1.4.0': {}
6207
6236 - '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.26.10)':
6208 + '@vue/babel-plugin-jsx@1.4.0(@babel/core@7.27.3)':
6209 dependencies:
6238 - '@babel/helper-module-imports': 7.25.9
6239 - '@babel/helper-plugin-utils': 7.26.5
6240 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10)
6241 - '@babel/template': 7.27.0
6242 - '@babel/traverse': 7.27.0
6243 - '@babel/types': 7.27.0
6210 + '@babel/helper-module-imports': 7.27.1
6211 + '@babel/helper-plugin-utils': 7.27.1
6212 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.3)
6213 + '@babel/template': 7.27.2
6214 + '@babel/traverse': 7.27.3
6215 + '@babel/types': 7.27.3
6216 '@vue/babel-helper-vue-transform-on': 1.4.0
6245 - '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.26.10)
6246 - '@vue/shared': 3.5.13
6217 + '@vue/babel-plugin-resolve-type': 1.4.0(@babel/core@7.27.3)
6218 + '@vue/shared': 3.5.15
6219 optionalDependencies:
6248 - '@babel/core': 7.26.10
6220 + '@babel/core': 7.27.3
6221 transitivePeerDependencies:
6222 - supports-color
6223
6252 - '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.26.10)':
6224 + '@vue/babel-plugin-resolve-type@1.4.0(@babel/core@7.27.3)':
6225 dependencies:
6254 - '@babel/code-frame': 7.26.2
6255 - '@babel/core': 7.26.10
6256 - '@babel/helper-module-imports': 7.25.9
6257 - '@babel/helper-plugin-utils': 7.26.5
6258 - '@babel/parser': 7.27.0
6259 - '@vue/compiler-sfc': 3.5.13
6226 + '@babel/code-frame': 7.27.1
6227 + '@babel/core': 7.27.3
6228 + '@babel/helper-module-imports': 7.27.1
6229 + '@babel/helper-plugin-utils': 7.27.1
6230 + '@babel/parser': 7.27.3
6231 + '@vue/compiler-sfc': 3.5.15
6232 transitivePeerDependencies:
6233 - supports-color
6234
6263 - '@vue/compiler-core@3.5.13':
6235 + '@vue/compiler-core@3.5.15':
6236 dependencies:
6265 - '@babel/parser': 7.27.0
6266 - '@vue/shared': 3.5.13
6237 + '@babel/parser': 7.27.3
6238 + '@vue/shared': 3.5.15
6239 entities: 4.5.0
6240 estree-walker: 2.0.2
6241 source-map-js: 1.2.1
6242
6271 - '@vue/compiler-dom@3.5.13':
6243 + '@vue/compiler-dom@3.5.15':
6244 dependencies:
6273 - '@vue/compiler-core': 3.5.13
6274 - '@vue/shared': 3.5.13
6245 + '@vue/compiler-core': 3.5.15
6246 + '@vue/shared': 3.5.15
6247
6276 - '@vue/compiler-sfc@3.5.13':
6248 + '@vue/compiler-sfc@3.5.15':
6249 dependencies:
6278 - '@babel/parser': 7.27.0
6279 - '@vue/compiler-core': 3.5.13
6280 - '@vue/compiler-dom': 3.5.13
6281 - '@vue/compiler-ssr': 3.5.13
6282 - '@vue/shared': 3.5.13
6250 + '@babel/parser': 7.27.3
6251 + '@vue/compiler-core': 3.5.15
6252 + '@vue/compiler-dom': 3.5.15
6253 + '@vue/compiler-ssr': 3.5.15
6254 + '@vue/shared': 3.5.15
6255 estree-walker: 2.0.2
6256 magic-string: 0.30.17
6257 postcss: 8.5.3
6258 source-map-js: 1.2.1
6259
6288 - '@vue/compiler-ssr@3.5.13':
6260 + '@vue/compiler-ssr@3.5.15':
6261 dependencies:
6290 - '@vue/compiler-dom': 3.5.13
6291 - '@vue/shared': 3.5.13
6262 + '@vue/compiler-dom': 3.5.15
6263 + '@vue/shared': 3.5.15
6264
6265 '@vue/compiler-vue2@2.7.16':
6266 dependencies:
@@ -6297,35 +6269,25 @@ snapshots:
6269
6270 '@vue/devtools-api@6.6.4': {}
6271
6300 - '@vue/devtools-api@7.7.2':
6272 + '@vue/devtools-api@7.7.6':
6273 dependencies:
6302 - '@vue/devtools-kit': 7.7.2
6274 + '@vue/devtools-kit': 7.7.6
6275
6304 - '@vue/devtools-core@7.7.5(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))(vue@3.5.13(typescript@5.8.3))':
6276 + '@vue/devtools-core@7.7.6(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))(vue@3.5.15(typescript@5.8.3))':
6277 dependencies:
6306 - '@vue/devtools-kit': 7.7.5
6307 - '@vue/devtools-shared': 7.7.5
6278 + '@vue/devtools-kit': 7.7.6
6279 + '@vue/devtools-shared': 7.7.6
6280 mitt: 3.0.1
6281 nanoid: 5.1.5
6282 pathe: 2.0.3
6311 - vite-hot-client: 2.0.4(vite@6.3.3(@types/node@22.15.2)(jiti@2.4.2)(lightningcss@1.29.2)(sass@1.87.0)(yaml@2.7.1))
6312 - vue: 3.5.13(typescript@5.8.3)
6283 + vite-hot-client: 2.0.4(vite@6.3.5(@types/node@22.15.23)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.0)(yaml@2.8.0))
6284 + vue: 3.5.15(typescript@5.8.3)
6285 transitivePeerDependencies:
6286 - vite
6287
6316 - '@vue/devtools-kit@7.7.2':
6288 + '@vue/devtools-kit@7.7.6':
6289 dependencies:
6318 - '@vue/devtools-shared': 7.7.2
6319 - birpc: 0.2.19
6320 - hookable: 5.5.3
6321 - mitt: 3.0.1
6322 - perfect-debounce: 1.0.0
6323 - speakingurl: 14.0.1
6324 - superjson: 2.2.2
6325 -
6326 - '@vue/devtools-kit@7.7.5':
6327 - dependencies:
6328 - '@vue/devtools-shared': 7.7.5
6290 + '@vue/devtools-shared': 7.7.6
6291 birpc: 2.3.0
6292 hookable: 5.5.3
6293 mitt: 3.0.1
@@ -6333,20 +6295,16 @@ snapshots:
6295 speakingurl: 14.0.1
6296 superjson: 2.2.2
6297
6336 - '@vue/devtools-shared@7.7.2':
6337 - dependencies:
6338 - rfdc: 1.4.1
6339 -
6340 - '@vue/devtools-shared@7.7.5':
6298 + '@vue/devtools-shared@7.7.6':
6299 dependencies:
6300 rfdc: 1.4.1
6301
6302 '@vue/language-core@2.2.10(typescript@5.8.3)':
6303 dependencies:
6346 - '@volar/language-core': 2.4.12
6347 - '@vue/compiler-dom': 3.5.13
6304 + '@volar/language-core': 2.4.14
6305 + '@vue/compiler-dom': 3.5.15
6306 '@vue/compiler-vue2': 2.7.16
6349 - '@vue/shared': 3.5.13
6307 + '@vue/shared': 3.5.15
6308 alien-signals: 1.0.13
6309 minimatch: 9.0.5
6310 muggle-string: 0.4.1
@@ -6354,52 +6312,66 @@ snapshots:
6312 optionalDependencies:
6313 typescript: 5.8.3
6314
6357 - '@vue/reactivity@3.5.13':
6315 + '@vue/reactivity@3.5.15':
6316 dependencies:
6359 - '@vue/shared': 3.5.13
6317 + '@vue/shared': 3.5.15
6318
6361 - '@vue/runtime-core@3.5.13':
6319 + '@vue/runtime-core@3.5.15':
6320 dependencies:
6363 - '@vue/reactivity': 3.5.13
6364 - '@vue/shared': 3.5.13
6321 + '@vue/reactivity': 3.5.15
6322 + '@vue/shared': 3.5.15
6323
6366 - '@vue/runtime-dom@3.5.13':
6324 + '@vue/runtime-dom@3.5.15':
6325 dependencies:
6368 - '@vue/reactivity': 3.5.13
6369 - '@vue/runtime-core': 3.5.13
6370 - '@vue/shared': 3.5.13
6326 + '@vue/reactivity': 3.5.15
6327 + '@vue/runtime-core': 3.5.15
6328 + '@vue/shared': 3.5.15
6329 csstype: 3.1.3
6330
6373 - '@vue/server-renderer@3.5.13(vue@3.5.13(typescript@5.8.3))':
6331 + '@vue/server-renderer@3.5.15(vue@3.5.15(typescript@5.8.3))':
6332 dependencies:
6375 - '@vue/compiler-ssr': 3.5.13
6376 - '@vue/shared': 3.5.13
6377 - vue: 3.5.13(typescript@5.8.3)
6333 + '@vue/compiler-ssr': 3.5.15
6334 + '@vue/shared': 3.5.15
6335 + vue: 3.5.15(typescript@5.8.3)
6336
6379 - '@vue/shared@3.5.13': {}
6337 + '@vue/shared@3.5.15': {}
6338
6339 '@vue/test-utils@2.4.6':
6340 dependencies:
6341 js-beautify: 1.15.4
6384 - vue-component-type-helpers: 2.2.8
6342 + vue-component-type-helpers: 2.2.10
6343
6386 - '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.13(typescript@5.8.3))':
6344 + '@vue/tsconfig@0.7.0(typescript@5.8.3)(vue@3.5.15(typescript@5.8.3))':
6345 optionalDependencies:
6346 typescript: 5.8.3
6389 - vue: 3.5.13(typescript@5.8.3)
6347 + vue: 3.5.15(typescript@5.8.3)
6348
6391 - '@vueuse/core@13.1.0(vue@3.5.13(typescript@5.8.3))':
6349 + '@vueuse/core@13.3.0(vue@3.5.15(typescript@5.8.3))':
6350 dependencies:
6351 '@types/web-bluetooth': 0.0.21
6394 - '@vueuse/metadata': 13.1.0
6395 - '@vueuse/shared': 13.1.0(vue@3.5.13(typescript@5.8.3))
6396 - vue: 3.5.13(typescript@5.8.3)
6352 + '@vueuse/metadata': 13.3.0
6353 + '@vueuse/shared': 13.3.0(vue@3.5.15(typescript@5.8.3))
6354 + vue: 3.5.15(typescript@5.8.3)
6355
6398 - '@vueuse/metadata@13.1.0': {}
6356 + '@vueuse/metadata@13.3.0': {}
6357
6400 - '@vueuse/shared@13.1.0(vue@3.5.13(typescript@5.8.3))':
6358 + '@vueuse/motion@3.0.3(vue@3.5.15(typescript@5.8.3))':
6359 dependencies:
6402 - vue: 3.5.13(typescript@5.8.3)
6360 + '@vueuse/core': 13.3.0(vue@3.5.15(typescript@5.8.3))
6361 + '@vueuse/shared': 13.3.0(vue@3.5.15(typescript@5.8.3))
6362 + defu: 6.1.4
6363 + framesync: 6.1.2
6364 + popmotion: 11.0.5
6365 + style-value-types: 5.1.2
6366 + vue: 3.5.15(typescript@5.8.3)
6367 + optionalDependencies:
6368 + '@nuxt/kit': 3.17.4
6369 + transitivePeerDependencies:
6370 + - magicast
6371 +
6372 + '@vueuse/shared@13.3.0(vue@3.5.15(typescript@5.8.3))':
6373 + dependencies:
6374 + vue: 3.5.15(typescript@5.8.3)
6375
6376 '@yr/monotone-cubic-spline@1.0.3': {}
6377
@@ -6443,15 +6415,15 @@ snapshots:
6415
6416 ansi-styles@6.2.1: {}
6417
6446 - ansis@3.17.0: {}
6418 + ansis@4.0.0: {}
6419
6448 - apexcharts@4.5.0:
6420 + apexcharts@4.7.0:
6421 dependencies:
6422 '@svgdotjs/svg.draggable.js': 3.0.6(@svgdotjs/svg.js@3.2.4)
6423 '@svgdotjs/svg.filter.js': 3.0.9
6424 '@svgdotjs/svg.js': 3.2.4
6453 - '@svgdotjs/svg.resize.js': 2.0.5(@svgdotjs/svg.js@3.2.4)(@svgdotjs/svg.select.js@4.0.2(@svgdotjs/svg.js@3.2.4))
6454 - '@svgdotjs/svg.select.js': 4.0.2(@svgdotjs/svg.js@3.2.4)
6425 + '@svgdotjs/svg.resize.js': 2.0.5(@svgdotjs/svg.js@3.2.4)(@svgdotjs/svg.select.js@4.0.3(@svgdotjs/svg.js@3.2.4))
6426 + '@svgdotjs/svg.select.js': 4.0.3(@svgdotjs/svg.js@3.2.4)
6427 '@yr/monotone-cubic-spline': 1.0.3
6428
6429 arch@2.2.0: {}
@@ -6494,9 +6466,9 @@ snapshots:
6466
6467 aws4@1.13.2: {}
6468
6497 - axios@1.9.0(debug@4.4.0):
6469 + axios@1.9.0(debug@4.4.1):
6470 dependencies:
6499 - follow-redirects: 1.15.9(debug@4.4.0)
6471 + follow-redirects: 1.15.9(debug@4.4.1)
6472 form-data: 4.0.2
6473 proxy-from-env: 1.1.0
6474 transitivePeerDependencies:
@@ -6510,8 +6482,6 @@ snapshots:
6482 dependencies:
6483 tweetnacl: 0.14.5
6484
6513 - birpc@0.2.19: {}
6514 -
6485 birpc@2.3.0: {}
6486
6487 blob-util@2.0.2: {}
@@ -6533,12 +6503,12 @@ snapshots:
6503 dependencies:
6504 fill-range: 7.1.1
6505
6536 - browserslist@4.24.4:
6506 + browserslist@4.24.5:
6507 dependencies:
6538 - caniuse-lite: 1.0.30001709
6539 - electron-to-chromium: 1.5.130
6508 + caniuse-lite: 1.0.30001718
6509 + electron-to-chromium: 1.5.159
6510 node-releases: 2.0.19
6541 - update-browserslist-db: 1.1.3(browserslist@4.24.4)
6511 + update-browserslist-db: 1.1.3(browserslist@4.24.5)
6512
6513 buffer-crc32@0.2.13: {}
6514

This file is too large to show in full.

frontend/src/App.vue
+3 -3
@@ -23,9 +23,11 @@
23 </template>
24
25 <script lang="ts" setup>
26 -import type { Layout, RouterTransition, ThemeNameEnum } from "@/types/theme.d"
26 import type { Component } from "vue"
27 import type { RouteLocationNormalized } from "vue-router"
28 +import type { Layout, RouterTransition, ThemeNameEnum } from "@/types/theme.d"
29 +import { computed, onBeforeMount, ref, watch } from "vue"
30 +import { useRoute, useRouter } from "vue-router"
31 import Blank from "@/app-layouts/Blank"
32 import Provider from "@/app-layouts/common/Provider.vue"
33 import SplashScreen from "@/app-layouts/common/SplashScreen.vue"
@@ -34,8 +36,6 @@ import SearchDialog from "@/components/common/SearchDialog.vue"
36 import { useAuthStore } from "@/stores/auth"
37 import { useMainStore } from "@/stores/main"
38 import { useThemeStore } from "@/stores/theme"
37 -import { computed, onBeforeMount, ref, watch } from "vue"
38 -import { useRoute, useRouter } from "vue-router"
39
40 const router = useRouter()
41 const route = useRoute()
frontend/src/api/endpoints/incidentManagement/alerts.ts
+1 -1
@@ -1,3 +1,4 @@
1 +import type { KeysOfUnion, UnionToIntersection } from "type-fest"
2 import type { FlaskBaseResponse } from "@/types/flask.d"
3 import type {
4 Alert,
@@ -9,7 +10,6 @@ import type {
10 AlertTag,
11 AlertTimeline
12 } from "@/types/incidentManagement/alerts.d"
12 -import type { KeysOfUnion, UnionToIntersection } from "type-fest"
13 import _castArray from "lodash/castArray"
14 import { HttpClient } from "../../httpClient"
15
frontend/src/api/endpoints/incidentManagement/cases.ts
+1 -1
@@ -1,3 +1,4 @@
1 +import type { KeysOfUnion, UnionToIntersection } from "type-fest"
2 import type { FlaskBaseResponse } from "@/types/flask.d"
3 import type {
4 Case,
@@ -6,7 +7,6 @@ import type {
7 CaseReportTemplateDataStore,
8 CaseStatus
9 } from "@/types/incidentManagement/cases.d"
9 -import type { KeysOfUnion, UnionToIntersection } from "type-fest"
10 import { HttpClient } from "../../httpClient"
11
12 export type CasesFilter =
frontend/src/api/endpoints/logs.ts
+1 -1
@@ -1,6 +1,6 @@
1 +import type { UnionToIntersection } from "type-fest"
2 import type { FlaskBaseResponse } from "@/types/flask.d"
3 import type { Log, LogsQuery, LogsQueryTimeRange } from "@/types/logs.d"
3 -import type { UnionToIntersection } from "type-fest"
4 import { HttpClient } from "../httpClient"
5
6 export default {
frontend/src/api/endpoints/mitre.ts new
+241
@@ -0,0 +1,241 @@
1 +/* eslint-disable jsdoc/no-multi-asterisks */
2 +import type { FlaskBaseResponse } from "@/types/flask.d"
3 +import type {
4 + MitreAtomicTest,
5 + MitreEventDetails,
6 + MitreGroupDetails,
7 + MitreMitigationDetails,
8 + MitreSoftwareDetails,
9 + MitreTacticDetails,
10 + MitreTechnique,
11 + MitreTechniquesDetails
12 +} from "@/types/mitre.d"
13 +import { HttpClient } from "../httpClient"
14 +
15 +export type MitreTechniquesAlertsQueryTimeRange = `${number}${"h" | "d" | "w"}`
16 +
17 +export interface MitreTechniquesAlertsQuery {
18 + /** Time range for the search (e.g., now-24h, now-7d) */
19 + time_range?: MitreTechniquesAlertsQueryTimeRange
20 + /** Maximum number of techniques to return per page */
21 + size?: number
22 + /** Page number for pagination */
23 + page?: number
24 + /** Filter by rule level */
25 + rule_level?: string
26 + /** Filter by rule group */
27 + rule_group?: string
28 + /** Override the field containing MITRE IDs */
29 + mitre_field?: string
30 + /** Index pattern to search; Default value : wazuh-* */
31 + index_pattern?: string
32 +}
33 +
34 +export interface MitreGroupsQuery {
35 + id: string
36 +}
37 +
38 +export interface MitreMitigationsQuery {
39 + id: string
40 +}
41 +
42 +export interface MitreSoftwareQuery {
43 + id: string
44 +}
45 +
46 +export interface MitreTacticsQuery {
47 + id: string
48 +}
49 +
50 +export interface MitreTechniquesQuery {
51 + external_id?: string
52 + id?: string
53 +}
54 +
55 +export interface MitreEventsQuery {
56 + /** MITRE ATT&CK technique ID (e.g., T1047, 1047) */
57 + technique_id: string
58 + /** Time range for the search (e.g., now-24h, now-7d) */
59 + time_range?: string
60 + /** Maximum number of techniques to return per page */
61 + size?: number
62 + /** Page number for pagination */
63 + page?: number
64 + /** Filter by rule level */
65 + rule_level?: string
66 + /** Filter by rule group */
67 + rule_group?: string
68 + /** Override the field containing MITRE IDs */
69 + mitre_field?: string
70 + /** Index pattern to search; Default value : wazuh-* */
71 + index_pattern?: string
72 +}
73 +
74 +export interface MitreAtomicTestsQuery {
75 + /** Maximum number of techniques to return per page */
76 + size?: number
77 + /** Page number for pagination */
78 + page?: number
79 +}
80 +
81 +export default {
82 + getMitreTechniquesAlerts(query: MitreTechniquesAlertsQuery, signal?: AbortSignal) {
83 + return HttpClient.get<
84 + FlaskBaseResponse & {
85 + total_alerts: number
86 + techniques_count: number
87 + techniques: MitreTechnique[]
88 + time_range: string
89 + field_used: string
90 + page: number
91 + page_size: number
92 + total_pages: number
93 + }
94 + >(`/wazuh_manager/mitre/techniques/alerts`, {
95 + params: {
96 + time_range: query?.time_range || "now-24h",
97 + size: query?.size || 25,
98 + page: query?.page || 1,
99 + rule_level: query?.rule_level,
100 + rule_group: query?.rule_group,
101 + mitre_field: query?.mitre_field,
102 + index_pattern: query?.index_pattern || "wazuh-*"
103 + },
104 + signal
105 + })
106 + },
107 + getMitreTechniques(query?: MitreTechniquesQuery) {
108 + let q: string | undefined
109 +
110 + if (query?.external_id) {
111 + q = `external_id=${query?.external_id}`
112 + }
113 +
114 + if (query?.id) {
115 + q = `id=${query?.id}`
116 + }
117 +
118 + return HttpClient.get<FlaskBaseResponse & { results: MitreTechniquesDetails[] }>(
119 + `/wazuh_manager/mitre/techniques`,
120 + {
121 + params: {
122 + q
123 + }
124 + }
125 + )
126 + },
127 + getMitreGroups(query?: MitreGroupsQuery) {
128 + let q: string | undefined
129 +
130 + if (query?.id) {
131 + q = `id=${query?.id}`
132 + }
133 +
134 + return HttpClient.get<FlaskBaseResponse & { results: MitreGroupDetails[]; total: number }>(
135 + `/wazuh_manager/mitre/groups`,
136 + {
137 + params: {
138 + q
139 + }
140 + }
141 + )
142 + },
143 + getMitreMitigations(query?: MitreMitigationsQuery) {
144 + let q: string | undefined
145 +
146 + if (query?.id) {
147 + q = `id=${query?.id}`
148 + }
149 +
150 + return HttpClient.get<FlaskBaseResponse & { results: MitreMitigationDetails[]; total: number }>(
151 + `/wazuh_manager/mitre/mitigations`,
152 + {
153 + params: {
154 + q
155 + }
156 + }
157 + )
158 + },
159 + getMitreSoftware(query?: MitreSoftwareQuery) {
160 + let q: string | undefined
161 +
162 + if (query?.id) {
163 + q = `id=${query?.id}`
164 + }
165 +
166 + return HttpClient.get<FlaskBaseResponse & { results: MitreSoftwareDetails[] }>(
167 + `/wazuh_manager/mitre/software`,
168 + {
169 + params: {
170 + q
171 + }
172 + }
173 + )
174 + },
175 + getMitreTactics(query?: MitreTacticsQuery) {
176 + let q: string | undefined
177 +
178 + if (query?.id) {
179 + q = `id=${query?.id}`
180 + }
181 +
182 + return HttpClient.get<FlaskBaseResponse & { results: MitreTacticDetails[] }>(`/wazuh_manager/mitre/tactics`, {
183 + params: {
184 + q
185 + }
186 + })
187 + },
188 + getMitreEvents(query: MitreEventsQuery, signal?: AbortSignal) {
189 + return HttpClient.get<
190 + FlaskBaseResponse & {
191 + technique_id: string
192 + technique_name: string
193 + total_alerts: number
194 + total_pages: number
195 + page_size: number
196 + page: number
197 + alerts: MitreEventDetails[]
198 + field_used: string
199 + time_range: string
200 + }
201 + >(`/wazuh_manager/mitre/techniques/${query.technique_id}/alerts`, {
202 + params: {
203 + time_range: query?.time_range || "now-24h",
204 + size: query?.size || 25,
205 + page: query?.page || 1,
206 + rule_level: query?.rule_level,
207 + rule_group: query?.rule_group,
208 + mitre_field: query?.mitre_field,
209 + index_pattern: query?.index_pattern || "wazuh-*"
210 + },
211 + signal
212 + })
213 + },
214 + getMitreAtomicTests(query: MitreAtomicTestsQuery, signal?: AbortSignal) {
215 + return HttpClient.get<
216 + FlaskBaseResponse & {
217 + total_techniques: number
218 + total_tests: number
219 + tests: MitreAtomicTest[]
220 + last_updated: Date
221 + page: number
222 + page_size: number
223 + total_pages: number
224 + }
225 + >(`/wazuh_manager/mitre/atomic-tests`, {
226 + params: {
227 + size: query?.size || 25,
228 + page: query?.page || 1
229 + },
230 + signal
231 + })
232 + },
233 + getMitreAtomicTestContent(technique_id: string) {
234 + return HttpClient.get<
235 + FlaskBaseResponse & {
236 + technique_id: string
237 + markdown_content: string
238 + }
239 + >(`/wazuh_manager/mitre/techniques/${technique_id}/atomic-tests`)
240 + }
241 +}
frontend/src/api/httpClient.ts
+1 -1
@@ -1,7 +1,7 @@
1 import type { AxiosRequestHeaders } from "axios"
2 +import axios from "axios"
3 import { useAuthStore } from "@/stores/auth"
4 import { isDebounceTimeOver, isJwtExpiring } from "@/utils/auth"
4 -import axios from "axios"
5 // import { useGlobalActions } from "@/composables/useGlobalActions"
6
7 const HttpClient = axios.create({
frontend/src/api/index.ts
+2
@@ -15,6 +15,7 @@ import indices from "./endpoints/indices"
15 import integrations from "./endpoints/integrations"
16 import license from "./endpoints/license"
17 import logs from "./endpoints/logs"
18 +import mitre from "./endpoints/mitre"
19 import monitoringAlerts from "./endpoints/monitoringAlerts"
20 import networkConnectors from "./endpoints/networkConnectors"
21 import portainer from "./endpoints/portainer"
@@ -57,5 +58,6 @@ export default {
58 sigma,
59 users,
60 sysmonConfig,
61 + mitre,
62 portainer
63 }
frontend/src/app-layouts/Blank/MainContainer.vue
+1 -1
@@ -14,10 +14,10 @@
14
15 <script lang="ts" setup>
16 import type { RouteLocationNormalizedGeneric } from "vue-router"
17 -import { useThemeStore } from "@/stores/theme"
17 import { NScrollbar } from "naive-ui"
18 import { computed, onMounted, ref } from "vue"
19 import { useRoute, useRouter } from "vue-router"
20 +import { useThemeStore } from "@/stores/theme"
21
22 const themeStore = useThemeStore()
23 const router = useRouter()
frontend/src/app-layouts/HorizontalNav/HeaderBar.vue
+2 -2
@@ -8,11 +8,11 @@
8 </template>
9
10 <script lang="ts" setup>
11 +import { NScrollbar } from "naive-ui"
12 +import { computed } from "vue"
13 import Logo from "@/app-layouts/common/Logo.vue"
14 import Navbar from "@/app-layouts/common/Navbar"
15 import { useThemeStore } from "@/stores/theme"
14 -import { NScrollbar } from "naive-ui"
15 -import { computed } from "vue"
16
17 const themeStore = useThemeStore()
18 const isDark = computed<boolean>(() => themeStore.isThemeDark)
frontend/src/app-layouts/HorizontalNav/MainContainer.vue
+3 -3
@@ -29,12 +29,12 @@
29
30 <script lang="ts" setup>
31 import type { RouteLocationNormalizedGeneric } from "vue-router"
32 -import MainFooter from "@/app-layouts/common/MainFooter.vue"
33 -import Toolbar from "@/app-layouts/common/Toolbar"
34 -import { useThemeStore } from "@/stores/theme"
32 import { NScrollbar } from "naive-ui"
33 import { computed, onMounted, ref } from "vue"
34 import { useRoute, useRouter } from "vue-router"
35 +import MainFooter from "@/app-layouts/common/MainFooter.vue"
36 +import Toolbar from "@/app-layouts/common/Toolbar"
37 +import { useThemeStore } from "@/stores/theme"
38
39 const themeStore = useThemeStore()
40 const router = useRouter()
frontend/src/app-layouts/HorizontalNav/Sidebar.vue
+3 -3
@@ -21,12 +21,12 @@
21 </template>
22
23 <script lang="ts" setup>
24 -import Navbar from "@/app-layouts/common/Navbar"
25 -import { useThemeStore } from "@/stores/theme"
26 -import { isMobile } from "@/utils"
24 import { onClickOutside, useElementHover } from "@vueuse/core"
25 import { NScrollbar } from "naive-ui"
26 import { computed, onMounted, ref, watch } from "vue"
27 +import Navbar from "@/app-layouts/common/Navbar"
28 +import { useThemeStore } from "@/stores/theme"
29 +import { isMobile } from "@/utils"
30 import SidebarFooter from "./SidebarFooter.vue"
31 import SidebarHeader from "./SidebarHeader.vue"
32
frontend/src/app-layouts/HorizontalNav/SidebarFooter.vue
+2 -2
@@ -5,10 +5,10 @@
5 </template>
6
7 <script lang="ts" setup>
8 -import { useThemeStore } from "@/stores/theme"
9 -import { renderIcon } from "@/utils"
8 import { NMenu } from "naive-ui"
9 import { computed, h, ref } from "vue"
10 +import { useThemeStore } from "@/stores/theme"
11 +import { renderIcon } from "@/utils"
12
13 const { collapsed = false } = defineProps<{
14 collapsed?: boolean
frontend/src/app-layouts/HorizontalNav/SidebarHeader.vue
+2 -2
@@ -30,11 +30,11 @@
30 </template>
31
32 <script lang="ts" setup>
33 +import { Icon as Iconify } from "@iconify/vue"
34 +import { computed } from "vue"
35 import Logo from "@/app-layouts/common/Logo.vue"
36 import Icon from "@/components/common/Icon.vue"
37 import { useThemeStore } from "@/stores/theme"
36 -import { Icon as Iconify } from "@iconify/vue"
37 -import { computed } from "vue"
38
39 const { logoMini } = defineProps<{
40 logoMini?: boolean
frontend/src/app-layouts/common/GlobalListener.vue
+1 -1
@@ -3,8 +3,8 @@
3 </template>
4
5 <script setup lang="ts">
6 -import { useGlobalActions } from "@/composables/useGlobalActions"
6 import { useMessage, useNotification } from "naive-ui"
7 +import { useGlobalActions } from "@/composables/useGlobalActions"
8
9 const message = useMessage()
10 const notification = useNotification()
frontend/src/app-layouts/common/Logo.vue
+1 -1
@@ -14,8 +14,8 @@
14 </template>
15
16 <script lang="ts" setup>
17 -import { useThemeStore } from "@/stores/theme"
17 import { computed } from "vue"
18 +import { useThemeStore } from "@/stores/theme"
19
20 const {
21 mini,
frontend/src/app-layouts/common/MainFooter.vue
+1 -1
@@ -23,9 +23,9 @@
23 </template>
24
25 <script lang="ts" setup>
26 +import { ref } from "vue"
27 import BrainIcon from "@/assets/icons/brain-icon.svg"
28 import Icon from "@/components/common/Icon.vue"
28 -import { ref } from "vue"
29
30 const { boxed } = defineProps<{
31 boxed: boolean
frontend/src/app-layouts/common/Navbar/Navbar.vue
+1 -1
@@ -25,11 +25,11 @@
25 import type { MenuInst } from "naive-ui"
26 import type { MenuMixedOption } from "naive-ui/es/menu/src/interface"
27 import type { RouteRecordNormalized } from "vue-router"
28 -import { useThemeStore } from "@/stores/theme"
28 import _uniq from "lodash/uniq"
29 import { NMenu } from "naive-ui"
30 import { computed, onBeforeMount, ref } from "vue"
31 import { useRoute, useRouter } from "vue-router"
32 +import { useThemeStore } from "@/stores/theme"
33 import getItems from "./items"
34
35 const { mode = "horizontal", collapsed = false } = defineProps<{
frontend/src/app-layouts/common/Navbar/items.tsx
+46 -14
@@ -1,9 +1,9 @@
1 import type { MenuMixedOption } from "naive-ui/es/menu/src/interface"
2 -import IncidentManagementIcon from "@/assets/icons/alert-settings-icon.svg"
3 -import { renderIcon } from "@/utils"
2 import { h } from "vue"
5 -
3 import { RouterLink } from "vue-router"
4 +import IncidentManagementIcon from "@/assets/icons/alert-settings-icon.svg"
5 +
6 +import { renderIcon } from "@/utils"
7
8 const OverviewIcon = "carbon:dashboard"
9 const IndiciesIcon = "ph:list-magnifying-glass"
@@ -143,18 +143,50 @@ export default function getItems(): MenuMixedOption[] {
143 ]
144 },
145 {
146 - label: () =>
147 - h(
148 - RouterLink,
149 - {
150 - to: {
151 - name: "Alerts"
152 - }
153 - },
154 - { default: () => "Alerts" }
155 - ),
146 + label: "Alerts",
147 key: "Alerts",
157 - icon: renderIcon(AlertsIcon)
148 + icon: renderIcon(AlertsIcon),
149 + children: [
150 + {
151 + label: () =>
152 + h(
153 + RouterLink,
154 + {
155 + to: {
156 + name: "Alerts-SIEM"
157 + }
158 + },
159 + { default: () => "SIEM" }
160 + ),
161 + key: "Alerts-SIEM"
162 + },
163 + {
164 + label: () =>
165 + h(
166 + RouterLink,
167 + {
168 + to: {
169 + name: "Alerts-Mitre"
170 + }
171 + },
172 + { default: () => "MITRE ATT&CK" }
173 + ),
174 + key: "Alerts-Mitre"
175 + },
176 + {
177 + label: () =>
178 + h(
179 + RouterLink,
180 + {
181 + to: {
182 + name: "Alerts-AtomicRedTeam"
183 + }
184 + },
185 + { default: () => "Atomic Red Team" }
186 + ),
187 + key: "Alerts-AtomicRedTeam"
188 + }
189 + ]
190 },
191 {
192 label: () =>
frontend/src/app-layouts/common/Provider.vue
+3 -3
@@ -26,9 +26,6 @@
26 <script lang="ts" setup>
27 import type { GlobalThemeOverrides } from "naive-ui"
28 import type { RtlItem } from "naive-ui/es/config-provider/src/internal-interface"
29 -import GlobalListener from "@/app-layouts/common/GlobalListener.vue"
30 -import { useLocalesStore } from "@/stores/i18n"
31 -import { useThemeStore } from "@/stores/theme"
29 import {
30 NConfigProvider,
31 NDialogProvider,
@@ -38,6 +35,9 @@ import {
35 NNotificationProvider
36 } from "naive-ui"
37 import { computed, onBeforeMount } from "vue"
38 +import GlobalListener from "@/app-layouts/common/GlobalListener.vue"
39 +import { useLocalesStore } from "@/stores/i18n"
40 +import { useThemeStore } from "@/stores/theme"
41 import { rtlStyles } from "./rtlProvider"
42
43 const localesStore = useLocalesStore()
frontend/src/app-layouts/common/Toolbar/Avatar.vue
+2 -2
@@ -5,11 +5,11 @@
5 </template>
6
7 <script lang="ts" setup>
8 -import { useAuthStore } from "@/stores/auth"
9 -import { renderIcon } from "@/utils"
8 import { NAvatar, NDropdown } from "naive-ui"
9 import { h, ref } from "vue"
10 import { useRouter } from "vue-router"
11 +import { useAuthStore } from "@/stores/auth"
12 +import { renderIcon } from "@/utils"
13
14 const UserIcon = "ion:person-outline"
15 const LicenseIcon = "carbon:license"
frontend/src/app-layouts/common/Toolbar/Breadcrumb.vue
+1 -1
@@ -18,7 +18,6 @@
18
19 <script lang="ts" setup>
20 import type { RouteLocationNormalizedLoaded } from "vue-router"
21 -import Icon from "@/components/common/Icon.vue"
21 import _capitalize from "lodash/capitalize"
22 import _compact from "lodash/compact"
23 import _isEqual from "lodash/isEqual"
@@ -26,6 +25,7 @@ import _split from "lodash/split"
25 import { NBreadcrumb, NBreadcrumbItem } from "naive-ui"
26 import { onBeforeMount, ref } from "vue"
27 import { useRoute, useRouter } from "vue-router"
28 +import Icon from "@/components/common/Icon.vue"
29
30 interface Page {
31 name: string
frontend/src/app-layouts/common/Toolbar/LocaleSwitch.vue
+2 -2
@@ -7,11 +7,11 @@
7 <script lang="ts" setup>
8 import type { SelectOption } from "naive-ui"
9 import type { VNodeChild } from "vue"
10 -import Icon from "@/components/common/Icon.vue"
11 -import { useLocalesStore } from "@/stores/i18n"
10 import { NPopselect } from "naive-ui"
11 import { computed, h } from "vue"
12 import { useI18n } from "vue-i18n"
13 +import Icon from "@/components/common/Icon.vue"
14 +import { useLocalesStore } from "@/stores/i18n"
15
16 const MultiLanguageIcon = "ion:language-outline"
17 const localesStore = useLocalesStore()
frontend/src/app-layouts/common/Toolbar/Notifications.vue
+2 -2
@@ -33,14 +33,14 @@
33 </template>
34
35 <script lang="ts" setup>
36 +import { NBadge, NButton, NDrawer, NDrawerContent, NPopover } from "naive-ui"
37 +import { computed, onBeforeMount, ref } from "vue"
38 import Icon from "@/components/common/Icon.vue"
39 import NotificationsList from "@/components/common/Notifications/List.vue"
40 import NotificationsToolbar from "@/components/common/Notifications/Toolbar.vue"
41 import { useHealthchecksNotify } from "@/composables/useHealthchecksNotify"
42 import { useNotifications } from "@/composables/useNotifications"
43 import { useThemeStore } from "@/stores/theme"
42 -import { NBadge, NButton, NDrawer, NDrawerContent, NPopover } from "naive-ui"
43 -import { computed, onBeforeMount, ref } from "vue"
44
45 const MAX_ITEMS = 7
46 const BellIcon = "ph:bell"
frontend/src/app-layouts/common/Toolbar/PinnedPagesV2.vue
+1 -1
@@ -61,7 +61,6 @@
61 import type { RemovableRef } from "@vueuse/core"
62 import type { ComputedRef } from "vue"
63 import type { RouteLocationNormalized, RouteRecordName } from "vue-router"
64 -import Icon from "@/components/common/Icon.vue"
64 import { useStorage } from "@vueuse/core"
65 import _split from "lodash/split"
66 import _takeRight from "lodash/takeRight"
@@ -69,6 +68,7 @@ import _uniqBy from "lodash/uniqBy"
68 import { NBadge, NButton, NPopover, NTag } from "naive-ui"
69 import { computed } from "vue"
70 import { useRouter } from "vue-router"
71 +import Icon from "@/components/common/Icon.vue"
72
73 interface Page {
74 name: RouteRecordName | string
frontend/src/app-layouts/common/Toolbar/Search.vue
+2 -2
@@ -10,11 +10,11 @@
10 </template>
11
12 <script lang="ts" setup>
13 +import { NText } from "naive-ui"
14 +import { onMounted, ref } from "vue"
15 import Icon from "@/components/common/Icon.vue"
16 import { useSearchDialog } from "@/composables/useSearchDialog"
17 import { getOS } from "@/utils"
16 -import { NText } from "naive-ui"
17 -import { onMounted, ref } from "vue"
18
19 const SearchIcon = "ion:search-outline"
20 const commandIcon = ref("⌘")
frontend/src/app-layouts/common/Toolbar/ThemeSwitch.vue
+2 -2
@@ -14,10 +14,10 @@
14 </template>
15
16 <script lang="ts" setup>
17 -import Icon from "@/components/common/Icon.vue"
18 -import { useThemeStore } from "@/stores/theme"
17 import { Icon as Iconify } from "@iconify/vue"
18 import { computed, nextTick } from "vue"
19 +import Icon from "@/components/common/Icon.vue"
20 +import { useThemeStore } from "@/stores/theme"
21
22 const Sunny = "ion:sunny"
23 const Moon = "ion:moon"
frontend/src/components/activeResponse/ActiveResponseActions.vue
+2 -2
@@ -34,11 +34,11 @@
34 </template>
35
36 <script setup lang="ts">
37 -import type { SupportedActiveResponse } from "@/types/activeResponse.d"
37 import type { Size } from "naive-ui/es/button/src/interface"
39 -import Icon from "@/components/common/Icon.vue"
38 +import type { SupportedActiveResponse } from "@/types/activeResponse.d"
39 import { NButton, NModal } from "naive-ui"
40 import { computed, ref, watch } from "vue"
41 +import Icon from "@/components/common/Icon.vue"
42 import ActiveResponseInvokeForm from "./ActiveResponseInvokeForm.vue"
43
44 const { activeResponse, size, agentId } = defineProps<{
frontend/src/components/activeResponse/ActiveResponseAgent.vue
+1 -1
@@ -23,9 +23,9 @@
23 <script setup lang="ts">
24 import type { SupportedActiveResponse } from "@/types/activeResponse.d"
25 import type { Agent } from "@/types/agents.d"
26 -import Api from "@/api"
26 import { NEmpty, NSpin, useMessage } from "naive-ui"
27 import { onBeforeMount, ref } from "vue"
28 +import Api from "@/api"
29 import ActiveResponseItem from "./ActiveResponseItem.vue"
30
31 const { embedded, agent } = defineProps<{
frontend/src/components/activeResponse/ActiveResponseDetails.vue
+1 -1
@@ -15,9 +15,9 @@
15
16 <script setup lang="ts">
17 import type { ActiveResponseDetails, SupportedActiveResponse } from "@/types/activeResponse.d"
18 -import Api from "@/api"
18 import { NEmpty, NSpin, useMessage } from "naive-ui"
19 import { defineAsyncComponent, onBeforeMount, ref } from "vue"
20 +import Api from "@/api"
21
22 const { activeResponse } = defineProps<{
23 activeResponse: SupportedActiveResponse
frontend/src/components/activeResponse/ActiveResponseInvokeForm.vue
+2 -2
@@ -28,13 +28,13 @@
28 </template>
29
30 <script setup lang="ts">
31 +import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
32 import type { InvokeRequest, InvokeRequestAction } from "@/api/endpoints/activeResponse"
33 import type { SupportedActiveResponse } from "@/types/activeResponse.d"
33 -import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
34 -import Api from "@/api"
34 import { NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
35 import isIP from "validator/es/lib/isIP"
36 import { computed, onMounted, ref, watch } from "vue"
37 +import Api from "@/api"
38
39 interface InvokeForm {
40 action: null | InvokeRequestAction
frontend/src/components/activeResponse/ActiveResponseItem.vue
+2 -2
@@ -41,10 +41,10 @@
41
42 <script setup lang="ts">
43 import type { SupportedActiveResponse } from "@/types/activeResponse.d"
44 -import CardEntity from "@/components/common/cards/CardEntity.vue"
45 -import Icon from "@/components/common/Icon.vue"
44 import { NButton, NModal } from "naive-ui"
45 import { ref, toRefs } from "vue"
46 +import CardEntity from "@/components/common/cards/CardEntity.vue"
47 +import Icon from "@/components/common/Icon.vue"
48 import ActiveResponseActions from "./ActiveResponseActions.vue"
49 import ActiveResponseDetails from "./ActiveResponseDetails.vue"
50
frontend/src/components/activeResponse/ActiveResponseWizard.vue
+3 -3
@@ -100,15 +100,15 @@
100 </template>
101
102 <script setup lang="ts">
103 +import type { StepsProps } from "naive-ui"
104 import type { SupportedActiveResponse } from "@/types/activeResponse.d"
105 import type { OsTypesLower } from "@/types/common.d"
105 -import type { StepsProps } from "naive-ui"
106 +import { NButton, NEmpty, NScrollbar, NSpin, NStep, NSteps, useMessage } from "naive-ui"
107 +import { computed, onBeforeMount, onMounted, ref, watch } from "vue"
108 import Api from "@/api"
109 import CardEntity from "@/components/common/cards/CardEntity.vue"
110 import Icon from "@/components/common/Icon.vue"
111 import { iconFromOs } from "@/utils"
110 -import { NButton, NEmpty, NScrollbar, NSpin, NStep, NSteps, useMessage } from "naive-ui"
111 -import { computed, onBeforeMount, onMounted, ref, watch } from "vue"
112 import ActiveResponseInvokeForm from "./ActiveResponseInvokeForm.vue"
113 import ActiveResponseItem from "./ActiveResponseItem.vue"
114
frontend/src/components/activeResponse/ActiveResponseWizardButton.vue
+1 -1
@@ -22,9 +22,9 @@
22
23 <script setup lang="ts">
24 import type { Size, Type } from "naive-ui/es/button/src/interface"
25 -import Icon from "@/components/common/Icon.vue"
25 import { NButton, NModal } from "naive-ui"
26 import { ref, watch } from "vue"
27 +import Icon from "@/components/common/Icon.vue"
28 import ActiveResponseWizard from "./ActiveResponseWizard.vue"
29
30 const { type, size } = defineProps<{
frontend/src/components/agents/AgentCard.vue
+2 -2
@@ -68,13 +68,13 @@
68
69 <script setup lang="ts">
70 import type { Agent } from "@/types/agents.d"
71 +import { NButton, NTooltip, useDialog, useMessage } from "naive-ui"
72 +import { computed, ref, toRefs } from "vue"
73 import CardEntity from "@/components/common/cards/CardEntity.vue"
74 import Icon from "@/components/common/Icon.vue"
75 import { useSettingsStore } from "@/stores/settings"
76 import { AgentStatus } from "@/types/agents.d"
77 import dayjs from "@/utils/dayjs"
76 -import { NButton, NTooltip, useDialog, useMessage } from "naive-ui"
77 -import { computed, ref, toRefs } from "vue"
78 import { handleDeleteAgent, toggleAgentCritical } from "./utils"
79
80 const props = defineProps<{
frontend/src/components/agents/AgentCases.vue
+2 -2
@@ -27,11 +27,11 @@
27
28 <script setup lang="ts">
29 import type { Agent } from "@/types/agents.d"
30 -import Api from "@/api"
31 -import SocCaseItem from "@/components/soc/SocCases/SocCaseItem.vue"
30 import axios from "axios"
31 import { NEmpty, NSpin, useMessage } from "naive-ui"
32 import { onBeforeMount, onBeforeUnmount, ref, toRefs } from "vue"
33 +import Api from "@/api"
34 +import SocCaseItem from "@/components/soc/SocCases/SocCaseItem.vue"
35
36 const props = defineProps<{
37 agent: Agent
frontend/src/components/agents/AgentToolbar.vue
+3 -3
@@ -69,14 +69,14 @@
69 </template>
70
71 <script setup lang="ts">
72 +import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface"
73 import type { Agent } from "@/types/agents.d"
74 import type { Customer } from "@/types/customers.d"
74 -import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface"
75 -import Api from "@/api"
76 -import Icon from "@/components/common/Icon.vue"
75 import { useWindowSize } from "@vueuse/core"
76 import { NButton, NCard, NDropdown, NInput, NScrollbar, useMessage } from "naive-ui"
77 import { computed, h, ref, toRefs } from "vue"
78 +import Api from "@/api"
79 +import Icon from "@/components/common/Icon.vue"
80
81 const props = defineProps<{
82 modelValue: string
frontend/src/components/agents/AgentVelociraptorIdForm.vue
+2 -2
@@ -30,10 +30,10 @@
30
31 <script setup lang="ts">
32 import type { Agent } from "@/types/agents.d"
33 -import Api from "@/api"
34 -import Icon from "@/components/common/Icon.vue"
33 import { NButton, NInput, NInputGroup, useMessage } from "naive-ui"
34 import { onBeforeMount, ref, toRefs } from "vue"
35 +import Api from "@/api"
36 +import Icon from "@/components/common/Icon.vue"
37
38 const props = defineProps<{
39 agent: Agent
frontend/src/components/agents/OverviewSection.vue
+1 -1
@@ -24,12 +24,12 @@
24
25 <script setup lang="ts">
26 import type { Agent } from "@/types/agents.d"
27 +import { computed, toRefs } from "vue"
28 import CardKV from "@/components/common/cards/CardKV.vue"
29 import Icon from "@/components/common/Icon.vue"
30 import { useGoto } from "@/composables/useGoto"
31 import { useSettingsStore } from "@/stores/settings"
32 import { formatDate } from "@/utils"
32 -import { computed, toRefs } from "vue"
33 import AgentVelociraptorIdForm from "./AgentVelociraptorIdForm.vue"
34
35 const props = defineProps<{
frontend/src/components/agents/agentFlow/AgentFlowCollectList.vue
+2 -2
@@ -27,11 +27,11 @@
27
28 <script setup lang="ts">
29 import type { CollectResult, FlowResult } from "@/types/flow.d"
30 -import Api from "@/api"
31 -import CollectItem from "@/components/artifacts/CollectItem.vue"
30 import { NEmpty, NSpin, useMessage } from "naive-ui"
31 import { nanoid } from "nanoid"
32 import { onBeforeMount, ref } from "vue"
33 +import Api from "@/api"
34 +import CollectItem from "@/components/artifacts/CollectItem.vue"
35
36 const { flow } = defineProps<{
37 flow: FlowResult
frontend/src/components/agents/agentFlow/AgentFlowItem.vue
+4 -4
@@ -170,6 +170,10 @@
170
171 <script setup lang="ts">
172 import type { FlowResult } from "@/types/flow.d"
173 +import _pick from "lodash/pick"
174 +import { NEmpty, NInput, NModal, NPopover, NScrollbar, NTabPane, NTabs } from "naive-ui"
175 +import { computed, defineAsyncComponent, ref } from "vue"
176 +import { SimpleJsonViewer } from "vue-sjv"
177 import Badge from "@/components/common/Badge.vue"
178 import CardEntity from "@/components/common/cards/CardEntity.vue"
179 import CardKV from "@/components/common/cards/CardKV.vue"
@@ -177,10 +181,6 @@ import Icon from "@/components/common/Icon.vue"
181 import { useSettingsStore } from "@/stores/settings"
182 import { formatDate } from "@/utils"
183 import dayjs from "@/utils/dayjs"
180 -import _pick from "lodash/pick"
181 -import { NEmpty, NInput, NModal, NPopover, NScrollbar, NTabPane, NTabs } from "naive-ui"
182 -import { computed, defineAsyncComponent, ref } from "vue"
183 -import { SimpleJsonViewer } from "vue-sjv"
184 import "@/assets/scss/overrides/vuesjv-override.scss"
185
186 const { flow, embedded } = defineProps<{ flow: FlowResult; embedded?: boolean }>()
frontend/src/components/agents/agentFlow/AgentFlowList.vue
+1 -1
@@ -28,10 +28,10 @@
28 <script setup lang="ts">
29 import type { Agent } from "@/types/agents.d"
30 import type { FlowResult } from "@/types/flow.d"
31 -import Api from "@/api"
31 import { NEmpty, NSpin, useMessage } from "naive-ui"
32 import { nanoid } from "nanoid"
33 import { onBeforeMount, ref, toRefs } from "vue"
34 +import Api from "@/api"
35 import AgentFlowItem from "./AgentFlowItem.vue"
36
37 interface FlowResultExt extends FlowResult {
frontend/src/components/agents/agentFlow/AgentFlowQueryStat.vue
+3 -3
@@ -86,15 +86,15 @@
86
87 <script setup lang="ts">
88 import type { FlowQueryStat } from "@/types/flow.d"
89 +import _pick from "lodash/pick"
90 +import { NInput, NModal, NTabPane, NTabs } from "naive-ui"
91 +import { computed, ref } from "vue"
92 import Badge from "@/components/common/Badge.vue"
93 import CardEntity from "@/components/common/cards/CardEntity.vue"
94 import CardKV from "@/components/common/cards/CardKV.vue"
95 import { useSettingsStore } from "@/stores/settings"
96 import { formatDate } from "@/utils"
97 import dayjs from "@/utils/dayjs"
95 -import _pick from "lodash/pick"
96 -import { NInput, NModal, NTabPane, NTabs } from "naive-ui"
97 -import { computed, ref } from "vue"
98
99 const { stat, embedded } = defineProps<{ stat: FlowQueryStat; embedded?: boolean }>()
100
frontend/src/components/agents/agentFlow/AgentFlowTimeline.vue
+1 -1
@@ -13,9 +13,9 @@
13
14 <script setup lang="ts">
15 import type { FlowResult } from "@/types/flow.d"
16 +import { NTimeline, NTimelineItem } from "naive-ui"
17 import { useSettingsStore } from "@/stores/settings"
18 import { formatDate } from "@/utils"
18 -import { NTimeline, NTimelineItem } from "naive-ui"
19
20 const { flow } = defineProps<{ flow: FlowResult }>()
21
frontend/src/components/agents/sca/ScaItem.vue
+3 -3
@@ -80,13 +80,13 @@
80
81 <script setup lang="ts">
82 import type { Agent, AgentSca } from "@/types/agents.d"
83 +import _pick from "lodash/pick"
84 +import { NCard, NInput, NStatistic, NTabPane, NTabs } from "naive-ui"
85 +import { computed, defineAsyncComponent } from "vue"
86 import CardKV from "@/components/common/cards/CardKV.vue"
87 import Icon from "@/components/common/Icon.vue"
88 import { useSettingsStore } from "@/stores/settings"
89 import { formatDate } from "@/utils"
87 -import _pick from "lodash/pick"
88 -import { NCard, NInput, NStatistic, NTabPane, NTabs } from "naive-ui"
89 -import { computed, defineAsyncComponent } from "vue"
90
91 const { sca, agent } = defineProps<{ sca: AgentSca; agent: Agent }>()
92
frontend/src/components/agents/sca/ScaResultItem.vue
+2 -2
@@ -73,11 +73,11 @@
73
74 <script setup lang="ts">
75 import type { ScaPolicyResult } from "@/types/agents.d"
76 +import { NButton, NModal } from "naive-ui"
77 +import { ref } from "vue"
78 import Badge from "@/components/common/Badge.vue"
79 import CardEntity from "@/components/common/cards/CardEntity.vue"
80 import Icon from "@/components/common/Icon.vue"
79 -import { NButton, NModal } from "naive-ui"
80 -import { ref } from "vue"
81 import ScaResultItemDetails from "./ScaResultItemDetails.vue"
82
83 const { data, embedded } = defineProps<{
frontend/src/components/agents/sca/ScaResultItemDetails.vue
+2 -2
@@ -144,11 +144,11 @@
144
145 <script setup lang="ts">
146 import type { ScaPolicyResult } from "@/types/agents.d"
147 -import CardKV from "@/components/common/cards/CardKV.vue"
148 -import vShiki from "@/directives/v-shiki"
147 import _pick from "lodash/pick"
148 import { NCard, NInput, NStatistic, NTabPane, NTabs } from "naive-ui"
149 import { computed } from "vue"
150 +import CardKV from "@/components/common/cards/CardKV.vue"
151 +import vShiki from "@/directives/v-shiki"
152
153 const { data } = defineProps<{
154 data: ScaPolicyResult
frontend/src/components/agents/sca/ScaResults.vue
+2 -2
@@ -89,11 +89,11 @@
89
90 <script setup lang="ts">
91 import type { Agent, AgentSca, ScaPolicyResult } from "@/types/agents.d"
92 -import Api from "@/api"
93 -import Icon from "@/components/common/Icon.vue"
92 import { useResizeObserver } from "@vueuse/core"
93 import { NButton, NEmpty, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
94 import { computed, onBeforeMount, ref, watch } from "vue"
95 +import Api from "@/api"
96 +import Icon from "@/components/common/Icon.vue"
97 import ScaResultItem from "./ScaResultItem.vue"
98
99 const { sca, agent } = defineProps<{ sca: AgentSca; agent: Agent }>()
frontend/src/components/agents/sca/ScaTable.vue
+4 -4
@@ -99,14 +99,14 @@
99
100 <script setup lang="ts">
101 import type { Agent, AgentSca } from "@/types/agents.d"
102 -import Api from "@/api"
103 -import Icon from "@/components/common/Icon.vue"
104 -import { useSettingsStore } from "@/stores/settings"
105 -import { formatDate } from "@/utils"
102 import { saveAs } from "file-saver"
103 import _truncate from "lodash/truncate"
104 import { NButton, NEmpty, NModal, NPopover, NScrollbar, NSpin, NTable, NTooltip, useMessage } from "naive-ui"
105 import { onBeforeMount, ref, toRefs } from "vue"
106 +import Api from "@/api"
107 +import Icon from "@/components/common/Icon.vue"
108 +import { useSettingsStore } from "@/stores/settings"
109 +import { formatDate } from "@/utils"
110 import ScaItem from "./ScaItem.vue"
111
112 interface SCAExt extends AgentSca {
frontend/src/components/agents/utils.ts
+2 -2
@@ -1,9 +1,9 @@
1 -import type { Agent } from "@/types/agents.d"
1 import type { DialogApiInjection } from "naive-ui/es/dialog/src/DialogProvider"
2 import type { MessageApiInjection } from "naive-ui/es/message/src/MessageProvider"
3 +import type { Agent } from "@/types/agents.d"
4 +import { h } from "vue"
5 import Api from "@/api"
6 import dayjs from "@/utils/dayjs"
6 -import { h } from "vue"
7
8 export function isAgentOnline(lastSeen: string) {
9 const lastSeenDate = dayjs(lastSeen)
frontend/src/components/agents/vulnerabilities/VulnerabilitiesGrid.vue
+3 -3
@@ -30,14 +30,14 @@
30 <script setup lang="ts">
31 import type { VulnerabilitySeverityType } from "@/api/endpoints/agents"
32 import type { Agent, AgentVulnerabilities } from "@/types/agents.d"
33 -import Api from "@/api"
34 -import { useSettingsStore } from "@/stores/settings"
35 -import { formatDate } from "@/utils"
33 import axios from "axios"
34 import { saveAs } from "file-saver"
35 import { NButton, NEmpty, NFormItem, NSelect, NSpin, useMessage } from "naive-ui"
36 import { nanoid } from "nanoid"
37 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
38 +import Api from "@/api"
39 +import { useSettingsStore } from "@/stores/settings"
40 +import { formatDate } from "@/utils"
41 import VulnerabilityCard from "./VulnerabilityCard.vue"
42
43 const props = defineProps<{
frontend/src/components/agents/vulnerabilities/VulnerabilityCard.vue
+4 -4
@@ -104,15 +104,15 @@
104
105 <script setup lang="ts">
106 import type { AgentVulnerabilities } from "@/types/agents.d"
107 -import CardKV from "@/components/common/cards/CardKV.vue"
108 -import Icon from "@/components/common/Icon.vue"
109 -import { useSettingsStore } from "@/stores/settings"
110 -import dayjs from "@/utils/dayjs"
107 import { cloneDeep } from "lodash"
108 import _split from "lodash/split"
109 import _truncate from "lodash/truncate"
110 import { NModal, NTabPane, NTabs, NTooltip } from "naive-ui"
111 import { computed, defineAsyncComponent, ref, toRefs } from "vue"
112 +import CardKV from "@/components/common/cards/CardKV.vue"
113 +import Icon from "@/components/common/Icon.vue"
114 +import { useSettingsStore } from "@/stores/settings"
115 +import dayjs from "@/utils/dayjs"
116
117 const props = defineProps<{
118 vulnerability: AgentVulnerabilities
frontend/src/components/alerts/Alert.vue
+4 -4
@@ -209,8 +209,11 @@
209 </template>
210
211 <script setup lang="ts">
212 -import type { Alert } from "@/types/alerts.d"
212 import type { SocAlertField } from "./type.d"
213 +import type { Alert } from "@/types/alerts.d"
214 +import _pick from "lodash/pick"
215 +import { NInput, NModal, NPopover, NTabPane, NTabs } from "naive-ui"
216 +import { computed, defineAsyncComponent, inject, ref, toRefs } from "vue"
217 import Badge from "@/components/common/Badge.vue"
218 import CardEntity from "@/components/common/cards/CardEntity.vue"
219 import CardKV from "@/components/common/cards/CardKV.vue"
@@ -218,9 +221,6 @@ import Icon from "@/components/common/Icon.vue"
221 import { useGoto } from "@/composables/useGoto"
222 import { useSettingsStore } from "@/stores/settings"
223 import { formatDate } from "@/utils"
221 -import _pick from "lodash/pick"
222 -import { NInput, NModal, NPopover, NTabPane, NTabs } from "naive-ui"
223 -import { computed, defineAsyncComponent, inject, ref, toRefs } from "vue"
224
225 const props = defineProps<{ alert: Alert; hideActions?: boolean; embedded?: boolean }>()
226 const AlertActions = defineAsyncComponent(() => import("./AlertActions.vue"))
frontend/src/components/alerts/AlertActions.vue
+3 -3
@@ -86,13 +86,13 @@
86 </template>
87
88 <script setup lang="ts">
89 -import type { Alert, WazuhRuleExclude } from "@/types/alerts.d"
89 import type { SocAlertField } from "./type.d"
91 -import Api from "@/api"
92 -import Icon from "@/components/common/Icon.vue"
90 +import type { Alert, WazuhRuleExclude } from "@/types/alerts.d"
91 import { NButton, NInput, NModal, useMessage } from "naive-ui"
92 import { computed, onBeforeMount, ref, watch } from "vue"
93 import { useRouter } from "vue-router"
94 +import Api from "@/api"
95 +import Icon from "@/components/common/Icon.vue"
96 import AlertWazuhRules from "./AlertWazuhRules.vue"
97
98 const { alert, size, socAlertField } = defineProps<{
frontend/src/components/alerts/AlertsFilters.vue
+2 -2
@@ -56,14 +56,14 @@
56 </template>
57
58 <script setup lang="ts">
59 -import type { AlertsQueryTimeRange, AlertsSummaryQuery } from "@/api/endpoints/alerts"
59 import type { SelectOption } from "naive-ui"
60 import type { VNodeChild } from "vue"
62 -import Icon from "@/components/common/Icon.vue"
61 +import type { AlertsQueryTimeRange, AlertsSummaryQuery } from "@/api/endpoints/alerts"
62 import { useStorage } from "@vueuse/core"
63 import _uniqBy from "lodash/uniqBy"
64 import { NButton, NEmpty, NFormItem, NInput, NInputGroup, NSelect } from "naive-ui"
65 import { h, onBeforeMount, toRefs, watch } from "vue"
66 +import Icon from "@/components/common/Icon.vue"
67
68 const props = defineProps<{ filters: AlertsSummaryQuery }>()
69 const emit = defineEmits<{
frontend/src/components/alerts/AlertsGraylogFilters.vue
+1 -1
@@ -22,10 +22,10 @@
22
23 <script setup lang="ts">
24 import type { AlertsQueryTimeRange, GraylogAlertsQuery } from "@/api/endpoints/alerts"
25 -import Icon from "@/components/common/Icon.vue"
25 import { useStorage } from "@vueuse/core"
26 import { NButton, NFormItem, NSelect } from "naive-ui"
27 import { onBeforeMount, toRefs } from "vue"
28 +import Icon from "@/components/common/Icon.vue"
29
30 const props = defineProps<{ filters: Partial<GraylogAlertsQuery> }>()
31 const emit = defineEmits<{
frontend/src/components/alerts/AlertsGraylogList.vue
+4 -4
@@ -68,15 +68,15 @@
68 </template>
69
70 <script setup lang="ts">
71 -import type { GraylogAlertsQuery } from "@/api/endpoints/alerts"
72 -import type { IndexStats } from "@/types/indices.d"
71 import type { AlertsSummaryExt } from "./AlertsSummary.vue"
72 import type { SocAlertField } from "./type.d"
75 -import Api from "@/api"
76 -import Icon from "@/components/common/Icon.vue"
73 +import type { GraylogAlertsQuery } from "@/api/endpoints/alerts"
74 +import type { IndexStats } from "@/types/indices.d"
75 import axios from "axios"
76 import { NButton, NDrawer, NDrawerContent, NEmpty, NPopover, NSpin, useMessage } from "naive-ui"
77 import { computed, defineAsyncComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, provide, ref } from "vue"
78 +import Api from "@/api"
79 +import Icon from "@/components/common/Icon.vue"
80 import AlertsGraylogFilters from "./AlertsGraylogFilters.vue"
81 import AlertsSummaryItem from "./AlertsSummary.vue"
82
frontend/src/components/alerts/AlertsList.vue
+4 -4
@@ -134,16 +134,16 @@
134 // import { alerts_summary } from "./mock"
135 // import type { AlertsSummary } from "@/types/alerts.d"
136
137 +import type { AlertsStatsCTX } from "./AlertsStats.vue"
138 +import type { AlertsSummaryExt } from "./AlertsSummary.vue"
139 import type { AlertsSummaryQuery } from "@/api/endpoints/alerts"
140 import type { Agent } from "@/types/agents.d"
141 import type { IndexStats } from "@/types/indices.d"
140 -import type { AlertsStatsCTX } from "./AlertsStats.vue"
141 -import type { AlertsSummaryExt } from "./AlertsSummary.vue"
142 -import Api from "@/api"
143 -import Icon from "@/components/common/Icon.vue"
142 import axios from "axios"
143 import { NButton, NDrawer, NDrawerContent, NEmpty, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
144 import { computed, defineAsyncComponent, nextTick, onBeforeMount, onBeforeUnmount, onMounted, ref, toRefs } from "vue"
145 +import Api from "@/api"
146 +import Icon from "@/components/common/Icon.vue"
147 import AlertsFilters from "./AlertsFilters.vue"
148 import AlertsStats from "./AlertsStats.vue"
149 import AlertsSummaryItem from "./AlertsSummary.vue"
frontend/src/components/alerts/AlertsStats.vue
+1 -1
@@ -77,10 +77,10 @@
77 <script setup lang="ts">
78 import type { AlertsSummaryQuery } from "@/api/endpoints/alerts"
79 import type { AlertsByHost, AlertsByRule, AlertsByRulePerHost } from "@/types/alerts.d"
80 -import Api from "@/api"
80 import axios from "axios"
81 import { NEmpty, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
82 import { onBeforeMount, onBeforeUnmount, onMounted, ref, toRefs } from "vue"
83 +import Api from "@/api"
84 import AlertsStatsItem from "./AlertsStatsItem.vue"
85 // import { alerts_by_host, alerts_by_rule, alerts_by_rule_per_host } from "./mock"
86
frontend/src/components/alerts/AlertsSummary.vue
+2 -2
@@ -51,12 +51,12 @@
51 <script setup lang="ts">
52 import type { AlertsSummary } from "@/types/alerts.d"
53 import type { IndexStats } from "@/types/indices.d"
54 +import { NButton, NScrollbar } from "naive-ui"
55 +import { ref } from "vue"
56 import CardEntity from "@/components/common/cards/CardEntity.vue"
57 import Icon from "@/components/common/Icon.vue"
58 import IndexIcon from "@/components/indices/IndexIcon.vue"
59 import { useGoto } from "@/composables/useGoto"
58 -import { NButton, NScrollbar } from "naive-ui"
59 -import { ref } from "vue"
60 import Alert from "./Alert.vue"
61
62 export interface AlertsSummaryExt extends AlertsSummary {
frontend/src/components/artifacts/ArtifactRecommendation.vue
+3 -3
@@ -71,14 +71,14 @@
71 </template>
72
73 <script setup lang="ts">
74 +import type { Size } from "naive-ui/es/button/src/interface"
75 import type { Recommendation } from "@/types/artifacts.d"
76 import type { OsTypesFull } from "@/types/common.d"
76 -import type { Size } from "naive-ui/es/button/src/interface"
77 -import Api from "@/api"
78 -import Icon from "@/components/common/Icon.vue"
77 import _uniqBy from "lodash/uniqBy"
78 import { NButton, NCard, NDivider, NEmpty, NModal, NSelect, NSpin, useMessage } from "naive-ui"
79 import { computed, ref } from "vue"
80 +import Api from "@/api"
81 +import Icon from "@/components/common/Icon.vue"
82
83 interface RecommendationStore {
84 os: OsTypesFull
frontend/src/components/artifacts/ArtifactsCollect.vue
+2 -2
@@ -91,11 +91,11 @@
91 import type { ArtifactsQuery, CollectRequest } from "@/api/endpoints/artifacts"
92 import type { Agent } from "@/types/agents.d"
93 import type { Artifact, CollectResult } from "@/types/artifacts.d"
94 -import Api from "@/api"
95 -import Icon from "@/components/common/Icon.vue"
94 import { NButton, NEmpty, NInput, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
95 import { nanoid } from "nanoid"
96 import { computed, nextTick, onBeforeMount, ref, toRefs } from "vue"
97 +import Api from "@/api"
98 +import Icon from "@/components/common/Icon.vue"
99 import CollectItem from "./CollectItem.vue"
100
101 const props = defineProps<{
frontend/src/components/artifacts/ArtifactsCommand.vue
+2 -2
@@ -116,14 +116,14 @@
116 import type { CommandRequest } from "@/api/endpoints/artifacts"
117 import type { Agent } from "@/types/agents.d"
118 import type { Artifact, CommandResult } from "@/types/artifacts.d"
119 +import { NButton, NEmpty, NInput, NSelect, NSpin, NTooltip, useMessage } from "naive-ui"
120 +import { computed, nextTick, onBeforeMount, ref, toRefs } from "vue"
121 import Api from "@/api"
122 import Badge from "@/components/common/Badge.vue"
123 import Icon from "@/components/common/Icon.vue"
124 import { useSettingsStore } from "@/stores/settings"
125 import { formatDate } from "@/utils"
126 import dayjs from "@/utils/dayjs"
125 -import { NButton, NEmpty, NInput, NSelect, NSpin, NTooltip, useMessage } from "naive-ui"
126 -import { computed, nextTick, onBeforeMount, ref, toRefs } from "vue"
127 import CommandItem from "./CommandItem.vue"
128
129 const props = defineProps<{
frontend/src/components/artifacts/ArtifactsList.vue
+2 -2
@@ -128,12 +128,12 @@
128 import type { ArtifactsQuery } from "@/api/endpoints/artifacts"
129 import type { Agent } from "@/types/agents.d"
130 import type { Artifact } from "@/types/artifacts.d"
131 -import Api from "@/api"
132 -import Icon from "@/components/common/Icon.vue"
131 import { useResizeObserver } from "@vueuse/core"
132 import _cloneDeep from "lodash/cloneDeep"
133 import { NBadge, NButton, NEmpty, NInputGroup, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
134 import { computed, nextTick, onBeforeMount, ref, toRefs, watch } from "vue"
135 +import Api from "@/api"
136 +import Icon from "@/components/common/Icon.vue"
137 import ArtifactItem from "./ArtifactItem.vue"
138
139 const props = defineProps<{ agentHostname?: string; agents?: Agent[]; artifacts?: Artifact[] }>()
frontend/src/components/artifacts/ArtifactsQuarantine.vue
+2 -2
@@ -81,10 +81,10 @@
81 import type { QuarantineRequest } from "@/api/endpoints/artifacts"
82 import type { Agent } from "@/types/agents.d"
83 import type { Artifact, QuarantineResult } from "@/types/artifacts.d"
84 -import Api from "@/api"
85 -import Icon from "@/components/common/Icon.vue"
84 import { NButton, NEmpty, NInput, NInputGroup, NSelect, NSpin, useMessage } from "naive-ui"
85 import { computed, nextTick, onBeforeMount, ref, toRefs } from "vue"
86 +import Api from "@/api"
87 +import Icon from "@/components/common/Icon.vue"
88 import QuarantineItem from "./QuarantineItem.vue"
89
90 const props = defineProps<{
frontend/src/components/artifacts/CollectItem.vue
+5 -5
@@ -32,16 +32,16 @@
32
33 <script setup lang="ts">
34 import type { CollectResult } from "@/types/artifacts.d"
35 -import CardEntity from "@/components/common/cards/CardEntity.vue"
36 -import CardKV from "@/components/common/cards/CardKV.vue"
37 -import { useSettingsStore } from "@/stores/settings"
38 -import { formatDate } from "@/utils"
39 -import dayjs from "@/utils/dayjs"
35 import _isNumber from "lodash/isNumber"
36 import _isString from "lodash/isString"
37 import { NModal } from "naive-ui"
38 import { onBeforeMount, ref } from "vue"
39 import { SimpleJsonViewer } from "vue-sjv"
40 +import CardEntity from "@/components/common/cards/CardEntity.vue"
41 +import CardKV from "@/components/common/cards/CardKV.vue"
42 +import { useSettingsStore } from "@/stores/settings"
43 +import { formatDate } from "@/utils"
44 +import dayjs from "@/utils/dayjs"
45 import "@/assets/scss/overrides/vuesjv-override.scss"
46
47 interface Prop {
frontend/src/components/artifacts/CommandItem.vue
+1 -1
@@ -49,9 +49,9 @@
49
50 <script setup lang="ts">
51 import type { CommandResult } from "@/types/artifacts.d"
52 +import { NInput } from "naive-ui"
53 import CardEntity from "@/components/common/cards/CardEntity.vue"
54 import Icon from "@/components/common/Icon.vue"
54 -import { NInput } from "naive-ui"
55
56 const { command } = defineProps<{ command: CommandResult }>()
57
frontend/src/components/auth/AuthForm.vue
+1 -1
@@ -18,9 +18,9 @@
18
19 <script lang="ts" setup>
20 import type { FormType } from "./types.d"
21 +import { computed, onBeforeMount, ref } from "vue"
22 import Logo from "@/app-layouts/common/Logo.vue"
23 import { useThemeStore } from "@/stores/theme"
23 -import { computed, onBeforeMount, ref } from "vue"
24 import SignIn from "./SignIn.vue"
25
26 const props = defineProps<{
frontend/src/components/auth/SignIn.vue
+2 -2
@@ -33,12 +33,12 @@
33 </template>
34
35 <script lang="ts" setup>
36 -import type { LoginPayload } from "@/types/auth.d"
36 import type { FormInst, FormRules, FormValidationError } from "naive-ui"
38 -import { useAuthStore } from "@/stores/auth"
37 +import type { LoginPayload } from "@/types/auth.d"
38 import { NButton, NForm, NFormItem, NInput, useMessage } from "naive-ui"
39 import { computed, ref, watch } from "vue"
40 import { useRouter } from "vue-router"
41 +import { useAuthStore } from "@/stores/auth"
42
43 interface ModelType {
44 username: string | null
frontend/src/components/auth/SignUp.vue
+3 -3
@@ -148,15 +148,15 @@
148 </template>
149
150 <script lang="ts" setup>
151 -import type { RegisterPayload } from "@/types/auth.d"
151 import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
153 -import Api from "@/api"
154 -import Icon from "@/components/common/Icon.vue"
152 +import type { RegisterPayload } from "@/types/auth.d"
153 import _trim from "lodash/trim"
154 import { NButton, NForm, NFormItem, NInput, NSpin, NStep, NSteps, useMessage } from "naive-ui"
155 import PasswordValidator from "password-validator"
156 import isEmail from "validator/es/lib/isEmail"
157 import { computed, ref } from "vue"
158 +import Api from "@/api"
159 +import Icon from "@/components/common/Icon.vue"
160 // import ImageCropper, { type ImageCropperResult } from "@/components/common/ImageCropper.vue"
161
162 interface ModelType {
frontend/src/components/cloudSecurityAssessment/AvailableReportsItem.vue
+2 -2
@@ -21,11 +21,11 @@
21
22 <script setup lang="ts">
23 import type { ScoutSuiteReport } from "@/types/cloudSecurityAssessment.d"
24 +import { NButton, NPopconfirm, useMessage } from "naive-ui"
25 +import { ref } from "vue"
26 import Api from "@/api"
27 import CardEntity from "@/components/common/cards/CardEntity.vue"
28 import { getBaseUrl } from "@/utils"
27 -import { NButton, NPopconfirm, useMessage } from "naive-ui"
28 -import { ref } from "vue"
29
30 const { report } = defineProps<{ report: ScoutSuiteReport }>()
31
frontend/src/components/cloudSecurityAssessment/AvailableReportsList.vue
+2 -2
@@ -62,10 +62,10 @@
62
63 <script setup lang="ts">
64 import type { ScoutSuiteReport } from "@/types/cloudSecurityAssessment.d"
65 -import Api from "@/api"
66 -import Icon from "@/components/common/Icon.vue"
65 import { NButton, NEmpty, NModal, NPopover, NSpin, useMessage } from "naive-ui"
66 import { computed, onBeforeMount, ref, watch } from "vue"
67 +import Api from "@/api"
68 +import Icon from "@/components/common/Icon.vue"
69 import AvailableReportsItem from "./AvailableReportsItem.vue"
70 import CreationReportForm from "./CreationReportForm.vue"
71
frontend/src/components/cloudSecurityAssessment/CloudSecurityAssessmentButton.vue
+1 -1
@@ -9,9 +9,9 @@
9
10 <script setup lang="ts">
11 import type { Size, Type } from "naive-ui/es/button/src/interface"
12 -import Icon from "@/components/common/Icon.vue"
12 import { NButton } from "naive-ui"
13 import { useRouter } from "vue-router"
14 +import Icon from "@/components/common/Icon.vue"
15
16 const { type, size } = defineProps<{
17 size?: Size
frontend/src/components/cloudSecurityAssessment/CreationReportForm.vue
+3 -3
@@ -59,6 +59,7 @@
59 </template>
60
61 <script setup lang="ts">
62 +import type { FormInst, FormRules, FormValidationError, MessageReactive } from "naive-ui"
63 import type {
64 ScoutSuiteAwsReportPayload,
65 ScoutSuiteAzureReportPayload,
@@ -66,11 +67,10 @@ import type {
67 ScoutSuiteReportPayload
68 } from "@/types/cloudSecurityAssessment.d"
69 import type { ApiCommonResponse, ApiError } from "@/types/common.d"
69 -import type { FormInst, FormRules, FormValidationError, MessageReactive } from "naive-ui"
70 -import Api from "@/api"
71 -import { ScoutSuiteReportType } from "@/types/cloudSecurityAssessment.d"
70 import { NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
71 import { computed, onBeforeMount, onMounted, ref, watch } from "vue"
72 +import Api from "@/api"
73 +import { ScoutSuiteReportType } from "@/types/cloudSecurityAssessment.d"
74 import AwsTypeForm from "./FormTypes/AwsTypeForm.vue"
75 import AzureTypeForm from "./FormTypes/AzureTypeForm.vue"
76 import GcpTypeForm from "./FormTypes/GcpTypeForm.vue"
frontend/src/components/cloudSecurityAssessment/FormTypes/AwsTypeForm.vue
+1 -1
@@ -18,8 +18,8 @@
18 </template>
19
20 <script setup lang="ts">
21 -import type { ScoutSuiteAwsReportPayload } from "@/types/cloudSecurityAssessment.d"
21 import type { FormInst, FormRules } from "naive-ui"
22 +import type { ScoutSuiteAwsReportPayload } from "@/types/cloudSecurityAssessment.d"
23 import { NForm, NFormItem, NInput } from "naive-ui"
24 import { computed, onMounted, ref, watch } from "vue"
25
frontend/src/components/cloudSecurityAssessment/FormTypes/AzureTypeForm.vue
+1 -1
@@ -23,8 +23,8 @@
23 </template>
24
25 <script setup lang="ts">
26 -import type { ScoutSuiteAzureReportPayload } from "@/types/cloudSecurityAssessment.d"
26 import type { FormInst, FormRules } from "naive-ui"
27 +import type { ScoutSuiteAzureReportPayload } from "@/types/cloudSecurityAssessment.d"
28 import { NForm, NFormItem, NInput } from "naive-ui"
29 import { computed, onMounted, ref, watch } from "vue"
30
frontend/src/components/cloudSecurityAssessment/FormTypes/GcpTypeForm.vue
+2 -2
@@ -17,11 +17,11 @@
17 </template>
18
19 <script setup lang="ts">
20 -import type { ScoutSuiteGcpReportPayload } from "@/types/cloudSecurityAssessment.d"
20 import type { FormInst, FormItemRule, FormRules, UploadFileInfo } from "naive-ui"
22 -import Icon from "@/components/common/Icon.vue"
21 +import type { ScoutSuiteGcpReportPayload } from "@/types/cloudSecurityAssessment.d"
22 import { NForm, NFormItem, NUpload, NUploadDragger } from "naive-ui"
23 import { computed, onMounted, ref, watch } from "vue"
24 +import Icon from "@/components/common/Icon.vue"
25
26 const emit = defineEmits<{
27 (e: "mounted", value: FormInst): void
frontend/src/components/common/CodeSource.vue
+1 -1
@@ -26,9 +26,9 @@
26 </template>
27
28 <script setup lang="ts">
29 -import vShiki from "@/directives/v-shiki"
29 import { NButton, NCard, NInput } from "naive-ui"
30 import { computed, ref } from "vue"
31 +import vShiki from "@/directives/v-shiki"
32
33 const {
34 code,
frontend/src/components/common/ExpandableText.vue
+1 -1
@@ -22,10 +22,10 @@
22 </template>
23
24 <script setup lang="ts">
25 -import vShiki from "@/directives/v-shiki"
25 import _truncate from "lodash/truncate"
26 import { NPopover } from "naive-ui"
27 import { toRefs } from "vue"
28 +import vShiki from "@/directives/v-shiki"
29
30 const props = defineProps<{
31 text: string
frontend/src/components/common/ListPercentage.vue
+1 -1
@@ -35,9 +35,9 @@
35
36 <script setup lang="ts">
37 import type { SafeAny } from "@/types/common.d"
38 -import { useThemeStore } from "@/stores/theme"
38 import { NEmpty, NProgress } from "naive-ui"
39 import { computed } from "vue"
40 +import { useThemeStore } from "@/stores/theme"
41
42 const { list, labelKey, percentageKey } = defineProps<{
43 list: SafeAny[]
frontend/src/components/common/LocaleSelect.vue
+2 -2
@@ -7,11 +7,11 @@
7 <script lang="ts" setup>
8 import type { SelectOption } from "naive-ui"
9 import type { VNodeChild } from "vue"
10 -import Icon from "@/components/common/Icon.vue"
11 -import { useLocalesStore } from "@/stores/i18n"
10 import { NSelect } from "naive-ui"
11 import { computed, h } from "vue"
12 import { useI18n } from "vue-i18n"
13 +import Icon from "@/components/common/Icon.vue"
14 +import { useLocalesStore } from "@/stores/i18n"
15
16 const localesStore = useLocalesStore()
17
frontend/src/components/common/Markdown.vue
+38 -5
@@ -1,27 +1,30 @@
1 <template>
2 <Suspense>
3 <vue-markdown-it
4 - :source="source"
4 + :source
5 :plugins="[
6 [
7 fromHighlighter(highlighter, {
8 themes: codeThemes
9 })
10 - ]
10 + ],
11 + markdownItLinkTargetBlank
12 ]"
13 class="markdown-style scrollbar-styled"
13 - :class="{ codeBgTransparent }"
14 + :class="{ 'code-bg-transparent': codeBgTransparent }"
15 @click="emit('click', $event)"
16 />
17 </Suspense>
18 </template>
19
20 <script setup lang="ts">
21 +import type MarkdownIt from "markdown-it/lib/index.mjs"
22 +import type Token from "markdown-it/lib/token.mjs"
23 import type { HighlighterGeneric } from "shiki/core"
21 -import { codeThemes, getHighlighter } from "@/utils/highlighter"
24 import { VueMarkdownIt } from "@f3ve/vue-markdown-it"
25 import { fromHighlighter } from "@shikijs/markdown-it/core"
26 import { toRefs } from "vue"
27 +import { codeThemes, getHighlighter } from "@/utils/highlighter"
28 import "@/assets/scss/overrides/vue-md-it-override.scss"
29
30 const props = defineProps<{
@@ -38,6 +41,36 @@ const highlighter: HighlighterGeneric<string, string> = (await getHighlighter())
41 string
42 >
43
44 +function markdownItLinkTargetBlank(md: MarkdownIt): void {
45 + const defaultRender =
46 + md.renderer.rules.link_open ||
47 + function (tokens: Token[], idx: number, options, _env, self) {
48 + return self.renderToken(tokens, idx, options)
49 + }
50 +
51 + md.renderer.rules.link_open = function (tokens: Token[], idx: number, options, env, self) {
52 + const token = tokens[idx]
53 +
54 + // Aggiungi target="_blank"
55 + const targetIndex = token.attrIndex("target")
56 + if (targetIndex < 0) {
57 + token.attrPush(["target", "_blank"])
58 + } else {
59 + token.attrs![targetIndex][1] = "_blank"
60 + }
61 +
62 + // Aggiungi rel="noopener noreferrer"
63 + const relIndex = token.attrIndex("rel")
64 + if (relIndex < 0) {
65 + token.attrPush(["rel", "noopener noreferrer"])
66 + } else {
67 + token.attrs![relIndex][1] = "noopener noreferrer"
68 + }
69 +
70 + return defaultRender(tokens, idx, options, env, self)
71 + }
72 +}
73 +
74 const { source, codeBgTransparent } = toRefs(props)
75 </script>
76
@@ -49,7 +82,7 @@ const { source, codeBgTransparent } = toRefs(props)
82 }
83 }
84
52 - &.codeBgTransparent {
85 + &.code-bg-transparent {
86 :deep() {
87 & > pre {
88 & > code {
frontend/src/components/common/Notifications/List.vue
+2 -2
@@ -43,11 +43,11 @@
43 </template>
44
45 <script lang="ts" setup>
46 -import Icon from "@/components/common/Icon.vue"
47 -import { useNotifications } from "@/composables/useNotifications"
46 import _take from "lodash/take"
47 import { NEmpty, NScrollbar, NTooltip } from "naive-ui"
48 import { computed } from "vue"
49 +import Icon from "@/components/common/Icon.vue"
50 +import { useNotifications } from "@/composables/useNotifications"
51
52 const props = defineProps<{
53 maxItems?: number
frontend/src/components/common/Notifications/Toolbar.vue
+1 -1
@@ -11,8 +11,8 @@
11 </template>
12
13 <script lang="ts" setup>
14 -import { useNotifications } from "@/composables/useNotifications"
14 import { NButton } from "naive-ui"
15 +import { useNotifications } from "@/composables/useNotifications"
16
17 const hasUnread = useNotifications().hasUnread
18 const hasNotifications = useNotifications().hasNotifications
frontend/src/components/common/PaginationIndeterminate.vue
+1 -1
@@ -37,9 +37,9 @@
37 </template>
38
39 <script setup lang="ts">
40 -import Icon from "@/components/common/Icon.vue"
40 import { NInputNumber, NSelect } from "naive-ui"
41 import { computed, toRefs, watch } from "vue"
42 +import Icon from "@/components/common/Icon.vue"
43
44 const props = defineProps<{ showPageSizes?: boolean; showSort?: boolean; pageSizes?: number[]; disabled?: boolean }>()
45 const page = defineModel<number>("page", { default: 1 })
frontend/src/components/common/Percentage.vue
+1 -1
@@ -42,8 +42,8 @@
42 </template>
43
44 <script setup lang="ts">
45 -import Icon from "@/components/common/Icon.vue"
45 import { NProgress } from "naive-ui"
46 +import Icon from "@/components/common/Icon.vue"
47
48 export interface PercentageProps {
49 value: number
frontend/src/components/common/SearchDialog.vue
+4 -4
@@ -71,6 +71,10 @@
71
72 <script lang="ts" setup>
73 import type { ScrollbarInst } from "naive-ui"
74 +import { useMagicKeys, whenever } from "@vueuse/core"
75 +import { NAvatar, NCard, NDivider, NModal, NScrollbar, NText } from "naive-ui"
76 +import { computed, onMounted, ref } from "vue"
77 +import Highlighter from "vue-highlight-words"
78 import Icon from "@/components/common/Icon.vue"
79 import { useFullscreenSwitch } from "@/composables/useFullscreenSwitch"
80 import { useGoto } from "@/composables/useGoto"
@@ -78,10 +82,6 @@ import { useSearchDialog } from "@/composables/useSearchDialog"
82 import { useThemeSwitch } from "@/composables/useThemeSwitch"
83 import { emitter } from "@/emitter"
84 import { getOS } from "@/utils"
81 -import { useMagicKeys, whenever } from "@vueuse/core"
82 -import { NAvatar, NCard, NDivider, NModal, NScrollbar, NText } from "naive-ui"
83 -import { computed, onMounted, ref } from "vue"
84 -import Highlighter from "vue-highlight-words"
85
86 interface GroupItem {
87 iconName: string | null
frontend/src/components/common/SegmentedPage.vue
+6 -1
@@ -77,10 +77,10 @@
77
78 <script setup lang="ts">
79 import type { SetupContext } from "vue"
80 -import Icon from "@/components/common/Icon.vue"
80 import { onClickOutside, useWindowSize } from "@vueuse/core"
81 import { NButton, NScrollbar, NSplit } from "naive-ui"
82 import { computed, onMounted, ref, useSlots, watch } from "vue"
83 +import Icon from "@/components/common/Icon.vue"
84
85 type SidebarPosition = "left" | "right"
86
@@ -374,6 +374,10 @@ onMounted(() => {
374 position: absolute;
375 }
376
377 + .sidebar-header {
378 + border-block-start: 1px solid var(--border-color);
379 + }
380 +
381 .sidebar-header,
382 .sidebar-footer {
383 padding: 0 var(--padding-x);
@@ -391,6 +395,7 @@ onMounted(() => {
395 }
396 .main {
397 .main-toolbar {
398 + border-block-start: 1px solid var(--border-color);
399 padding: 0 var(--padding-x);
400 gap: 14px;
401
frontend/src/components/common/XMLEditor.vue
+1 -1
@@ -18,13 +18,13 @@
18
19 import type { Extension } from "@codemirror/state"
20 import type { EditorView } from "@codemirror/view"
21 -import { useThemeStore } from "@/stores/theme"
21 import { redo, redoDepth, undo, undoDepth } from "@codemirror/commands"
22 import { xml } from "@codemirror/lang-xml"
23 import { oneDark } from "@codemirror/theme-one-dark"
24 import { tomorrow } from "thememirror"
25 import { computed, onMounted, ref, shallowRef, watch } from "vue"
26 import { Codemirror } from "vue-codemirror"
27 +import { useThemeStore } from "@/stores/theme"
28
29 export interface XMLEditorCtx {
30 undo: () => void
frontend/src/components/common/cards/CardStats.vue
+1 -1
@@ -20,9 +20,9 @@
20 </template>
21
22 <script setup lang="ts">
23 -import Icon from "@/components/common/Icon.vue"
23 import { NCard } from "naive-ui"
24 import { toRefs } from "vue"
25 +import Icon from "@/components/common/Icon.vue"
26
27 const props = defineProps<{
28 title: string
frontend/src/components/common/cards/CardStatsBars.vue
+1 -1
@@ -46,10 +46,10 @@
46 </template>
47
48 <script setup lang="ts">
49 -import Icon from "@/components/common/Icon.vue"
49 import _round from "lodash/round"
50 import { NCard } from "naive-ui"
51 import { computed } from "vue"
52 +import Icon from "@/components/common/Icon.vue"
53
54 export interface ItemProps {
55 value: number
frontend/src/components/common/cards/CardStatsIcon.vue
+1 -1
@@ -9,9 +9,9 @@
9 </template>
10
11 <script setup lang="ts">
12 +import { computed } from "vue"
13 import Icon from "@/components/common/Icon.vue"
14 import { useThemeStore } from "@/stores/theme"
14 -import { computed } from "vue"
15
16 const {
17 boxSize = 40,
frontend/src/components/common/cards/CardStatsMulti.vue
+1 -1
@@ -30,9 +30,9 @@
30 </template>
31
32 <script setup lang="ts">
33 -import Icon from "@/components/common/Icon.vue"
33 import { NCard } from "naive-ui"
34 import { toRefs } from "vue"
35 +import Icon from "@/components/common/Icon.vue"
36
37 export interface ItemProps {
38 value: number | string
frontend/src/components/connectors/ConfigForm/ConfigForm.vue
+3 -3
@@ -66,6 +66,7 @@
66 </template>
67
68 <script setup lang="ts">
69 +import type { FormInst, FormRules, FormValidationError } from "naive-ui"
70 import type {
71 Connector,
72 ConnectorForm,
@@ -73,12 +74,11 @@ import type {
74 ConnectorFormOptions,
75 ConnectorRequestPayload
76 } from "@/types/connectors.d"
76 -import type { FormInst, FormRules, FormValidationError } from "naive-ui"
77 -import Api from "@/api"
78 -import { ConnectorFormType } from "@/types/connectors.d"
77 import _pick from "lodash/pick"
78 import { NAvatar, NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
79 import { computed, onMounted, ref, toRefs, watch } from "vue"
80 +import Api from "@/api"
81 +import { ConnectorFormType } from "@/types/connectors.d"
82 import CredentialsType from "./FormTypes/CredentialsType.vue"
83 import FileType from "./FormTypes/FileType.vue"
84 import HostType from "./FormTypes/HostType.vue"
frontend/src/components/connectors/ConfigForm/FormTypes/FileType.vue
+1 -1
@@ -23,9 +23,9 @@
23
24 <script setup lang="ts">
25 import type { FormInst, FormItemRule, FormRules, UploadFileInfo } from "naive-ui"
26 -import Icon from "@/components/common/Icon.vue"
26 import { NForm, NFormItem, NUpload, NUploadDragger } from "naive-ui"
27 import { onMounted, ref, toRefs } from "vue"
28 +import Icon from "@/components/common/Icon.vue"
29
30 export interface IFileForm {
31 connector_file: File | null
frontend/src/components/connectors/ConnectorItem.vue
+2 -2
@@ -98,12 +98,12 @@
98
99 <script setup lang="ts">
100 import type { Connector } from "@/types/connectors.d"
101 +import { NAvatar, NButton, NCard, NModal, useMessage } from "naive-ui"
102 +import { computed, ref, toRefs } from "vue"
103 import Api from "@/api"
104 import Badge from "@/components/common/Badge.vue"
105 import CardEntity from "@/components/common/cards/CardEntity.vue"
106 import Icon from "@/components/common/Icon.vue"
105 -import { NAvatar, NButton, NCard, NModal, useMessage } from "naive-ui"
106 -import { computed, ref, toRefs } from "vue"
107 import ConfigForm from "./ConfigForm"
108
109 const props = defineProps<{
frontend/src/components/connectors/ConnectorsList.vue
+1 -1
@@ -29,9 +29,9 @@
29
30 <script setup lang="ts">
31 import type { Connector } from "@/types/connectors.d"
32 -import Api from "@/api"
32 import { NEmpty, NSpin, useMessage } from "naive-ui"
33 import { computed, onBeforeMount, ref } from "vue"
34 +import Api from "@/api"
35 import ConnectorItem from "./ConnectorItem.vue"
36
37 const message = useMessage()
frontend/src/components/customers/CustomerAgents.vue
+2 -2
@@ -19,11 +19,11 @@
19 <script setup lang="ts">
20 import type { Agent } from "@/types/agents.d"
21 import type { Customer } from "@/types/customers.d"
22 +import { NEmpty, NSpin, useMessage } from "naive-ui"
23 +import { onBeforeMount, ref, toRefs } from "vue"
24 import Api from "@/api"
25 import AgentCard from "@/components/agents/AgentCard.vue"
26 import { useGoto } from "@/composables/useGoto"
25 -import { NEmpty, NSpin, useMessage } from "naive-ui"
26 -import { onBeforeMount, ref, toRefs } from "vue"
27
28 const props = defineProps<{
29 customer: Customer
frontend/src/components/customers/CustomerCreationButton.vue
+2 -2
@@ -59,10 +59,10 @@
59
60 <script setup lang="ts">
61 import type { Size } from "naive-ui/es/button/src/interface"
62 -import Icon from "@/components/common/Icon.vue"
63 -import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
62 import { NButton, NDrawer, NDrawerContent } from "naive-ui"
63 import { computed, ref, watch } from "vue"
64 +import Icon from "@/components/common/Icon.vue"
65 +import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
66 import CustomerForm from "./CustomerForm.vue"
67
68 const { customersCount, disabled, size } = defineProps<{
frontend/src/components/customers/CustomerForm.vue
+2 -2
@@ -32,13 +32,13 @@
32 </template>
33
34 <script setup lang="ts">
35 -import type { Customer } from "@/types/customers.d"
35 import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
37 -import Api from "@/api"
36 +import type { Customer } from "@/types/customers.d"
37 import _get from "lodash/get"
38 import _trim from "lodash/trim"
39 import { NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
40 import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from "vue"
41 +import Api from "@/api"
42
43 const props = defineProps<{
44 customer?: Customer
frontend/src/components/customers/CustomerInfo.vue
+2 -2
@@ -39,11 +39,11 @@
39
40 <script setup lang="ts">
41 import type { Customer } from "@/types/customers.d"
42 +import { NButton, useDialog, useMessage } from "naive-ui"
43 +import { h, ref, toRefs, watch } from "vue"
44 import Api from "@/api"
45 import CardKV from "@/components/common/cards/CardKV.vue"
46 import Icon from "@/components/common/Icon.vue"
45 -import { NButton, useDialog, useMessage } from "naive-ui"
46 -import { h, ref, toRefs, watch } from "vue"
47 import CustomerForm from "./CustomerForm.vue"
48
49 const props = defineProps<{
frontend/src/components/customers/CustomerItem.vue
+3 -3
@@ -242,14 +242,14 @@
242
243 <script setup lang="ts">
244 import type { Customer, CustomerMeta } from "@/types/customers.d"
245 +import _toSafeInteger from "lodash/toSafeInteger"
246 +import { NAvatar, NButton, NModal, NPopover, NScrollbar, NTabPane, NTabs, useMessage } from "naive-ui"
247 +import { computed, defineAsyncComponent, onBeforeMount, ref, toRefs, watch } from "vue"
248 import Api from "@/api"
249 import Badge from "@/components/common/Badge.vue"
250 import CardEntity from "@/components/common/cards/CardEntity.vue"
251 import Icon from "@/components/common/Icon.vue"
252 import { hashMD5 } from "@/utils"
250 -import _toSafeInteger from "lodash/toSafeInteger"
251 -import { NAvatar, NButton, NModal, NPopover, NScrollbar, NTabPane, NTabs, useMessage } from "naive-ui"
252 -import { computed, defineAsyncComponent, onBeforeMount, ref, toRefs, watch } from "vue"
253
254 const props = defineProps<{
255 customer: Customer
frontend/src/components/customers/CustomerMetaForm.vue
+2 -2
@@ -31,14 +31,14 @@
31 </template>
32
33 <script setup lang="ts">
34 -import type { CustomerMeta } from "@/types/customers.d"
34 import type { FormInst, FormRules, FormValidationError } from "naive-ui"
36 -import Api from "@/api"
35 +import type { CustomerMeta } from "@/types/customers.d"
36 import _get from "lodash/get"
37 import _toSafeInteger from "lodash/toSafeInteger"
38 import _trim from "lodash/trim"
39 import { NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
40 import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from "vue"
41 +import Api from "@/api"
42
43 interface CustomerMetaExt extends Omit<CustomerMeta, "id" | "customer_meta_iris_customer_id"> {
44 id: string
frontend/src/components/customers/CustomerWazuhWorker.vue
+5 -5
@@ -137,6 +137,11 @@
137
138 <script setup lang="ts">
139 import type { PortainerStack } from "@/types/portainer.d"
140 +import _castArray from "lodash/castArray"
141 +import _pick from "lodash/pick"
142 +import { NButton, NEmpty, NModal, NSpin, useMessage } from "naive-ui"
143 +import { computed, onBeforeMount, ref } from "vue"
144 +import { SimpleJsonViewer } from "vue-sjv"
145 import Api from "@/api"
146 import Badge from "@/components/common/Badge.vue"
147 import CardEntity from "@/components/common/cards/CardEntity.vue"
@@ -145,11 +150,6 @@ import Icon from "@/components/common/Icon.vue"
150 import { useSettingsStore } from "@/stores/settings"
151 import { PortainerStackStatus } from "@/types/portainer.d"
152 import { formatDate } from "@/utils"
148 -import _castArray from "lodash/castArray"
149 -import _pick from "lodash/pick"
150 -import { NButton, NEmpty, NModal, NSpin, useMessage } from "naive-ui"
151 -import { computed, onBeforeMount, ref } from "vue"
152 -import { SimpleJsonViewer } from "vue-sjv"
153 import "@/assets/scss/overrides/vuesjv-override.scss"
154
155 const { stackId } = defineProps<{ stackId: number }>()
frontend/src/components/customers/CustomersList.vue
+1 -1
@@ -32,9 +32,9 @@
32
33 <script setup lang="ts">
34 import type { Customer } from "@/types/customers.d"
35 -import Api from "@/api"
35 import { NEmpty, NSpin, useMessage } from "naive-ui"
36 import { computed, nextTick, onBeforeMount, ref, toRefs, watch } from "vue"
37 +import Api from "@/api"
38 import CustomerItem from "./CustomerItem.vue"
39
40 const props = defineProps<{ highlight: string | null | undefined; reload?: boolean }>()
frontend/src/components/customers/healthcheck/CustomerHealthcheckItem.vue
+3 -3
@@ -12,7 +12,7 @@
12 <template #default>
13 <div class="flex grow flex-col gap-1">
14 <div class="flex flex-wrap items-center gap-2">
15 - <Icon :name="iconFromOs(healthData.os)" :size="16"></Icon>
15 + <Icon :name="iconFromOs(healthData.os)" :size="16" />
16 {{ healthData.os }}
17 </div>
18 <p>
@@ -94,6 +94,8 @@
94
95 <script setup lang="ts">
96 import type { CustomerAgentHealth, CustomerHealthcheckSource } from "@/types/customers.d"
97 +import { NModal, NPopover } from "naive-ui"
98 +import { computed, ref } from "vue"
99 import Badge from "@/components/common/Badge.vue"
100 import CardEntity from "@/components/common/cards/CardEntity.vue"
101 import CardKV from "@/components/common/cards/CardKV.vue"
@@ -102,8 +104,6 @@ import { useGoto } from "@/composables/useGoto"
104 import { useSettingsStore } from "@/stores/settings"
105 import { iconFromOs } from "@/utils"
106 import dayjs from "@/utils/dayjs"
105 -import { NModal, NPopover } from "naive-ui"
106 -import { computed, ref } from "vue"
107
108 const { healthData, source, embedded, type } = defineProps<{
109 healthData: CustomerAgentHealth
frontend/src/components/customers/healthcheck/CustomerHealthcheckList.vue
+2 -2
@@ -55,12 +55,12 @@
55 <script setup lang="ts">
56 import type { CustomerAgentsHealthcheckQuery } from "@/api/endpoints/customers"
57 import type { CustomerAgentHealth, CustomerHealthcheckSource } from "@/types/customers.d"
58 -import Api from "@/api"
59 -import Icon from "@/components/common/Icon.vue"
58 import { watchDebounced } from "@vueuse/core"
59 import _get from "lodash/get"
60 import { NEmpty, NInputGroup, NInputNumber, NSelect, NSpin, useMessage } from "naive-ui"
61 import { onBeforeMount, ref, watch } from "vue"
62 +import Api from "@/api"
63 +import Icon from "@/components/common/Icon.vue"
64 import CustomerHealthcheckItem from "./CustomerHealthcheckItem.vue"
65
66 const { source, customerCode } = defineProps<{
frontend/src/components/customers/integrations/CustomerIntegrationActions.vue
+3 -3
@@ -17,13 +17,13 @@
17 </template>
18
19 <script setup lang="ts">
20 +import type { Size } from "naive-ui/es/button/src/interface"
21 import type { ApiCommonResponse } from "@/types/common.d"
22 import type { CustomerIntegration } from "@/types/integrations.d"
22 -import type { Size } from "naive-ui/es/button/src/interface"
23 -import Api from "@/api"
24 -import Icon from "@/components/common/Icon.vue"
23 import { NButton, useDialog, useMessage } from "naive-ui"
24 import { computed, ref, watch } from "vue"
25 +import Api from "@/api"
26 +import Icon from "@/components/common/Icon.vue"
27 import { handleDeleteIntegration } from "./utils"
28
29 const { integration, hideDeleteButton, size } = defineProps<{
frontend/src/components/customers/integrations/CustomerIntegrationDetails.vue
+4 -4
@@ -69,15 +69,15 @@
69 </template>
70
71 <script setup lang="ts">
72 +import type { FormInst, FormRules, FormValidationError } from "naive-ui"
73 import type { IntegrationAuthKeyPairs, UpdateIntegrationPayload } from "@/api/endpoints/integrations"
74 import type { CustomerIntegration } from "@/types/integrations.d"
74 -import type { FormInst, FormRules, FormValidationError } from "naive-ui"
75 -import Api from "@/api"
76 -import CardKV from "@/components/common/cards/CardKV.vue"
77 -import Icon from "@/components/common/Icon.vue"
75 import _uniqBy from "lodash/uniqBy"
76 import { NButton, NCollapseTransition, NForm, NFormItem, NInput, NSpin, useDialog, useMessage } from "naive-ui"
77 import { computed, ref } from "vue"
78 +import Api from "@/api"
79 +import CardKV from "@/components/common/cards/CardKV.vue"
80 +import Icon from "@/components/common/Icon.vue"
81 import { handleDeleteIntegration } from "./utils"
82
83 const props = defineProps<{
frontend/src/components/customers/integrations/CustomerIntegrationForm.vue
+3 -3
@@ -80,14 +80,14 @@
80 </template>
81
82 <script setup lang="ts">
83 +import type { StepsProps } from "naive-ui"
84 import type { NewIntegration } from "@/api/endpoints/integrations"
85 import type { ServiceItemData } from "@/components/services/types"
85 -import type { StepsProps } from "naive-ui"
86 +import { NButton, NFormItem, NInput, NScrollbar, NSelect, NStep, NSteps, useMessage } from "naive-ui"
87 +import { computed, ref, watch } from "vue"
88 import Api from "@/api"
89 import Icon from "@/components/common/Icon.vue"
90 import IntegrationsList from "@/components/integrations/IntegrationsList.vue"
89 -import { NButton, NFormItem, NInput, NScrollbar, NSelect, NStep, NSteps, useMessage } from "naive-ui"
90 -import { computed, ref, watch } from "vue"
91
92 interface AuthKeysInput {
93 key: string
frontend/src/components/customers/integrations/CustomerIntegrationItem.vue
+2 -2
@@ -49,11 +49,11 @@
49
50 <script setup lang="ts">
51 import type { CustomerIntegration } from "@/types/integrations.d"
52 +import { NButton, NModal } from "naive-ui"
53 +import { computed, defineAsyncComponent, ref } from "vue"
54 import Badge from "@/components/common/Badge.vue"
55 import CardEntity from "@/components/common/cards/CardEntity.vue"
56 import Icon from "@/components/common/Icon.vue"
55 -import { NButton, NModal } from "naive-ui"
56 -import { computed, defineAsyncComponent, ref } from "vue"
57 import CustomerIntegrationActions from "./CustomerIntegrationActions.vue"
58
59 const { integration: customerIntegration, embedded } = defineProps<{
frontend/src/components/customers/integrations/CustomerIntegrations.vue
+2 -2
@@ -45,10 +45,10 @@
45
46 <script setup lang="ts">
47 import type { CustomerIntegration } from "@/types/integrations.d"
48 -import Api from "@/api"
49 -import Icon from "@/components/common/Icon.vue"
48 import { NButton, NEmpty, NSpin, useMessage } from "naive-ui"
49 import { computed, onBeforeMount, ref } from "vue"
50 +import Api from "@/api"
51 +import Icon from "@/components/common/Icon.vue"
52 import CustomerIntegrationForm from "./CustomerIntegrationForm.vue"
53 import CustomerIntegrationItem from "./CustomerIntegrationItem.vue"
54
frontend/src/components/customers/integrations/utils.ts
+2 -2
@@ -1,8 +1,8 @@
1 -import type { CustomerIntegration } from "@/types/integrations.d"
1 import type { DialogApiInjection } from "naive-ui/es/dialog/src/DialogProvider"
2 import type { MessageApiInjection } from "naive-ui/es/message/src/MessageProvider"
4 -import Api from "@/api"
3 +import type { CustomerIntegration } from "@/types/integrations.d"
4 import { h } from "vue"
5 +import Api from "@/api"
6
7 export interface DeleteIntegrationParams {
8 integration: CustomerIntegration
frontend/src/components/customers/networkConnectors/CustomerNetworkConnectorActions.vue
+4 -4
@@ -76,14 +76,14 @@
76 </template>
77
78 <script setup lang="ts">
79 -import type { FortinetProvision } from "@/api/endpoints/networkConnectors"
80 -import type { CustomerNetworkConnector } from "@/types/networkConnectors.d"
79 import type { Size } from "naive-ui/es/button/src/interface"
80 import type { FortinetModel } from "./provisions/FortinetForm.vue"
83 -import Api from "@/api"
84 -import Icon from "@/components/common/Icon.vue"
81 +import type { FortinetProvision } from "@/api/endpoints/networkConnectors"
82 +import type { CustomerNetworkConnector } from "@/types/networkConnectors.d"
83 import { NButton, NModal, NSpin, useDialog, useMessage } from "naive-ui"
84 import { computed, h, ref, watch } from "vue"
85 +import Api from "@/api"
86 +import Icon from "@/components/common/Icon.vue"
87 import FortinetForm from "./provisions/FortinetForm.vue"
88
89 const { networkConnector, hideDeleteButton, size } = defineProps<{
frontend/src/components/customers/networkConnectors/CustomerNetworkConnectorForm.vue
+3 -3
@@ -80,14 +80,14 @@
80 </template>
81
82 <script setup lang="ts">
83 +import type { StepsProps } from "naive-ui"
84 import type { NewNetworkConnector } from "@/api/endpoints/networkConnectors"
85 import type { ServiceItemData } from "@/components/services/types"
85 -import type { StepsProps } from "naive-ui"
86 +import { NButton, NFormItem, NInput, NScrollbar, NSelect, NStep, NSteps, useMessage } from "naive-ui"
87 +import { computed, ref, watch } from "vue"
88 import Api from "@/api"
89 import Icon from "@/components/common/Icon.vue"
90 import NetworkConnectorsList from "@/components/networkConnectors/NetworkConnectorsList.vue"
89 -import { NButton, NFormItem, NInput, NScrollbar, NSelect, NStep, NSteps, useMessage } from "naive-ui"
90 -import { computed, ref, watch } from "vue"
91
92 interface AuthKeysInput {
93 key: string
frontend/src/components/customers/networkConnectors/CustomerNetworkConnectorItem.vue
+3 -3
@@ -59,13 +59,13 @@
59
60 <script setup lang="ts">
61 import type { CustomerNetworkConnector } from "@/types/networkConnectors.d"
62 +import _uniqBy from "lodash/uniqBy"
63 +import { NButton, NModal } from "naive-ui"
64 +import { computed, ref, toRefs } from "vue"
65 import Badge from "@/components/common/Badge.vue"
66 import CardEntity from "@/components/common/cards/CardEntity.vue"
67 import CardKV from "@/components/common/cards/CardKV.vue"
68 import Icon from "@/components/common/Icon.vue"
66 -import _uniqBy from "lodash/uniqBy"
67 -import { NButton, NModal } from "naive-ui"
68 -import { computed, ref, toRefs } from "vue"
69 import CustomerNetworkConnectorActions from "./CustomerNetworkConnectorActions.vue"
70
71 const props = defineProps<{
frontend/src/components/customers/networkConnectors/CustomerNetworkConnectors.vue
+2 -2
@@ -50,10 +50,10 @@
50
51 <script setup lang="ts">
52 import type { CustomerNetworkConnector } from "@/types/networkConnectors.d"
53 -import Api from "@/api"
54 -import Icon from "@/components/common/Icon.vue"
53 import { NButton, NEmpty, NSpin, useMessage } from "naive-ui"
54 import { computed, onBeforeMount, ref } from "vue"
55 +import Api from "@/api"
56 +import Icon from "@/components/common/Icon.vue"
57 import CustomerNetworkConnectorForm from "./CustomerNetworkConnectorForm.vue"
58 import CustomerNetworkConnectorItem from "./CustomerNetworkConnectorItem.vue"
59
frontend/src/components/customers/notifications/CustomerNotificationsWorkflows.vue
+2 -2
@@ -48,10 +48,10 @@
48
49 <script setup lang="ts">
50 import type { IncidentNotification } from "@/types/incidentManagement/notifications.d"
51 -import Api from "@/api"
52 -import Icon from "@/components/common/Icon.vue"
51 import { NButton, NEmpty, NSpin, useMessage } from "naive-ui"
52 import { defineAsyncComponent, onBeforeMount, ref } from "vue"
53 +import Api from "@/api"
54 +import Icon from "@/components/common/Icon.vue"
55
56 const { customerCode } = defineProps<{
57 customerCode: string
frontend/src/components/customers/notifications/CustomerNotificationsWorkflowsForm.vue
+2 -2
@@ -29,12 +29,12 @@
29 </template>
30
31 <script setup lang="ts">
32 +import type { FormInst, FormRules, FormValidationError } from "naive-ui"
33 import type { IncidentNotificationPayload } from "@/api/endpoints/incidentManagement/notification"
34 import type { IncidentNotification } from "@/types/incidentManagement/notifications.d"
34 -import type { FormInst, FormRules, FormValidationError } from "naive-ui"
35 -import Api from "@/api"
35 import { NButton, NForm, NFormItem, NInput, NSpin, NSwitch, useMessage } from "naive-ui"
36 import { computed, onMounted, ref, watch } from "vue"
37 +import Api from "@/api"
38
39 interface IncidentNotificationForm {
40 shuffle_workflow_id: string
frontend/src/components/customers/notifications/CustomerNotificationsWorkflowsItem.vue
+2 -2
@@ -42,10 +42,10 @@
42
43 <script setup lang="ts">
44 import type { IncidentNotification } from "@/types/incidentManagement/notifications.d"
45 -import CardEntity from "@/components/common/cards/CardEntity.vue"
46 -import Icon from "@/components/common/Icon.vue"
45 import { NModal } from "naive-ui"
46 import { defineAsyncComponent, ref, toRefs, watch } from "vue"
47 +import CardEntity from "@/components/common/cards/CardEntity.vue"
48 +import Icon from "@/components/common/Icon.vue"
49
50 const props = defineProps<{
51 incidentNotification: IncidentNotification
frontend/src/components/customers/provision/CustomerDefaultSettingsButton.vue
+1 -1
@@ -20,9 +20,9 @@
20 </template>
21
22 <script setup lang="ts">
23 -import Icon from "@/components/common/Icon.vue"
23 import { NButton, NModal } from "naive-ui"
24 import { ref, watch } from "vue"
25 +import Icon from "@/components/common/Icon.vue"
26 import CustomerDefaultSettingsForm from "./CustomerDefaultSettingsForm.vue"
27
28 const SettingsIcon = "carbon:settings-edit"
frontend/src/components/customers/provision/CustomerDefaultSettingsForm.vue
+2 -2
@@ -35,15 +35,15 @@
35 </template>
36
37 <script setup lang="ts">
38 -import type { CustomerProvisioningDefaultSettings } from "@/types/customers.d"
38 import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
40 -import Api from "@/api"
39 +import type { CustomerProvisioningDefaultSettings } from "@/types/customers.d"
40 import _get from "lodash/get"
41 import _trim from "lodash/trim"
42 import { NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
43 import isIP from "validator/es/lib/isIP"
44 import isURL from "validator/es/lib/isURL"
45 import { computed, onBeforeMount, onMounted, ref, watch } from "vue"
46 +import Api from "@/api"
47
48 const emit = defineEmits<{
49 (e: "update:loading", value: boolean): void
frontend/src/components/customers/provision/CustomerProvision.vue
+2 -2
@@ -47,11 +47,11 @@
47
48 <script setup lang="ts">
49 import type { CustomerMeta } from "@/types/customers.d"
50 +import { NButton, useDialog, useMessage } from "naive-ui"
51 +import { computed, h, ref, toRefs } from "vue"
52 import Api from "@/api"
53 import CardKV from "@/components/common/cards/CardKV.vue"
54 import Icon from "@/components/common/Icon.vue"
53 -import { NButton, useDialog, useMessage } from "naive-ui"
54 -import { computed, h, ref, toRefs } from "vue"
55 import CustomerProvisionWizard from "./CustomerProvisionWizard.vue"
56
57 const props = defineProps<{
frontend/src/components/customers/provision/CustomerProvisionWizard.vue
+3 -3
@@ -268,10 +268,8 @@
268 </template>
269
270 <script setup lang="ts">
271 -import type { CustomerMeta, CustomerProvision, CustomerProvisioningDefaultSettings } from "@/types/customers.d"
271 import type { FormInst, FormItemRule, FormRules, FormValidationError, StepsProps } from "naive-ui"
273 -import Api from "@/api"
274 -import Icon from "@/components/common/Icon.vue"
272 +import type { CustomerMeta, CustomerProvision, CustomerProvisioningDefaultSettings } from "@/types/customers.d"
273 import _uniqBy from "lodash/uniqBy"
274 import {
275 NButton,
@@ -292,6 +290,8 @@ import isIP from "validator/es/lib/isIP"
290 import isPort from "validator/es/lib/isPort"
291 import isURL from "validator/es/lib/isURL"
292 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
293 +import Api from "@/api"
294 +import Icon from "@/components/common/Icon.vue"
295
296 const props = defineProps<{
297 customerCode: string
frontend/src/components/graylog/Alerts/Item.vue
+1 -1
@@ -79,12 +79,12 @@
79
80 <script setup lang="ts">
81 import type { AlertsEventElement } from "@/types/graylog/alerts.d"
82 +import { NPopover, NTimeline, NTimelineItem } from "naive-ui"
83 import CardEntity from "@/components/common/cards/CardEntity.vue"
84 import Icon from "@/components/common/Icon.vue"
85 import { useGoto } from "@/composables/useGoto"
86 import { useSettingsStore } from "@/stores/settings"
87 import { formatDate } from "@/utils"
87 -import { NPopover, NTimeline, NTimelineItem } from "naive-ui"
88
89 const { alertsEvent } = defineProps<{ alertsEvent: AlertsEventElement }>()
90
frontend/src/components/graylog/Alerts/List.vue
+3 -3
@@ -77,12 +77,12 @@
77
78 <script setup lang="ts">
79 import type { AlertsEventElement, AlertsQuery } from "@/types/graylog/alerts.d"
80 -import Api from "@/api"
81 -import Icon from "@/components/common/Icon.vue"
82 -import dayjs from "@/utils/dayjs"
80 import { useResizeObserver } from "@vueuse/core"
81 import { NButton, NEmpty, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
82 import { computed, onBeforeMount, ref, watch } from "vue"
83 +import Api from "@/api"
84 +import Icon from "@/components/common/Icon.vue"
85 +import dayjs from "@/utils/dayjs"
86 import AlertsEventItem from "./Item.vue"
87
88 const emit = defineEmits<{
frontend/src/components/graylog/Events/Item.vue
+1 -1
@@ -71,10 +71,10 @@
71
72 <script setup lang="ts">
73 import type { EventDefinition } from "@/types/graylog/event-definition.d"
74 -import CardEntity from "@/components/common/cards/CardEntity.vue"
74 import { NInput, NModal, NTabPane, NTabs, NTooltip } from "naive-ui"
75 import { ref, toRefs } from "vue"
76 import { SimpleJsonViewer } from "vue-sjv"
77 +import CardEntity from "@/components/common/cards/CardEntity.vue"
78 import "@/assets/scss/overrides/vuesjv-override.scss"
79
80 const props = defineProps<{ event: EventDefinition; highlight: boolean | null | undefined }>()
frontend/src/components/graylog/Events/List.vue
+3 -3
@@ -46,12 +46,12 @@
46 </template>
47
48 <script setup lang="ts">
49 -import type { EventDefinition } from "@/types/graylog/event-definition.d"
49 import type { SelectMixedOption } from "naive-ui/es/select/src/interface"
51 -import Api from "@/api"
52 -import Icon from "@/components/common/Icon.vue"
50 +import type { EventDefinition } from "@/types/graylog/event-definition.d"
51 import { NButton, NEmpty, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
52 import { computed, nextTick, onBeforeMount, ref, toRefs, watch } from "vue"
53 +import Api from "@/api"
54 +import Icon from "@/components/common/Icon.vue"
55 import EventItem from "./Item.vue"
56
57 const props = defineProps<{ highlight: string | null | undefined }>()
frontend/src/components/graylog/Inputs/Item.vue
+3 -3
@@ -113,15 +113,15 @@
113
114 <script setup lang="ts">
115 import type { InputExtended } from "@/types/graylog/inputs.d"
116 +import { NButton, NModal, NTabPane, NTabs, NTooltip, useMessage } from "naive-ui"
117 +import { computed, ref } from "vue"
118 +import { SimpleJsonViewer } from "vue-sjv"
119 import Api from "@/api"
120 import Badge from "@/components/common/Badge.vue"
121 import CardEntity from "@/components/common/cards/CardEntity.vue"
122 import Icon from "@/components/common/Icon.vue"
123 import { useSettingsStore } from "@/stores/settings"
124 import { formatDate } from "@/utils"
122 -import { NButton, NModal, NTabPane, NTabs, NTooltip, useMessage } from "naive-ui"
123 -import { computed, ref } from "vue"
124 -import { SimpleJsonViewer } from "vue-sjv"
125 import "@/assets/scss/overrides/vuesjv-override.scss"
126
127 const { input, embedded } = defineProps<{ input: InputExtended; embedded?: boolean }>()
frontend/src/components/graylog/Inputs/List.vue
+2 -2
@@ -54,10 +54,10 @@
54
55 <script setup lang="ts">
56 import type { ConfiguredInput, InputExtended, RunningInput } from "@/types/graylog/inputs.d"
57 -import Api from "@/api"
58 -import Icon from "@/components/common/Icon.vue"
57 import { NButton, NEmpty, NPopover, NScrollbar, NSelect, NSpin, useMessage } from "naive-ui"
58 import { computed, onBeforeMount, ref } from "vue"
59 +import Api from "@/api"
60 +import Icon from "@/components/common/Icon.vue"
61 import InputItem from "./Item.vue"
62
63 const InfoIcon = "carbon:information"
frontend/src/components/graylog/Messages/List.vue
+2 -2
@@ -44,11 +44,11 @@
44
45 <script setup lang="ts">
46 import type { MessageExtended } from "@/types/graylog/messages.d"
47 -import Api from "@/api"
48 -import Icon from "@/components/common/Icon.vue"
47 import { NButton, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
48 import { nanoid } from "nanoid"
49 import { onBeforeMount, ref, watch } from "vue"
50 +import Api from "@/api"
51 +import Icon from "@/components/common/Icon.vue"
52 import MessageItem from "./Item.vue"
53
54 const InfoIcon = "carbon:information"
frontend/src/components/graylog/Metrics/UncommittedEntries.vue
+3 -3
@@ -24,14 +24,14 @@
24 </template>
25
26 <script setup lang="ts">
27 +import { NButton } from "naive-ui"
28 +import { computed, ref, toRefs, watch } from "vue"
29 +import apexchart from "vue3-apexcharts"
30 import Icon from "@/components/common/Icon.vue"
31 import { useGoto } from "@/composables/useGoto"
32 import { usHealthcheckStore } from "@/stores/healthcheck"
33 import { useThemeStore } from "@/stores/theme"
34 import dayjs from "@/utils/dayjs"
32 -import { NButton } from "naive-ui"
33 -import { computed, ref, toRefs, watch } from "vue"
34 -import apexchart from "vue3-apexcharts"
35 import "@/assets/scss/overrides/apexchart-override.scss"
36
37 const props = defineProps<{
frontend/src/components/graylog/MonitoringAlerts/CustomAlertButton.vue
+1 -1
@@ -20,9 +20,9 @@
20 </template>
21
22 <script setup lang="ts">
23 -import Icon from "@/components/common/Icon.vue"
23 import { NButton, NModal } from "naive-ui"
24 import { ref, watch } from "vue"
25 +import Icon from "@/components/common/Icon.vue"
26 import CustomAlertForm from "./CustomAlertForm.vue"
27
28 const DangerIcon = "majesticons:exclamation-line"
frontend/src/components/graylog/MonitoringAlerts/CustomAlertForm.vue
+4 -4
@@ -143,16 +143,16 @@
143 </template>
144
145 <script setup lang="ts">
146 -import type { CustomProvisionPayload } from "@/api/endpoints/monitoringAlerts"
146 import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
148 -import Api from "@/api"
149 -import Icon from "@/components/common/Icon.vue"
150 -import { CustomProvisionPriority } from "@/types/monitoringAlerts.d"
147 +import type { CustomProvisionPayload } from "@/api/endpoints/monitoringAlerts"
148 import _get from "lodash/get"
149 import _toSafeInteger from "lodash/toSafeInteger"
150 import _trim from "lodash/trim"
151 import { NButton, NCard, NForm, NFormItem, NInput, NInputNumber, NSelect, NSpin, useMessage } from "naive-ui"
152 import { computed, onMounted, ref, watch } from "vue"
153 +import Api from "@/api"
154 +import Icon from "@/components/common/Icon.vue"
155 +import { CustomProvisionPriority } from "@/types/monitoringAlerts.d"
156
157 interface CustomProvisionForm {
158 alert_name: string
frontend/src/components/graylog/MonitoringAlerts/Item.vue
+3 -3
@@ -76,15 +76,15 @@
76 </template>
77
78 <script setup lang="ts">
79 +import type { FormRules, FormValidationError } from "naive-ui"
80 import type { ProvisionsMonitoringAlertParams } from "@/api/endpoints/monitoringAlerts"
81 import type { AvailableMonitoringAlert } from "@/types/monitoringAlerts.d"
81 -import type { FormRules, FormValidationError } from "naive-ui"
82 +import { NButton, NForm, NFormItem, NInputNumber, NModal, NSpin, useMessage } from "naive-ui"
83 +import { ref } from "vue"
84 import Api from "@/api"
85 import Badge from "@/components/common/Badge.vue"
86 import CardEntity from "@/components/common/cards/CardEntity.vue"
87 import Icon from "@/components/common/Icon.vue"
86 -import { NButton, NForm, NFormItem, NInputNumber, NModal, NSpin, useMessage } from "naive-ui"
87 -import { ref } from "vue"
88
89 const { alert, isEnabled } = defineProps<{ alert: AvailableMonitoringAlert; isEnabled: boolean }>()
90
frontend/src/components/graylog/MonitoringAlerts/List.vue
+2 -2
@@ -66,10 +66,10 @@
66 <script setup lang="ts">
67 import type { EventDefinition } from "@/types/graylog/event-definition.d"
68 import type { AvailableMonitoringAlert } from "@/types/monitoringAlerts.d"
69 -import Api from "@/api"
70 -import Icon from "@/components/common/Icon.vue"
69 import { NButton, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
70 import { computed, onBeforeMount, ref } from "vue"
71 +import Api from "@/api"
72 +import Icon from "@/components/common/Icon.vue"
73 import CustomAlertButton from "./CustomAlertButton.vue"
74 import MonitoringAlert from "./Item.vue"
75
frontend/src/components/graylog/Pipelines/PipeDetails.vue
+3 -3
@@ -41,13 +41,13 @@
41 </template>
42
43 <script setup lang="ts">
44 -import type { PipelineFull, PipelineFullStage } from "@/types/graylog/pipelines.d"
44 import type { RuleExtended } from "./RulesSmallList.vue"
45 +import type { PipelineFull, PipelineFullStage } from "@/types/graylog/pipelines.d"
46 +import { NButton, NPopover, NScrollbar, NTimeline, NTimelineItem } from "naive-ui"
47 +import { computed, toRefs } from "vue"
48 import Icon from "@/components/common/Icon.vue"
49 import { useSettingsStore } from "@/stores/settings"
50 import { formatDate } from "@/utils"
49 -import { NButton, NPopover, NScrollbar, NTimeline, NTimelineItem } from "naive-ui"
50 -import { computed, toRefs } from "vue"
51 import RulesSmallList from "./RulesSmallList.vue"
52
53 interface PipelineFullStageExt extends Omit<PipelineFullStage, "rules" | "rule_ids"> {
frontend/src/components/graylog/Pipelines/PipeInfo.vue
+2 -2
@@ -44,10 +44,10 @@
44
45 <script setup lang="ts">
46 import type { Pipeline } from "@/types/graylog/pipelines.d"
47 -import { useSettingsStore } from "@/stores/settings"
48 -import { formatDate } from "@/utils"
47 import { NInput, NTabPane, NTabs } from "naive-ui"
48 import { toRefs } from "vue"
49 +import { useSettingsStore } from "@/stores/settings"
50 +import { formatDate } from "@/utils"
51
52 const props = defineProps<{ pipeline?: Pipeline }>()
53 const { pipeline } = toRefs(props)
frontend/src/components/graylog/Pipelines/PipeList.vue
+2 -2
@@ -47,13 +47,13 @@
47
48 <script setup lang="ts">
49 import type { PipelineFull } from "@/types/graylog/pipelines.d"
50 +import { NButton, NCard, NCollapse, NCollapseItem, NEmpty, NModal, NSpin, useMessage } from "naive-ui"
51 +import { onBeforeMount, ref, watch } from "vue"
52 import Api from "@/api"
53 import Icon from "@/components/common/Icon.vue"
54 import PipeDetails from "@/components/graylog/Pipelines/PipeDetails.vue"
55 import PipeInfo from "@/components/graylog/Pipelines/PipeInfo.vue"
56 import PipeTitle from "@/components/graylog/Pipelines/PipeTitle.vue"
55 -import { NButton, NCard, NCollapse, NCollapseItem, NEmpty, NModal, NSpin, useMessage } from "naive-ui"
56 -import { onBeforeMount, ref, watch } from "vue"
57
58 const emit = defineEmits<{
59 (e: "openRule", value: string): void
frontend/src/components/graylog/Pipelines/PipeTitle.vue
+1 -1
@@ -12,9 +12,9 @@
12
13 <script setup lang="ts">
14 import type { Pipeline } from "@/types/graylog/pipelines.d"
15 -import Icon from "@/components/common/Icon.vue"
15 import { NTooltip } from "naive-ui"
16 import { computed, toRefs } from "vue"
17 +import Icon from "@/components/common/Icon.vue"
18
19 const props = defineProps<{ pipeline: Pipeline }>()
20 const { pipeline } = toRefs(props)
frontend/src/components/graylog/Pipelines/Rule.vue
+2 -2
@@ -75,12 +75,12 @@
75
76 <script setup lang="ts">
77 import type { PipelineRule } from "@/types/graylog/pipelines.d"
78 +import { NInput, NModal, NPopover, NTimeline, NTimelineItem } from "naive-ui"
79 +import { ref, toRefs } from "vue"
80 import CardEntity from "@/components/common/cards/CardEntity.vue"
81 import Icon from "@/components/common/Icon.vue"
82 import { useSettingsStore } from "@/stores/settings"
83 import { formatDate } from "@/utils"
82 -import { NInput, NModal, NPopover, NTimeline, NTimelineItem } from "naive-ui"
83 -import { ref, toRefs } from "vue"
84
85 const props = defineProps<{ rule: PipelineRule; embedded?: boolean; highlight: boolean | null | undefined }>()
86 const { rule, highlight, embedded } = toRefs(props)
frontend/src/components/graylog/Pipelines/RulesList.vue
+2 -2
@@ -9,11 +9,11 @@
9 </template>
10
11 <script setup lang="ts">
12 -import type { PipelineRule } from "@/types/graylog/pipelines.d"
12 import type { ScrollbarInst } from "naive-ui"
14 -import Api from "@/api"
13 +import type { PipelineRule } from "@/types/graylog/pipelines.d"
14 import { NScrollbar, NSpin, useMessage } from "naive-ui"
15 import { nextTick, onBeforeMount, ref, toRefs, watch } from "vue"
16 +import Api from "@/api"
17 import Rule from "./Rule.vue"
18
19 const props = defineProps<{ highlight: string | null | undefined }>()
frontend/src/components/graylog/Pipelines/RulesSmallList.vue
+1 -1
@@ -15,9 +15,9 @@
15 </template>
16
17 <script setup lang="ts">
18 -import Icon from "@/components/common/Icon.vue"
18 import { NButton } from "naive-ui"
19 import { toRefs } from "vue"
20 +import Icon from "@/components/common/Icon.vue"
21
22 export interface RuleExtended {
23 title: string
frontend/src/components/graylog/Streams/Item.vue
+3 -3
@@ -101,15 +101,15 @@
101
102 <script setup lang="ts">
103 import type { Stream } from "@/types/graylog/stream.d"
104 +import { NButton, NModal, useMessage } from "naive-ui"
105 +import { ref, toRefs } from "vue"
106 +import { SimpleJsonViewer } from "vue-sjv"
107 import Api from "@/api"
108 import Badge from "@/components/common/Badge.vue"
109 import CardEntity from "@/components/common/cards/CardEntity.vue"
110 import Icon from "@/components/common/Icon.vue"
111 import { useSettingsStore } from "@/stores/settings"
112 import { formatDate } from "@/utils"
110 -import { NButton, NModal, useMessage } from "naive-ui"
111 -import { ref, toRefs } from "vue"
112 -import { SimpleJsonViewer } from "vue-sjv"
113 import "@/assets/scss/overrides/vuesjv-override.scss"
114
115 const props = defineProps<{ stream: Stream }>()
frontend/src/components/graylog/Streams/List.vue
+2 -2
@@ -92,11 +92,11 @@
92
93 <script setup lang="ts">
94 import type { Stream } from "@/types/graylog/stream.d"
95 -import Api from "@/api"
96 -import Icon from "@/components/common/Icon.vue"
95 import { useResizeObserver } from "@vueuse/core"
96 import { NButton, NDivider, NEmpty, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
97 import { computed, onBeforeMount, ref } from "vue"
98 +import Api from "@/api"
99 +import Icon from "@/components/common/Icon.vue"
100 import StreamItem from "./Item.vue"
101
102 const FilterIcon = "carbon:filter-edit"
frontend/src/components/healthcheck/HealthcheckItem.vue
+1 -1
@@ -23,12 +23,12 @@
23
24 <script setup lang="ts">
25 import type { InfluxDBAlert } from "@/types/healthchecks.d"
26 +import { computed } from "vue"
27 import CardEntity from "@/components/common/cards/CardEntity.vue"
28 import Icon from "@/components/common/Icon.vue"
29 import { useSettingsStore } from "@/stores/settings"
30 import { InfluxDBAlertLevel } from "@/types/healthchecks.d"
31 import dayjs from "@/utils/dayjs"
31 -import { computed } from "vue"
32
33 const { alert } = defineProps<{ alert: InfluxDBAlert }>()
34
frontend/src/components/healthcheck/HealthcheckList.vue
+3 -3
@@ -63,13 +63,13 @@
63
64 <script setup lang="ts">
65 import type { InfluxDBAlert } from "@/types/healthchecks.d"
66 -import Api from "@/api"
67 -import Icon from "@/components/common/Icon.vue"
68 -import { InfluxDBAlertLevel } from "@/types/healthchecks.d"
66 import { useResizeObserver } from "@vueuse/core"
67 import _orderBy from "lodash/orderBy"
68 import { NButton, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
69 import { computed, onBeforeMount, ref } from "vue"
70 +import Api from "@/api"
71 +import Icon from "@/components/common/Icon.vue"
72 +import { InfluxDBAlertLevel } from "@/types/healthchecks.d"
73 import HealthcheckItem from "./HealthcheckItem.vue"
74
75 const message = useMessage()
frontend/src/components/incidentManagement/alerts/AlertAsset.vue
+3 -3
@@ -158,14 +158,14 @@
158
159 <script setup lang="ts">
160 import type { AlertAsset, AlertContext } from "@/types/incidentManagement/alerts.d"
161 +import _truncate from "lodash/truncate"
162 +import { NCard, NDivider, NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
163 +import { computed, defineAsyncComponent, ref, watch } from "vue"
164 import Api from "@/api"
165 import Badge from "@/components/common/Badge.vue"
166 import CardEntity from "@/components/common/cards/CardEntity.vue"
167 import Icon from "@/components/common/Icon.vue"
168 import { useGoto } from "@/composables/useGoto"
166 -import _truncate from "lodash/truncate"
167 -import { NCard, NDivider, NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
168 -import { computed, defineAsyncComponent, ref, watch } from "vue"
169
170 const { asset, embedded, badge } = defineProps<{ asset: AlertAsset; embedded?: boolean; badge?: boolean }>()
171
frontend/src/components/incidentManagement/alerts/AlertAssetInfo.vue
+3 -3
@@ -83,13 +83,13 @@
83
84 <script setup lang="ts">
85 import type { AlertAsset, AlertDetails } from "@/types/incidentManagement/alerts.d"
86 +import _omit from "lodash/omit"
87 +import { NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
88 +import { computed, defineAsyncComponent, ref, toRefs, watch } from "vue"
89 import Api from "@/api"
90 import CardKV from "@/components/common/cards/CardKV.vue"
91 import Icon from "@/components/common/Icon.vue"
92 import { useGoto } from "@/composables/useGoto"
90 -import _omit from "lodash/omit"
91 -import { NModal, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
92 -import { computed, defineAsyncComponent, ref, toRefs, watch } from "vue"
93
94 const props = defineProps<{ asset: AlertAsset }>()
95
frontend/src/components/incidentManagement/alerts/AlertAssignUser.vue
+2 -2
@@ -13,11 +13,11 @@
13 </template>
14
15 <script setup lang="ts">
16 -import type { Alert } from "@/types/incidentManagement/alerts.d"
16 import type { Ref } from "vue"
18 -import Api from "@/api"
17 +import type { Alert } from "@/types/incidentManagement/alerts.d"
18 import { NPopselect, useMessage } from "naive-ui"
19 import { computed, inject, onBeforeMount, ref, toRefs, watch } from "vue"
20 +import Api from "@/api"
21
22 const props = defineProps<{
23 alert: Alert
frontend/src/components/incidentManagement/alerts/AlertComment.vue
+2 -2
@@ -80,12 +80,12 @@
80
81 <script setup lang="ts">
82 import type { AlertComment } from "@/types/incidentManagement/alerts.d"
83 +import { NAvatar, NButton, NInput, NPopconfirm, useMessage } from "naive-ui"
84 +import { defineAsyncComponent, onBeforeMount, ref, toRefs } from "vue"
85 import Api from "@/api"
86 import Icon from "@/components/common/Icon.vue"
87 import { useSettingsStore } from "@/stores/settings"
88 import { formatDate, getAvatar, getNameInitials } from "@/utils"
87 -import { NAvatar, NButton, NInput, NPopconfirm, useMessage } from "naive-ui"
88 -import { defineAsyncComponent, onBeforeMount, ref, toRefs } from "vue"
89
90 type Mode = "view" | "edit"
91
frontend/src/components/incidentManagement/alerts/AlertCommentsList.vue
+3 -3
@@ -47,12 +47,12 @@
47
48 <script setup lang="ts">
49 import type { AlertComment } from "@/types/incidentManagement/alerts.d"
50 -import Api from "@/api"
51 -import Icon from "@/components/common/Icon.vue"
52 -import { useAuthStore } from "@/stores/auth"
50 import _trim from "lodash/trim"
51 import { NButton, NEmpty, NInput, NSpin, useMessage } from "naive-ui"
52 import { computed, ref, toRefs } from "vue"
53 +import Api from "@/api"
54 +import Icon from "@/components/common/Icon.vue"
55 +import { useAuthStore } from "@/stores/auth"
56 import AlertCommentItem from "./AlertComment.vue"
57
58 const props = defineProps<{ comments: AlertComment[]; alertId: number }>()
frontend/src/components/incidentManagement/alerts/AlertCreateCaseButton.vue
+2 -2
@@ -9,10 +9,10 @@
9
10 <script setup lang="ts">
11 import type { Alert } from "@/types/incidentManagement/alerts.d"
12 -import Api from "@/api"
13 -import Icon from "@/components/common/Icon.vue"
12 import { NButton, useMessage } from "naive-ui"
13 import { ref, toRefs } from "vue"
14 +import Api from "@/api"
15 +import Icon from "@/components/common/Icon.vue"
16
17 const props = defineProps<{ alert: Alert }>()
18 const emit = defineEmits<{
frontend/src/components/incidentManagement/alerts/AlertDetailTimeline.vue
+2 -2
@@ -17,11 +17,11 @@
17
18 <script setup lang="ts">
19 import type { AlertAsset, AlertTimeline } from "@/types/incidentManagement/alerts.d"
20 +import { NSpin, NTimeline, NTimelineItem, useMessage } from "naive-ui"
21 +import { onBeforeMount, ref } from "vue"
22 import Api from "@/api"
23 import { useSettingsStore } from "@/stores/settings"
24 import { formatDate } from "@/utils"
23 -import { NSpin, NTimeline, NTimelineItem, useMessage } from "naive-ui"
24 -import { onBeforeMount, ref } from "vue"
25 import AlertDetailTimelineItem from "./AlertDetailTimelineItem.vue"
26
27 const { asset } = defineProps<{ asset: AlertAsset }>()
frontend/src/components/incidentManagement/alerts/AlertDetailTimelineItem.vue
+3 -3
@@ -49,13 +49,13 @@
49
50 <script setup lang="ts">
51 import type { AlertTimeline } from "@/types/incidentManagement/alerts.d"
52 +import _omit from "lodash/omit"
53 +import { NModal, NTabPane, NTabs } from "naive-ui"
54 +import { computed, defineAsyncComponent, ref, toRefs } from "vue"
55 import CardEntity from "@/components/common/cards/CardEntity.vue"
56 import CardKV from "@/components/common/cards/CardKV.vue"
57 import Icon from "@/components/common/Icon.vue"
58 import { useGoto } from "@/composables/useGoto"
56 -import _omit from "lodash/omit"
57 -import { NModal, NTabPane, NTabs } from "naive-ui"
58 -import { computed, defineAsyncComponent, ref, toRefs } from "vue"
59
60 const props = defineProps<{ timelineData: AlertTimeline; embedded?: boolean }>()
61
frontend/src/components/incidentManagement/alerts/AlertDetails.vue
+1 -1
@@ -43,10 +43,10 @@
43
44 <script setup lang="ts">
45 import type { Alert, AlertComment, AlertIOC } from "@/types/incidentManagement/alerts.d"
46 -import Api from "@/api"
46 import _clone from "lodash/cloneDeep"
47 import { NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
48 import { defineAsyncComponent, onBeforeMount, ref, toRefs } from "vue"
49 +import Api from "@/api"
50
51 const props = defineProps<{
52 alertData?: Alert
frontend/src/components/incidentManagement/alerts/AlertIoCItem.vue
+2 -2
@@ -32,11 +32,11 @@
32
33 <script setup lang="ts">
34 import type { AlertIOC } from "@/types/incidentManagement/alerts"
35 +import { NButton, NPopconfirm, useMessage } from "naive-ui"
36 +import { ref } from "vue"
37 import Api from "@/api"
38 import CardEntity from "@/components/common/cards/CardEntity.vue"
39 import VirusTotalEnrichmentButton from "@/components/threatIntel/VirusTotalEnrichmentButton.vue"
38 -import { NButton, NPopconfirm, useMessage } from "naive-ui"
39 -import { ref } from "vue"
40
41 const { ioc, embedded, alertId } = defineProps<{
42 ioc: AlertIOC
frontend/src/components/incidentManagement/alerts/AlertIoCsForm.vue
+2 -2
@@ -54,17 +54,17 @@
54 </template>
55
56 <script setup lang="ts">
57 +import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
58 import type { AlertIocPayload } from "@/api/endpoints/incidentManagement/alerts"
59 import type { DeepNullable } from "@/types/common"
60 import type { AlertIOC } from "@/types/incidentManagement/alerts.d"
60 -import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
61 -import Api from "@/api"
61 import _get from "lodash/get"
62 import _trim from "lodash/trim"
63 import { NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
64 import isIP from "validator/es/lib/isIP"
65 import isURL from "validator/es/lib/isURL"
66 import { computed, onMounted, ref, toRefs, watch } from "vue"
67 +import Api from "@/api"
68
69 const props = defineProps<{ alertId: number }>()
70 const emit = defineEmits<{
frontend/src/components/incidentManagement/alerts/AlertIoCsList.vue
+2 -2
@@ -49,10 +49,10 @@
49
50 <script setup lang="ts">
51 import type { AlertIOC } from "@/types/incidentManagement/alerts.d"
52 -import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
53 -import Icon from "@/components/common/Icon.vue"
52 import { NButton, NCollapseTransition, NEmpty } from "naive-ui"
53 import { computed, ref, toRefs } from "vue"
54 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
55 +import Icon from "@/components/common/Icon.vue"
56 import AlertIoCItem from "./AlertIoCItem.vue"
57 import AlertIoCsForm from "./AlertIoCsForm.vue"
58
frontend/src/components/incidentManagement/alerts/AlertItem.vue
+4 -4
@@ -271,6 +271,10 @@
271
272 <script setup lang="ts">
273 import type { Alert } from "@/types/incidentManagement/alerts.d"
274 +import _clone from "lodash/cloneDeep"
275 +import _truncate from "lodash/truncate"
276 +import { NButton, NCard, NCheckbox, NModal, NPopover, NSpin, NTooltip, useDialog, useMessage } from "naive-ui"
277 +import { computed, defineAsyncComponent, onMounted, ref, toRefs, watch } from "vue"
278 import Api from "@/api"
279 import Badge from "@/components/common/Badge.vue"
280 import CardEntity from "@/components/common/cards/CardEntity.vue"
@@ -278,10 +282,6 @@ import Icon from "@/components/common/Icon.vue"
282 import { useGoto } from "@/composables/useGoto"
283 import { useSettingsStore } from "@/stores/settings"
284 import { formatDate } from "@/utils"
281 -import _clone from "lodash/cloneDeep"
282 -import _truncate from "lodash/truncate"
283 -import { NButton, NCard, NCheckbox, NModal, NPopover, NSpin, NTooltip, useDialog, useMessage } from "naive-ui"
284 -import { computed, defineAsyncComponent, onMounted, ref, toRefs, watch } from "vue"
285 import AssigneeIcon from "../common/AssigneeIcon.vue"
286 import StatusIcon from "../common/StatusIcon.vue"
287 import AlertAssignUser from "./AlertAssignUser.vue"
frontend/src/components/incidentManagement/alerts/AlertLinkedCases.vue
+2 -2
@@ -33,11 +33,11 @@
33
34 <script setup lang="ts">
35 import type { Alert } from "@/types/incidentManagement/alerts.d"
36 +import { NButton, NPopover, useMessage } from "naive-ui"
37 +import { computed, defineAsyncComponent, ref, watch } from "vue"
38 import Api from "@/api"
39 import Icon from "@/components/common/Icon.vue"
40 import { useGoto } from "@/composables/useGoto"
39 -import { NButton, NPopover, useMessage } from "naive-ui"
40 -import { computed, defineAsyncComponent, ref, watch } from "vue"
41
42 const props = defineProps<{ alert: Alert }>()
43
frontend/src/components/incidentManagement/alerts/AlertMergeCaseButton.vue
+4 -4
@@ -54,15 +54,15 @@
54 </template>
55
56 <script setup lang="ts">
57 -import type { Alert } from "@/types/incidentManagement/alerts.d"
58 -import type { Case } from "@/types/incidentManagement/cases.d"
57 import type { Size } from "naive-ui/es/button/src/interface"
58 import type { Ref } from "vue"
61 -import Api from "@/api"
62 -import Icon from "@/components/common/Icon.vue"
59 +import type { Alert } from "@/types/incidentManagement/alerts.d"
60 +import type { Case } from "@/types/incidentManagement/cases.d"
61 import _orderBy from "lodash/orderBy"
62 import { NButton, NEmpty, NModal, NScrollbar, NSpin, useMessage } from "naive-ui"
63 import { inject, ref, watch } from "vue"
64 +import Api from "@/api"
65 +import Icon from "@/components/common/Icon.vue"
66 import CaseItem from "../cases/CaseItem.vue"
67
68 const { alerts, size } = defineProps<{ alerts: Alert[]; size?: Size }>()
frontend/src/components/incidentManagement/alerts/AlertOverview.vue
+2 -2
@@ -163,11 +163,11 @@
163
164 <script setup lang="ts">
165 import type { Alert } from "@/types/incidentManagement/alerts.d"
166 +import { NButton, NSpin, useDialog, useMessage } from "naive-ui"
167 +import { computed, defineAsyncComponent, ref, toRefs } from "vue"
168 import CardKV from "@/components/common/cards/CardKV.vue"
169 import Icon from "@/components/common/Icon.vue"
170 import { useGoto } from "@/composables/useGoto"
169 -import { NButton, NSpin, useDialog, useMessage } from "naive-ui"
170 -import { computed, defineAsyncComponent, ref, toRefs } from "vue"
171 import AssigneeIcon from "../common/AssigneeIcon.vue"
172 import StatusIcon from "../common/StatusIcon.vue"
173 import AlertAssignUser from "./AlertAssignUser.vue"
frontend/src/components/incidentManagement/alerts/AlertStatusSwitch.vue
+1 -1
@@ -14,9 +14,9 @@
14
15 <script setup lang="ts">
16 import type { Alert, AlertStatus } from "@/types/incidentManagement/alerts.d"
17 -import Api from "@/api"
17 import { NPopselect, useMessage } from "naive-ui"
18 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
19 +import Api from "@/api"
20
21 const props = defineProps<{
22 alert: Alert
frontend/src/components/incidentManagement/alerts/AlertTags.vue
+2 -2
@@ -26,11 +26,11 @@
26
27 <script setup lang="ts">
28 import type { Alert } from "@/types/incidentManagement/alerts.d"
29 -import Api from "@/api"
30 -import Icon from "@/components/common/Icon.vue"
29 import _trim from "lodash/trim"
30 import { NButton, NDynamicTags, NSpin, NTag, useMessage } from "naive-ui"
31 import { ref, toRefs } from "vue"
32 +import Api from "@/api"
33 +import Icon from "@/components/common/Icon.vue"
34
35 const props = defineProps<{ alert: Alert }>()
36 const emit = defineEmits<{
frontend/src/components/incidentManagement/alerts/AlertTimeline.vue
+1 -1
@@ -7,9 +7,9 @@
7
8 <script setup lang="ts">
9 import type { Alert } from "@/types/incidentManagement/alerts.d"
10 +import { NTimeline, NTimelineItem } from "naive-ui"
11 import { useSettingsStore } from "@/stores/settings"
12 import { formatDate } from "@/utils"
12 -import { NTimeline, NTimelineItem } from "naive-ui"
13
14 const { alert } = defineProps<{ alert: Alert }>()
15
frontend/src/components/incidentManagement/alerts/AlertsFilters.vue
+4 -4
@@ -153,19 +153,19 @@
153 </template>
154
155 <script setup lang="ts">
156 +import type { Ref } from "vue"
157 +import type { AlertsListFilter } from "./types.d"
158 import type { AlertsFilterTypes, AlertsListFilterValue } from "@/api/endpoints/incidentManagement/alerts"
159 import type { Customer } from "@/types/customers.d"
160 import type { AlertStatus } from "@/types/incidentManagement/alerts.d"
161 import type { SourceName } from "@/types/incidentManagement/sources.d"
160 -import type { Ref } from "vue"
161 -import type { AlertsListFilter } from "./types.d"
162 -import Api from "@/api"
163 -import Icon from "@/components/common/Icon.vue"
162 import _cloneDeep from "lodash/cloneDeep"
163 import _isEqual from "lodash/isEqual"
164 import { NButton, NDropdown, NInput, NInputGroup, NInputGroupLabel, NSelect, useMessage } from "naive-ui"
165 import { computed, inject, onBeforeMount, onMounted, ref } from "vue"
166 import { useRoute, useRouter } from "vue-router"
167 +import Api from "@/api"
168 +import Icon from "@/components/common/Icon.vue"
169
170 const { useQueryString, preset } = defineProps<{ useQueryString?: boolean; preset?: AlertsListFilter[] }>()
171
frontend/src/components/incidentManagement/alerts/AlertsList.vue
+4 -4
@@ -220,13 +220,10 @@
220 </template>
221
222 <script setup lang="ts">
223 +import type { AlertsListFilter } from "./types.d"
224 import type { AlertsQuery } from "@/api/endpoints/incidentManagement/alerts"
225 import type { Alert } from "@/types/incidentManagement/alerts.d"
226 import type { Case } from "@/types/incidentManagement/cases.d"
226 -import type { AlertsListFilter } from "./types.d"
227 -import Api from "@/api"
228 -import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
229 -import Icon from "@/components/common/Icon.vue"
227 import { useResizeObserver, useStorage } from "@vueuse/core"
228 import axios from "axios"
229 import _orderBy from "lodash/orderBy"
@@ -245,6 +242,9 @@ import {
242 useMessage
243 } from "naive-ui"
244 import { computed, defineAsyncComponent, nextTick, onBeforeMount, provide, ref, watch } from "vue"
245 +import Api from "@/api"
246 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
247 +import Icon from "@/components/common/Icon.vue"
248 import AlertItem from "./AlertItem.vue"
249 import AlertsFilters from "./AlertsFilters.vue"
250
frontend/src/components/incidentManagement/alerts/utils.ts
+2 -2
@@ -1,8 +1,8 @@
1 -import type { Alert } from "@/types/incidentManagement/alerts.d"
1 import type { DialogApiInjection } from "naive-ui/es/dialog/src/DialogProvider"
2 import type { MessageApiInjection } from "naive-ui/es/message/src/MessageProvider"
4 -import Api from "@/api"
3 +import type { Alert } from "@/types/incidentManagement/alerts.d"
4 import { h } from "vue"
5 +import Api from "@/api"
6
7 export interface DeleteAlertParams {
8 alert: Alert
frontend/src/components/incidentManagement/cases/CaseAssignUser.vue
+2 -2
@@ -13,11 +13,11 @@
13 </template>
14
15 <script setup lang="ts">
16 -import type { Case } from "@/types/incidentManagement/cases.d"
16 import type { Ref } from "vue"
18 -import Api from "@/api"
17 +import type { Case } from "@/types/incidentManagement/cases.d"
18 import { NPopselect, useMessage } from "naive-ui"
19 import { computed, inject, onBeforeMount, ref, toRefs, watch } from "vue"
20 +import Api from "@/api"
21
22 const props = defineProps<{
23 caseData: Case
frontend/src/components/incidentManagement/cases/CaseCreationButton.vue
+2 -2
@@ -24,11 +24,11 @@
24 </template>
25
26 <script setup lang="ts">
27 -import type { Case } from "@/types/incidentManagement/cases"
27 import type { Size } from "naive-ui/es/button/src/interface"
29 -import Icon from "@/components/common/Icon.vue"
28 +import type { Case } from "@/types/incidentManagement/cases"
29 import { NButton, NModal } from "naive-ui"
30 import { ref, watch } from "vue"
31 +import Icon from "@/components/common/Icon.vue"
32 import CaseCreationForm from "./CaseCreationForm.vue"
33
34 const { showIcon, size } = defineProps<{ showIcon?: boolean; size?: Size }>()
frontend/src/components/incidentManagement/cases/CaseCreationForm.vue
+3 -3
@@ -70,15 +70,15 @@
70 </template>
71
72 <script setup lang="ts">
73 -import type { Customer } from "@/types/customers.d"
74 -import type { Case, CasePayload, CaseStatus } from "@/types/incidentManagement/cases.d"
73 import type { FormInst, FormRules, FormValidationError } from "naive-ui"
74 import type { Ref } from "vue"
77 -import Api from "@/api"
75 +import type { Customer } from "@/types/customers.d"
76 +import type { Case, CasePayload, CaseStatus } from "@/types/incidentManagement/cases.d"
77 import _get from "lodash/get"
78 import _trim from "lodash/trim"
79 import { NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
80 import { computed, inject, onBeforeMount, onMounted, ref, watch } from "vue"
81 +import Api from "@/api"
82
83 const emit = defineEmits<{
84 (e: "update:loading", value: boolean): void
frontend/src/components/incidentManagement/cases/CaseDataStore.vue
+3 -3
@@ -71,12 +71,12 @@
71 </template>
72
73 <script setup lang="ts">
74 -import type { CaseDataStore } from "@/types/incidentManagement/cases.d"
74 import type { UploadFileInfo } from "naive-ui"
76 -import Api from "@/api"
77 -import Icon from "@/components/common/Icon.vue"
75 +import type { CaseDataStore } from "@/types/incidentManagement/cases.d"
76 import { NButton, NCollapseTransition, NEmpty, NSpin, NUpload, NUploadDragger, useMessage } from "naive-ui"
77 import { computed, onBeforeMount, ref } from "vue"
78 +import Api from "@/api"
79 +import Icon from "@/components/common/Icon.vue"
80 import CaseDataStoreItem from "./CaseDataStoreItem.vue"
81
82 const { caseId } = defineProps<{
frontend/src/components/incidentManagement/cases/CaseDataStoreItem.vue
+4 -4
@@ -68,16 +68,16 @@
68
69 <script setup lang="ts">
70 import type { CaseDataStore } from "@/types/incidentManagement/cases"
71 +import bytes from "bytes"
72 +import { saveAs } from "file-saver"
73 +import { NButton, NPopconfirm, useMessage } from "naive-ui"
74 +import { computed, ref } from "vue"
75 import Api from "@/api"
76 import Badge from "@/components/common/Badge.vue"
77 import CardEntity from "@/components/common/cards/CardEntity.vue"
78 import Icon from "@/components/common/Icon.vue"
79 import { useSettingsStore } from "@/stores/settings"
80 import { formatDate } from "@/utils"
77 -import bytes from "bytes"
78 -import { saveAs } from "file-saver"
79 -import { NButton, NPopconfirm, useMessage } from "naive-ui"
80 -import { computed, ref } from "vue"
81
82 const { dataStoreFile, embedded } = defineProps<{
83 dataStoreFile: CaseDataStore
frontend/src/components/incidentManagement/cases/CaseDetails.vue
+1 -1
@@ -41,10 +41,10 @@
41
42 <script setup lang="ts">
43 import type { Case } from "@/types/incidentManagement/cases.d"
44 -import Api from "@/api"
44 import _clone from "lodash/cloneDeep"
45 import { NEmpty, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
46 import { defineAsyncComponent, onBeforeMount, ref, toRefs } from "vue"
47 +import Api from "@/api"
48
49 const props = defineProps<{
50 caseData?: Case
frontend/src/components/incidentManagement/cases/CaseItem.vue
+4 -4
@@ -224,6 +224,10 @@
224
225 <script setup lang="ts">
226 import type { Case } from "@/types/incidentManagement/cases.d"
227 +import _clone from "lodash/cloneDeep"
228 +import _truncate from "lodash/truncate"
229 +import { NButton, NCard, NCollapse, NCollapseItem, NEmpty, NModal, NSpin, useDialog, useMessage } from "naive-ui"
230 +import { computed, onBeforeMount, onMounted, ref, toRefs } from "vue"
231 import Api from "@/api"
232 import Badge from "@/components/common/Badge.vue"
233 import CardEntity from "@/components/common/cards/CardEntity.vue"
@@ -231,10 +235,6 @@ import Icon from "@/components/common/Icon.vue"
235 import { useGoto } from "@/composables/useGoto"
236 import { useSettingsStore } from "@/stores/settings"
237 import { formatDate } from "@/utils"
234 -import _clone from "lodash/cloneDeep"
235 -import _truncate from "lodash/truncate"
236 -import { NButton, NCard, NCollapse, NCollapseItem, NEmpty, NModal, NSpin, useDialog, useMessage } from "naive-ui"
237 -import { computed, onBeforeMount, onMounted, ref, toRefs } from "vue"
238 import AlertItem from "../alerts/AlertItem.vue"
239 import AssigneeIcon from "../common/AssigneeIcon.vue"
240 import StatusIcon from "../common/StatusIcon.vue"
frontend/src/components/incidentManagement/cases/CaseNotificationButton.vue
+2 -2
@@ -18,10 +18,10 @@
18
19 <script setup lang="ts">
20 import type { Size } from "naive-ui/es/button/src/interface"
21 -import Api from "@/api"
22 -import Icon from "@/components/common/Icon.vue"
21 import { NButton, NTooltip, useMessage } from "naive-ui"
22 import { ref } from "vue"
23 +import Api from "@/api"
24 +import Icon from "@/components/common/Icon.vue"
25
26 const { size, caseId, notificationInvokedNumber } = defineProps<{
27 size?: Size
frontend/src/components/incidentManagement/cases/CaseOverview.vue
+2 -2
@@ -146,13 +146,13 @@
146
147 <script setup lang="ts">
148 import type { Case } from "@/types/incidentManagement/cases.d"
149 +import { NButton, NSpin, useDialog, useMessage } from "naive-ui"
150 +import { ref, toRefs } from "vue"
151 import CardKV from "@/components/common/cards/CardKV.vue"
152 import Icon from "@/components/common/Icon.vue"
153 import { useGoto } from "@/composables/useGoto"
154 import { useSettingsStore } from "@/stores/settings"
155 import { formatDate } from "@/utils"
154 -import { NButton, NSpin, useDialog, useMessage } from "naive-ui"
155 -import { ref, toRefs } from "vue"
156 import AssigneeIcon from "../common/AssigneeIcon.vue"
157 import StatusIcon from "../common/StatusIcon.vue"
158 import CaseAssignUser from "./CaseAssignUser.vue"
frontend/src/components/incidentManagement/cases/CaseReportButton.vue
+6 -6
@@ -52,14 +52,10 @@
52 </template>
53
54 <script setup lang="ts">
55 -import type { CaseReportPayload } from "@/api/endpoints/incidentManagement/cases"
56 -import type { DeepNullable } from "@/types/common"
55 import type { FormInst, FormRules, FormValidationError } from "naive-ui"
56 import type { Size } from "naive-ui/es/button/src/interface"
59 -import Api from "@/api"
60 -import Icon from "@/components/common/Icon.vue"
61 -import { useSettingsStore } from "@/stores/settings"
62 -import { formatDate } from "@/utils"
57 +import type { CaseReportPayload } from "@/api/endpoints/incidentManagement/cases"
58 +import type { DeepNullable } from "@/types/common"
59 import { saveAs } from "file-saver"
60 import {
61 NButton,
@@ -74,6 +70,10 @@ import {
70 useMessage
71 } from "naive-ui"
72 import { computed, ref } from "vue"
73 +import Api from "@/api"
74 +import Icon from "@/components/common/Icon.vue"
75 +import { useSettingsStore } from "@/stores/settings"
76 +import { formatDate } from "@/utils"
77 import CaseReportTemplateSelect from "./CaseReportTemplateSelect.vue"
78
79 const { size, caseId } = defineProps<{ size?: Size; caseId: number }>()
frontend/src/components/incidentManagement/cases/CaseReportTemplateManager.vue
+3 -3
@@ -135,9 +135,6 @@
135
136 <script setup lang="ts">
137 import type { UploadFileInfo } from "naive-ui"
138 -import Api from "@/api"
139 -import Icon from "@/components/common/Icon.vue"
140 -import { useCaseReportTemplateStore } from "@/stores/caseReportTemplate"
138 import saveAs from "file-saver"
139 import {
140 NButton,
@@ -152,6 +149,9 @@ import {
149 useMessage
150 } from "naive-ui"
151 import { computed, onBeforeMount, ref, watch } from "vue"
152 +import Api from "@/api"
153 +import Icon from "@/components/common/Icon.vue"
154 +import { useCaseReportTemplateStore } from "@/stores/caseReportTemplate"
155
156 const UploadIcon = "carbon:cloud-upload"
157 const DownloadIcon = "carbon:document-download"
frontend/src/components/incidentManagement/cases/CaseReportTemplateSelect.vue
+2 -2
@@ -30,10 +30,10 @@
30 </template>
31
32 <script setup lang="ts">
33 -import Icon from "@/components/common/Icon.vue"
34 -import { useCaseReportTemplateStore } from "@/stores/caseReportTemplate"
33 import { NButton, NInputGroup, NModal, NSelect } from "naive-ui"
34 import { computed, onBeforeMount, ref } from "vue"
35 +import Icon from "@/components/common/Icon.vue"
36 +import { useCaseReportTemplateStore } from "@/stores/caseReportTemplate"
37 import CaseReportTemplateManager from "./CaseReportTemplateManager.vue"
38
39 const templateName = defineModel<string | null>("value", { default: null })
frontend/src/components/incidentManagement/cases/CaseStatusSwitch.vue
+1 -1
@@ -14,9 +14,9 @@
14
15 <script setup lang="ts">
16 import type { Case, CaseStatus } from "@/types/incidentManagement/cases.d"
17 -import Api from "@/api"
17 import { NPopselect, useMessage } from "naive-ui"
18 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
19 +import Api from "@/api"
20
21 const props = defineProps<{
22 caseData: Case
frontend/src/components/incidentManagement/cases/CasesExport.vue
+5 -5
@@ -10,18 +10,18 @@
10 </template>
11
12 <script setup lang="ts">
13 -import type { Customer } from "@/types/customers.d"
13 import type { Size } from "naive-ui/es/button/src/interface"
14 import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface"
15 import type { Ref } from "vue"
17 -import Api from "@/api"
18 -import Icon from "@/components/common/Icon.vue"
19 -import { useSettingsStore } from "@/stores/settings"
20 -import { formatDate } from "@/utils"
16 +import type { Customer } from "@/types/customers.d"
17 import { useWindowSize } from "@vueuse/core"
18 import { saveAs } from "file-saver"
19 import { NButton, NDropdown, useMessage } from "naive-ui"
20 import { computed, h, inject, ref } from "vue"
21 +import Api from "@/api"
22 +import Icon from "@/components/common/Icon.vue"
23 +import { useSettingsStore } from "@/stores/settings"
24 +import { formatDate } from "@/utils"
25
26 const { size, showIcon } = defineProps<{ size?: Size; showIcon?: boolean }>()
27
frontend/src/components/incidentManagement/cases/CasesList.vue
+2 -2
@@ -182,8 +182,6 @@
182 import type { CasesFilter, CasesFilterTypes } from "@/api/endpoints/incidentManagement/cases"
183 import type { Customer } from "@/types/customers.d"
184 import type { Case, CaseStatus } from "@/types/incidentManagement/cases.d"
185 -import Api from "@/api"
186 -import Icon from "@/components/common/Icon.vue"
185 import { useResizeObserver } from "@vueuse/core"
186 import _cloneDeep from "lodash/cloneDeep"
187 import _orderBy from "lodash/orderBy"
@@ -200,6 +198,8 @@ import {
198 useMessage
199 } from "naive-ui"
200 import { computed, nextTick, onBeforeMount, provide, ref, toRefs, watch } from "vue"
201 +import Api from "@/api"
202 +import Icon from "@/components/common/Icon.vue"
203 import CaseCreationButton from "./CaseCreationButton.vue"
204 import CaseItem from "./CaseItem.vue"
205 import CasesExport from "./CasesExport.vue"
frontend/src/components/incidentManagement/cases/utils.ts
+2 -2
@@ -1,8 +1,8 @@
1 -import type { Case } from "@/types/incidentManagement/cases.d"
1 import type { DialogApiInjection } from "naive-ui/es/dialog/src/DialogProvider"
2 import type { MessageApiInjection } from "naive-ui/es/message/src/MessageProvider"
4 -import Api from "@/api"
3 +import type { Case } from "@/types/incidentManagement/cases.d"
4 import { h } from "vue"
5 +import Api from "@/api"
6
7 export interface DeleteCaseParams {
8 caseData: Case
frontend/src/components/incidentManagement/common/AssigneeIcon.vue
+1 -1
@@ -3,8 +3,8 @@
3 </template>
4
5 <script setup lang="ts">
6 -import Icon from "@/components/common/Icon.vue"
6 import { toRefs } from "vue"
7 +import Icon from "@/components/common/Icon.vue"
8
9 const props = defineProps<{ assignee: string | null; size?: number }>()
10 const { assignee, size } = toRefs(props)
frontend/src/components/incidentManagement/common/StatusIcon.vue
+1 -1
@@ -15,8 +15,8 @@
15
16 <script setup lang="ts">
17 import type { AlertStatus } from "@/types/incidentManagement/alerts.d"
18 -import Icon from "@/components/common/Icon.vue"
18 import { toRefs } from "vue"
19 +import Icon from "@/components/common/Icon.vue"
20
21 const props = defineProps<{ status: AlertStatus | null; size?: number }>()
22 const { status, size } = toRefs(props)
frontend/src/components/incidentManagement/exclusionRules/ExclusionRuleDetails.vue
+3 -3
@@ -99,6 +99,9 @@
99
100 <script setup lang="ts">
101 import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
102 +import _pick from "lodash/pick"
103 +import { NSpin, NTabPane, NTabs } from "naive-ui"
104 +import { computed, ref, toRefs } from "vue"
105 import Badge from "@/components/common/Badge.vue"
106 import CardKV from "@/components/common/cards/CardKV.vue"
107 import CodeSource from "@/components/common/CodeSource.vue"
@@ -106,9 +109,6 @@ import Icon from "@/components/common/Icon.vue"
109 import { useGoto } from "@/composables/useGoto"
110 import { useSettingsStore } from "@/stores/settings"
111 import { formatDate } from "@/utils"
109 -import _pick from "lodash/pick"
110 -import { NSpin, NTabPane, NTabs } from "naive-ui"
111 -import { computed, ref, toRefs } from "vue"
112 import ExclusionRuleStatusToggler from "./ExclusionRuleStatusToggler.vue"
113
114 const props = defineProps<{
frontend/src/components/incidentManagement/exclusionRules/ExclusionRuleForm.vue
+3 -3
@@ -105,16 +105,16 @@
105 </template>
106
107 <script setup lang="ts">
108 +import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
109 import type { ExclusionRulePayload } from "@/api/endpoints/incidentManagement/exclusionRules"
110 import type { Customer } from "@/types/customers.d"
111 import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules"
111 -import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
112 -import Api from "@/api"
113 -import Icon from "@/components/common/Icon.vue"
112 import _get from "lodash/get"
113 import _trim from "lodash/trim"
114 import { NAlert, NButton, NCheckbox, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
115 import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from "vue"
116 +import Api from "@/api"
117 +import Icon from "@/components/common/Icon.vue"
118
119 interface FieldMatch {
120 id: string
frontend/src/components/incidentManagement/exclusionRules/ExclusionRuleItem.vue
+2 -2
@@ -115,6 +115,8 @@
115
116 <script setup lang="ts">
117 import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
118 +import { NButton, NCard, NModal, NSpin, useDialog, useMessage } from "naive-ui"
119 +import { computed, h, ref, toRefs } from "vue"
120 import Api from "@/api"
121 import Badge from "@/components/common/Badge.vue"
122 import CardEntity from "@/components/common/cards/CardEntity.vue"
@@ -122,8 +124,6 @@ import Icon from "@/components/common/Icon.vue"
124 import { useGoto } from "@/composables/useGoto"
125 import { useSettingsStore } from "@/stores/settings"
126 import { formatDate } from "@/utils"
125 -import { NButton, NCard, NModal, NSpin, useDialog, useMessage } from "naive-ui"
126 -import { computed, h, ref, toRefs } from "vue"
127 import ExclusionRuleDetails from "./ExclusionRuleDetails.vue"
128 import ExclusionRuleForm from "./ExclusionRuleForm.vue"
129 import ExclusionRuleStatusToggler from "./ExclusionRuleStatusToggler.vue"
frontend/src/components/incidentManagement/exclusionRules/ExclusionRuleStatusToggler.vue
+3 -3
@@ -11,12 +11,12 @@
11 </template>
12
13 <script setup lang="ts">
14 -import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
14 import type { CSSProperties } from "vue"
16 -import Api from "@/api"
17 -import { useThemeStore } from "@/stores/theme"
15 +import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
16 import { NSwitch, useMessage } from "naive-ui"
17 import { computed, ref, toRefs, watch } from "vue"
18 +import Api from "@/api"
19 +import { useThemeStore } from "@/stores/theme"
20
21 const props = defineProps<{
22 entity: ExclusionRule
frontend/src/components/incidentManagement/exclusionRules/ExclusionRulesList.vue
+2 -2
@@ -95,11 +95,11 @@
95 <script setup lang="ts">
96 import type { ExclusionRulesQuery } from "@/api/endpoints/incidentManagement/exclusionRules"
97 import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
98 -import Api from "@/api"
99 -import Icon from "@/components/common/Icon.vue"
98 import { useResizeObserver } from "@vueuse/core"
99 import { NBadge, NButton, NCheckbox, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
100 import { onBeforeMount, ref, watch } from "vue"
101 +import Api from "@/api"
102 +import Icon from "@/components/common/Icon.vue"
103 import ExclusionRuleItem from "./ExclusionRuleItem.vue"
104 import NewExclusionRuleButton from "./NewExclusionRuleButton.vue"
105
frontend/src/components/incidentManagement/exclusionRules/NewExclusionRuleButton.vue
+1 -1
@@ -23,9 +23,9 @@
23 </template>
24
25 <script setup lang="ts">
26 -import Icon from "@/components/common/Icon.vue"
26 import { NButton, NModal } from "naive-ui"
27 import { ref, toRefs, watch } from "vue"
28 +import Icon from "@/components/common/Icon.vue"
29 import ExclusionRuleForm from "./ExclusionRuleForm.vue"
30
31 const props = defineProps<{ hideButtonExtendedLabel?: boolean }>()
frontend/src/components/incidentManagement/sources/ConfiguredSourceItem.vue
+2 -2
@@ -35,10 +35,10 @@
35
36 <script setup lang="ts">
37 import type { SourceName } from "@/types/incidentManagement/sources.d"
38 -import Api from "@/api"
39 -import CardEntity from "@/components/common/cards/CardEntity.vue"
38 import { NButton, NModal, NPopconfirm, useMessage } from "naive-ui"
39 import { ref } from "vue"
40 +import Api from "@/api"
41 +import CardEntity from "@/components/common/cards/CardEntity.vue"
42 import SourceConfigurationDetails from "./SourceConfigurationDetails.vue"
43
44 const { source } = defineProps<{ source: SourceName }>()
frontend/src/components/incidentManagement/sources/ConfiguredSourcesList.vue
+2 -2
@@ -46,10 +46,10 @@
46
47 <script setup lang="ts">
48 import type { SourceName } from "@/types/incidentManagement/sources.d"
49 -import Api from "@/api"
50 -import Icon from "@/components/common/Icon.vue"
49 import { NButton, NEmpty, NPopover, NSpin, useMessage } from "naive-ui"
50 import { computed, onBeforeMount, ref } from "vue"
51 +import Api from "@/api"
52 +import Icon from "@/components/common/Icon.vue"
53 import ConfiguredSourceItem from "./ConfiguredSourceItem.vue"
54 import NewConfiguredSourceButton from "./NewConfiguredSourceButton.vue"
55
frontend/src/components/incidentManagement/sources/NewConfiguredSourceButton.vue
+2 -2
@@ -28,10 +28,10 @@
28
29 <script setup lang="ts">
30 import type { SourceName } from "@/types/incidentManagement/sources.d"
31 -import Api from "@/api"
32 -import Icon from "@/components/common/Icon.vue"
31 import { NButton, NModal, useMessage } from "naive-ui"
32 import { onBeforeMount, ref, watch } from "vue"
33 +import Api from "@/api"
34 +import Icon from "@/components/common/Icon.vue"
35 import SourceConfigurationWizard from "./SourceConfigurationWizard.vue"
36
37 const { disabledSources } = defineProps<{ disabledSources?: SourceName[] }>()
frontend/src/components/incidentManagement/sources/SourceConfigurationDetails.vue
+2 -2
@@ -34,10 +34,10 @@
34 <script setup lang="ts">
35 import type { ApiError } from "@/types/common.d"
36 import type { SourceConfiguration, SourceName } from "@/types/incidentManagement/sources.d"
37 -import Api from "@/api"
38 -import Icon from "@/components/common/Icon.vue"
37 import { NButton, NSpin, useMessage } from "naive-ui"
38 import { onBeforeMount, ref } from "vue"
39 +import Api from "@/api"
40 +import Icon from "@/components/common/Icon.vue"
41 import SourceConfigurationForm from "./SourceConfigurationForm.vue"
42 import SourceConfigurationViewer from "./SourceConfigurationViewer.vue"
43
frontend/src/components/incidentManagement/sources/SourceConfigurationForm.vue
+2 -2
@@ -171,12 +171,12 @@
171 </template>
172
173 <script setup lang="ts">
174 -import type { SourceConfiguration, SourceConfigurationModel, SourceName } from "@/types/incidentManagement/sources.d"
174 import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
176 -import Api from "@/api"
175 +import type { SourceConfiguration, SourceConfigurationModel, SourceName } from "@/types/incidentManagement/sources.d"
176 import _intersection from "lodash/intersection"
177 import { NAlert, NButton, NForm, NFormItem, NInput, NSelect, NSpin, useMessage } from "naive-ui"
178 import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from "vue"
179 +import Api from "@/api"
180
181 const props = defineProps<{
182 sourceConfigurationModel?: SourceConfigurationModel
frontend/src/components/incidentManagement/sources/SourceConfigurationWizard.vue
+3 -3
@@ -72,13 +72,13 @@
72 </template>
73
74 <script setup lang="ts">
75 +import type { StepsProps } from "naive-ui"
76 import type { ApiError } from "@/types/common.d"
77 import type { SourceConfiguration, SourceConfigurationModel, SourceName } from "@/types/incidentManagement/sources.d"
77 -import type { StepsProps } from "naive-ui"
78 -import Api from "@/api"
79 -import Icon from "@/components/common/Icon.vue"
78 import { NButton, NScrollbar, NSelect, NSpin, NStep, NSteps, useMessage } from "naive-ui"
79 import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from "vue"
80 +import Api from "@/api"
81 +import Icon from "@/components/common/Icon.vue"
82 import SourceConfigurationForm from "./SourceConfigurationForm.vue"
83
84 const props = defineProps<{ disabledSources?: SourceName[] }>()
frontend/src/components/indices/ClusterHealth.vue
+2 -2
@@ -38,10 +38,10 @@
38
39 <script setup lang="ts">
40 import type { ClusterHealth } from "@/types/indices.d"
41 -import Api from "@/api"
42 -import IndexIcon from "@/components/indices/IndexIcon.vue"
41 import { NCard, NEmpty, NScrollbar, NSpin, useMessage } from "naive-ui"
42 import { onBeforeMount, ref } from "vue"
43 +import Api from "@/api"
44 +import IndexIcon from "@/components/indices/IndexIcon.vue"
45
46 const message = useMessage()
47 const cluster = ref<ClusterHealth | null>(null)
frontend/src/components/indices/Details.vue
+2 -2
@@ -56,11 +56,11 @@
56
57 <script setup lang="ts">
58 import type { IndexShard, IndexStats } from "@/types/indices.d"
59 -import Api from "@/api"
60 -import IndexCard from "@/components/indices/IndexCard.vue"
59 import { NCard, NScrollbar, NSelect, NSpin, NTable, useMessage } from "naive-ui"
60 import { nanoid } from "nanoid"
61 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
62 +import Api from "@/api"
63 +import IndexCard from "@/components/indices/IndexCard.vue"
64
65 type IndexModel = IndexStats | null | ""
66
frontend/src/components/indices/IndexCard.vue
+2 -2
@@ -61,12 +61,12 @@
61
62 <script setup lang="ts">
63 import type { IndexStats } from "@/types/indices.d"
64 +import { NButton, NTooltip, useDialog, useMessage } from "naive-ui"
65 +import { h, ref, toRefs } from "vue"
66 import Api from "@/api"
67 import CardEntity from "@/components/common/cards/CardEntity.vue"
68 import Icon from "@/components/common/Icon.vue"
69 import IndexIcon from "@/components/indices/IndexIcon.vue"
68 -import { NButton, NTooltip, useDialog, useMessage } from "naive-ui"
69 -import { h, ref, toRefs } from "vue"
70
71 const props = defineProps<{
72 index: IndexStats
frontend/src/components/indices/IndexIcon.vue
+1 -1
@@ -8,9 +8,9 @@
8
9 <script setup lang="ts">
10 import type { IndexStats } from "@/types/indices.d"
11 +import { toRefs } from "vue"
12 import Icon from "@/components/common/Icon.vue"
13 import { IndexHealth } from "@/types/indices.d"
13 -import { toRefs } from "vue"
14
15 const props = defineProps<{
16 health: IndexStats["health"]
frontend/src/components/indices/Marquee.vue
+3 -3
@@ -43,12 +43,12 @@
43
44 <script setup lang="ts">
45 import type { IndexStats } from "@/types/indices.d"
46 -import Api from "@/api"
47 -import IndexIcon from "@/components/indices/IndexIcon.vue"
48 -import { useThemeStore } from "@/stores/theme"
46 import { NCard, NEmpty, NSpin, useMessage } from "naive-ui"
47 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
48 import { Vue3Marquee } from "vue3-marquee"
49 +import Api from "@/api"
50 +import IndexIcon from "@/components/indices/IndexIcon.vue"
51 +import { useThemeStore } from "@/stores/theme"
52
53 const props = defineProps<{
54 indices?: IndexStats[] | null
frontend/src/components/indices/NodeAllocation.vue
+1 -1
@@ -71,10 +71,10 @@
71
72 <script setup lang="ts">
73 import type { IndexAllocation } from "@/types/indices.d"
74 -import Api from "@/api"
74 import { NCard, NEmpty, NProgress, NScrollbar, NSpin, useMessage } from "naive-ui"
75 import { nanoid } from "nanoid"
76 import { onBeforeMount, ref } from "vue"
77 +import Api from "@/api"
78
79 const message = useMessage()
80 const indicesAllocation = ref<IndexAllocation[]>([])
frontend/src/components/indices/TopIndices.vue
+4 -4
@@ -9,19 +9,19 @@
9 </template>
10
11 <script setup lang="ts">
12 -import type { IndexStats } from "@/types/indices.d"
12 import type { ECharts } from "echarts/core"
14 -import { useThemeStore } from "@/stores/theme"
15 -import { IndexHealth } from "@/types/indices.d"
13 +import type { IndexStats } from "@/types/indices.d"
14 import bytes from "bytes"
17 -
15 import { PieChart } from "echarts/charts"
16 import { GridComponent, LegendComponent, TooltipComponent } from "echarts/components"
17 +
18 import { init as echartsInit, use as echartsUse } from "echarts/core"
19 import { CanvasRenderer } from "echarts/renderers"
20 import _ from "lodash"
21 import { NCard, NSpin } from "naive-ui"
22 import { computed, onMounted, ref, toRefs, watch } from "vue"
23 +import { useThemeStore } from "@/stores/theme"
24 +import { IndexHealth } from "@/types/indices.d"
25
26 const props = defineProps<{
27 indices: IndexStats[] | null
frontend/src/components/indices/UnhealthyIndices.vue
+2 -2
@@ -35,11 +35,11 @@
35
36 <script setup lang="ts">
37 import type { IndexStats } from "@/types/indices.d"
38 +import { NCard, NEmpty, NScrollbar, NSpin } from "naive-ui"
39 +import { computed, toRefs } from "vue"
40 import Icon from "@/components/common/Icon.vue"
41 import IndexCard from "@/components/indices/IndexCard.vue"
42 import { IndexHealth } from "@/types/indices.d"
41 -import { NCard, NEmpty, NScrollbar, NSpin } from "naive-ui"
42 -import { computed, toRefs } from "vue"
43
44 const props = defineProps<{
45 indices: IndexStats[] | null
frontend/src/components/integrations/IntegrationsList.vue
+2 -2
@@ -13,10 +13,10 @@
13
14 <script setup lang="ts">
15 import type { ServiceItemData } from "../services/types"
16 -import Api from "@/api"
17 -import ServicesList from "@/components/services/List.vue"
16 import { useMessage } from "naive-ui"
17 import { onBeforeMount, ref } from "vue"
18 +import Api from "@/api"
19 +import ServicesList from "@/components/services/List.vue"
20
21 const { embedded, hideTotals, selectable, disabledIdsList } = defineProps<{
22 embedded?: boolean
frontend/src/components/license/LicenseCheckoutResponse.vue
+2 -2
@@ -31,11 +31,11 @@
31
32 <script setup lang="ts">
33 import type { LicenseKey } from "@/types/license.d"
34 +import { NButton, NCard, NSpin, useMessage } from "naive-ui"
35 +import { onBeforeMount, ref, toRefs } from "vue"
36 import Api from "@/api"
37 import Icon from "@/components/common/Icon.vue"
38 import { useGoto } from "@/composables/useGoto"
37 -import { NButton, NCard, NSpin, useMessage } from "naive-ui"
38 -import { onBeforeMount, ref, toRefs } from "vue"
39
40 const props = defineProps<{ type: "success" | "error"; data?: { email?: string } }>()
41 const { type, data } = toRefs(props)
frontend/src/components/license/LicenseCheckoutWizard.vue
+3 -3
@@ -79,13 +79,13 @@
79 </template>
80
81 <script setup lang="ts">
82 -import type { CheckoutPayload, License, LicenseCustomer, LicenseFeatures, SubscriptionFeature } from "@/types/license.d"
82 import type { FormItemRule, FormRules } from "naive-ui"
84 -import Api from "@/api"
85 -import Icon from "@/components/common/Icon.vue"
83 +import type { CheckoutPayload, License, LicenseCustomer, LicenseFeatures, SubscriptionFeature } from "@/types/license.d"
84 import { NButton, NEmpty, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
85 import isEmail from "validator/es/lib/isEmail"
86 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
87 +import Api from "@/api"
88 +import Icon from "@/components/common/Icon.vue"
89 import SubscriptionCard from "./SubscriptionCard.vue"
90
91 const props = defineProps<{
frontend/src/components/license/LicenseDetails.vue
+3 -3
@@ -95,15 +95,15 @@
95
96 <script setup lang="ts">
97 import type { License, LicenseFeatures } from "@/types/license.d"
98 +import _startCase from "lodash/startCase"
99 +import { NSpin, useMessage } from "naive-ui"
100 +import { computed, defineAsyncComponent, onBeforeMount, onMounted, ref, toRefs } from "vue"
101 import Api from "@/api"
102 import Badge from "@/components/common/Badge.vue"
103 import CardKV from "@/components/common/cards/CardKV.vue"
104 import Icon from "@/components/common/Icon.vue"
105 import { useSettingsStore } from "@/stores/settings"
106 import { formatDate } from "@/utils"
104 -import _startCase from "lodash/startCase"
105 -import { NSpin, useMessage } from "naive-ui"
106 -import { computed, defineAsyncComponent, onBeforeMount, onMounted, ref, toRefs } from "vue"
107
108 const props = defineProps<{
109 licenseData?: License
frontend/src/components/license/LicenseFeatureCheck.vue
+2 -2
@@ -76,11 +76,11 @@
76
77 <script setup lang="ts">
78 import type { LicenseFeatures } from "@/types/license.d"
79 +import { NButton, NCard, NModal, NTooltip } from "naive-ui"
80 +import { ref, watch, watchEffect } from "vue"
81 import Api from "@/api"
82 import Icon from "@/components/common/Icon.vue"
83 import { useGoto } from "@/composables/useGoto"
82 -import { NButton, NCard, NModal, NTooltip } from "naive-ui"
83 -import { ref, watch, watchEffect } from "vue"
84
85 const { feature, feedback, disabled, forceShowFeedback } = defineProps<{
86 feature: LicenseFeatures
frontend/src/components/license/LicenseFeatures.vue
+2 -2
@@ -105,10 +105,10 @@
105
106 <script setup lang="ts">
107 import type { License, LicenseFeatures, LicenseKey, SubscriptionFeature } from "@/types/license.d"
108 -import Api from "@/api"
109 -import Icon from "@/components/common/Icon.vue"
108 import { NButton, NEmpty, NModal, NPopover, NScrollbar, NSpin, useMessage } from "naive-ui"
109 import { computed, onBeforeMount, onMounted, ref, toRefs } from "vue"
110 +import Api from "@/api"
111 +import Icon from "@/components/common/Icon.vue"
112 import LicenseCheckoutWizard from "./LicenseCheckoutWizard.vue"
113 import LicenseDetails from "./LicenseDetails.vue"
114 import LicenseLoadForm from "./LicenseLoadForm.vue"
frontend/src/components/license/LicenseLoadForm.vue
+2 -2
@@ -14,10 +14,10 @@
14
15 <script setup lang="ts">
16 import type { LicenseKey } from "@/types/license.d"
17 -import Api from "@/api"
18 -import Icon from "@/components/common/Icon.vue"
17 import { NButton, NInput, NSpin, useMessage } from "naive-ui"
18 import { computed, ref } from "vue"
19 +import Api from "@/api"
20 +import Icon from "@/components/common/Icon.vue"
21
22 const emit = defineEmits<{
23 (e: "uploaded"): void
frontend/src/components/license/SubscriptionCard.vue
+2 -2
@@ -85,12 +85,12 @@
85 <script setup lang="ts">
86 import type { CancelSubscriptionPayload } from "@/api/endpoints/license"
87 import type { License, SubscriptionFeature } from "@/types/license.d"
88 +import { NButton, NModal, NPopconfirm, NSpin, useMessage } from "naive-ui"
89 +import { ref, toRefs } from "vue"
90 import Api from "@/api"
91 import CardEntity from "@/components/common/cards/CardEntity.vue"
92 import Icon from "@/components/common/Icon.vue"
93 import { price } from "@/utils"
92 -import { NButton, NModal, NPopconfirm, NSpin, useMessage } from "naive-ui"
93 -import { ref, toRefs } from "vue"
94
95 const props = defineProps<{
96 subscription: SubscriptionFeature
frontend/src/components/license/deprecated/LicenseCheckout.vue
+2 -2
@@ -36,10 +36,10 @@
36
37 <script setup lang="ts">
38 import type { LicenseKey } from "@/types/license.d"
39 -import Api from "@/api"
40 -import Icon from "@/components/common/Icon.vue"
39 import { NButton, NModal, useMessage } from "naive-ui"
40 import { onBeforeMount, ref } from "vue"
41 +import Api from "@/api"
42 +import Icon from "@/components/common/Icon.vue"
43 import LicenseCheckoutWizard from "./LicenseCheckoutWizard.vue"
44
45 const emit = defineEmits<{
frontend/src/components/license/deprecated/LicenseEditor.vue
+3 -3
@@ -112,15 +112,15 @@
112 </template>
113
114 <script setup lang="ts">
115 +import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
116 /** @deprecated */
117 import type { NewLicensePayload } from "@/api/endpoints/license"
118 import type { LicenseKey } from "@/types/license.d"
118 -import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
119 -import Api from "@/api"
120 -import Icon from "@/components/common/Icon.vue"
119 import { NButton, NForm, NFormItem, NInput, NInputNumber, NSpin, useMessage } from "naive-ui"
120 import isEmail from "validator/es/lib/isEmail"
121 import { computed, onBeforeMount, ref } from "vue"
122 +import Api from "@/api"
123 +import Icon from "@/components/common/Icon.vue"
124
125 const emit = defineEmits<{
126 (e: "updated"): void
frontend/src/components/logs/LogItem.vue
+1 -1
@@ -64,13 +64,13 @@
64 <script setup lang="ts">
65 import type { Log } from "@/types/logs.d"
66 import type { User } from "@/types/user.d"
67 +import { computed } from "vue"
68 import Badge from "@/components/common/Badge.vue"
69 import CardEntity from "@/components/common/cards/CardEntity.vue"
70 import Icon from "@/components/common/Icon.vue"
71 import { useSettingsStore } from "@/stores/settings"
72 import { LogEventType } from "@/types/logs.d"
73 import dayjs from "@/utils/dayjs"
73 -import { computed } from "vue"
74
75 const { log, users } = defineProps<{ log: Log; users?: User[] }>()
76
frontend/src/components/logs/LogsFilters.vue
+2 -2
@@ -58,12 +58,12 @@
58 <script setup lang="ts">
59 import type { LogsQueryEventType, LogsQueryTimeRange, LogsQueryTypes, LogsQueryValues } from "@/types/logs.d"
60 import type { User } from "@/types/user.d"
61 -import Api from "@/api"
62 -import { LogEventType } from "@/types/logs.d"
61 import _cloneDeep from "lodash/cloneDeep"
62 import _toSafeInteger from "lodash/toSafeInteger"
63 import { NButton, NInput, NInputGroup, NInputNumber, NSelect } from "naive-ui"
64 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
65 +import Api from "@/api"
66 +import { LogEventType } from "@/types/logs.d"
67
68 const props = defineProps<{ users?: User[]; fetchingUsers?: boolean }>()
69
frontend/src/components/logs/LogsList.vue
+3 -3
@@ -118,14 +118,14 @@
118 <script setup lang="ts">
119 import type { Log, LogsQuery, LogsQueryTimeRange, LogsQueryTypes, LogsQueryValues } from "@/types/logs.d"
120 import type { User } from "@/types/user.d"
121 -import Api from "@/api"
122 -import Icon from "@/components/common/Icon.vue"
123 -import { LogEventType } from "@/types/logs.d"
121 import { useResizeObserver } from "@vueuse/core"
122 import _orderBy from "lodash/orderBy"
123 import { NBadge, NButton, NEmpty, NModal, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
124 import { nanoid } from "nanoid"
125 import { computed, onBeforeMount, ref, toRefs } from "vue"
126 +import Api from "@/api"
127 +import Icon from "@/components/common/Icon.vue"
128 +import { LogEventType } from "@/types/logs.d"
129 import LogItem from "./LogItem.vue"
130 import LogsFilters from "./LogsFilters.vue"
131
frontend/src/components/mitre/AtomicTests/List.vue new
+141
@@ -0,0 +1,141 @@
1 +<template>
2 + <div class="flex flex-col gap-4">
3 + <div class="flex flex-col">
4 + <div ref="header" class="header flex items-center justify-end gap-2">
5 + <div class="info flex grow gap-5">
6 + <n-popover overlap placement="bottom-start">
7 + <template #trigger>
8 + <div class="bg-default rounded-lg">
9 + <n-button size="small" class="!cursor-help">
10 + <template #icon>
11 + <Icon :name="InfoIcon"></Icon>
12 + </template>
13 + </n-button>
14 + </div>
15 + </template>
16 + <div class="flex flex-col gap-2">
17 + <div class="box">
18 + Total:
19 + <code>{{ total }}</code>
20 + </div>
21 + </div>
22 + </n-popover>
23 + </div>
24 + <n-pagination
25 + v-model:page="currentPage"
26 + v-model:page-size="pageSize"
27 + :item-count="total"
28 + :page-slot="pageSlot"
29 + :show-size-picker="showSizePicker"
30 + :page-sizes="pageSizes"
31 + :simple="simpleMode"
32 + />
33 + </div>
34 +
35 + <n-spin :show="loading">
36 + <div class="my-3 flex min-h-28 flex-col gap-2">
37 + <template v-if="list.length">
38 + <TechniqueCard v-for="item of list" :key="item.technique_id" :entity="item" />
39 + </template>
40 + <template v-else>
41 + <n-empty v-if="!loading" description="No items found" class="h-48 justify-center" />
42 + </template>
43 + </div>
44 + </n-spin>
45 + <div class="flex justify-end">
46 + <n-pagination
47 + v-if="list.length > 3"
48 + v-model:page="currentPage"
49 + :page-size="pageSize"
50 + :item-count="total"
51 + :page-slot="6"
52 + />
53 + </div>
54 + </div>
55 + </div>
56 +</template>
57 +
58 +<script setup lang="ts">
59 +import type { MitreAtomicTestsQuery } from "@/api/endpoints/mitre"
60 +import type { MitreAtomicTest } from "@/types/mitre.d"
61 +import { useResizeObserver, watchDebounced } from "@vueuse/core"
62 +import axios from "axios"
63 +import { NButton, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
64 +import { computed, ref } from "vue"
65 +import Api from "@/api"
66 +import Icon from "@/components/common/Icon.vue"
67 +import TechniqueCard from "./TechniqueCard.vue"
68 +
69 +const loading = ref(false)
70 +const message = useMessage()
71 +const list = ref<MitreAtomicTest[]>([])
72 +const header = ref()
73 +const currentPage = ref(1)
74 +const total = ref(0)
75 +const compactMode = ref(false)
76 +const simpleMode = ref(false)
77 +const showSizePicker = computed(() => !compactMode.value)
78 +const pageSizes = [25, 50, 100, 150, 200]
79 +const pageSize = ref(pageSizes[0])
80 +const pageSlot = ref(8)
81 +const InfoIcon = "carbon:information"
82 +
83 +let abortController: AbortController | null = null
84 +
85 +function getList() {
86 + abortController?.abort()
87 + abortController = new AbortController()
88 +
89 + loading.value = true
90 +
91 + const query: MitreAtomicTestsQuery = {
92 + size: pageSize.value,
93 + page: currentPage.value
94 + }
95 +
96 + Api.mitre
97 + .getMitreAtomicTests(query, abortController.signal)
98 + .then(res => {
99 + loading.value = false
100 +
101 + if (res.data.success) {
102 + list.value = res.data?.tests || []
103 + total.value = res.data?.total_techniques || 0
104 + } else {
105 + message.warning(res.data?.message || "An error occurred. Please try again later.")
106 + }
107 + })
108 + .catch(err => {
109 + if (!axios.isCancel(err)) {
110 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
111 + loading.value = false
112 + }
113 + })
114 +}
115 +
116 +useResizeObserver(header, entries => {
117 + const entry = entries[0]
118 + const { width } = entry.contentRect
119 +
120 + if (width < 650) {
121 + compactMode.value = true
122 + pageSlot.value = 5
123 + } else {
124 + compactMode.value = false
125 + pageSlot.value = 8
126 + }
127 +
128 + simpleMode.value = width < 450
129 +})
130 +
131 +watchDebounced([currentPage, pageSize], getList, {
132 + deep: true,
133 + debounce: 300,
134 + immediate: true
135 +})
136 +// MOCK
137 +/*
138 +list.value = techniqueAlertsResponse.alerts
139 +total.value = techniqueAlertsResponse.total_alerts
140 +*/
141 +</script>
frontend/src/components/mitre/AtomicTests/TechniqueCard.vue new
+50
@@ -0,0 +1,50 @@
1 +<template>
2 + <div>
3 + <CardEntity hoverable clickable :embedded class="@container" @click.stop="showDetails = true">
4 + <template #headerMain>#{{ entity.technique_id }}</template>
5 + <template #headerExtra>
6 + test count:
7 + <code>{{ entity.test_count }}</code>
8 + </template>
9 + <template #default>{{ entity.technique_name }}</template>
10 + <template #footer>
11 + <div class="flex flex-wrap items-center gap-3">
12 + <Badge v-if="entity.has_prerequisites" color="primary" type="splitted">
13 + <template #label>has prerequisites</template>
14 + </Badge>
15 +
16 + <Badge v-for="cat of entity.categories" :key="cat" color="primary">
17 + <template #iconLeft><Icon :name="iconFromOs(cat)" :size="14" /></template>
18 + <template #value>{{ cat }}</template>
19 + </Badge>
20 + </div>
21 + </template>
22 + </CardEntity>
23 +
24 + <n-modal
25 + v-model:show="showDetails"
26 + preset="card"
27 + :style="{ maxWidth: 'min(800px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
28 + :title="`Technique: ${entity.technique_name}`"
29 + :bordered="false"
30 + segmented
31 + >
32 + <TechniqueCardContent :technique-id="entity.technique_id" />
33 + </n-modal>
34 + </div>
35 +</template>
36 +
37 +<script setup lang="ts">
38 +import type { MitreAtomicTest } from "@/types/mitre.d"
39 +import { NModal } from "naive-ui"
40 +import { ref } from "vue"
41 +import Badge from "@/components/common/Badge.vue"
42 +import CardEntity from "@/components/common/cards/CardEntity.vue"
43 +import Icon from "@/components/common/Icon.vue"
44 +import { iconFromOs } from "@/utils"
45 +import TechniqueCardContent from "./TechniqueCardContent.vue"
46 +
47 +const { entity } = defineProps<{ entity: MitreAtomicTest; embedded?: boolean }>()
48 +
49 +const showDetails = ref(false)
50 +</script>
frontend/src/components/mitre/AtomicTests/TechniqueCardContent.vue new
+54
@@ -0,0 +1,54 @@
1 +<template>
2 + <div class="active-response-details">
3 + <n-spin :show="loading" class="min-h-48">
4 + <template v-if="content">
5 + <Suspense>
6 + <Markdown :source="content" />
7 + </Suspense>
8 + </template>
9 + <template v-else>
10 + <n-empty v-if="!loading" description="No description found" class="h-48 justify-center" />
11 + </template>
12 + </n-spin>
13 + </div>
14 +</template>
15 +
16 +<script setup lang="ts">
17 +import { NEmpty, NSpin, useMessage } from "naive-ui"
18 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
19 +import Api from "@/api"
20 +
21 +const { techniqueId } = defineProps<{
22 + techniqueId: string
23 +}>()
24 +
25 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
26 +
27 +const message = useMessage()
28 +const loading = ref(false)
29 +const content = ref<string>()
30 +
31 +function getContent() {
32 + loading.value = true
33 +
34 + Api.mitre
35 + .getMitreAtomicTestContent(techniqueId)
36 + .then(res => {
37 + if (res.data.success) {
38 + content.value = res.data?.markdown_content
39 + } else {
40 + message.warning(res.data?.message || "An error occurred. Please try again later.")
41 + }
42 + })
43 + .catch(err => {
44 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
45 + })
46 + .finally(() => {
47 + loading.value = false
48 + })
49 +}
50 +
51 +onBeforeMount(() => {
52 + getContent()
53 +})
54 +</script>
frontend/src/components/mitre/Group/GroupCard.vue new
+122
@@ -0,0 +1,122 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" :loading="loadingDetails" @click="showDetails = true">
4 + <template #headerMain>{{ id }}</template>
5 + <template #headerExtra>
6 + <span v-if="groupDetails" class="text-default">
7 + {{ groupDetails.external_id }}
8 + </span>
9 + <n-skeleton v-else text :width="100" :height="18" />
10 + </template>
11 + <template #default>
12 + <div v-if="groupDetails">
13 + {{ groupDetails.name }}
14 + </div>
15 + <n-skeleton v-else text style="width: 60%" :height="20" />
16 + </template>
17 + <template #footer>
18 + <p v-if="groupDetails" class="cursor-text" @click.stop="() => {}">
19 + <Suspense>
20 + <Markdown :source="groupDetails.description" />
21 + </Suspense>
22 + </p>
23 + <div v-else>
24 + <n-skeleton text :repeat="2" :height="16" />
25 + <n-skeleton text style="width: 40%" :height="16" />
26 + </div>
27 + </template>
28 + </CardEntity>
29 + <n-modal
30 + v-model:show="showDetails"
31 + display-directive="show"
32 + preset="card"
33 + content-class="!p-0"
34 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
35 + :title="`Group • ${id}`"
36 + :bordered="false"
37 + segmented
38 + >
39 + <n-tabs type="line" animated :tabs-padding="24">
40 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
41 + <div class="px-7 pb-7 pt-4">
42 + <GroupDetails :entity="groupDetails" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane
46 + name="Software"
47 + :tab="`Software (${groupDetails?.software?.length || 0})`"
48 + display-directive="show:lazy"
49 + >
50 + <div class="px-7 pb-7 pt-4">
51 + <SoftwareList v-if="groupDetails" :list="groupDetails.software" />
52 + </div>
53 + </n-tab-pane>
54 + <n-tab-pane
55 + name="Techniques"
56 + :tab="`Techniques (${groupDetails?.techniques?.length || 0})`"
57 + display-directive="show:lazy"
58 + >
59 + <div class="px-7 pb-7 pt-4">
60 + <TechniquesList v-if="groupDetails" :list="groupDetails.techniques" />
61 + </div>
62 + </n-tab-pane>
63 + </n-tabs>
64 + </n-modal>
65 + </div>
66 +</template>
67 +
68 +<script setup lang="ts">
69 +import type { MitreGroupDetails } from "@/types/mitre.d"
70 +import { NModal, NSkeleton, NTabPane, NTabs, useMessage } from "naive-ui"
71 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
72 +import Api from "@/api"
73 +import CardEntity from "@/components/common/cards/CardEntity.vue"
74 +import SoftwareList from "../Software/SoftwareList.vue"
75 +import TechniquesList from "../Technique/TechniquesList.vue"
76 +import GroupDetails from "./GroupDetails.vue"
77 +
78 +const { id, entity } = defineProps<{
79 + id: string
80 + entity?: MitreGroupDetails
81 +}>()
82 +
83 +const emit = defineEmits<{
84 + (e: "loaded", value: MitreGroupDetails): void
85 +}>()
86 +
87 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
88 +
89 +const showDetails = ref(false)
90 +const message = useMessage()
91 +const loadingDetails = ref(false)
92 +const groupDetails = ref<MitreGroupDetails | undefined>(undefined)
93 +
94 +function getDetails(id: string) {
95 + loadingDetails.value = true
96 +
97 + Api.mitre
98 + .getMitreGroups({ id })
99 + .then(res => {
100 + if (res.data.success) {
101 + groupDetails.value = res.data.results?.[0] || null
102 + if (groupDetails.value) emit("loaded", groupDetails.value)
103 + } else {
104 + message.warning(res.data?.message || "An error occurred. Please try again later.")
105 + }
106 + })
107 + .catch(err => {
108 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
109 + })
110 + .finally(() => {
111 + loadingDetails.value = false
112 + })
113 +}
114 +
115 +onBeforeMount(() => {
116 + if (entity) {
117 + groupDetails.value = entity
118 + } else if (id) {
119 + getDetails(id)
120 + }
121 +})
122 +</script>
frontend/src/components/mitre/Group/GroupDetails.vue new
+162
@@ -0,0 +1,162 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="groupDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ groupDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ groupDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="groupDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="groupDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 +
26 + <CardKV v-if="groupDetails.references?.length">
27 + <template #key>references</template>
28 + <template #value>
29 + <References :references="groupDetails.references" />
30 + </template>
31 + </CardKV>
32 + </div>
33 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
34 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
35 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
36 + <div class="flex flex-col gap-0.5 text-sm">
37 + <div class="text-secondary font-mono text-xs">external_id</div>
38 + <div>{{ groupDetails.external_id }}</div>
39 + </div>
40 + <div class="flex flex-col gap-0.5 text-sm">
41 + <div class="text-secondary font-mono text-xs">created_time</div>
42 + <div>{{ formatDate(groupDetails.created_time, dFormats.datetime) }}</div>
43 + </div>
44 + <div class="flex flex-col gap-0.5 text-sm">
45 + <div class="text-secondary font-mono text-xs">modified_time</div>
46 + <div>{{ formatDate(groupDetails.modified_time, dFormats.datetime) }}</div>
47 + </div>
48 + <div class="flex flex-col gap-0.5 text-sm">
49 + <div class="text-secondary font-mono text-xs">url</div>
50 + <div>
51 + <a :href="groupDetails.url" target="_blank" rel="nofollow noopener noreferrer">
52 + {{ groupDetails.url }}
53 + </a>
54 + </div>
55 + </div>
56 + <div class="flex flex-col gap-0.5 text-sm">
57 + <div class="text-secondary font-mono text-xs">source</div>
58 + <div>{{ groupDetails.source }}</div>
59 + </div>
60 + <div class="flex flex-col gap-0.5 text-sm">
61 + <div class="text-secondary font-mono text-xs">mitre_version</div>
62 + <div>{{ groupDetails.mitre_version }}</div>
63 + </div>
64 + <div class="flex flex-col gap-0.5 text-sm">
65 + <div class="text-secondary font-mono text-xs">country</div>
66 + <div>{{ groupDetails.country || "—" }}</div>
67 + </div>
68 + <div class="flex flex-col gap-0.5 text-sm">
69 + <div class="text-secondary font-mono text-xs">aliases</div>
70 + <div class="mt-0.5 flex flex-wrap gap-1">
71 + <template v-if="!groupDetails.aliases?.length">—</template>
72 + <template v-else>
73 + <code v-for="item of groupDetails.aliases" :key="item" class="text-xs">
74 + {{ item }}
75 + </code>
76 + </template>
77 + </div>
78 + </div>
79 + </n-card>
80 +
81 + <div class="flex flex-wrap gap-1">
82 + <Badge v-if="groupDetails.deprecated" color="primary" class="text-xs! font-mono">
83 + <template #value>deprecated</template>
84 + </Badge>
85 + </div>
86 + </div>
87 + </div>
88 + </div>
89 + </n-spin>
90 +</template>
91 +
92 +<script setup lang="ts">
93 +import type { MitreGroupDetails } from "@/types/mitre.d"
94 +import { useElementBounding, useRafFn } from "@vueuse/core"
95 +import { useMotionProperties } from "@vueuse/motion"
96 +import { NCard, NSpin, useMessage } from "naive-ui"
97 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
98 +import Api from "@/api"
99 +import Badge from "@/components/common/Badge.vue"
100 +import CardKV from "@/components/common/cards/CardKV.vue"
101 +import { useSettingsStore } from "@/stores/settings"
102 +import { formatDate } from "@/utils"
103 +import References from "../common/References.vue"
104 +
105 +const { externalId, entity } = defineProps<{
106 + externalId?: string
107 + entity?: MitreGroupDetails
108 +}>()
109 +
110 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
111 +
112 +const dFormats = useSettingsStore().dateFormat
113 +const message = useMessage()
114 +const loadingDetails = ref(false)
115 +const groupDetails = ref<MitreGroupDetails | null>(null)
116 +
117 +const sidebarRef = ref(null)
118 +const sidebarCardRef = ref(null)
119 +const { top: sidebarTop } = useElementBounding(sidebarRef)
120 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
121 +
122 +const { resume } = useRafFn(
123 + () => {
124 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
125 + styleCardTransform.translateY = `${targetY}px`
126 + },
127 + { immediate: false }
128 +)
129 +
130 +watch(sidebarTop, () => {
131 + resume()
132 +})
133 +
134 +function getDetails(id: string) {
135 + loadingDetails.value = true
136 +
137 + Api.mitre
138 + .getMitreGroups({ id })
139 + .then(res => {
140 + if (res.data.success) {
141 + groupDetails.value = res.data.results?.[0] || null
142 + } else {
143 + message.warning(res.data?.message || "An error occurred. Please try again later.")
144 + }
145 + })
146 + .catch(err => {
147 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
148 + })
149 + .finally(() => {
150 + loadingDetails.value = false
151 + })
152 +}
153 +
154 +onBeforeMount(() => {
155 + if (externalId) {
156 + getDetails(externalId)
157 + }
158 + if (entity) {
159 + groupDetails.value = entity
160 + }
161 +})
162 +</script>
frontend/src/components/mitre/Group/GroupsList.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <GroupCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreGroupDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import GroupCard from "./GroupCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const groups = ref<{ id: string; entity?: MitreGroupDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return groups.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + groups.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/Mitigation/MitigationCard.vue new
+112
@@ -0,0 +1,112 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" :loading="loadingDetails" @click="showDetails = true">
4 + <template #headerMain>{{ id }}</template>
5 + <template #headerExtra>
6 + <span v-if="mitigationDetails" class="text-default">
7 + {{ mitigationDetails.external_id }}
8 + </span>
9 + <n-skeleton v-else text :width="100" :height="18" />
10 + </template>
11 + <template #default>
12 + <div v-if="mitigationDetails">
13 + {{ mitigationDetails.name }}
14 + </div>
15 + <n-skeleton v-else text style="width: 60%" :height="20" />
16 + </template>
17 + <template #footer>
18 + <p v-if="mitigationDetails" class="cursor-text" @click.stop="() => {}">
19 + <Suspense>
20 + <Markdown :source="mitigationDetails.description" />
21 + </Suspense>
22 + </p>
23 + <div v-else>
24 + <n-skeleton text :repeat="2" :height="16" />
25 + <n-skeleton text style="width: 40%" :height="16" />
26 + </div>
27 + </template>
28 + </CardEntity>
29 + <n-modal
30 + v-model:show="showDetails"
31 + display-directive="show"
32 + preset="card"
33 + content-class="!p-0"
34 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
35 + :title="`Mitigation • ${id}`"
36 + :bordered="false"
37 + segmented
38 + >
39 + <n-tabs type="line" animated :tabs-padding="24">
40 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
41 + <div class="px-7 pb-7 pt-4">
42 + <MitigationDetails :entity="mitigationDetails" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane
46 + name="Techniques"
47 + :tab="`Techniques (${mitigationDetails?.techniques?.length || 0})`"
48 + display-directive="show:lazy"
49 + >
50 + <div class="px-7 pb-7 pt-4">
51 + <TechniquesList v-if="mitigationDetails" :list="mitigationDetails.techniques" />
52 + </div>
53 + </n-tab-pane>
54 + </n-tabs>
55 + </n-modal>
56 + </div>
57 +</template>
58 +
59 +<script setup lang="ts">
60 +import type { MitreMitigationDetails } from "@/types/mitre.d"
61 +import { NModal, NSkeleton, NTabPane, NTabs, useMessage } from "naive-ui"
62 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
63 +import Api from "@/api"
64 +import CardEntity from "@/components/common/cards/CardEntity.vue"
65 +import TechniquesList from "../Technique/TechniquesList.vue"
66 +import MitigationDetails from "./MitigationDetails.vue"
67 +
68 +const { id, entity } = defineProps<{
69 + id: string
70 + entity?: MitreMitigationDetails
71 +}>()
72 +
73 +const emit = defineEmits<{
74 + (e: "loaded", value: MitreMitigationDetails): void
75 +}>()
76 +
77 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
78 +
79 +const showDetails = ref(false)
80 +const message = useMessage()
81 +const loadingDetails = ref(false)
82 +const mitigationDetails = ref<MitreMitigationDetails | undefined>(undefined)
83 +
84 +function getDetails(id: string) {
85 + loadingDetails.value = true
86 +
87 + Api.mitre
88 + .getMitreMitigations({ id })
89 + .then(res => {
90 + if (res.data.success) {
91 + mitigationDetails.value = res.data.results?.[0] || null
92 + if (mitigationDetails.value) emit("loaded", mitigationDetails.value)
93 + } else {
94 + message.warning(res.data?.message || "An error occurred. Please try again later.")
95 + }
96 + })
97 + .catch(err => {
98 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
99 + })
100 + .finally(() => {
101 + loadingDetails.value = false
102 + })
103 +}
104 +
105 +onBeforeMount(() => {
106 + if (entity) {
107 + mitigationDetails.value = entity
108 + } else if (id) {
109 + getDetails(id)
110 + }
111 +})
112 +</script>
frontend/src/components/mitre/Mitigation/MitigationDetails.vue new
+147
@@ -0,0 +1,147 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="mitigationDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ mitigationDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ mitigationDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="mitigationDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="mitigationDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 +
26 + <CardKV v-if="mitigationDetails.references?.length">
27 + <template #key>references</template>
28 + <template #value>
29 + <References :references="mitigationDetails.references" />
30 + </template>
31 + </CardKV>
32 + </div>
33 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
34 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
35 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
36 + <div class="flex flex-col gap-0.5 text-sm">
37 + <div class="text-secondary font-mono text-xs">external_id</div>
38 + <div>{{ mitigationDetails.external_id }}</div>
39 + </div>
40 + <div class="flex flex-col gap-0.5 text-sm">
41 + <div class="text-secondary font-mono text-xs">created_time</div>
42 + <div>{{ formatDate(mitigationDetails.created_time, dFormats.datetime) }}</div>
43 + </div>
44 + <div class="flex flex-col gap-0.5 text-sm">
45 + <div class="text-secondary font-mono text-xs">modified_time</div>
46 + <div>{{ formatDate(mitigationDetails.modified_time, dFormats.datetime) }}</div>
47 + </div>
48 + <div class="flex flex-col gap-0.5 text-sm">
49 + <div class="text-secondary font-mono text-xs">url</div>
50 + <div>
51 + <a :href="mitigationDetails.url" target="_blank" rel="nofollow noopener noreferrer">
52 + {{ mitigationDetails.url }}
53 + </a>
54 + </div>
55 + </div>
56 + <div class="flex flex-col gap-0.5 text-sm">
57 + <div class="text-secondary font-mono text-xs">source</div>
58 + <div>{{ mitigationDetails.source }}</div>
59 + </div>
60 + <div class="flex flex-col gap-0.5 text-sm">
61 + <div class="text-secondary font-mono text-xs">mitre_version</div>
62 + <div>{{ mitigationDetails.mitre_version }}</div>
63 + </div>
64 + </n-card>
65 +
66 + <div class="flex flex-wrap gap-1">
67 + <Badge v-if="mitigationDetails.deprecated" color="primary" class="text-xs! font-mono">
68 + <template #value>deprecated</template>
69 + </Badge>
70 + </div>
71 + </div>
72 + </div>
73 + </div>
74 + </n-spin>
75 +</template>
76 +
77 +<script setup lang="ts">
78 +import type { MitreMitigationDetails } from "@/types/mitre.d"
79 +import { useElementBounding, useRafFn } from "@vueuse/core"
80 +import { useMotionProperties } from "@vueuse/motion"
81 +import { NCard, NSpin, useMessage } from "naive-ui"
82 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
83 +import Api from "@/api"
84 +import Badge from "@/components/common/Badge.vue"
85 +import CardKV from "@/components/common/cards/CardKV.vue"
86 +import { useSettingsStore } from "@/stores/settings"
87 +import { formatDate } from "@/utils"
88 +import References from "../common/References.vue"
89 +
90 +const { externalId, entity } = defineProps<{
91 + externalId?: string
92 + entity?: MitreMitigationDetails
93 +}>()
94 +
95 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
96 +
97 +const dFormats = useSettingsStore().dateFormat
98 +const message = useMessage()
99 +const loadingDetails = ref(false)
100 +const mitigationDetails = ref<MitreMitigationDetails | null>(null)
101 +
102 +const sidebarRef = ref(null)
103 +const sidebarCardRef = ref(null)
104 +const { top: sidebarTop } = useElementBounding(sidebarRef)
105 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
106 +
107 +const { resume } = useRafFn(
108 + () => {
109 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
110 + styleCardTransform.translateY = `${targetY}px`
111 + },
112 + { immediate: false }
113 +)
114 +
115 +watch(sidebarTop, () => {
116 + resume()
117 +})
118 +
119 +function getDetails(id: string) {
120 + loadingDetails.value = true
121 +
122 + Api.mitre
123 + .getMitreMitigations({ id })
124 + .then(res => {
125 + if (res.data.success) {
126 + mitigationDetails.value = res.data.results?.[0] || null
127 + } else {
128 + message.warning(res.data?.message || "An error occurred. Please try again later.")
129 + }
130 + })
131 + .catch(err => {
132 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
133 + })
134 + .finally(() => {
135 + loadingDetails.value = false
136 + })
137 +}
138 +
139 +onBeforeMount(() => {
140 + if (externalId) {
141 + getDetails(externalId)
142 + }
143 + if (entity) {
144 + mitigationDetails.value = entity
145 + }
146 +})
147 +</script>
frontend/src/components/mitre/Mitigation/MitigationsList.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <MitigationCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreMitigationDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import MitigationCard from "./MitigationCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const mitigations = ref<{ id: string; entity?: MitreMitigationDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return mitigations.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + mitigations.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/Software/SoftwareCard.vue new
+122
@@ -0,0 +1,122 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" :loading="loadingDetails" @click="showDetails = true">
4 + <template #headerMain>{{ id }}</template>
5 + <template #headerExtra>
6 + <span v-if="softwareDetails" class="text-default">
7 + {{ softwareDetails.external_id }}
8 + </span>
9 + <n-skeleton v-else text :width="100" :height="18" />
10 + </template>
11 + <template #default>
12 + <div v-if="softwareDetails">
13 + {{ softwareDetails.name }}
14 + </div>
15 + <n-skeleton v-else text style="width: 60%" :height="20" />
16 + </template>
17 + <template #footer>
18 + <p v-if="softwareDetails" class="cursor-text" @click.stop="() => {}">
19 + <Suspense>
20 + <Markdown :source="softwareDetails.description" />
21 + </Suspense>
22 + </p>
23 + <div v-else>
24 + <n-skeleton text :repeat="2" :height="16" />
25 + <n-skeleton text style="width: 40%" :height="16" />
26 + </div>
27 + </template>
28 + </CardEntity>
29 + <n-modal
30 + v-model:show="showDetails"
31 + display-directive="show"
32 + preset="card"
33 + content-class="!p-0"
34 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
35 + :title="`Software • ${id}`"
36 + :bordered="false"
37 + segmented
38 + >
39 + <n-tabs type="line" animated :tabs-padding="24">
40 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
41 + <div class="px-7 pb-7 pt-4">
42 + <SoftwareDetails :entity="softwareDetails" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane
46 + name="Groups"
47 + :tab="`Groups (${softwareDetails?.groups?.length || 0})`"
48 + display-directive="show:lazy"
49 + >
50 + <div class="px-7 pb-7 pt-4">
51 + <GroupsList v-if="softwareDetails" :list="softwareDetails.groups" />
52 + </div>
53 + </n-tab-pane>
54 + <n-tab-pane
55 + name="Techniques"
56 + :tab="`Techniques (${softwareDetails?.techniques?.length || 0})`"
57 + display-directive="show:lazy"
58 + >
59 + <div class="px-7 pb-7 pt-4">
60 + <TechniquesList v-if="softwareDetails" :list="softwareDetails.techniques" />
61 + </div>
62 + </n-tab-pane>
63 + </n-tabs>
64 + </n-modal>
65 + </div>
66 +</template>
67 +
68 +<script setup lang="ts">
69 +import type { MitreSoftwareDetails } from "@/types/mitre.d"
70 +import { NModal, NSkeleton, NTabPane, NTabs, useMessage } from "naive-ui"
71 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
72 +import Api from "@/api"
73 +import CardEntity from "@/components/common/cards/CardEntity.vue"
74 +import GroupsList from "../Group/GroupsList.vue"
75 +import TechniquesList from "../Technique/TechniquesList.vue"
76 +import SoftwareDetails from "./SoftwareDetails.vue"
77 +
78 +const { id, entity } = defineProps<{
79 + id: string
80 + entity?: MitreSoftwareDetails
81 +}>()
82 +
83 +const emit = defineEmits<{
84 + (e: "loaded", value: MitreSoftwareDetails): void
85 +}>()
86 +
87 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
88 +
89 +const showDetails = ref(false)
90 +const message = useMessage()
91 +const loadingDetails = ref(false)
92 +const softwareDetails = ref<MitreSoftwareDetails | undefined>(undefined)
93 +
94 +function getDetails(id: string) {
95 + loadingDetails.value = true
96 +
97 + Api.mitre
98 + .getMitreSoftware({ id })
99 + .then(res => {
100 + if (res.data.success) {
101 + softwareDetails.value = res.data.results?.[0] || null
102 + if (softwareDetails.value) emit("loaded", softwareDetails.value)
103 + } else {
104 + message.warning(res.data?.message || "An error occurred. Please try again later.")
105 + }
106 + })
107 + .catch(err => {
108 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
109 + })
110 + .finally(() => {
111 + loadingDetails.value = false
112 + })
113 +}
114 +
115 +onBeforeMount(() => {
116 + if (entity) {
117 + softwareDetails.value = entity
118 + } else if (id) {
119 + getDetails(id)
120 + }
121 +})
122 +</script>
frontend/src/components/mitre/Software/SoftwareDetails.vue new
+173
@@ -0,0 +1,173 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="softwareDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ softwareDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ softwareDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="softwareDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="softwareDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 +
26 + <CardKV v-if="softwareDetails.references?.length">
27 + <template #key>references</template>
28 + <template #value>
29 + <References :references="softwareDetails.references" />
30 + </template>
31 + </CardKV>
32 + </div>
33 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
34 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
35 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
36 + <div class="flex flex-col gap-0.5 text-sm">
37 + <div class="text-secondary font-mono text-xs">external_id</div>
38 + <div>{{ softwareDetails.external_id }}</div>
39 + </div>
40 + <div class="flex flex-col gap-0.5 text-sm">
41 + <div class="text-secondary font-mono text-xs">created_time</div>
42 + <div>{{ formatDate(softwareDetails.created_time, dFormats.datetime) }}</div>
43 + </div>
44 + <div class="flex flex-col gap-0.5 text-sm">
45 + <div class="text-secondary font-mono text-xs">modified_time</div>
46 + <div>{{ formatDate(softwareDetails.modified_time, dFormats.datetime) }}</div>
47 + </div>
48 + <div class="flex flex-col gap-0.5 text-sm">
49 + <div class="text-secondary font-mono text-xs">url</div>
50 + <div>
51 + <a :href="softwareDetails.url" target="_blank" rel="nofollow noopener noreferrer">
52 + {{ softwareDetails.url }}
53 + </a>
54 + </div>
55 + </div>
56 + <div class="flex flex-col gap-0.5 text-sm">
57 + <div class="text-secondary font-mono text-xs">source</div>
58 + <div>{{ softwareDetails.source }}</div>
59 + </div>
60 + <div class="flex flex-col gap-0.5 text-sm">
61 + <div class="text-secondary font-mono text-xs">type</div>
62 + <div>{{ softwareDetails.type || "—" }}</div>
63 + </div>
64 + <div class="flex flex-col gap-0.5 text-sm">
65 + <div class="text-secondary font-mono text-xs">mitre_version</div>
66 + <div>{{ softwareDetails.mitre_version }}</div>
67 + </div>
68 + <div class="flex flex-col gap-0.5 text-sm">
69 + <div class="text-secondary font-mono text-xs">platforms</div>
70 + <div class="mt-0.5 flex flex-wrap gap-1">
71 + <template v-if="!softwareDetails.platforms?.length">—</template>
72 + <template v-else>
73 + <code v-for="item of softwareDetails.platforms" :key="item" class="text-xs">
74 + {{ item }}
75 + </code>
76 + </template>
77 + </div>
78 + </div>
79 + <div class="flex flex-col gap-0.5 text-sm">
80 + <div class="text-secondary font-mono text-xs">aliases</div>
81 + <div class="mt-0.5 flex flex-wrap gap-1">
82 + <template v-if="!softwareDetails.aliases?.length">—</template>
83 + <template v-else>
84 + <code v-for="item of softwareDetails.aliases" :key="item" class="text-xs">
85 + {{ item }}
86 + </code>
87 + </template>
88 + </div>
89 + </div>
90 + </n-card>
91 +
92 + <div class="flex flex-wrap gap-1">
93 + <Badge v-if="softwareDetails.deprecated" color="primary" class="text-xs! font-mono">
94 + <template #value>deprecated</template>
95 + </Badge>
96 + </div>
97 + </div>
98 + </div>
99 + </div>
100 + </n-spin>
101 +</template>
102 +
103 +<script setup lang="ts">
104 +import type { MitreSoftwareDetails } from "@/types/mitre.d"
105 +import { useElementBounding, useRafFn } from "@vueuse/core"
106 +import { useMotionProperties } from "@vueuse/motion"
107 +import { NCard, NSpin, useMessage } from "naive-ui"
108 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
109 +import Api from "@/api"
110 +import Badge from "@/components/common/Badge.vue"
111 +import CardKV from "@/components/common/cards/CardKV.vue"
112 +import { useSettingsStore } from "@/stores/settings"
113 +import { formatDate } from "@/utils"
114 +import References from "../common/References.vue"
115 +
116 +const { externalId, entity } = defineProps<{
117 + externalId?: string
118 + entity?: MitreSoftwareDetails
119 +}>()
120 +
121 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
122 +
123 +const dFormats = useSettingsStore().dateFormat
124 +const message = useMessage()
125 +const loadingDetails = ref(false)
126 +const softwareDetails = ref<MitreSoftwareDetails | null>(null)
127 +
128 +const sidebarRef = ref(null)
129 +const sidebarCardRef = ref(null)
130 +const { top: sidebarTop } = useElementBounding(sidebarRef)
131 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
132 +
133 +const { resume } = useRafFn(
134 + () => {
135 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
136 + styleCardTransform.translateY = `${targetY}px`
137 + },
138 + { immediate: false }
139 +)
140 +
141 +watch(sidebarTop, () => {
142 + resume()
143 +})
144 +
145 +function getDetails(id: string) {
146 + loadingDetails.value = true
147 +
148 + Api.mitre
149 + .getMitreSoftware({ id })
150 + .then(res => {
151 + if (res.data.success) {
152 + softwareDetails.value = res.data.results?.[0] || null
153 + } else {
154 + message.warning(res.data?.message || "An error occurred. Please try again later.")
155 + }
156 + })
157 + .catch(err => {
158 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
159 + })
160 + .finally(() => {
161 + loadingDetails.value = false
162 + })
163 +}
164 +
165 +onBeforeMount(() => {
166 + if (externalId) {
167 + getDetails(externalId)
168 + }
169 + if (entity) {
170 + softwareDetails.value = entity
171 + }
172 +})
173 +</script>
frontend/src/components/mitre/Software/SoftwareList.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <SoftwareCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreSoftwareDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import SoftwareCard from "./SoftwareCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const software = ref<{ id: string; entity?: MitreSoftwareDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return software.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + software.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/Tactic/TacticCard.vue new
+112
@@ -0,0 +1,112 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" :loading="loadingDetails" @click="showDetails = true">
4 + <template #headerMain>{{ id }}</template>
5 + <template #headerExtra>
6 + <span v-if="tacticDetails" class="text-default">
7 + {{ tacticDetails.external_id }}
8 + </span>
9 + <n-skeleton v-else text :width="100" :height="18" />
10 + </template>
11 + <template #default>
12 + <div v-if="tacticDetails">
13 + {{ tacticDetails.name }}
14 + </div>
15 + <n-skeleton v-else text style="width: 60%" :height="20" />
16 + </template>
17 + <template #footer>
18 + <p v-if="tacticDetails" class="cursor-text" @click.stop="() => {}">
19 + <Suspense>
20 + <Markdown :source="tacticDetails.description" />
21 + </Suspense>
22 + </p>
23 + <div v-else>
24 + <n-skeleton text :repeat="2" :height="16" />
25 + <n-skeleton text style="width: 40%" :height="16" />
26 + </div>
27 + </template>
28 + </CardEntity>
29 + <n-modal
30 + v-model:show="showDetails"
31 + display-directive="show"
32 + preset="card"
33 + content-class="!p-0"
34 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
35 + :title="`Tactic • ${id}`"
36 + :bordered="false"
37 + segmented
38 + >
39 + <n-tabs type="line" animated :tabs-padding="24">
40 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
41 + <div class="px-7 pb-7 pt-4">
42 + <TacticDetails :entity="tacticDetails" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane
46 + name="Techniques"
47 + :tab="`Techniques (${tacticDetails?.techniques?.length || 0})`"
48 + display-directive="show:lazy"
49 + >
50 + <div class="px-7 pb-7 pt-4">
51 + <TechniquesList v-if="tacticDetails" :list="tacticDetails.techniques" />
52 + </div>
53 + </n-tab-pane>
54 + </n-tabs>
55 + </n-modal>
56 + </div>
57 +</template>
58 +
59 +<script setup lang="ts">
60 +import type { MitreTacticDetails } from "@/types/mitre.d"
61 +import { NModal, NSkeleton, NTabPane, NTabs, useMessage } from "naive-ui"
62 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
63 +import Api from "@/api"
64 +import CardEntity from "@/components/common/cards/CardEntity.vue"
65 +import TechniquesList from "../Technique/TechniquesList.vue"
66 +import TacticDetails from "./TacticDetails.vue"
67 +
68 +const { id, entity } = defineProps<{
69 + id: string
70 + entity?: MitreTacticDetails
71 +}>()
72 +
73 +const emit = defineEmits<{
74 + (e: "loaded", value: MitreTacticDetails): void
75 +}>()
76 +
77 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
78 +
79 +const showDetails = ref(false)
80 +const message = useMessage()
81 +const loadingDetails = ref(false)
82 +const tacticDetails = ref<MitreTacticDetails | undefined>(undefined)
83 +
84 +function getDetails(id: string) {
85 + loadingDetails.value = true
86 +
87 + Api.mitre
88 + .getMitreTactics({ id })
89 + .then(res => {
90 + if (res.data.success) {
91 + tacticDetails.value = res.data.results?.[0] || null
92 + if (tacticDetails.value) emit("loaded", tacticDetails.value)
93 + } else {
94 + message.warning(res.data?.message || "An error occurred. Please try again later.")
95 + }
96 + })
97 + .catch(err => {
98 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
99 + })
100 + .finally(() => {
101 + loadingDetails.value = false
102 + })
103 +}
104 +
105 +onBeforeMount(() => {
106 + if (entity) {
107 + tacticDetails.value = entity
108 + } else if (id) {
109 + getDetails(id)
110 + }
111 +})
112 +</script>
frontend/src/components/mitre/Tactic/TacticDetails.vue new
+140
@@ -0,0 +1,140 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="tacticDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ tacticDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ tacticDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="tacticDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="tacticDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 +
26 + <CardKV v-if="tacticDetails.references?.length">
27 + <template #key>references</template>
28 + <template #value>
29 + <References :references="tacticDetails.references" />
30 + </template>
31 + </CardKV>
32 + </div>
33 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
34 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
35 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
36 + <div class="flex flex-col gap-0.5 text-sm">
37 + <div class="text-secondary font-mono text-xs">external_id</div>
38 + <div>{{ tacticDetails.external_id }}</div>
39 + </div>
40 + <div class="flex flex-col gap-0.5 text-sm">
41 + <div class="text-secondary font-mono text-xs">short_name</div>
42 + <div>{{ tacticDetails.short_name }}</div>
43 + </div>
44 + <div class="flex flex-col gap-0.5 text-sm">
45 + <div class="text-secondary font-mono text-xs">created_time</div>
46 + <div>{{ formatDate(tacticDetails.created_time, dFormats.datetime) }}</div>
47 + </div>
48 + <div class="flex flex-col gap-0.5 text-sm">
49 + <div class="text-secondary font-mono text-xs">modified_time</div>
50 + <div>{{ formatDate(tacticDetails.modified_time, dFormats.datetime) }}</div>
51 + </div>
52 + <div class="flex flex-col gap-0.5 text-sm">
53 + <div class="text-secondary font-mono text-xs">url</div>
54 + <div>
55 + <a :href="tacticDetails.url" target="_blank" rel="nofollow noopener noreferrer">
56 + {{ tacticDetails.url }}
57 + </a>
58 + </div>
59 + </div>
60 + <div class="flex flex-col gap-0.5 text-sm">
61 + <div class="text-secondary font-mono text-xs">source</div>
62 + <div>{{ tacticDetails.source }}</div>
63 + </div>
64 + </n-card>
65 + </div>
66 + </div>
67 + </div>
68 + </n-spin>
69 +</template>
70 +
71 +<script setup lang="ts">
72 +import type { MitreTacticDetails } from "@/types/mitre.d"
73 +import { useElementBounding, useRafFn } from "@vueuse/core"
74 +import { useMotionProperties } from "@vueuse/motion"
75 +import { NCard, NSpin, useMessage } from "naive-ui"
76 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
77 +import Api from "@/api"
78 +import CardKV from "@/components/common/cards/CardKV.vue"
79 +import { useSettingsStore } from "@/stores/settings"
80 +import { formatDate } from "@/utils"
81 +import References from "../common/References.vue"
82 +
83 +const { externalId, entity } = defineProps<{
84 + externalId?: string
85 + entity?: MitreTacticDetails
86 +}>()
87 +
88 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
89 +
90 +const dFormats = useSettingsStore().dateFormat
91 +const message = useMessage()
92 +const loadingDetails = ref(false)
93 +const tacticDetails = ref<MitreTacticDetails | null>(null)
94 +
95 +const sidebarRef = ref(null)
96 +const sidebarCardRef = ref(null)
97 +const { top: sidebarTop } = useElementBounding(sidebarRef)
98 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
99 +
100 +const { resume } = useRafFn(
101 + () => {
102 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
103 + styleCardTransform.translateY = `${targetY}px`
104 + },
105 + { immediate: false }
106 +)
107 +
108 +watch(sidebarTop, () => {
109 + resume()
110 +})
111 +
112 +function getDetails(id: string) {
113 + loadingDetails.value = true
114 +
115 + Api.mitre
116 + .getMitreTactics({ id })
117 + .then(res => {
118 + if (res.data.success) {
119 + tacticDetails.value = res.data.results?.[0] || null
120 + } else {
121 + message.warning(res.data?.message || "An error occurred. Please try again later.")
122 + }
123 + })
124 + .catch(err => {
125 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
126 + })
127 + .finally(() => {
128 + loadingDetails.value = false
129 + })
130 +}
131 +
132 +onBeforeMount(() => {
133 + if (externalId) {
134 + getDetails(externalId)
135 + }
136 + if (entity) {
137 + tacticDetails.value = entity
138 + }
139 +})
140 +</script>
frontend/src/components/mitre/Tactic/TacticsList.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <TacticCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreTacticDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import TacticCard from "./TacticCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const tactics = ref<{ id: string; entity?: MitreTacticDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return tactics.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + tactics.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/Technique/TechniqueCard.vue new
+153
@@ -0,0 +1,153 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" :loading="loadingDetails" @click="showDetails = true">
4 + <template #headerMain>{{ id }}</template>
5 + <template #headerExtra>
6 + <span v-if="techniqueDetails" class="text-default">
7 + {{ techniqueDetails.external_id }}
8 + </span>
9 + <n-skeleton v-else text :width="100" :height="18" />
10 + </template>
11 + <template #default>
12 + <div v-if="techniqueDetails">
13 + {{ techniqueDetails.name }}
14 + </div>
15 + <n-skeleton v-else text style="width: 60%" :height="20" />
16 + </template>
17 + <template #footer>
18 + <p v-if="techniqueDetails" class="cursor-text" @click.stop="() => {}">
19 + <Suspense>
20 + <Markdown :source="techniqueDetails.description" />
21 + </Suspense>
22 + </p>
23 + <div v-else>
24 + <n-skeleton text :repeat="2" :height="16" />
25 + <n-skeleton text style="width: 40%" :height="16" />
26 + </div>
27 + </template>
28 + </CardEntity>
29 + <n-modal
30 + v-model:show="showDetails"
31 + display-directive="show"
32 + preset="card"
33 + content-class="!p-0"
34 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
35 + :title="`Technique • ${id}`"
36 + :bordered="false"
37 + segmented
38 + >
39 + <n-tabs type="line" animated :tabs-padding="24">
40 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
41 + <div class="px-7 pb-7 pt-4">
42 + <TechniqueAlertDetails :entity="techniqueDetails" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane
46 + name="Tactics"
47 + :tab="`Tactics (${techniqueDetails?.tactics?.length || 0})`"
48 + display-directive="show:lazy"
49 + >
50 + <div class="px-7 pb-7 pt-4">
51 + <TacticsList v-if="techniqueDetails" :list="techniqueDetails.tactics" />
52 + </div>
53 + </n-tab-pane>
54 + <n-tab-pane
55 + name="Mitigations"
56 + :tab="`Mitigations (${techniqueDetails?.mitigations?.length || 0})`"
57 + display-directive="show:lazy"
58 + >
59 + <div class="px-7 pb-7 pt-4">
60 + <MitigationsList v-if="techniqueDetails" :list="techniqueDetails.mitigations" />
61 + </div>
62 + </n-tab-pane>
63 + <n-tab-pane
64 + v-if="techniqueDetails?.techniques?.length"
65 + name="Techniques"
66 + :tab="`Techniques (${techniqueDetails?.techniques?.length || 0})`"
67 + display-directive="show:lazy"
68 + >
69 + <div class="px-7 pb-7 pt-4">
70 + <TechniquesList :list="techniqueDetails.techniques" />
71 + </div>
72 + </n-tab-pane>
73 + <n-tab-pane
74 + name="Groups"
75 + :tab="`Groups (${techniqueDetails?.groups?.length || 0})`"
76 + display-directive="show:lazy"
77 + >
78 + <div class="px-7 pb-7 pt-4">
79 + <GroupsList v-if="techniqueDetails" :list="techniqueDetails.groups" />
80 + </div>
81 + </n-tab-pane>
82 + <n-tab-pane
83 + name="Software"
84 + :tab="`Software (${techniqueDetails?.software?.length || 0})`"
85 + display-directive="show:lazy"
86 + >
87 + <div class="px-7 pb-7 pt-4">
88 + <SoftwareList v-if="techniqueDetails" :list="techniqueDetails.software" />
89 + </div>
90 + </n-tab-pane>
91 + </n-tabs>
92 + </n-modal>
93 + </div>
94 +</template>
95 +
96 +<script setup lang="ts">
97 +import type { MitreTechniqueDetails } from "@/types/mitre.d"
98 +import { NModal, NSkeleton, NTabPane, NTabs, useMessage } from "naive-ui"
99 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
100 +import Api from "@/api"
101 +import CardEntity from "@/components/common/cards/CardEntity.vue"
102 +import GroupsList from "../Group/GroupsList.vue"
103 +import MitigationsList from "../Mitigation/MitigationsList.vue"
104 +import SoftwareList from "../Software/SoftwareList.vue"
105 +import TacticsList from "../Tactic/TacticsList.vue"
106 +import TechniqueAlertDetails from "../TechniqueAlert/TechniqueAlertDetails.vue"
107 +import TechniquesList from "./TechniquesList.vue"
108 +
109 +const { id, entity } = defineProps<{
110 + id: string
111 + entity?: MitreTechniqueDetails
112 +}>()
113 +
114 +const emit = defineEmits<{
115 + (e: "loaded", value: MitreTechniqueDetails): void
116 +}>()
117 +
118 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
119 +
120 +const showDetails = ref(false)
121 +const message = useMessage()
122 +const loadingDetails = ref(false)
123 +const techniqueDetails = ref<MitreTechniqueDetails | undefined>(undefined)
124 +
125 +function getDetails(id: string) {
126 + loadingDetails.value = true
127 +
128 + Api.mitre
129 + .getMitreTechniques({ id })
130 + .then(res => {
131 + if (res.data.success) {
132 + techniqueDetails.value = res.data.results?.[0] || null
133 + if (techniqueDetails.value) emit("loaded", techniqueDetails.value)
134 + } else {
135 + message.warning(res.data?.message || "An error occurred. Please try again later.")
136 + }
137 + })
138 + .catch(err => {
139 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
140 + })
141 + .finally(() => {
142 + loadingDetails.value = false
143 + })
144 +}
145 +
146 +onBeforeMount(() => {
147 + if (entity) {
148 + techniqueDetails.value = entity
149 + } else if (id) {
150 + getDetails(id)
151 + }
152 +})
153 +</script>
frontend/src/components/mitre/Technique/TechniquesList.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <TechniqueCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreTechniqueDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import TechniqueCard from "./TechniqueCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const techniques = ref<{ id: string; entity?: MitreTechniqueDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return techniques.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + techniques.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/TechniqueAlert/TechniqueAlertCard.vue new
+59
@@ -0,0 +1,59 @@
1 +<template>
2 + <div>
3 + <CardEntity embedded clickable hoverable size="small" @click="showDetails = true">
4 + <template #header>
5 + <div class="flex items-start justify-between gap-4">
6 + <div>
7 + {{ entity.technique_id }} •
8 + <span class="text-default">{{ entity.technique_name }}</span>
9 + </div>
10 +
11 + <div class="flex items-center gap-2 whitespace-nowrap">
12 + <n-tooltip>
13 + <template #trigger>
14 + <Icon name="carbon:time" :size="16" />
15 + </template>
16 + <div class="flex flex-wrap gap-2 text-xs">
17 + <span class="text-secondary">last seen:</span>
18 + <span>{{ formatDate(entity.last_seen, dFormats.datetimesec) }}</span>
19 + </div>
20 + </n-tooltip>
21 + <code>
22 + {{ entity.count }}
23 + </code>
24 + </div>
25 + </div>
26 + </template>
27 + </CardEntity>
28 + <n-modal
29 + v-model:show="showDetails"
30 + display-directive="show"
31 + preset="card"
32 + content-class="!p-0"
33 + :style="{ maxWidth: 'min(900px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
34 + :title="`${entity.technique_id} • ${entity.technique_name}`"
35 + :bordered="false"
36 + segmented
37 + >
38 + <TechniqueAlertOverview :external-id="entity.technique_id" />
39 + </n-modal>
40 + </div>
41 +</template>
42 +
43 +<script setup lang="ts">
44 +import type { MitreTechnique } from "@/types/mitre.d"
45 +import { NModal, NTooltip } from "naive-ui"
46 +import { ref } from "vue"
47 +import CardEntity from "@/components/common/cards/CardEntity.vue"
48 +import Icon from "@/components/common/Icon.vue"
49 +import { useSettingsStore } from "@/stores/settings"
50 +import { formatDate } from "@/utils"
51 +import TechniqueAlertOverview from "./TechniqueAlertOverview.vue"
52 +
53 +const { entity } = defineProps<{
54 + entity: MitreTechnique
55 +}>()
56 +
57 +const dFormats = useSettingsStore().dateFormat
58 +const showDetails = ref(false)
59 +</script>
frontend/src/components/mitre/TechniqueAlert/TechniqueAlertDetails.vue new
+189
@@ -0,0 +1,189 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="techniqueDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ techniqueDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ techniqueDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="techniqueDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="techniqueDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 + <CardKV>
26 + <template #key>mitre_detection (v{{ techniqueDetails.mitre_version }})</template>
27 + <template #value>
28 + <span class="whitespace-pre-wrap">
29 + {{ techniqueDetails.mitre_detection ?? "—" }}
30 + </span>
31 + </template>
32 + </CardKV>
33 + <CardKV v-if="techniqueDetails.references?.length">
34 + <template #key>references</template>
35 + <template #value>
36 + <References :references="techniqueDetails.references" />
37 + </template>
38 + </CardKV>
39 + </div>
40 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
41 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
42 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
43 + <div class="flex flex-col gap-0.5 text-sm">
44 + <div class="text-secondary font-mono text-xs">external_id</div>
45 + <div>{{ techniqueDetails.external_id }}</div>
46 + </div>
47 + <div class="flex flex-col gap-0.5 text-sm">
48 + <div class="text-secondary font-mono text-xs">created_time</div>
49 + <div>{{ formatDate(techniqueDetails.created_time, dFormats.datetime) }}</div>
50 + </div>
51 + <div class="flex flex-col gap-0.5 text-sm">
52 + <div class="text-secondary font-mono text-xs">modified_time</div>
53 + <div>{{ formatDate(techniqueDetails.modified_time, dFormats.datetime) }}</div>
54 + </div>
55 + <div class="flex flex-col gap-0.5 text-sm">
56 + <div class="text-secondary font-mono text-xs">url</div>
57 + <div>
58 + <a :href="techniqueDetails.url" target="_blank" rel="nofollow noopener noreferrer">
59 + {{ techniqueDetails.url }}
60 + </a>
61 + </div>
62 + </div>
63 + <div class="flex flex-col gap-0.5 text-sm">
64 + <div class="text-secondary font-mono text-xs">source</div>
65 + <div>{{ techniqueDetails.source }}</div>
66 + </div>
67 + <div v-if="techniqueDetails.subtechnique_of" class="flex flex-col gap-0.5 text-sm">
68 + <div class="text-secondary font-mono text-xs">subtechnique_of</div>
69 + <div>{{ techniqueDetails.subtechnique_of }}</div>
70 + </div>
71 + <div class="flex flex-col gap-0.5 text-sm">
72 + <div class="text-secondary font-mono text-xs">platforms</div>
73 + <div class="mt-0.5 flex flex-wrap gap-1">
74 + <template v-if="!techniqueDetails.platforms?.length">—</template>
75 + <template v-else>
76 + <code v-for="item of techniqueDetails.platforms" :key="item" class="text-xs">
77 + {{ item }}
78 + </code>
79 + </template>
80 + </div>
81 + </div>
82 + <div class="flex flex-col gap-0.5 text-sm">
83 + <div class="text-secondary font-mono text-xs">data_sources</div>
84 + <div class="mt-0.5 flex flex-wrap gap-1">
85 + <template v-if="!techniqueDetails.data_sources?.length">—</template>
86 + <template v-else>
87 + <code v-for="item of techniqueDetails.data_sources" :key="item" class="text-xs">
88 + {{ item }}
89 + </code>
90 + </template>
91 + </div>
92 + </div>
93 + </n-card>
94 +
95 + <div class="flex flex-wrap gap-1">
96 + <Badge v-if="techniqueDetails.deprecated" color="primary" class="text-xs! font-mono">
97 + <template #value>deprecated</template>
98 + </Badge>
99 + <Badge v-if="techniqueDetails.remote_support" color="primary">
100 + <template #value>remote_support</template>
101 + </Badge>
102 + <Badge v-if="techniqueDetails.network_requirements" color="primary">
103 + <template #value>network_requirements</template>
104 + </Badge>
105 + <Badge v-if="techniqueDetails.is_subtechnique" color="primary">
106 + <template #value>subtechnique</template>
107 + </Badge>
108 + </div>
109 + </div>
110 + </div>
111 + </div>
112 + </n-spin>
113 +</template>
114 +
115 +<script setup lang="ts">
116 +import type { MitreTechniqueDetails } from "@/types/mitre.d"
117 +import { useElementBounding, useRafFn } from "@vueuse/core"
118 +import { useMotionProperties } from "@vueuse/motion"
119 +import { NCard, NSpin, useMessage } from "naive-ui"
120 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
121 +import Api from "@/api"
122 +import Badge from "@/components/common/Badge.vue"
123 +import CardKV from "@/components/common/cards/CardKV.vue"
124 +import { useSettingsStore } from "@/stores/settings"
125 +import { formatDate } from "@/utils"
126 +import References from "../common/References.vue"
127 +
128 +const { externalId, id, entity } = defineProps<{
129 + externalId?: string
130 + id?: string
131 + entity?: MitreTechniqueDetails
132 +}>()
133 +
134 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
135 +
136 +const dFormats = useSettingsStore().dateFormat
137 +const message = useMessage()
138 +const loadingDetails = ref(false)
139 +const techniqueDetails = ref<MitreTechniqueDetails | null>(null)
140 +
141 +const sidebarRef = ref(null)
142 +const sidebarCardRef = ref(null)
143 +const { top: sidebarTop } = useElementBounding(sidebarRef)
144 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
145 +
146 +const { resume } = useRafFn(
147 + () => {
148 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
149 + styleCardTransform.translateY = `${targetY}px`
150 + },
151 + { immediate: false }
152 +)
153 +
154 +watch(sidebarTop, () => {
155 + resume()
156 +})
157 +
158 +function getDetails(query: { external_id: string } | { id: string }) {
159 + loadingDetails.value = true
160 +
161 + Api.mitre
162 + .getMitreTechniques(query)
163 + .then(res => {
164 + if (res.data.success) {
165 + techniqueDetails.value = res.data.results?.[0] || null
166 + } else {
167 + message.warning(res.data?.message || "An error occurred. Please try again later.")
168 + }
169 + })
170 + .catch(err => {
171 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
172 + })
173 + .finally(() => {
174 + loadingDetails.value = false
175 + })
176 +}
177 +
178 +onBeforeMount(() => {
179 + if (externalId) {
180 + getDetails({ external_id: externalId })
181 + }
182 + if (id) {
183 + getDetails({ id })
184 + }
185 + if (entity) {
186 + techniqueDetails.value = entity
187 + }
188 +})
189 +</script>
frontend/src/components/mitre/TechniqueAlert/TechniqueAlertOverview.vue new
+101
@@ -0,0 +1,101 @@
1 +<template>
2 + <n-spin :show="loadingDetails">
3 + <n-tabs type="line" animated :tabs-padding="24">
4 + <n-tab-pane name="Overview" tab="Overview" display-directive="show:lazy">
5 + <div class="px-7 pb-7 pt-4">
6 + <TechniqueAlertDetails v-if="techniqueDetails" :entity="techniqueDetails" />
7 + </div>
8 + </n-tab-pane>
9 + <n-tab-pane
10 + name="Groups"
11 + :tab="`Groups (${techniqueDetails?.groups?.length || 0})`"
12 + display-directive="show:lazy"
13 + >
14 + <div class="px-7 pb-7 pt-4">
15 + <GroupsList v-if="techniqueDetails" :list="techniqueDetails.groups" />
16 + </div>
17 + </n-tab-pane>
18 + <n-tab-pane
19 + name="Mitigations"
20 + :tab="`Mitigations (${techniqueDetails?.mitigations?.length || 0})`"
21 + display-directive="show:lazy"
22 + >
23 + <div class="px-7 pb-7 pt-4">
24 + <MitigationsList v-if="techniqueDetails" :list="techniqueDetails.mitigations" />
25 + </div>
26 + </n-tab-pane>
27 + <n-tab-pane
28 + name="Software"
29 + :tab="`Software (${techniqueDetails?.software?.length || 0})`"
30 + display-directive="show:lazy"
31 + >
32 + <div class="px-7 pb-7 pt-4">
33 + <SoftwareList v-if="techniqueDetails" :list="techniqueDetails.software" />
34 + </div>
35 + </n-tab-pane>
36 + <n-tab-pane
37 + name="Tactics"
38 + :tab="`Tactics (${techniqueDetails?.tactics?.length || 0})`"
39 + display-directive="show:lazy"
40 + >
41 + <div class="px-7 pb-7 pt-4">
42 + <TacticsList v-if="techniqueDetails" :list="techniqueDetails.tactics" />
43 + </div>
44 + </n-tab-pane>
45 + <n-tab-pane name="Alerts" tab="Alerts" display-directive="show:lazy">
46 + <div class="px-7 pb-7 pt-4">
47 + <TechniqueEventsList v-if="techniqueDetails" :external-id />
48 + </div>
49 + </n-tab-pane>
50 + </n-tabs>
51 + </n-spin>
52 +</template>
53 +
54 +<script setup lang="ts">
55 +import type { MitreTechniqueDetails } from "@/types/mitre.d"
56 +import { NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
57 +import { onBeforeMount, ref } from "vue"
58 +import Api from "@/api"
59 +import GroupsList from "../Group/GroupsList.vue"
60 +import MitigationsList from "../Mitigation/MitigationsList.vue"
61 +import SoftwareList from "../Software/SoftwareList.vue"
62 +import TacticsList from "../Tactic/TacticsList.vue"
63 +import TechniqueEventsList from "../TechniqueEvents/List.vue"
64 +import TechniqueAlertDetails from "./TechniqueAlertDetails.vue"
65 +
66 +const { externalId } = defineProps<{
67 + externalId: string
68 +}>()
69 +
70 +const message = useMessage()
71 +const loadingDetails = ref(false)
72 +const techniqueDetails = ref<MitreTechniqueDetails | undefined>(undefined)
73 +
74 +function getDetails(id: string) {
75 + loadingDetails.value = true
76 +
77 + Api.mitre
78 + .getMitreTechniques({ external_id: id })
79 + .then(res => {
80 + if (res.data.success) {
81 + techniqueDetails.value = res.data.results?.[0] || null
82 + } else {
83 + message.warning(res.data?.message || "An error occurred. Please try again later.")
84 + }
85 + })
86 + .catch(err => {
87 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
88 + })
89 + .finally(() => {
90 + loadingDetails.value = false
91 + })
92 +}
93 +
94 +onBeforeMount(() => {
95 + getDetails(externalId)
96 + // MOCK
97 + /*
98 + techniqueDetails.value = techniqueResultDetails
99 + */
100 +})
101 +</script>
frontend/src/components/mitre/TechniqueEvents/Filters.vue new
+159
@@ -0,0 +1,159 @@
1 +<template>
2 + <div class="flex flex-wrap gap-3">
3 + <div>
4 + <n-popover placement="top-start" trigger="click" overlap>
5 + <template #trigger>
6 + <n-badge :show="!!mitreField" dot type="success" :offset="[0, 6]">
7 + <n-button size="small" secondary class="px-2!">
8 + <template #icon>
9 + <Icon :name="ConfigIcon" :size="16" />
10 + </template>
11 + </n-button>
12 + </n-badge>
13 + </template>
14 +
15 + <div class="pb-2 pt-1">
16 + <div class="text-secondary mb-1 text-sm">Mitre field:</div>
17 + <n-input v-model:value="mitreField" size="small" clearable class="!w-40" />
18 + </div>
19 + </n-popover>
20 + </div>
21 + <div>
22 + <n-input-group>
23 + <n-select
24 + v-model:value="filterTimeRange.unit"
25 + :options="unitOptions"
26 + placeholder="Time unit"
27 + size="small"
28 + class="!w-24"
29 + />
30 + <n-input-number
31 + v-model:value="filterTimeRange.value"
32 + :min="1"
33 + placeholder="Value"
34 + class="!w-26"
35 + size="small"
36 + :parse="parseTimeValue"
37 + />
38 + </n-input-group>
39 + </div>
40 + <div v-for="filter of usedFilters" :key="filter.type">
41 + <n-input-group>
42 + <n-input-group-label size="small">{{ getFilterLabel(filter.type) }}</n-input-group-label>
43 + <n-input v-model:value="filter.value" autosize placeholder="Input..." size="small" class="!min-w-30" />
44 + <n-button size="small" secondary tabindex="-1" @click="delFilter(filter.type)">
45 + <template #icon>
46 + <Icon :name="DelIcon" />
47 + </template>
48 + </n-button>
49 + </n-input-group>
50 + </div>
51 +
52 + <n-dropdown
53 + v-if="availableFilters.length"
54 + placement="bottom-start"
55 + trigger="click"
56 + :options="availableFilters"
57 + @select="addFilter"
58 + >
59 + <n-button size="small" dashed>
60 + <template #icon>
61 + <Icon :name="AddIcon" />
62 + </template>
63 + Add filter
64 + </n-button>
65 + </n-dropdown>
66 + </div>
67 +</template>
68 +
69 +<script setup lang="ts">
70 +import _toSafeInteger from "lodash/toSafeInteger"
71 +import {
72 + NBadge,
73 + NButton,
74 + NDropdown,
75 + NInput,
76 + NInputGroup,
77 + NInputGroupLabel,
78 + NInputNumber,
79 + NPopover,
80 + NSelect
81 +} from "naive-ui"
82 +import { computed, ref, watch } from "vue"
83 +import Icon from "@/components/common/Icon.vue"
84 +
85 +const emit = defineEmits<{
86 + (e: "update", value: { type: string; value: string }[]): void
87 +}>()
88 +
89 +const usedFilters = ref<{ type: string; value: string | null }[]>([{ type: "index_pattern", value: "wazuh-*" }])
90 +
91 +const filterTimeRange = ref({
92 + unit: "h",
93 + value: 24
94 +})
95 +
96 +const mitreField = ref<string | null>(null)
97 +
98 +const unitOptions: { label: string; value: "h" | "d" | "w" }[] = [
99 + { label: "Hours", value: "h" },
100 + { label: "Days", value: "d" },
101 + { label: "Weeks", value: "w" }
102 +]
103 +
104 +const proxyFilters = computed<{ type: string; value: string }[]>(() => {
105 + const filters = [
106 + { type: "time_range", value: `now-${filterTimeRange.value.value}${filterTimeRange.value.unit}` },
107 + ...usedFilters.value.filter(o => !!o.value)
108 + ] as { type: string; value: string }[]
109 +
110 + if (mitreField.value) {
111 + filters.push({ type: "mitre_field", value: mitreField.value })
112 + }
113 +
114 + return filters
115 +})
116 +
117 +const ConfigIcon = "carbon:settings"
118 +const AddIcon = "carbon:add"
119 +const DelIcon = "carbon:delete"
120 +
121 +const typeOptions: { label: string; value: string }[] = [
122 + { label: "Rule level", value: "rule_level" },
123 + { label: "Rule group", value: "rule_group" },
124 + { label: "Index pattern", value: "index_pattern" }
125 +]
126 +
127 +const availableFilters = computed(() =>
128 + typeOptions
129 + .filter(o => !usedFilters.value.map(o => o.type).includes(o.value))
130 + .map(t => ({ key: t.value, label: t.label }))
131 +)
132 +
133 +function getFilterLabel(type: string): string {
134 + return typeOptions.find(o => o.value === type)?.label || type
135 +}
136 +
137 +function addFilter(key: string) {
138 + usedFilters.value.push({ type: key, value: null })
139 +}
140 +
141 +function delFilter(key: string) {
142 + usedFilters.value = usedFilters.value.filter(o => o.type !== key)
143 +}
144 +
145 +function parseTimeValue(input: string) {
146 + return _toSafeInteger(input) || 1
147 +}
148 +
149 +watch(
150 + proxyFilters,
151 + val => {
152 + emit("update", val)
153 + },
154 + {
155 + deep: true,
156 + immediate: true
157 + }
158 +)
159 +</script>
frontend/src/components/mitre/TechniqueEvents/List.vue new
+157
@@ -0,0 +1,157 @@
1 +<template>
2 + <div class="flex flex-col gap-4">
3 + <Filters @update="filters = $event" />
4 +
5 + <div class="flex flex-col">
6 + <div ref="header" class="header flex items-center justify-end gap-2">
7 + <div class="info flex grow gap-5">
8 + <n-popover overlap placement="bottom-start">
9 + <template #trigger>
10 + <div class="bg-default rounded-lg">
11 + <n-button size="small" class="!cursor-help">
12 + <template #icon>
13 + <Icon :name="InfoIcon"></Icon>
14 + </template>
15 + </n-button>
16 + </div>
17 + </template>
18 + <div class="flex flex-col gap-2">
19 + <div class="box">
20 + Total:
21 + <code>{{ total }}</code>
22 + </div>
23 + </div>
24 + </n-popover>
25 + </div>
26 + <n-pagination
27 + v-model:page="currentPage"
28 + v-model:page-size="pageSize"
29 + :item-count="total"
30 + :page-slot="pageSlot"
31 + :show-size-picker="showSizePicker"
32 + :page-sizes="pageSizes"
33 + :simple="simpleMode"
34 + />
35 + </div>
36 +
37 + <n-spin :show="loading">
38 + <div class="my-3 flex min-h-28 flex-col gap-2">
39 + <template v-if="alertsList.length">
40 + <TechniqueEventCard v-for="alert of alertsList" :key="alert.id" :alert embedded />
41 + </template>
42 + <template v-else>
43 + <n-empty v-if="!loading" description="No items found" class="h-48 justify-center" />
44 + </template>
45 + </div>
46 + </n-spin>
47 + <div class="flex justify-end">
48 + <n-pagination
49 + v-if="alertsList.length > 3"
50 + v-model:page="currentPage"
51 + :page-size="pageSize"
52 + :item-count="total"
53 + :page-slot="6"
54 + />
55 + </div>
56 + </div>
57 + </div>
58 +</template>
59 +
60 +<script setup lang="ts">
61 +import type { MitreEventsQuery, MitreTechniquesAlertsQueryTimeRange } from "@/api/endpoints/mitre"
62 +import type { MitreEventDetails } from "@/types/mitre.d"
63 +import { useResizeObserver, watchDebounced } from "@vueuse/core"
64 +import axios from "axios"
65 +import { NButton, NEmpty, NPagination, NPopover, NSpin, useMessage } from "naive-ui"
66 +import { computed, ref } from "vue"
67 +import Api from "@/api"
68 +import Icon from "@/components/common/Icon.vue"
69 +import Filters from "./Filters.vue"
70 +import TechniqueEventCard from "./TechniqueEventCard.vue"
71 +
72 +const { externalId } = defineProps<{
73 + externalId: string
74 +}>()
75 +
76 +const filters = ref<{ type: string; value: string }[]>([])
77 +const loading = ref(false)
78 +const message = useMessage()
79 +const alertsList = ref<MitreEventDetails[]>([])
80 +const header = ref()
81 +const currentPage = ref(1)
82 +const total = ref(0)
83 +const compactMode = ref(false)
84 +const simpleMode = ref(false)
85 +const showSizePicker = computed(() => !compactMode.value)
86 +const pageSizes = [25, 50, 100, 150, 200]
87 +const pageSize = ref(pageSizes[0])
88 +const pageSlot = ref(8)
89 +const InfoIcon = "carbon:information"
90 +
91 +let abortController: AbortController | null = null
92 +
93 +function getList() {
94 + abortController?.abort()
95 + abortController = new AbortController()
96 +
97 + loading.value = true
98 +
99 + const query: MitreEventsQuery = {
100 + technique_id: externalId,
101 + time_range: filters.value?.find(o => o.type === "time_range")?.value as
102 + | MitreTechniquesAlertsQueryTimeRange
103 + | undefined,
104 + size: pageSize.value,
105 + page: currentPage.value,
106 + rule_level: filters.value?.find(o => o.type === "rule_level")?.value,
107 + rule_group: filters.value?.find(o => o.type === "rule_group")?.value,
108 + mitre_field: filters.value?.find(o => o.type === "mitre_field")?.value,
109 + index_pattern: filters.value?.find(o => o.type === "index_pattern")?.value
110 + }
111 +
112 + Api.mitre
113 + .getMitreEvents(query, abortController.signal)
114 + .then(res => {
115 + loading.value = false
116 +
117 + if (res.data.success) {
118 + alertsList.value = res.data?.alerts || []
119 + total.value = res.data?.total_alerts || 0
120 + } else {
121 + message.warning(res.data?.message || "An error occurred. Please try again later.")
122 + }
123 + })
124 + .catch(err => {
125 + if (!axios.isCancel(err)) {
126 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
127 + loading.value = false
128 + }
129 + })
130 +}
131 +
132 +useResizeObserver(header, entries => {
133 + const entry = entries[0]
134 + const { width } = entry.contentRect
135 +
136 + if (width < 650) {
137 + compactMode.value = true
138 + pageSlot.value = 5
139 + } else {
140 + compactMode.value = false
141 + pageSlot.value = 8
142 + }
143 +
144 + simpleMode.value = width < 450
145 +})
146 +
147 +watchDebounced([filters, currentPage, pageSize], getList, {
148 + deep: true,
149 + debounce: 300,
150 + immediate: true
151 +})
152 +// MOCK
153 +/*
154 +alertsList.value = techniqueAlertsResponse.alerts
155 +total.value = techniqueAlertsResponse.total_alerts
156 +*/
157 +</script>
frontend/src/components/mitre/TechniqueEvents/TechniqueEventCard.vue new
+402
@@ -0,0 +1,402 @@
1 +<template>
2 + <div>
3 + <CardEntity hoverable clickable :embedded class="@container" @click.stop="showDetails = true">
4 + <template #headerMain>#{{ alert.id }}</template>
5 + <template #headerExtra>
6 + {{ formatDate(alert.timestamp_utc, dFormats.datetimesec) }}
7 + </template>
8 + <template #default>
9 + <div class="flex flex-col gap-1">
10 + {{ alert.rule_description }}
11 + <p>
12 + {{ alert.rule_groups }}
13 + </p>
14 + </div>
15 + </template>
16 + <template #mainExtra>
17 + <div class="flex flex-wrap items-center gap-3">
18 + <Badge type="splitted" color="primary">
19 + <template #iconLeft>
20 + <Icon :name="TargetIcon" :size="13" class="!opacity-80" />
21 + </template>
22 + <template #label>Fired times</template>
23 + <template #value>
24 + {{ alert.rule_firedtimes }}
25 + </template>
26 + </Badge>
27 +
28 + <n-popover overlap placement="bottom-start">
29 + <template #trigger>
30 + <Badge type="splitted" color="primary" hint-cursor>
31 + <template #iconLeft>
32 + <Icon :name="AgentIcon" :size="13" class="!opacity-80" />
33 + </template>
34 + <template #label>Agent</template>
35 + <template #value>
36 + <div class="flex flex-wrap items-center gap-2">
37 + {{ alert.agent_name }} / {{ alert.agent_labels_customer }}
38 + <Icon :name="InfoIcon" :size="13" class="!opacity-80" />
39 + </div>
40 + </template>
41 + </Badge>
42 + </template>
43 + <div class="flex flex-col gap-1">
44 + <div class="box">
45 + agent_id:
46 + <code class="text-primary cursor-pointer" @click.stop="gotoAgent(alert.agent_id)">
47 + {{ alert.agent_id }}
48 + <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
49 + </code>
50 + </div>
51 + <div class="box">
52 + agent_ip:
53 + <code>{{ alert.agent_ip }}</code>
54 + </div>
55 + <div class="box">
56 + agent_name:
57 + <code>{{ alert.agent_name }}</code>
58 + </div>
59 + <div class="box">
60 + agent_labels_customer:
61 + <code
62 + class="text-primary cursor-pointer"
63 + @click.stop="gotoCustomer({ code: alert.agent_labels_customer })"
64 + >
65 + {{ alert.agent_labels_customer }}
66 + <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
67 + </code>
68 + </div>
69 + </div>
70 + </n-popover>
71 + <Badge type="splitted" color="primary">
72 + <template #label>syslog</template>
73 + <template #value>{{ alert.syslog_type }} / {{ alert.syslog_level }}</template>
74 + </Badge>
75 + <Badge type="splitted" color="primary" class="@2xl:!flex !hidden">
76 + <template #label>manager</template>
77 + <template #value>
78 + {{ alert.manager_name }}
79 + </template>
80 + </Badge>
81 + <Badge type="splitted" color="primary" class="@2xl:!flex !hidden">
82 + <template #label>decoder</template>
83 + <template #value>
84 + {{ alert.decoder_name }}
85 + </template>
86 + </Badge>
87 + <Badge type="splitted" color="primary" class="@2xl:!flex !hidden">
88 + <template #label>source</template>
89 + <template #value>
90 + {{ alert.source }}
91 + </template>
92 + </Badge>
93 + </div>
94 + </template>
95 + </CardEntity>
96 +
97 + <n-modal
98 + v-model:show="showDetails"
99 + preset="card"
100 + content-class="!p-0"
101 + :style="{ maxWidth: 'min(800px, 90vw)', minHeight: 'min(600px, 90vh)', overflow: 'hidden' }"
102 + :title="`Alert: ${alert.id}`"
103 + :bordered="false"
104 + segmented
105 + >
106 + <n-tabs type="line" animated :tabs-padding="24">
107 + <n-tab-pane name="Agent" tab="Agent" display-directive="show">
108 + <div v-if="agentProperties" class="grid-auto-fit-200 grid gap-2 p-7 pt-4">
109 + <CardKV v-for="(value, key) of agentProperties" :key="key">
110 + <template #key>
111 + {{ key }}
112 + </template>
113 + <template #value>
114 + <template v-if="key === 'agent_id'">
115 + <code class="text-primary cursor-pointer" @click.stop="gotoAgent(`${value}`)">
116 + {{ value }}
117 + <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
118 + </code>
119 + </template>
120 + <template v-else-if="key === 'agent_labels_customer'">
121 + <code
122 + class="text-primary cursor-pointer"
123 + @click.stop="gotoCustomer(value ? { code: value.toString() } : undefined)"
124 + >
125 + {{ value }}
126 + <Icon :name="LinkIcon" :size="13" class="relative top-0.5" />
127 + </code>
128 + </template>
129 + <template v-else>
130 + {{ value || "-" }}
131 + </template>
132 + </template>
133 + </CardKV>
134 + </div>
135 + </n-tab-pane>
136 +
137 + <n-tab-pane
138 + v-for="tabCard of tabsCards"
139 + :key="tabCard.tab"
140 + :name="tabCard.tab"
141 + :tab="tabCard.tab"
142 + display-directive="show"
143 + >
144 + <div v-if="tabCard.properties" class="grid-auto-fit-200 grid gap-2 p-7 pt-4">
145 + <CardKV v-for="(value, key) of tabCard.properties" :key="key">
146 + <template #key>
147 + {{ key }}
148 + </template>
149 + <template #value>
150 + {{ value || "-" }}
151 + </template>
152 + </CardKV>
153 + </div>
154 + </n-tab-pane>
155 +
156 + <n-tab-pane name="DNS" tab="DNS" display-directive="show">
157 + <div class="px-7 pt-4">
158 + <CardKV v-if="alert.data_dns_answers">
159 + <template #key>data_dns_answers</template>
160 + <template #value>
161 + <CodeSource :code="alert.data_dns_answers" :decode="false" />
162 + </template>
163 + </CardKV>
164 + </div>
165 + <div v-if="dnsProperties" class="grid-auto-fit-200 grid gap-2 p-7 pt-2">
166 + <CardKV v-for="(value, key) of dnsProperties" :key="key">
167 + <template #key>
168 + {{ key }}
169 + </template>
170 + <template #value>
171 + {{ value || "-" }}
172 + </template>
173 + </CardKV>
174 + </div>
175 + </n-tab-pane>
176 +
177 + <n-tab-pane name="GL2" tab="GL2" display-directive="show">
178 + <div class="px-7 pt-4">
179 + <CardKV v-if="alert.gl2_processing_error">
180 + <template #key>gl2_processing_error</template>
181 + <template #value>
182 + {{ alert.gl2_processing_error }}
183 + </template>
184 + </CardKV>
185 + </div>
186 + <div v-if="gl2Properties" class="grid-auto-fit-200 grid gap-2 p-7 pt-2">
187 + <CardKV v-for="(value, key) of gl2Properties" :key="key">
188 + <template #key>
189 + {{ key }}
190 + </template>
191 + <template #value>
192 + {{ value || "-" }}
193 + </template>
194 + </CardKV>
195 + </div>
196 + </n-tab-pane>
197 +
198 + <n-tab-pane v-if="alert.message" name="Message" tab="Message" display-directive="show">
199 + <div class="p-7 pt-4">
200 + <CodeSource :code="alert.message" :decode="false" />
201 + </div>
202 + </n-tab-pane>
203 +
204 + <n-tab-pane v-if="alert.location" name="Location" tab="Location" display-directive="show">
205 + <div class="p-7 pt-4">
206 + <CodeSource :code="alert.location" :decode="false" />
207 + </div>
208 + </n-tab-pane>
209 +
210 + <n-tab-pane v-if="alert.streams?.length" name="Streams" tab="Streams" display-directive="show">
211 + <div class="flex flex-wrap gap-3 p-7 pt-4">
212 + <ul>
213 + <li v-for="stream of alert.streams" :key="stream">
214 + <code>{{ stream }}</code>
215 + </li>
216 + </ul>
217 + </div>
218 + </n-tab-pane>
219 +
220 + <n-tab-pane name="Details" tab="Details" display-directive="show:lazy">
221 + <div class="p-7 pt-4">
222 + <CodeSource :code="alert" lang="json" :decode="false" />
223 + </div>
224 + </n-tab-pane>
225 + </n-tabs>
226 + </n-modal>
227 + </div>
228 +</template>
229 +
230 +<script setup lang="ts">
231 +import type { MitreEventDetails } from "@/types/mitre.d"
232 +import _pick from "lodash/pick"
233 +import { NModal, NPopover, NTabPane, NTabs } from "naive-ui"
234 +import { computed, defineAsyncComponent, ref, toRefs } from "vue"
235 +import Badge from "@/components/common/Badge.vue"
236 +import CardEntity from "@/components/common/cards/CardEntity.vue"
237 +import CardKV from "@/components/common/cards/CardKV.vue"
238 +import Icon from "@/components/common/Icon.vue"
239 +import { useGoto } from "@/composables/useGoto"
240 +import { useSettingsStore } from "@/stores/settings"
241 +import { formatDate } from "@/utils"
242 +
243 +const props = defineProps<{ alert: MitreEventDetails; hideActions?: boolean; embedded?: boolean }>()
244 +const CodeSource = defineAsyncComponent(() => import("@/components/common/CodeSource.vue"))
245 +
246 +const { alert, embedded } = toRefs(props)
247 +
248 +const InfoIcon = "carbon:information"
249 +const TargetIcon = "zondicons:target"
250 +const AgentIcon = "carbon:police"
251 +const LinkIcon = "carbon:launch"
252 +
253 +const { gotoCustomer, gotoAgent } = useGoto()
254 +const showDetails = ref(false)
255 +const dFormats = useSettingsStore().dateFormat
256 +
257 +const tabsCards = computed(() => [
258 + {
259 + tab: "Host",
260 + properties: _pick(alert.value, [
261 + "data_host_architecture",
262 + "data_host_id",
263 + "data_host_mac",
264 + "data_host_name",
265 + "data_host_hostname",
266 + "data_host_containerized",
267 + "data_host_ip",
268 + "data_host_os_codename",
269 + "data_host_os_family",
270 + "data_host_os_kernel",
271 + "data_host_os_name",
272 + "data_host_os_platform",
273 + "data_host_os_type",
274 + "data_host_os_version"
275 + ])
276 + },
277 + {
278 + tab: "Network",
279 + properties: _pick(alert.value, [
280 + "data_network_protocol",
281 + "data_network_transport",
282 + "data_network_type",
283 + "data_network_bytes",
284 + "data_network_direction",
285 + "data_network_community_id",
286 + "traffic_direction"
287 + ])
288 + },
289 + {
290 + tab: "Event",
291 + properties: _pick(alert.value, [
292 + "data_event_category",
293 + "data_event_dataset",
294 + "data_event_duration",
295 + "data_event_end",
296 + "data_event_kind",
297 + "data_event_start",
298 + "data_event_type",
299 + "data_type"
300 + ])
301 + },
302 + {
303 + tab: "Timestamp",
304 + properties: _pick(alert.value, ["timestamp", "timestamp_utc", "data_@timestamp", "msg_timestamp"])
305 + },
306 + {
307 + tab: "Source",
308 + properties: _pick(alert.value, ["data_source_ip", "data_source_port", "data_source_bytes"])
309 + },
310 + {
311 + tab: "Destination",
312 + properties: _pick(alert.value, ["data_destination_ip", "data_destination_port", "data_destination_bytes"])
313 + },
314 + {
315 + tab: "Client",
316 + properties: _pick(alert.value, ["data_client_ip", "data_client_port", "data_client_bytes"])
317 + },
318 + {
319 + tab: "Server",
320 + properties: _pick(alert.value, ["data_server_ip", "data_server_port", "data_server_bytes"])
321 + },
322 + {
323 + tab: "Cluster",
324 + properties: _pick(alert.value, ["cluster_name", "cluster_node"])
325 + },
326 + {
327 + tab: "Rule",
328 + properties: _pick(alert.value, [
329 + "rule_id",
330 + "rule_level",
331 + "rule_mail",
332 + "rule_mitre_id",
333 + "rule_mitre_tactic",
334 + "rule_mitre_technique",
335 + "rule_description",
336 + "rule_firedtimes",
337 + "rule_groups",
338 + "rule_group1",
339 + "rule_group2",
340 + "rule_group3"
341 + ])
342 + }
343 +])
344 +
345 +const agentProperties = computed(() => {
346 + return _pick(alert.value, [
347 + "agent_id",
348 + "agent_name",
349 + "agent_ip",
350 + "data_agent_id",
351 + "data_agent_name",
352 + "data_agent_type",
353 + "data_agent_version",
354 + "data_agent_ephemeral_id",
355 + "agent_labels_customer"
356 + ])
357 +})
358 +
359 +const dnsProperties = computed(() => {
360 + return _pick(alert.value, [
361 + "data_dns_answers_count",
362 + "data_dns_authorities_count",
363 + "data_dns_flags_authentic_data",
364 + "data_dns_flags_authoritative",
365 + "data_dns_flags_checking_disabled",
366 + "data_dns_flags_recursion_available",
367 + "data_dns_flags_recursion_desired",
368 + "data_dns_flags_truncated_response",
369 + "data_dns_header_flags",
370 + "data_dns_id",
371 + "data_dns_op_code",
372 + "data_dns_opt_do",
373 + "data_dns_opt_ext_rcode",
374 + "data_dns_opt_udp_size",
375 + "data_dns_opt_version",
376 + "data_dns_question_class",
377 + "data_dns_question_etld_plus_one",
378 + "data_dns_question_name",
379 + "data_dns_question_registered_domain",
380 + "data_dns_question_subdomain",
381 + "data_dns_question_top_level_domain",
382 + "data_dns_question_type",
383 + "data_dns_resolved_ip",
384 + "data_dns_response_code",
385 + "data_dns_type",
386 + "dns_query",
387 + "dns_response_code",
388 + "dns_answer"
389 + ])
390 +})
391 +
392 +const gl2Properties = computed(() => {
393 + return _pick(alert.value, [
394 + "gl2_remote_ip",
395 + "gl2_source_node",
396 + "gl2_accounted_message_size",
397 + "gl2_remote_port",
398 + "gl2_source_input",
399 + "gl2_message_id"
400 + ])
401 +})
402 +</script>
frontend/src/components/mitre/TechniqueEvents/TechniqueEventDetails.vue new
+173
@@ -0,0 +1,173 @@
1 +<template>
2 + <n-spin :show="loadingDetails" content-class="min-h-40">
3 + <div v-if="softwareDetails" class="flex flex-col gap-4 md:flex-row">
4 + <div class="flex grow flex-col gap-3">
5 + <code class="self-start">
6 + {{ softwareDetails.id ?? "—" }}
7 + </code>
8 +
9 + <CardKV>
10 + <template #key>name</template>
11 + <template #value>
12 + <span class="whitespace-pre-wrap">
13 + {{ softwareDetails.name ?? "—" }}
14 + </span>
15 + </template>
16 + </CardKV>
17 + <CardKV v-if="softwareDetails.description" class="[&_p]:text-white">
18 + <template #key>description</template>
19 + <template #value>
20 + <Suspense>
21 + <Markdown :source="softwareDetails.description" />
22 + </Suspense>
23 + </template>
24 + </CardKV>
25 +
26 + <CardKV v-if="softwareDetails.references?.length">
27 + <template #key>references</template>
28 + <template #value>
29 + <References :references="softwareDetails.references" />
30 + </template>
31 + </CardKV>
32 + </div>
33 + <div ref="sidebarRef" class="md:max-w-70 shrink-0 basis-1/3">
34 + <div ref="sidebarCardRef" class="flex flex-col gap-2 will-change-transform">
35 + <n-card content-class="bg-secondary flex flex-col gap-3 rounded-lg" size="small">
36 + <div class="flex flex-col gap-0.5 text-sm">
37 + <div class="text-secondary font-mono text-xs">external_id</div>
38 + <div>{{ softwareDetails.external_id }}</div>
39 + </div>
40 + <div class="flex flex-col gap-0.5 text-sm">
41 + <div class="text-secondary font-mono text-xs">created_time</div>
42 + <div>{{ formatDate(softwareDetails.created_time, dFormats.datetime) }}</div>
43 + </div>
44 + <div class="flex flex-col gap-0.5 text-sm">
45 + <div class="text-secondary font-mono text-xs">modified_time</div>
46 + <div>{{ formatDate(softwareDetails.modified_time, dFormats.datetime) }}</div>
47 + </div>
48 + <div class="flex flex-col gap-0.5 text-sm">
49 + <div class="text-secondary font-mono text-xs">url</div>
50 + <div>
51 + <a :href="softwareDetails.url" target="_blank" rel="nofollow noopener noreferrer">
52 + {{ softwareDetails.url }}
53 + </a>
54 + </div>
55 + </div>
56 + <div class="flex flex-col gap-0.5 text-sm">
57 + <div class="text-secondary font-mono text-xs">source</div>
58 + <div>{{ softwareDetails.source }}</div>
59 + </div>
60 + <div class="flex flex-col gap-0.5 text-sm">
61 + <div class="text-secondary font-mono text-xs">type</div>
62 + <div>{{ softwareDetails.type || "—" }}</div>
63 + </div>
64 + <div class="flex flex-col gap-0.5 text-sm">
65 + <div class="text-secondary font-mono text-xs">mitre_version</div>
66 + <div>{{ softwareDetails.mitre_version }}</div>
67 + </div>
68 + <div class="flex flex-col gap-0.5 text-sm">
69 + <div class="text-secondary font-mono text-xs">platforms</div>
70 + <div class="mt-0.5 flex flex-wrap gap-1">
71 + <template v-if="!softwareDetails.platforms?.length">—</template>
72 + <template v-else>
73 + <code v-for="item of softwareDetails.platforms" :key="item" class="text-xs">
74 + {{ item }}
75 + </code>
76 + </template>
77 + </div>
78 + </div>
79 + <div class="flex flex-col gap-0.5 text-sm">
80 + <div class="text-secondary font-mono text-xs">aliases</div>
81 + <div class="mt-0.5 flex flex-wrap gap-1">
82 + <template v-if="!softwareDetails.aliases?.length">—</template>
83 + <template v-else>
84 + <code v-for="item of softwareDetails.aliases" :key="item" class="text-xs">
85 + {{ item }}
86 + </code>
87 + </template>
88 + </div>
89 + </div>
90 + </n-card>
91 +
92 + <div class="flex flex-wrap gap-1">
93 + <Badge v-if="softwareDetails.deprecated" color="primary" class="text-xs! font-mono">
94 + <template #value>deprecated</template>
95 + </Badge>
96 + </div>
97 + </div>
98 + </div>
99 + </div>
100 + </n-spin>
101 +</template>
102 +
103 +<script setup lang="ts">
104 +import type { MitreSoftwareDetails } from "@/types/mitre.d"
105 +import { useElementBounding, useRafFn } from "@vueuse/core"
106 +import { useMotionProperties } from "@vueuse/motion"
107 +import { NCard, NSpin, useMessage } from "naive-ui"
108 +import { defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
109 +import Api from "@/api"
110 +import Badge from "@/components/common/Badge.vue"
111 +import CardKV from "@/components/common/cards/CardKV.vue"
112 +import { useSettingsStore } from "@/stores/settings"
113 +import { formatDate } from "@/utils"
114 +import References from "../common/References.vue"
115 +
116 +const { externalId, entity } = defineProps<{
117 + externalId?: string
118 + entity?: MitreSoftwareDetails
119 +}>()
120 +
121 +const Markdown = defineAsyncComponent(() => import("@/components/common/Markdown.vue"))
122 +
123 +const dFormats = useSettingsStore().dateFormat
124 +const message = useMessage()
125 +const loadingDetails = ref(false)
126 +const softwareDetails = ref<MitreSoftwareDetails | null>(null)
127 +
128 +const sidebarRef = ref(null)
129 +const sidebarCardRef = ref(null)
130 +const { top: sidebarTop } = useElementBounding(sidebarRef)
131 +const { transform: styleCardTransform } = useMotionProperties(sidebarCardRef)
132 +
133 +const { resume } = useRafFn(
134 + () => {
135 + const targetY = sidebarTop.value <= 50 ? sidebarTop.value * -1 + 50 : 0
136 + styleCardTransform.translateY = `${targetY}px`
137 + },
138 + { immediate: false }
139 +)
140 +
141 +watch(sidebarTop, () => {
142 + resume()
143 +})
144 +
145 +function getDetails(id: string) {
146 + loadingDetails.value = true
147 +
148 + Api.mitre
149 + .getMitreSoftware({ id })
150 + .then(res => {
151 + if (res.data.success) {
152 + softwareDetails.value = res.data.results?.[0] || null
153 + } else {
154 + message.warning(res.data?.message || "An error occurred. Please try again later.")
155 + }
156 + })
157 + .catch(err => {
158 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
159 + })
160 + .finally(() => {
161 + loadingDetails.value = false
162 + })
163 +}
164 +
165 +onBeforeMount(() => {
166 + if (externalId) {
167 + getDetails(externalId)
168 + }
169 + if (entity) {
170 + softwareDetails.value = entity
171 + }
172 +})
173 +</script>
frontend/src/components/mitre/TechniqueEvents/TechniqueEventOverview.vue new
+42
@@ -0,0 +1,42 @@
1 +<template>
2 + <div class="flex flex-col gap-3">
3 + <div v-for="item of itemsPaginated" :key="item.id">
4 + <SoftwareCard :id="item.id" :entity="item.entity" @loaded="item.entity = $event" />
5 + </div>
6 + <div v-if="list.length" class="flex justify-end">
7 + <n-pagination
8 + v-model:page="currentPage"
9 + v-model:page-size="pageSize"
10 + :item-count="list.length"
11 + :page-slot="6"
12 + />
13 + </div>
14 + <n-empty v-else description="No items found" class="h-48 justify-center" />
15 + </div>
16 +</template>
17 +
18 +<script setup lang="ts">
19 +import type { MitreSoftwareDetails } from "@/types/mitre.d"
20 +import { NEmpty, NPagination } from "naive-ui"
21 +import { computed, onMounted, ref } from "vue"
22 +import SoftwareCard from "./SoftwareCard.vue"
23 +
24 +const { list } = defineProps<{
25 + list: string[]
26 +}>()
27 +
28 +const pageSize = ref(5)
29 +const currentPage = ref(1)
30 +const software = ref<{ id: string; entity?: MitreSoftwareDetails }[]>([])
31 +
32 +const itemsPaginated = computed(() => {
33 + const from = (currentPage.value - 1) * pageSize.value
34 + const to = currentPage.value * pageSize.value
35 +
36 + return software.value.slice(from, to)
37 +})
38 +
39 +onMounted(() => {
40 + software.value = list.map(o => ({ id: o, entity: undefined }))
41 +})
42 +</script>
frontend/src/components/mitre/TechniquesAlerts/Filters.vue new
+159
@@ -0,0 +1,159 @@
1 +<template>
2 + <div class="flex flex-wrap gap-3">
3 + <div>
4 + <n-popover placement="top-start" trigger="click" overlap>
5 + <template #trigger>
6 + <n-badge :show="!!mitreField" dot type="success" :offset="[0, 6]">
7 + <n-button size="small" secondary class="px-2!">
8 + <template #icon>
9 + <Icon :name="ConfigIcon" :size="16" />
10 + </template>
11 + </n-button>
12 + </n-badge>
13 + </template>
14 +
15 + <div class="pb-2 pt-1">
16 + <div class="text-secondary mb-1 text-sm">Mitre field:</div>
17 + <n-input v-model:value="mitreField" size="small" clearable class="!w-40" />
18 + </div>
19 + </n-popover>
20 + </div>
21 + <div>
22 + <n-input-group>
23 + <n-select
24 + v-model:value="filterTimeRange.unit"
25 + :options="unitOptions"
26 + placeholder="Time unit"
27 + size="small"
28 + class="!w-24"
29 + />
30 + <n-input-number
31 + v-model:value="filterTimeRange.value"
32 + :min="1"
33 + placeholder="Value"
34 + class="!w-26"
35 + size="small"
36 + :parse="parseTimeValue"
37 + />
38 + </n-input-group>
39 + </div>
40 + <div v-for="filter of usedFilters" :key="filter.type">
41 + <n-input-group>
42 + <n-input-group-label size="small">{{ getFilterLabel(filter.type) }}</n-input-group-label>
43 + <n-input v-model:value="filter.value" autosize placeholder="Input..." size="small" class="!min-w-30" />
44 + <n-button size="small" secondary tabindex="-1" @click="delFilter(filter.type)">
45 + <template #icon>
46 + <Icon :name="DelIcon" />
47 + </template>
48 + </n-button>
49 + </n-input-group>
50 + </div>
51 +
52 + <n-dropdown
53 + v-if="availableFilters.length"
54 + placement="bottom-start"
55 + trigger="click"
56 + :options="availableFilters"
57 + @select="addFilter"
58 + >
59 + <n-button size="small" dashed>
60 + <template #icon>
61 + <Icon :name="AddIcon" />
62 + </template>
63 + Add filter
64 + </n-button>
65 + </n-dropdown>
66 + </div>
67 +</template>
68 +
69 +<script setup lang="ts">
70 +import _toSafeInteger from "lodash/toSafeInteger"
71 +import {
72 + NBadge,
73 + NButton,
74 + NDropdown,
75 + NInput,
76 + NInputGroup,
77 + NInputGroupLabel,
78 + NInputNumber,
79 + NPopover,
80 + NSelect
81 +} from "naive-ui"
82 +import { computed, ref, watch } from "vue"
83 +import Icon from "@/components/common/Icon.vue"
84 +
85 +const emit = defineEmits<{
86 + (e: "update", value: { type: string; value: string }[]): void
87 +}>()
88 +
89 +const usedFilters = ref<{ type: string; value: string | null }[]>([{ type: "index_pattern", value: "wazuh-*" }])
90 +
91 +const filterTimeRange = ref({
92 + unit: "h",
93 + value: 24
94 +})
95 +
96 +const mitreField = ref<string | null>(null)
97 +
98 +const unitOptions: { label: string; value: "h" | "d" | "w" }[] = [
99 + { label: "Hours", value: "h" },
100 + { label: "Days", value: "d" },
101 + { label: "Weeks", value: "w" }
102 +]
103 +
104 +const proxyFilters = computed<{ type: string; value: string }[]>(() => {
105 + const filters = [
106 + { type: "time_range", value: `now-${filterTimeRange.value.value}${filterTimeRange.value.unit}` },
107 + ...usedFilters.value.filter(o => !!o.value)
108 + ] as { type: string; value: string }[]
109 +
110 + if (mitreField.value) {
111 + filters.push({ type: "mitre_field", value: mitreField.value })
112 + }
113 +
114 + return filters
115 +})
116 +
117 +const ConfigIcon = "carbon:settings"
118 +const AddIcon = "carbon:add"
119 +const DelIcon = "carbon:delete"
120 +
121 +const typeOptions: { label: string; value: string }[] = [
122 + { label: "Rule level", value: "rule_level" },
123 + { label: "Rule group", value: "rule_group" },
124 + { label: "Index pattern", value: "index_pattern" }
125 +]
126 +
127 +const availableFilters = computed(() =>
128 + typeOptions
129 + .filter(o => !usedFilters.value.map(o => o.type).includes(o.value))
130 + .map(t => ({ key: t.value, label: t.label }))
131 +)
132 +
133 +function getFilterLabel(type: string): string {
134 + return typeOptions.find(o => o.value === type)?.label || type
135 +}
136 +
137 +function addFilter(key: string) {
138 + usedFilters.value.push({ type: key, value: null })
139 +}
140 +
141 +function delFilter(key: string) {
142 + usedFilters.value = usedFilters.value.filter(o => o.type !== key)
143 +}
144 +
145 +function parseTimeValue(input: string) {
146 + return _toSafeInteger(input) || 1
147 +}
148 +
149 +watch(
150 + proxyFilters,
151 + val => {
152 + emit("update", val)
153 + },
154 + {
155 + deep: true,
156 + immediate: true
157 + }
158 +)
159 +</script>
frontend/src/components/mitre/TechniquesAlerts/List.vue new
+224
@@ -0,0 +1,224 @@
1 +<template>
2 + <SegmentedPage toolbar-height="60px" toolbar-height-mobile="50px" padding="16px" enable-resize>
3 + <template #sidebar-header>
4 + <n-button v-if="areAllTacticsSelected" :focusable="false" @click="toggleAllTactics(false)">
5 + <template #icon>
6 + <Icon name="carbon:checkbox" :size="16" />
7 + </template>
8 + Unselect all
9 + </n-button>
10 + <n-button v-else type="primary" :focusable="false" @click="toggleAllTactics(true)">
11 + <template #icon>
12 + <Icon name="carbon:checkbox-checked" :size="16" />
13 + </template>
14 + Select all
15 + </n-button>
16 + </template>
17 + <template #sidebar-content>
18 + <n-spin :show="loading">
19 + <div class="flex flex-col gap-4">
20 + <div v-for="tactic of tacticsList" :key="tactic.id" class="flex items-center gap-3">
21 + <n-checkbox
22 + :checked="isTacticSelected(tactic.id)"
23 + @update-checked="toggleTacticSelect(tactic.id)"
24 + >
25 + <div class="flex items-center gap-2">
26 + <span>{{ tactic.name }}</span>
27 + <code class="whitespace-nowrap">{{ tactic.count }}</code>
28 + </div>
29 + </n-checkbox>
30 + </div>
31 + </div>
32 + <n-empty v-if="!tacticsList.length" description="No tactics available" class="h-48 justify-center" />
33 + </n-spin>
34 + </template>
35 + <template #main-toolbar>
36 + <div class="flex items-center gap-4">
37 + <n-input v-model:value="textFilter" placeholder="Search by technique name" clearable>
38 + <template #prefix>
39 + <Icon name="carbon:search" :size="16" />
40 + </template>
41 + </n-input>
42 + <div v-if="hasNoCountAlerts" class="min-w-32 max-w-32">
43 + <n-checkbox v-model:checked="hideNoAlertsTechniques" class="items-center!" size="large">
44 + <span class="text-xs/tight">Hide techniques with no alerts</span>
45 + </n-checkbox>
46 + </div>
47 + </div>
48 + </template>
49 + <template #main-content>
50 + <n-spin :show="loading">
51 + <div class="grid-auto-fill-250 grid gap-2">
52 + <TechniqueAlertCard
53 + v-for="technique of filteredTechniques"
54 + :key="technique.technique_id"
55 + :entity="technique"
56 + class="flex"
57 + />
58 + </div>
59 + <n-empty v-if="!filteredTechniques.length" description="No items found" class="h-48 justify-center" />
60 + </n-spin>
61 + </template>
62 + </SegmentedPage>
63 +</template>
64 +
65 +<script setup lang="ts">
66 +import type { MitreTechniquesAlertsQuery, MitreTechniquesAlertsQueryTimeRange } from "@/api/endpoints/mitre"
67 +import type { MitreTechnique } from "@/types/mitre.d"
68 +import { watchDebounced } from "@vueuse/core"
69 +import axios from "axios"
70 +import { NButton, NCheckbox, NEmpty, NInput, NSpin, useMessage } from "naive-ui"
71 +import { computed, ref, toRefs, watch } from "vue"
72 +import Api from "@/api"
73 +import Icon from "@/components/common/Icon.vue"
74 +import SegmentedPage from "@/components/common/SegmentedPage.vue"
75 +import TechniqueAlertCard from "../TechniqueAlert/TechniqueAlertCard.vue"
76 +
77 +const props = defineProps<{
78 + filters?: { type: string; value: string }[]
79 +}>()
80 +
81 +const { filters } = toRefs(props)
82 +const loading = ref(false)
83 +const message = useMessage()
84 +const techniquesList = ref<MitreTechnique[]>([])
85 +const currentPage = ref(1)
86 +const hideNoAlertsTechniques = ref(false)
87 +const textFilter = ref<string | null>(null)
88 +let abortController: AbortController | null = null
89 +
90 +const selectedTactics = ref<string[]>([])
91 +
92 +const tacticsList = computed(() => {
93 + const list: { name: string; id: string; count: number }[] = []
94 +
95 + for (const technique of techniquesList.value) {
96 + for (const tactic of technique.tactics) {
97 + const savedTactic = list.find(o => o.id === tactic.id)
98 + if (savedTactic) {
99 + savedTactic.count += technique.count
100 + } else {
101 + list.push({
102 + name: tactic.name,
103 + id: tactic.id,
104 + count: technique.count
105 + })
106 + }
107 + }
108 + }
109 +
110 + return list
111 +})
112 +
113 +const filteredTechniques = computed(() => {
114 + return techniquesList.value
115 + .filter(a => {
116 + for (const tactic of a.tactics) {
117 + if (selectedTactics.value.includes(tactic.id)) {
118 + return true
119 + }
120 + }
121 +
122 + return false
123 + })
124 + .filter(a => !textFilter.value || a.technique_name.toLowerCase().includes(textFilter.value.toLowerCase()))
125 + .filter(a => !hideNoAlertsTechniques.value || (hideNoAlertsTechniques.value && a.count))
126 +})
127 +
128 +const areAllTacticsSelected = computed(() => {
129 + return selectedTactics.value.length === tacticsList.value.length
130 +})
131 +
132 +const hasNoCountAlerts = computed(() => !!techniquesList.value.filter(o => !o.count).length)
133 +
134 +function isTacticSelected(id: string) {
135 + return !!selectedTactics.value.find(o => o === id)
136 +}
137 +
138 +function toggleTacticSelect(id: string) {
139 + const index = selectedTactics.value.findIndex(o => o === id)
140 +
141 + if (selectedTactics.value.find(o => o === id)) {
142 + selectedTactics.value.splice(index, 1)
143 + } else {
144 + selectedTactics.value.push(id)
145 + }
146 +}
147 +
148 +function toggleAllTactics(state: boolean) {
149 + if (state) {
150 + selectedTactics.value = tacticsList.value.map(o => o.id)
151 + } else {
152 + selectedTactics.value = []
153 + }
154 +}
155 +
156 +function resetList() {
157 + techniquesList.value = []
158 + currentPage.value = 1
159 + getList()
160 +}
161 +
162 +function nextPage() {
163 + currentPage.value++
164 + getList()
165 +}
166 +
167 +function getList() {
168 + abortController?.abort()
169 + abortController = new AbortController()
170 +
171 + loading.value = true
172 +
173 + const query: MitreTechniquesAlertsQuery = {
174 + time_range: filters.value?.find(o => o.type === "time_range")?.value as
175 + | MitreTechniquesAlertsQueryTimeRange
176 + | undefined,
177 + size: 300,
178 + page: currentPage.value,
179 + rule_level: filters.value?.find(o => o.type === "rule_level")?.value,
180 + rule_group: filters.value?.find(o => o.type === "rule_group")?.value,
181 + mitre_field: filters.value?.find(o => o.type === "mitre_field")?.value,
182 + index_pattern: filters.value?.find(o => o.type === "index_pattern")?.value
183 + }
184 +
185 + Api.mitre
186 + .getMitreTechniquesAlerts(query, abortController.signal)
187 + .then(res => {
188 + loading.value = false
189 +
190 + if (res.data.success) {
191 + techniquesList.value = [...techniquesList.value, ...res.data.techniques]
192 + if (res.data.total_pages > currentPage.value) {
193 + nextPage()
194 + }
195 + } else {
196 + message.warning(res.data?.message || "An error occurred. Please try again later.")
197 + }
198 + })
199 + .catch(err => {
200 + if (!axios.isCancel(err)) {
201 + message.error(err.response?.data?.message || "An error occurred. Please try again later.")
202 + loading.value = false
203 + }
204 + })
205 +}
206 +
207 +watch(
208 + tacticsList,
209 + () => {
210 + toggleAllTactics(true)
211 + },
212 + { deep: true, immediate: true }
213 +)
214 +
215 +watchDebounced(filters, resetList, {
216 + deep: true,
217 + debounce: 300,
218 + immediate: true
219 +})
220 +// MOCK
221 +/*
222 +techniquesList.value = techniques
223 +*/
224 +</script>
frontend/src/components/mitre/common/References.vue new
+21
@@ -0,0 +1,21 @@
1 +<template>
2 + <div class="divide-border flex flex-col gap-4 divide-y-2">
3 + <div v-for="reference of references" :key="reference.url" class="flex flex-col gap-0.5 pb-1 text-sm">
4 + <div>{{ reference.source }}</div>
5 + <div class="text-secondary text-xs">{{ reference.description }}</div>
6 + <div>
7 + <a :href="reference.url" target="_blank" rel="nofollow noopener noreferrer">
8 + {{ reference.url }}
9 + </a>
10 + </div>
11 + </div>
12 + </div>
13 +</template>
14 +
15 +<script setup lang="ts">
16 +import type { MitreReference } from "@/types/mitre.d"
17 +
18 +const { references } = defineProps<{
19 + references: MitreReference[]
20 +}>()
21 +</script>
frontend/src/components/mitre/mock.ts new
+3689
@@ -0,0 +1,3689 @@
1 +import type { MitreEventDetails, MitreTechniqueDetails } from "@/types/mitre.d"
2 +
3 +export const techniques = [
4 + {
5 + technique_id: "T1071",
6 + technique_name: "Application Layer Protocol",
7 + count: 99423,
8 + last_seen: "2025-05-09T16:02:20.205496Z",
9 + tactics: [
10 + {
11 + id: "x-mitre-tactic--f72804c5-f15a-449e-a5da-2eecd181f813",
12 + name: "Command and Control",
13 + short_name: "command-and-control"
14 + }
15 + ]
16 + },
17 + {
18 + technique_id: "T1565.001",
19 + technique_name: "Stored Data Manipulation",
20 + count: 47,
21 + last_seen: "2025-05-09T16:02:20.205614Z",
22 + tactics: [
23 + {
24 + id: "x-mitre-tactic--5569339b-94c2-49ee-afb3-2222936582c8",
25 + name: "Impact",
26 + short_name: "impact"
27 + }
28 + ]
29 + },
30 + {
31 + technique_id: "T1560",
32 + technique_name: "Archive Collected Data",
33 + count: 25,
34 + last_seen: "2025-05-09T16:02:20.205925Z",
35 + tactics: [
36 + {
37 + id: "x-mitre-tactic--d108ce10-2419-4cf9-a774-46161d6c6cfe",
38 + name: "Collection",
39 + short_name: "collection"
40 + }
41 + ]
42 + },
43 + {
44 + technique_id: "T1078",
45 + technique_name: "Valid Accounts",
46 + count: 16,
47 + last_seen: "2025-05-09T16:02:20.206013Z",
48 + tactics: [
49 + {
50 + id: "x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
51 + name: "Persistence",
52 + short_name: "persistence"
53 + },
54 + {
55 + id: "x-mitre-tactic--5e29b093-294e-49e9-a803-dab3d73b77dd",
56 + name: "Privilege Escalation",
57 + short_name: "privilege-escalation"
58 + },
59 + {
60 + id: "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
61 + name: "Defense Evasion",
62 + short_name: "defense-evasion"
63 + },
64 + {
65 + id: "x-mitre-tactic--ffd5bcee-6e16-4dd2-8eca-7b3beedf33ca",
66 + name: "Initial Access",
67 + short_name: "initial-access"
68 + }
69 + ]
70 + },
71 + {
72 + technique_id: "T1222",
73 + technique_name: "File and Directory Permissions Modification",
74 + count: 10,
75 + last_seen: "2025-05-09T16:02:20.206062Z",
76 + tactics: [
77 + {
78 + id: "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
79 + name: "Defense Evasion",
80 + short_name: "defense-evasion"
81 + }
82 + ]
83 + },
84 + {
85 + technique_id: "T1543",
86 + technique_name: "Create or Modify System Process",
87 + count: 9,
88 + last_seen: "2025-05-09T16:02:20.206100Z",
89 + tactics: [
90 + {
91 + id: "x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
92 + name: "Persistence",
93 + short_name: "persistence"
94 + },
95 + {
96 + id: "x-mitre-tactic--5e29b093-294e-49e9-a803-dab3d73b77dd",
97 + name: "Privilege Escalation",
98 + short_name: "privilege-escalation"
99 + }
100 + ]
101 + },
102 + {
103 + technique_id: "T1078",
104 + technique_name: "Valid Accounts, Remote Services",
105 + count: 2,
106 + last_seen: "2025-05-09T16:02:20.206137Z",
107 + tactics: [
108 + {
109 + id: "x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
110 + name: "Persistence",
111 + short_name: "persistence"
112 + },
113 + {
114 + id: "x-mitre-tactic--5e29b093-294e-49e9-a803-dab3d73b77dd",
115 + name: "Privilege Escalation",
116 + short_name: "privilege-escalation"
117 + },
118 + {
119 + id: "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
120 + name: "Defense Evasion",
121 + short_name: "defense-evasion"
122 + },
123 + {
124 + id: "x-mitre-tactic--ffd5bcee-6e16-4dd2-8eca-7b3beedf33ca",
125 + name: "Initial Access",
126 + short_name: "initial-access"
127 + }
128 + ]
129 + },
130 + {
131 + technique_id: "T1021",
132 + technique_name: "Valid Accounts, Remote Services",
133 + count: 2,
134 + last_seen: "2025-05-09T16:02:20.206170Z",
135 + tactics: [
136 + {
137 + id: "x-mitre-tactic--7141578b-e50b-4dcc-bfa4-08a8dd689e9e",
138 + name: "Lateral Movement",
139 + short_name: "lateral-movement"
140 + }
141 + ]
142 + },
143 + {
144 + technique_id: "T1110.001",
145 + technique_name: "Password Guessing",
146 + count: 2,
147 + last_seen: "2025-05-09T16:02:20.206205Z",
148 + tactics: [
149 + {
150 + id: "x-mitre-tactic--2558fd61-8c75-4730-94c4-11926db2a263",
151 + name: "Credential Access",
152 + short_name: "credential-access"
153 + }
154 + ]
155 + },
156 + {
157 + technique_id: "T1562.001",
158 + technique_name: "Disable or Modify Tools",
159 + count: 2,
160 + last_seen: "2025-05-09T16:02:20.206239Z",
161 + tactics: [
162 + {
163 + id: "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
164 + name: "Defense Evasion",
165 + short_name: "defense-evasion"
166 + }
167 + ]
168 + },
169 + {
170 + technique_id: "T1046",
171 + technique_name: "Network Service Discovery",
172 + count: 1,
173 + last_seen: "2025-05-09T16:02:20.206271Z",
174 + tactics: [
175 + {
176 + id: "x-mitre-tactic--c17c5845-175e-4421-9713-829d0573dbc9",
177 + name: "Discovery",
178 + short_name: "discovery"
179 + }
180 + ]
181 + },
182 + {
183 + technique_id: "T104X",
184 + technique_name: "Network Service Discovery",
185 + count: 0,
186 + last_seen: "2025-05-09T16:02:20.206271Z",
187 + tactics: [
188 + {
189 + id: "x-mitre-tactic--c17c5845-175e-4421-9713-829d0573dbc9",
190 + name: "Discovery",
191 + short_name: "discovery"
192 + }
193 + ]
194 + },
195 + {
196 + technique_id: "T1548.003",
197 + technique_name: "Sudo and Sudo Caching",
198 + count: 1,
199 + last_seen: "2025-05-09T16:02:20.206307Z",
200 + tactics: [
201 + {
202 + id: "x-mitre-tactic--5e29b093-294e-49e9-a803-dab3d73b77dd",
203 + name: "Privilege Escalation",
204 + short_name: "privilege-escalation"
205 + },
206 + {
207 + id: "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
208 + name: "Defense Evasion",
209 + short_name: "defense-evasion"
210 + }
211 + ]
212 + }
213 +]
214 +
215 +export const techniqueResultDetails: MitreTechniqueDetails = {
216 + description:
217 + "Adversaries may obtain and abuse credentials of existing accounts as a means of gaining Initial Access, Persistence, Privilege Escalation, or Defense Evasion. Compromised credentials may be used to bypass access controls placed on various resources on systems within the network and may even be used for persistent access to remote systems and externally available services, such as VPNs, Outlook Web Access, network devices, and remote desktop.(Citation: volexity_0day_sophos_FW) Compromised credentials may also grant an adversary increased privilege to specific systems or access to restricted areas of the network. Adversaries may choose not to use malware or tools in conjunction with the legitimate access those credentials provide to make it harder to detect their presence.\n\nIn some cases, adversaries may abuse inactive accounts: for example, those belonging to individuals who are no longer part of an organization. Using these accounts may allow the adversary to evade detection, as the original account user will not be present to identify any anomalous activity taking place on their account.(Citation: CISA MFA PrintNightmare)\n\nThe overlap of permissions for local, domain, and cloud accounts across a network of systems is of concern because the adversary may be able to pivot across accounts and systems to reach a high level of access (i.e., domain or enterprise administrator) to bypass access controls set within the enterprise.(Citation: TechNet Credential Theft)",
218 + name: "Valid Accounts",
219 + id: "attack-pattern--b17a1a56-e99c-403c-8948-561df0cffe81",
220 + modified_time: new Date("2023-03-30T21:01:51.631000Z"),
221 + created_time: new Date("2017-05-31T21:31:00.645000Z"),
222 + tactics: [
223 + "x-mitre-tactic--5bc1d813-693e-4823-9961-abf9af4b0e92",
224 + "x-mitre-tactic--5e29b093-294e-49e9-a803-dab3d73b77dd",
225 + "x-mitre-tactic--78b23412-0651-46d7-a540-170a1ce8bd5a",
226 + "x-mitre-tactic--ffd5bcee-6e16-4dd2-8eca-7b3beedf33ca"
227 + ],
228 + url: "https://attack.mitre.org/techniques/T1078",
229 + source: "mitre-attack",
230 + external_id: "T1078",
231 + references: [
232 + {
233 + url: "https://www.cisa.gov/uscert/ncas/alerts/aa22-074a",
234 + description:
235 + "Cybersecurity and Infrastructure Security Agency. (2022, March 15). Russian State-Sponsored Cyber Actors Gain Network Access by Exploiting Default Multifactor Authentication Protocols and “PrintNightmare” Vulnerability. Retrieved March 16, 2022.",
236 + source: "CISA MFA PrintNightmare"
237 + },
238 + {
239 + url: "https://technet.microsoft.com/en-us/library/dn487457.aspx",
240 + description: "Microsoft. (2016, April 15). Audit Policy Recommendations. Retrieved June 3, 2016.",
241 + source: "TechNet Audit Policy"
242 + },
243 + {
244 + url: "https://technet.microsoft.com/en-us/library/dn535501.aspx",
245 + description:
246 + "Microsoft. (2016, April 15). Attractive Accounts for Credential Theft. Retrieved June 3, 2016.",
247 + source: "TechNet Credential Theft"
248 + },
249 + {
250 + url: "https://www.volexity.com/blog/2022/06/15/driftingcloud-zero-day-sophos-firewall-exploitation-and-an-insidious-breach/",
251 + description:
252 + "Adair, S., Lancaster, T., Volexity Threat Research. (2022, June 15). DriftingCloud: Zero-Day Sophos Firewall Exploitation and an Insidious Breach. Retrieved July 1, 2022.",
253 + source: "volexity_0day_sophos_FW"
254 + }
255 + ],
256 + mitigations: [
257 + "course-of-action--25dc1ce8-eb55-4333-ae30-a7cb4f5894a1",
258 + "course-of-action--2a4f6c11-a4a7-4cb9-b0ef-6ae1bb3a718a",
259 + "course-of-action--90c218c3-fbf8-4830-98a7-e8cfb7eaa485",
260 + "course-of-action--93e7968a-9074-4eac-8ae9-9f5200ec3317",
261 + "course-of-action--9bb9e696-bff8-4ae1-9454-961fc7d91d5f",
262 + "course-of-action--e3388c78-2a8d-47c2-8422-c1398b324462",
263 + "course-of-action--f9f9e6ef-bc0a-41ad-ba11-0924e5e84c4c"
264 + ],
265 + subtechnique_of: null,
266 + techniques: null,
267 + groups: [
268 + "intrusion-set--06a11b7e-2a36-47fe-8d3e-82c265df3258",
269 + "intrusion-set--18854f55-ac7c-4634-bd9a-352dd07613b7",
270 + "intrusion-set--1c63d4ec-0a75-4daa-b1df-0d11af3d3cc1",
271 + "intrusion-set--222fbd21-fc4f-4b7e-9f85-0e6e3a76c33f",
272 + "intrusion-set--2a7914cf-dff3-428d-ab0f-1014d1c28aeb",
273 + "intrusion-set--3753cc21-2dae-4dfb-8481-d004e74502cc",
274 + "intrusion-set--381fcf73-60f6-4ab2-9991-6af3cbc35192",
275 + "intrusion-set--38fd6a28-3353-4f2b-bb2b-459fecd5c648",
276 + "intrusion-set--44e43fad-ffcb-4210-abcf-eaaed9735f80",
277 + "intrusion-set--4ca1929c-7d64-4aab-b849-badbfc0c760d",
278 + "intrusion-set--55033a4d-3ffe-46b2-99b4-2c1541e9ce1c",
279 + "intrusion-set--5cbe0d3b-6fb1-471f-b591-4b192915116d",
280 + "intrusion-set--5f3d0238-d058-44a9-8812-3dd1b6741a8c",
281 + "intrusion-set--6713ab67-e25b-49cc-808d-2b36d4fbc35c",
282 + "intrusion-set--7113eaa5-ba79-4fb3-b68a-398ee9cd698e",
283 + "intrusion-set--85403903-15e0-4f9f-9be4-a259ecad4022",
284 + "intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542",
285 + "intrusion-set--8c1f0187-0826-4320-bddc-5f326cfcfe2c",
286 + "intrusion-set--90784c1e-4aba-40eb-9adf-7556235e6384",
287 + "intrusion-set--9538b1a4-4120-4e2d-bf59-3b11fcab05a4",
288 + "intrusion-set--a0cb9370-e39b-44d5-9f50-ef78e412b973",
289 + "intrusion-set--bef4c620-0787-42a8-a96d-b7eb6e85917c",
290 + "intrusion-set--c21dd6f1-1364-4a70-a1f7-783080ec34ee",
291 + "intrusion-set--c93fccb1-e8e8-42cf-ae33-2ad1d183913a",
292 + "intrusion-set--d0b3393b-3bec-4ba3-bda9-199d30db47b6",
293 + "intrusion-set--d13c8a7f-740b-4efa-a232-de7d6bb05321",
294 + "intrusion-set--d8bc9788-4f7d-41a9-9e9d-ee1ea18a8cf7",
295 + "intrusion-set--dd2d9ca6-505b-4860-a604-233685b802c7",
296 + "intrusion-set--fb366179-766c-4a4a-afa1-52bff1fd601c",
297 + "intrusion-set--fbd29c89-18ba-4c2d-b792-51c0adee049f",
298 + "intrusion-set--fbe9387f-34e6-4828-ac28-3080020c597b",
299 + "intrusion-set--fd19bd82-1b14-49a1-a176-6cdc46b8a826",
300 + "intrusion-set--fe98767f-9df8-42b9-83c9-004b1dec8647"
301 + ],
302 + software: [
303 + "malware--0efefea5-78da-4022-92bc-d726139e8883",
304 + "malware--67e6d66b-1b82-4699-b47a-e2efb6268d14",
305 + "malware--68dca94f-c11d-421e-9287-7c501108e18c",
306 + "malware--d6e55656-e43f-411f-a7af-45df650471c5",
307 + "malware--e401d4fe-f0c9-44f0-98e6-f93487678808",
308 + "malware--f8774023-8021-4ece-9aca-383ac89d2759"
309 + ],
310 + mitre_detection:
311 + "Configure robust, consistent account activity audit policies across the enterprise and with externally accessible services.(Citation: TechNet Audit Policy) Look for suspicious account behavior across systems that share accounts, either user, admin, or service accounts. Examples: one account logged into multiple systems simultaneously; multiple accounts logged into the same machine simultaneously; accounts logged in at odd times or outside of business hours. Activity may be from interactive login sessions or process ownership from accounts being used to execute binaries on a remote system as a particular account. Correlate other security systems with login information (e.g., a user has an active login session but has not entered the building or does not have VPN access).\n\nPerform regular audits of domain and local system accounts to detect accounts that may have been created by an adversary for persistence. Checks on these accounts could also include whether default accounts such as Guest have been activated. These audits should also include checks on any appliances and applications for default credentials or SSH keys, and if any are discovered, they should be updated immediately.",
312 + mitre_version: "2.6",
313 + deprecated: 1,
314 + remote_support: 1,
315 + network_requirements: 1,
316 + platforms: ["macos", "linux"],
317 + data_sources: [],
318 + is_subtechnique: true
319 +}
320 +
321 +export const techniqueAlertsResponse = {
322 + success: true,
323 + message: "Found 16941 alerts for MITRE technique T1071 (page 1 of 678)",
324 + technique_id: "T1071",
325 + technique_name: "Unknown Technique",
326 + total_alerts: 16941,
327 + alerts: [
328 + {
329 + data_source_ip: "192.168.100.1",
330 + data_host_architecture: "x86_64",
331 + agent_id: "032",
332 + agent_name: "piHole",
333 + gl2_remote_ip: "10.255.255.13",
334 + data_resource: "configuration.apple.com.akadns.net",
335 + agent_labels_customer: "00001",
336 + data_ecs_version: "8.0.0",
337 + timestamp_utc: "2025-05-23T20:24:39.281Z",
338 + data_host_os_codename: "bullseye",
339 + syslog_type: "wazuh",
340 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
341 + id: "1748031882.83790627",
342 + data_server_port: "53",
343 + data_dns_question_etld_plus_one: "akadns.net",
344 + rule_mitre_tactic: "Command and Control",
345 + gl2_accounted_message_size: 6790,
346 + data_agent_type: "packetbeat",
347 + streams: ["660320f176ca320e8393f057"],
348 + rule_mitre_id: "T1071",
349 + data_destination_bytes: "161",
350 + data_event_dataset: "dns",
351 + "data_@metadata_beat": "packetbeat",
352 + agent_ip: "192.168.100.3",
353 + data_source_port: "56852",
354 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
355 + data_event_kind: "event",
356 + data_network_protocol: "dns",
357 + dns_response_code: "NOERROR",
358 + dns_query: "configuration.apple.com.akadns.net",
359 + data_dns_response_code: "NOERROR",
360 + data_network_community_id: "1:c3kBWjBq1Y4lt9NUsnCGWqbsdTo=",
361 + data_dns_flags_truncated_response: "false",
362 + rule_mail: false,
363 + data_dns_opt_udp_size: "1232",
364 + data_event_category: "network",
365 + data_dns_flags_recursion_available: "true",
366 + data_dns_opt_version: "0",
367 + timestamp: "2025-05-23 20:24:43.696",
368 + data_host_mac: "00-0C-29-09-D5-9B",
369 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
370 + data_destination_port: "53",
371 + data_dns_type: "answer",
372 + traffic_direction: "ingress",
373 + rule_id: "200300",
374 + data_dns_question_class: "IN",
375 + cluster_node: "ASHWZHMA.socfortress.local",
376 + dst_port: "53",
377 + "data_@timestamp": "2025-05-23T20:24:39.281Z",
378 + data_host_os_platform: "debian",
379 + data_event_duration: "83329433",
380 + data_host_name: "piHole",
381 + data_dns_flags_recursion_desired: "true",
382 + data_dns_question_subdomain: "configuration.apple.com",
383 + gl2_remote_port: 39934,
384 + data_host_os_type: "linux",
385 + source: "10.255.255.13",
386 + gl2_source_input: "660320f176ca320e8393f030",
387 + rule_level: 3,
388 + data_event_type: "connection, protocol",
389 + data_host_os_family: "debian",
390 + data_dns_additionals_count: "0",
391 + data_dns_flags_authentic_data: "false",
392 + protocol: "udp",
393 + data_dns_answers:
394 + "{data=configuration.apple.com.edgekey.net, name=configuration.apple.com.akadns.net, type=CNAME, class=IN, ttl=300}, {type=CNAME, class=IN, ttl=21600, data=e673.dsce9.akamaiedge.net, name=configuration.apple.com.edgekey.net}, {data=96.7.172.24, name=e673.dsce9.akamaiedge.net, type=A, class=IN, ttl=20}",
395 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
396 + data_event_start: "2025-05-23T20:24:39.281Z",
397 + rule_description: "Linux: DNS Query to configuration.apple.com.akadns.net",
398 + data_agent_version: "8.7.1",
399 + data_related_ip: "192.168.100.1, 192.168.100.3, 96.7.172.24",
400 + data_status: "OK",
401 + data_query: "class IN, type A, configuration.apple.com.akadns.net",
402 + "data_@metadata_type": "_doc",
403 + data_method: "QUERY",
404 + data_server_ip: "192.168.100.3",
405 + data_dns_question_registered_domain: "akadns.net",
406 + gl2_message_id: "01JVZD3JDGEMHZEJPMJTDHQP5N",
407 + data_dns_answers_count: "3",
408 + data_network_type: "ipv4",
409 + data_dns_opt_ext_rcode: "NOERROR",
410 + data_client_port: "56852",
411 + data_network_bytes: "224",
412 + data_dns_resolved_ip: "96.7.172.24",
413 + data_host_containerized: "false",
414 + true: 1748031882.283551,
415 + data_host_hostname: "piHole",
416 + rule_groups: "linux, packetbeat, dns",
417 + data_client_bytes: "63",
418 + data_dns_question_type: "A",
419 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
420 + data_destination_ip: "192.168.100.3",
421 + rule_mitre_technique: "Application Layer Protocol",
422 + rule_firedtimes: 295,
423 + data_network_transport: "udp",
424 + dst_ip: "192.168.100.3",
425 + src_ip: "192.168.100.1",
426 + decoder_name: "json",
427 + syslog_level: "INFO",
428 + data_dns_op_code: "QUERY",
429 + data_host_os_version: "11 (bullseye)",
430 + data_host_os_kernel: "5.10.0-21-amd64",
431 + cluster_name: "socfortress",
432 + data_source_bytes: "63",
433 + gl2_processing_error:
434 + 'Replaced invalid timestamp value in message <f5f58dd4-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:42.282+0000> caused exception: Invalid format: "2025-05-23T20:24:42.282+0000" is malformed at "T20:24:42.282+0000".',
435 + data_dns_opt_do: "true",
436 + data_dns_authorities_count: "0",
437 + data_dns_question_name: "configuration.apple.com.akadns.net",
438 + message:
439 + '{"true":1748031882.283551,"timestamp":"2025-05-23T20:24:42.282+0000","rule":{"level":3,"description":"Linux: DNS Query to configuration.apple.com.akadns.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":295,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031882.83790627","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:39.281Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"resource":"configuration.apple.com.akadns.net","method":"QUERY","server":{"ip":"192.168.100.3","port":"53","bytes":"161"},"ecs":{"version":"8.0.0"},"host":{"architecture":"x86_64","name":"piHole","os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole"},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"event":{"end":"2025-05-23T20:24:39.364Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"83329433","start":"2025-05-23T20:24:39.281Z"},"type":"dns","destination":{"ip":"192.168.100.3","port":"53","bytes":"161"},"dns":{"id":"29374","resolved_ip":["96.7.172.24"],"additionals_count":"0","type":"answer","opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"},"authorities_count":"0","answers_count":"3","op_code":"QUERY","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"response_code":"NOERROR","header_flags":["RD","RA","DO"],"question":{"subdomain":"configuration.apple.com","name":"configuration.apple.com.akadns.net","type":"A","class":"IN","etld_plus_one":"akadns.net","registered_domain":"akadns.net","top_level_domain":"net"},"answers":[{"data":"configuration.apple.com.edgekey.net","name":"configuration.apple.com.akadns.net","type":"CNAME","class":"IN","ttl":"300"},{"type":"CNAME","class":"IN","ttl":"21600","data":"e673.dsce9.akamaiedge.net","name":"configuration.apple.com.edgekey.net"},{"data":"96.7.172.24","name":"e673.dsce9.akamaiedge.net","type":"A","class":"IN","ttl":"20"}]},"query":"class IN, type A, configuration.apple.com.akadns.net","client":{"bytes":"63","ip":"192.168.100.1","port":"56852"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:c3kBWjBq1Y4lt9NUsnCGWqbsdTo=","bytes":"224"},"related":{"ip":["192.168.100.1","192.168.100.3","96.7.172.24"]},"source":{"port":"56852","bytes":"63","ip":"192.168.100.1"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
440 + dns_answer: "96.7.172.24",
441 + data_dns_id: "29374",
442 + src_port: "56852",
443 + manager_name: "ASHWZHMA",
444 + data_dns_question_top_level_domain: "net",
445 + data_network_direction: "ingress",
446 + data_event_end: "2025-05-23T20:24:39.364Z",
447 + data_agent_name: "piHole",
448 + data_server_bytes: "161",
449 + data_dns_flags_authoritative: "false",
450 + data_client_ip: "192.168.100.1",
451 + data_type: "dns",
452 + data_dns_header_flags: "RD, RA, DO",
453 + data_dns_flags_checking_disabled: "false",
454 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
455 + "data_@metadata_version": "8.7.1",
456 + data_host_os_name: "Debian GNU/Linux",
457 + rule_group3: "dns",
458 + msg_timestamp: "2025-05-23T20:24:42.282Z",
459 + rule_group2: "packetbeat",
460 + rule_group1: "linux"
461 + },
462 + {
463 + data_source_ip: "192.168.100.1",
464 + data_host_architecture: "x86_64",
465 + agent_id: "032",
466 + agent_name: "piHole",
467 + gl2_remote_ip: "10.255.255.13",
468 + data_resource: "e673.dsce9.akamaiedge.net",
469 + agent_labels_customer: "00001",
470 + data_ecs_version: "8.0.0",
471 + timestamp_utc: "2025-05-23T20:24:39.365Z",
472 + data_host_os_codename: "bullseye",
473 + syslog_type: "wazuh",
474 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
475 + id: "1748031882.83787816",
476 + data_server_port: "53",
477 + data_dns_question_etld_plus_one: "akamaiedge.net",
478 + rule_mitre_tactic: "Command and Control",
479 + gl2_accounted_message_size: 6217,
480 + data_agent_type: "packetbeat",
481 + streams: ["660320f176ca320e8393f057"],
482 + rule_mitre_id: "T1071",
483 + data_destination_bytes: "70",
484 + data_event_dataset: "dns",
485 + "data_@metadata_beat": "packetbeat",
486 + agent_ip: "192.168.100.3",
487 + data_source_port: "6412",
488 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
489 + data_event_kind: "event",
490 + data_network_protocol: "dns",
491 + dns_response_code: "NOERROR",
492 + dns_query: "e673.dsce9.akamaiedge.net",
493 + data_dns_response_code: "NOERROR",
494 + data_network_community_id: "1:HBo2k5NK+I6PNOc3BZguhbjy1lg=",
495 + data_dns_flags_truncated_response: "false",
496 + rule_mail: false,
497 + data_dns_opt_udp_size: "1232",
498 + data_event_category: "network",
499 + data_dns_flags_recursion_available: "true",
500 + data_dns_opt_version: "0",
501 + timestamp: "2025-05-23 20:24:43.055",
502 + data_host_mac: "00-0C-29-09-D5-9B",
503 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
504 + data_destination_port: "53",
505 + data_dns_type: "answer",
506 + traffic_direction: "ingress",
507 + rule_id: "200300",
508 + data_dns_question_class: "IN",
509 + cluster_node: "ASHWZHMA.socfortress.local",
510 + dst_port: "53",
511 + "data_@timestamp": "2025-05-23T20:24:39.365Z",
512 + data_event_duration: "14214021",
513 + data_host_os_platform: "debian",
514 + data_dns_flags_recursion_desired: "true",
515 + data_host_name: "piHole",
516 + data_dns_question_subdomain: "e673.dsce9",
517 + gl2_remote_port: 39934,
518 + data_host_os_type: "linux",
519 + source: "10.255.255.13",
520 + gl2_source_input: "660320f176ca320e8393f030",
521 + rule_level: 3,
522 + data_event_type: "connection, protocol",
523 + data_host_os_family: "debian",
524 + data_dns_additionals_count: "0",
525 + data_dns_flags_authentic_data: "false",
526 + protocol: "udp",
527 + data_dns_answers: "{ttl=14, data=23.203.24.27, name=e673.dsce9.akamaiedge.net, type=A, class=IN}",
528 + data_event_start: "2025-05-23T20:24:39.365Z",
529 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
530 + rule_description: "Linux: DNS Query to e673.dsce9.akamaiedge.net",
531 + data_related_ip: "192.168.100.1, 192.168.100.3, 23.203.24.27",
532 + data_agent_version: "8.7.1",
533 + data_status: "OK",
534 + data_query: "class IN, type A, e673.dsce9.akamaiedge.net",
535 + "data_@metadata_type": "_doc",
536 + data_server_ip: "192.168.100.3",
537 + data_method: "QUERY",
538 + data_dns_question_registered_domain: "akamaiedge.net",
539 + gl2_message_id: "01JVZD3HSFBX25DM8ZBYKKCCN9",
540 + data_dns_answers_count: "1",
541 + data_network_type: "ipv4",
542 + data_dns_opt_ext_rcode: "NOERROR",
543 + data_client_port: "6412",
544 + data_network_bytes: "124",
545 + data_dns_resolved_ip: "23.203.24.27",
546 + data_host_containerized: "false",
547 + true: 1748031882.283367,
548 + data_host_hostname: "piHole",
549 + rule_groups: "linux, packetbeat, dns",
550 + data_client_bytes: "54",
551 + data_dns_question_type: "A",
552 + data_destination_ip: "192.168.100.3",
553 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
554 + rule_mitre_technique: "Application Layer Protocol",
555 + rule_firedtimes: 294,
556 + data_network_transport: "udp",
557 + dst_ip: "192.168.100.3",
558 + src_ip: "192.168.100.1",
559 + decoder_name: "json",
560 + syslog_level: "INFO",
561 + data_dns_op_code: "QUERY",
562 + data_host_os_version: "11 (bullseye)",
563 + data_host_os_kernel: "5.10.0-21-amd64",
564 + cluster_name: "socfortress",
565 + data_source_bytes: "54",
566 + gl2_processing_error:
567 + 'Replaced invalid timestamp value in message <f5f58dd3-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:42.282+0000> caused exception: Invalid format: "2025-05-23T20:24:42.282+0000" is malformed at "T20:24:42.282+0000".',
568 + data_dns_opt_do: "true",
569 + data_dns_authorities_count: "0",
570 + data_dns_question_name: "e673.dsce9.akamaiedge.net",
571 + message:
572 + '{"true":1748031882.283367,"timestamp":"2025-05-23T20:24:42.282+0000","rule":{"level":3,"description":"Linux: DNS Query to e673.dsce9.akamaiedge.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":294,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031882.83787816","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:39.365Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"destination":{"port":"53","bytes":"70","ip":"192.168.100.3"},"server":{"bytes":"70","ip":"192.168.100.3","port":"53"},"event":{"end":"2025-05-23T20:24:39.379Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"14214021","start":"2025-05-23T20:24:39.365Z"},"source":{"ip":"192.168.100.1","port":"6412","bytes":"54"},"query":"class IN, type A, e673.dsce9.akamaiedge.net","method":"QUERY","resource":"e673.dsce9.akamaiedge.net","type":"dns","dns":{"authorities_count":"0","id":"36717","response_code":"NOERROR","flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"type":"answer","op_code":"QUERY","answers_count":"1","answers":[{"ttl":"14","data":"23.203.24.27","name":"e673.dsce9.akamaiedge.net","type":"A","class":"IN"}],"additionals_count":"0","header_flags":["RD","RA","DO"],"question":{"etld_plus_one":"akamaiedge.net","registered_domain":"akamaiedge.net","top_level_domain":"net","subdomain":"e673.dsce9","name":"e673.dsce9.akamaiedge.net","type":"A","class":"IN"},"resolved_ip":["23.203.24.27"]},"client":{"ip":"192.168.100.1","port":"6412","bytes":"54"},"network":{"bytes":"124","type":"ipv4","transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:HBo2k5NK+I6PNOc3BZguhbjy1lg="},"related":{"ip":["192.168.100.1","192.168.100.3","23.203.24.27"]},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"ecs":{"version":"8.0.0"},"host":{"containerized":"false","name":"piHole","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
573 + dns_answer: "23.203.24.27",
574 + data_dns_id: "36717",
575 + src_port: "6412",
576 + manager_name: "ASHWZHMA",
577 + data_dns_question_top_level_domain: "net",
578 + data_network_direction: "ingress",
579 + data_event_end: "2025-05-23T20:24:39.379Z",
580 + data_agent_name: "piHole",
581 + data_server_bytes: "70",
582 + data_dns_flags_authoritative: "false",
583 + data_client_ip: "192.168.100.1",
584 + data_type: "dns",
585 + data_dns_header_flags: "RD, RA, DO",
586 + data_dns_flags_checking_disabled: "false",
587 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
588 + "data_@metadata_version": "8.7.1",
589 + data_host_os_name: "Debian GNU/Linux",
590 + rule_group3: "dns",
591 + msg_timestamp: "2025-05-23T20:24:42.282Z",
592 + rule_group2: "packetbeat",
593 + rule_group1: "linux"
594 + },
595 + {
596 + data_source_ip: "192.168.100.3",
597 + data_host_architecture: "x86_64",
598 + agent_id: "032",
599 + agent_name: "piHole",
600 + gl2_remote_ip: "10.255.255.13",
601 + data_resource: "e673.dsce9.akamaiedge.net",
602 + agent_labels_customer: "00001",
603 + data_ecs_version: "8.0.0",
604 + timestamp_utc: "2025-05-23T20:24:39.365Z",
605 + data_host_os_codename: "bullseye",
606 + syslog_type: "wazuh",
607 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
608 + id: "1748031882.83793735",
609 + data_server_port: "53",
610 + data_dns_question_etld_plus_one: "akamaiedge.net",
611 + rule_mitre_tactic: "Command and Control",
612 + gl2_accounted_message_size: 6177,
613 + data_agent_type: "packetbeat",
614 + streams: ["660320f176ca320e8393f057"],
615 + rule_mitre_id: "T1071",
616 + data_destination_bytes: "70",
617 + data_event_dataset: "dns",
618 + "data_@metadata_beat": "packetbeat",
619 + agent_ip: "192.168.100.3",
620 + data_source_port: "40999",
621 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
622 + data_event_kind: "event",
623 + data_network_protocol: "dns",
624 + dns_response_code: "NOERROR",
625 + dns_query: "e673.dsce9.akamaiedge.net",
626 + data_dns_response_code: "NOERROR",
627 + data_network_community_id: "1:MV4kAmot/Pl2lVf7gcKfTi6Js+Q=",
628 + data_dns_flags_truncated_response: "false",
629 + rule_mail: false,
630 + data_dns_opt_udp_size: "1232",
631 + data_event_category: "network",
632 + data_dns_flags_recursion_available: "true",
633 + data_dns_opt_version: "0",
634 + timestamp: "2025-05-23 20:24:43.055",
635 + data_host_mac: "00-0C-29-09-D5-9B",
636 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
637 + data_destination_port: "53",
638 + data_dns_type: "answer",
639 + traffic_direction: "egress",
640 + rule_id: "200300",
641 + data_dns_question_class: "IN",
642 + cluster_node: "ASHWZHMA.socfortress.local",
643 + dst_port: "53",
644 + "data_@timestamp": "2025-05-23T20:24:39.365Z",
645 + data_host_os_platform: "debian",
646 + data_event_duration: "14121063",
647 + data_dns_flags_recursion_desired: "true",
648 + data_host_name: "piHole",
649 + data_dns_question_subdomain: "e673.dsce9",
650 + gl2_remote_port: 39934,
651 + data_host_os_type: "linux",
652 + source: "10.255.255.13",
653 + gl2_source_input: "660320f176ca320e8393f030",
654 + rule_level: 3,
655 + data_event_type: "connection, protocol",
656 + data_host_os_family: "debian",
657 + data_dns_additionals_count: "0",
658 + data_dns_flags_authentic_data: "false",
659 + protocol: "udp",
660 + data_dns_answers: "{data=23.203.24.27, name=e673.dsce9.akamaiedge.net, type=A, class=IN, ttl=14}",
661 + data_event_start: "2025-05-23T20:24:39.365Z",
662 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
663 + rule_description: "Linux: DNS Query to e673.dsce9.akamaiedge.net",
664 + data_related_ip: "192.168.100.3, 1.1.1.3, 23.203.24.27",
665 + data_agent_version: "8.7.1",
666 + data_status: "OK",
667 + data_query: "class IN, type A, e673.dsce9.akamaiedge.net",
668 + "data_@metadata_type": "_doc",
669 + data_server_ip: "1.1.1.3",
670 + data_dns_question_registered_domain: "akamaiedge.net",
671 + data_method: "QUERY",
672 + gl2_message_id: "01JVZD3HSFFBP2GCAREGTN6HMK",
673 + data_dns_answers_count: "1",
674 + data_network_type: "ipv4",
675 + data_dns_opt_ext_rcode: "NOERROR",
676 + data_client_port: "40999",
677 + data_network_bytes: "124",
678 + data_dns_resolved_ip: "23.203.24.27",
679 + data_host_containerized: "false",
680 + true: 1748031882.955625,
681 + data_host_hostname: "piHole",
682 + rule_groups: "linux, packetbeat, dns",
683 + data_client_bytes: "54",
684 + data_dns_question_type: "A",
685 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
686 + data_destination_ip: "1.1.1.3",
687 + rule_mitre_technique: "Application Layer Protocol",
688 + rule_firedtimes: 296,
689 + data_network_transport: "udp",
690 + dst_ip: "1.1.1.3",
691 + src_ip: "192.168.100.3",
692 + decoder_name: "json",
693 + syslog_level: "INFO",
694 + data_dns_op_code: "QUERY",
695 + data_host_os_version: "11 (bullseye)",
696 + data_host_os_kernel: "5.10.0-21-amd64",
697 + cluster_name: "socfortress",
698 + data_source_bytes: "54",
699 + gl2_processing_error:
700 + 'Replaced invalid timestamp value in message <f5f58dd5-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:42.282+0000> caused exception: Invalid format: "2025-05-23T20:24:42.282+0000" is malformed at "T20:24:42.282+0000".',
701 + data_dns_opt_do: "true",
702 + data_dns_authorities_count: "0",
703 + data_dns_question_name: "e673.dsce9.akamaiedge.net",
704 + message:
705 + '{"true":1748031882.955625,"timestamp":"2025-05-23T20:24:42.282+0000","rule":{"level":3,"description":"Linux: DNS Query to e673.dsce9.akamaiedge.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":296,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031882.83793735","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:39.365Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"ecs":{"version":"8.0.0"},"client":{"bytes":"54","ip":"192.168.100.3","port":"40999"},"server":{"ip":"1.1.1.3","port":"53","bytes":"70"},"dns":{"resolved_ip":["23.203.24.27"],"op_code":"QUERY","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"answers":[{"data":"23.203.24.27","name":"e673.dsce9.akamaiedge.net","type":"A","class":"IN","ttl":"14"}],"authorities_count":"0","type":"answer","response_code":"NOERROR","header_flags":["RD","RA","DO"],"question":{"subdomain":"e673.dsce9","name":"e673.dsce9.akamaiedge.net","type":"A","class":"IN","etld_plus_one":"akamaiedge.net","registered_domain":"akamaiedge.net","top_level_domain":"net"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"id":"35268","answers_count":"1","additionals_count":"0"},"resource":"e673.dsce9.akamaiedge.net","host":{"architecture":"x86_64","os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","name":"piHole","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole"},"event":{"start":"2025-05-23T20:24:39.365Z","end":"2025-05-23T20:24:39.379Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"14121063"},"destination":{"ip":"1.1.1.3","port":"53","bytes":"70"},"query":"class IN, type A, e673.dsce9.akamaiedge.net","source":{"ip":"192.168.100.3","port":"40999","bytes":"54"},"related":{"ip":["192.168.100.3","1.1.1.3","23.203.24.27"]},"agent":{"id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3"},"method":"QUERY","type":"dns","network":{"protocol":"dns","direction":"egress","community_id":"1:MV4kAmot/Pl2lVf7gcKfTi6Js+Q=","bytes":"124","type":"ipv4","transport":"udp"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
706 + dns_answer: "23.203.24.27",
707 + data_dns_id: "35268",
708 + src_port: "40999",
709 + manager_name: "ASHWZHMA",
710 + data_dns_question_top_level_domain: "net",
711 + data_network_direction: "egress",
712 + data_event_end: "2025-05-23T20:24:39.379Z",
713 + data_agent_name: "piHole",
714 + data_client_ip: "192.168.100.3",
715 + data_server_bytes: "70",
716 + data_dns_flags_authoritative: "false",
717 + data_dns_header_flags: "RD, RA, DO",
718 + data_type: "dns",
719 + data_dns_flags_checking_disabled: "false",
720 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
721 + "data_@metadata_version": "8.7.1",
722 + data_host_os_name: "Debian GNU/Linux",
723 + rule_group3: "dns",
724 + msg_timestamp: "2025-05-23T20:24:42.282Z",
725 + rule_group2: "packetbeat",
726 + rule_group1: "linux"
727 + },
728 + {
729 + data_source_ip: "192.168.100.1",
730 + data_host_architecture: "x86_64",
731 + agent_id: "032",
732 + agent_name: "piHole",
733 + gl2_remote_ip: "10.255.255.13",
734 + data_resource: "api.coinbase.com",
735 + agent_labels_customer: "00001",
736 + data_ecs_version: "8.0.0",
737 + timestamp_utc: "2025-05-23T20:24:33.880Z",
738 + data_host_os_codename: "bullseye",
739 + syslog_type: "wazuh",
740 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
741 + id: "1748031876.83781905",
742 + data_dns_question_etld_plus_one: "coinbase.com",
743 + data_server_port: "53",
744 + rule_mitre_tactic: "Command and Control",
745 + gl2_accounted_message_size: 6537,
746 + data_agent_type: "packetbeat",
747 + streams: ["660320f176ca320e8393f057"],
748 + rule_mitre_id: "T1071",
749 + data_destination_bytes: "101",
750 + data_event_dataset: "dns",
751 + "data_@metadata_beat": "packetbeat",
752 + agent_ip: "192.168.100.3",
753 + data_source_port: "8819",
754 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
755 + data_event_kind: "event",
756 + data_network_protocol: "dns",
757 + dns_response_code: "NOERROR",
758 + dns_query: "api.coinbase.com",
759 + data_dns_response_code: "NOERROR",
760 + data_network_community_id: "1:3pXnmtDLbo/xBY/ZfO1IbbPnnt0=",
761 + data_dns_flags_truncated_response: "false",
762 + rule_mail: false,
763 + data_dns_opt_udp_size: "1232",
764 + data_event_category: "network",
765 + data_dns_flags_recursion_available: "true",
766 + data_dns_opt_version: "0",
767 + timestamp: "2025-05-23 20:24:38.056",
768 + data_host_mac: "00-0C-29-09-D5-9B",
769 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
770 + data_destination_port: "53",
771 + data_dns_type: "answer",
772 + traffic_direction: "ingress",
773 + rule_id: "200300",
774 + data_dns_question_class: "IN",
775 + cluster_node: "ASHWZHMA.socfortress.local",
776 + dst_port: "53",
777 + "data_@timestamp": "2025-05-23T20:24:33.880Z",
778 + data_event_duration: "17771034",
779 + data_host_os_platform: "debian",
780 + data_dns_flags_recursion_desired: "true",
781 + data_host_name: "piHole",
782 + data_dns_question_subdomain: "api",
783 + gl2_remote_port: 39928,
784 + data_host_os_type: "linux",
785 + source: "10.255.255.13",
786 + gl2_source_input: "660320f176ca320e8393f030",
787 + rule_level: 3,
788 + data_event_type: "connection, protocol",
789 + data_host_os_family: "debian",
790 + data_dns_additionals_count: "0",
791 + data_dns_flags_authentic_data: "false",
792 + protocol: "udp",
793 + data_dns_answers:
794 + "{data=2606:4700:4400::6812:230f, name=api.coinbase.com, type=AAAA, class=IN, ttl=300}, {data=2606:4700:4400::ac40:98f1, name=api.coinbase.com, type=AAAA, class=IN, ttl=300}",
795 + data_event_start: "2025-05-23T20:24:33.880Z",
796 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
797 + rule_description: "Linux: DNS Query to api.coinbase.com",
798 + data_agent_version: "8.7.1",
799 + data_related_ip: "192.168.100.1, 192.168.100.3, 2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
800 + data_status: "OK",
801 + data_query: "class IN, type AAAA, api.coinbase.com",
802 + "data_@metadata_type": "_doc",
803 + data_dns_question_registered_domain: "coinbase.com",
804 + data_method: "QUERY",
805 + data_server_ip: "192.168.100.3",
806 + gl2_message_id: "01JVZD3CX8PMYGGT699MWPN15D",
807 + data_dns_answers_count: "2",
808 + data_network_type: "ipv4",
809 + data_dns_opt_ext_rcode: "NOERROR",
810 + data_client_port: "8819",
811 + data_network_bytes: "146",
812 + data_dns_resolved_ip: "2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
813 + data_host_containerized: "false",
814 + true: 1748031876.269145,
815 + data_host_hostname: "piHole",
816 + rule_groups: "linux, packetbeat, dns",
817 + data_client_bytes: "45",
818 + data_dns_question_type: "AAAA",
819 + data_destination_ip: "192.168.100.3",
820 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
821 + rule_mitre_technique: "Application Layer Protocol",
822 + rule_firedtimes: 292,
823 + data_network_transport: "udp",
824 + dst_ip: "192.168.100.3",
825 + src_ip: "192.168.100.1",
826 + decoder_name: "json",
827 + syslog_level: "INFO",
828 + data_dns_op_code: "QUERY",
829 + data_host_os_version: "11 (bullseye)",
830 + data_host_os_kernel: "5.10.0-21-amd64",
831 + cluster_name: "socfortress",
832 + data_source_bytes: "45",
833 + gl2_processing_error:
834 + 'Replaced invalid timestamp value in message <f2fac463-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:36.268+0000> caused exception: Invalid format: "2025-05-23T20:24:36.268+0000" is malformed at "T20:24:36.268+0000".',
835 + data_dns_opt_do: "true",
836 + data_dns_authorities_count: "0",
837 + data_dns_question_name: "api.coinbase.com",
838 + message:
839 + '{"true":1748031876.269145,"timestamp":"2025-05-23T20:24:36.268+0000","rule":{"level":3,"description":"Linux: DNS Query to api.coinbase.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":292,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031876.83781905","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:33.880Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"resource":"api.coinbase.com","dns":{"authorities_count":"0","additionals_count":"0","type":"answer","op_code":"QUERY","id":"42058","response_code":"NOERROR","answers_count":"2","resolved_ip":["2606:4700:4400::6812:230f","2606:4700:4400::ac40:98f1"],"flags":{"truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false"},"header_flags":["RD","RA","DO"],"question":{"class":"IN","etld_plus_one":"coinbase.com","registered_domain":"coinbase.com","top_level_domain":"com","subdomain":"api","name":"api.coinbase.com","type":"AAAA"},"opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"answers":[{"data":"2606:4700:4400::6812:230f","name":"api.coinbase.com","type":"AAAA","class":"IN","ttl":"300"},{"data":"2606:4700:4400::ac40:98f1","name":"api.coinbase.com","type":"AAAA","class":"IN","ttl":"300"}]},"method":"QUERY","type":"dns","event":{"category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"17771034","start":"2025-05-23T20:24:33.880Z","end":"2025-05-23T20:24:33.898Z","kind":"event"},"ecs":{"version":"8.0.0"},"destination":{"port":"53","bytes":"101","ip":"192.168.100.3"},"host":{"containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"name":"piHole","mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50"},"source":{"ip":"192.168.100.1","port":"8819","bytes":"45"},"server":{"ip":"192.168.100.3","port":"53","bytes":"101"},"agent":{"type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:3pXnmtDLbo/xBY/ZfO1IbbPnnt0=","bytes":"146"},"client":{"ip":"192.168.100.1","port":"8819","bytes":"45"},"related":{"ip":["192.168.100.1","192.168.100.3","2606:4700:4400::6812:230f","2606:4700:4400::ac40:98f1"]},"query":"class IN, type AAAA, api.coinbase.com"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
840 + dns_answer: "2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
841 + data_dns_id: "42058",
842 + src_port: "8819",
843 + manager_name: "ASHWZHMA",
844 + data_dns_question_top_level_domain: "com",
845 + data_network_direction: "ingress",
846 + data_event_end: "2025-05-23T20:24:33.898Z",
847 + data_agent_name: "piHole",
848 + data_dns_flags_authoritative: "false",
849 + data_server_bytes: "101",
850 + data_client_ip: "192.168.100.1",
851 + data_dns_header_flags: "RD, RA, DO",
852 + data_type: "dns",
853 + data_dns_flags_checking_disabled: "false",
854 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
855 + "data_@metadata_version": "8.7.1",
856 + data_host_os_name: "Debian GNU/Linux",
857 + rule_group3: "dns",
858 + msg_timestamp: "2025-05-23T20:24:36.268Z",
859 + rule_group2: "packetbeat",
860 + rule_group1: "linux"
861 + },
862 + {
863 + data_source_ip: "192.168.100.3",
864 + data_host_architecture: "x86_64",
865 + agent_id: "032",
866 + agent_name: "piHole",
867 + gl2_remote_ip: "10.255.255.13",
868 + data_resource: "github.com",
869 + agent_labels_customer: "00001",
870 + data_ecs_version: "8.0.0",
871 + timestamp_utc: "2025-05-23T20:24:31.373Z",
872 + data_host_os_codename: "bullseye",
873 + syslog_type: "wazuh",
874 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
875 + id: "1748031874.83775437",
876 + data_server_port: "53",
877 + data_dns_question_etld_plus_one: "github.com",
878 + rule_mitre_tactic: "Command and Control",
879 + gl2_accounted_message_size: 5932,
880 + data_agent_type: "packetbeat",
881 + streams: ["660320f176ca320e8393f057"],
882 + rule_mitre_id: "T1071",
883 + data_destination_bytes: "55",
884 + data_event_dataset: "dns",
885 + "data_@metadata_beat": "packetbeat",
886 + agent_ip: "192.168.100.3",
887 + data_source_port: "56650",
888 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
889 + data_event_kind: "event",
890 + data_network_protocol: "dns",
891 + dns_response_code: "NOERROR",
892 + dns_query: "github.com",
893 + data_dns_response_code: "NOERROR",
894 + data_network_community_id: "1:njv02kf9+WW6JlYlcSaxjqsSfqI=",
895 + data_dns_flags_truncated_response: "false",
896 + rule_mail: false,
897 + data_dns_opt_udp_size: "1232",
898 + data_event_category: "network",
899 + data_dns_flags_recursion_available: "true",
900 + data_dns_opt_version: "0",
901 + timestamp: "2025-05-23 20:24:38.056",
902 + data_host_mac: "00-0C-29-09-D5-9B",
903 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
904 + data_destination_port: "53",
905 + data_dns_type: "answer",
906 + traffic_direction: "egress",
907 + rule_id: "200300",
908 + data_dns_question_class: "IN",
909 + cluster_node: "ASHWZHMA.socfortress.local",
910 + dst_port: "53",
911 + "data_@timestamp": "2025-05-23T20:24:31.373Z",
912 + data_event_duration: "15729989",
913 + data_host_os_platform: "debian",
914 + data_dns_flags_recursion_desired: "true",
915 + data_host_name: "piHole",
916 + gl2_remote_port: 39928,
917 + data_host_os_type: "linux",
918 + source: "10.255.255.13",
919 + gl2_source_input: "660320f176ca320e8393f030",
920 + rule_level: 3,
921 + data_event_type: "connection, protocol",
922 + data_host_os_family: "debian",
923 + data_dns_additionals_count: "0",
924 + data_dns_flags_authentic_data: "false",
925 + protocol: "udp",
926 + data_dns_answers: "{name=github.com, type=A, class=IN, ttl=54, data=140.82.114.4}",
927 + data_event_start: "2025-05-23T20:24:31.373Z",
928 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
929 + rule_description: "Linux: DNS Query to github.com",
930 + data_related_ip: "192.168.100.3, 1.1.1.3, 140.82.114.4",
931 + data_agent_version: "8.7.1",
932 + data_status: "OK",
933 + data_query: "class IN, type A, github.com",
934 + "data_@metadata_type": "_doc",
935 + data_server_ip: "1.1.1.3",
936 + data_method: "QUERY",
937 + data_dns_question_registered_domain: "github.com",
938 + gl2_message_id: "01JVZD3CX8TTGERKKB0MZHWP29",
939 + data_dns_answers_count: "1",
940 + data_network_type: "ipv4",
941 + data_dns_opt_ext_rcode: "NOERROR",
942 + data_client_port: "56650",
943 + data_network_bytes: "94",
944 + data_dns_resolved_ip: "140.82.114.4",
945 + data_host_containerized: "false",
946 + true: 1748031874.268436,
947 + data_host_hostname: "piHole",
948 + rule_groups: "linux, packetbeat, dns",
949 + data_client_bytes: "39",
950 + data_dns_question_type: "A",
951 + data_destination_ip: "1.1.1.3",
952 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
953 + rule_mitre_technique: "Application Layer Protocol",
954 + rule_firedtimes: 290,
955 + data_network_transport: "udp",
956 + dst_ip: "1.1.1.3",
957 + src_ip: "192.168.100.3",
958 + decoder_name: "json",
959 + syslog_level: "INFO",
960 + data_dns_op_code: "QUERY",
961 + data_host_os_version: "11 (bullseye)",
962 + data_host_os_kernel: "5.10.0-21-amd64",
963 + cluster_name: "socfortress",
964 + data_source_bytes: "39",
965 + gl2_processing_error:
966 + 'Replaced invalid timestamp value in message <f2fac460-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:34.266+0000> caused exception: Invalid format: "2025-05-23T20:24:34.266+0000" is malformed at "T20:24:34.266+0000".',
967 + data_dns_opt_do: "true",
968 + data_dns_authorities_count: "0",
969 + data_dns_question_name: "github.com",
970 + message:
971 + '{"true":1748031874.268436,"timestamp":"2025-05-23T20:24:34.266+0000","rule":{"level":3,"description":"Linux: DNS Query to github.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":290,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031874.83775437","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:31.373Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"event":{"type":["connection","protocol"],"dataset":"dns","duration":"15729989","start":"2025-05-23T20:24:31.373Z","end":"2025-05-23T20:24:31.389Z","kind":"event","category":["network"]},"resource":"github.com","client":{"ip":"192.168.100.3","port":"56650","bytes":"39"},"related":{"ip":["192.168.100.3","1.1.1.3","140.82.114.4"]},"query":"class IN, type A, github.com","ecs":{"version":"8.0.0"},"server":{"ip":"1.1.1.3","port":"53","bytes":"55"},"type":"dns","destination":{"ip":"1.1.1.3","port":"53","bytes":"55"},"method":"QUERY","dns":{"type":"answer","id":"10393","resolved_ip":["140.82.114.4"],"authorities_count":"0","header_flags":["RD","RA","DO"],"question":{"registered_domain":"github.com","top_level_domain":"com","name":"github.com","type":"A","class":"IN","etld_plus_one":"github.com"},"answers_count":"1","answers":[{"name":"github.com","type":"A","class":"IN","ttl":"54","data":"140.82.114.4"}],"additionals_count":"0","op_code":"QUERY","flags":{"authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"},"response_code":"NOERROR","opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"}},"host":{"name":"piHole","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye"},"id":"8986bcccef884a1ebe34f1ccd31b4f50"},"network":{"community_id":"1:njv02kf9+WW6JlYlcSaxjqsSfqI=","bytes":"94","type":"ipv4","transport":"udp","protocol":"dns","direction":"egress"},"source":{"ip":"192.168.100.3","port":"56650","bytes":"39"},"agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
972 + dns_answer: "140.82.114.4",
973 + data_dns_id: "10393",
974 + src_port: "56650",
975 + manager_name: "ASHWZHMA",
976 + data_dns_question_top_level_domain: "com",
977 + data_network_direction: "egress",
978 + data_event_end: "2025-05-23T20:24:31.389Z",
979 + data_agent_name: "piHole",
980 + data_client_ip: "192.168.100.3",
981 + data_server_bytes: "55",
982 + data_dns_flags_authoritative: "false",
983 + data_type: "dns",
984 + data_dns_header_flags: "RD, RA, DO",
985 + data_dns_flags_checking_disabled: "false",
986 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
987 + "data_@metadata_version": "8.7.1",
988 + data_host_os_name: "Debian GNU/Linux",
989 + rule_group3: "dns",
990 + msg_timestamp: "2025-05-23T20:24:34.266Z",
991 + rule_group2: "packetbeat",
992 + rule_group1: "linux"
993 + },
994 + {
995 + data_source_ip: "192.168.100.3",
996 + data_host_architecture: "x86_64",
997 + agent_id: "032",
998 + agent_name: "piHole",
999 + gl2_remote_ip: "10.255.255.13",
1000 + data_resource: "api.coinbase.com",
1001 + agent_labels_customer: "00001",
1002 + data_ecs_version: "8.0.0",
1003 + timestamp_utc: "2025-05-23T20:24:33.880Z",
1004 + data_host_os_codename: "bullseye",
1005 + syslog_type: "wazuh",
1006 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1007 + id: "1748031876.83784869",
1008 + data_server_port: "53",
1009 + data_dns_question_etld_plus_one: "coinbase.com",
1010 + rule_mitre_tactic: "Command and Control",
1011 + gl2_accounted_message_size: 6497,
1012 + data_agent_type: "packetbeat",
1013 + streams: ["660320f176ca320e8393f057"],
1014 + rule_mitre_id: "T1071",
1015 + data_destination_bytes: "101",
1016 + data_event_dataset: "dns",
1017 + "data_@metadata_beat": "packetbeat",
1018 + agent_ip: "192.168.100.3",
1019 + data_source_port: "52260",
1020 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1021 + data_event_kind: "event",
1022 + data_network_protocol: "dns",
1023 + dns_response_code: "NOERROR",
1024 + dns_query: "api.coinbase.com",
1025 + data_dns_response_code: "NOERROR",
1026 + data_network_community_id: "1:cHbmaBX78sZuvoLLR5j5BGNbP8s=",
1027 + data_dns_flags_truncated_response: "false",
1028 + rule_mail: false,
1029 + data_dns_opt_udp_size: "1232",
1030 + data_event_category: "network",
1031 + data_dns_flags_recursion_available: "true",
1032 + data_dns_opt_version: "0",
1033 + timestamp: "2025-05-23 20:24:38.056",
1034 + data_host_mac: "00-0C-29-09-D5-9B",
1035 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1036 + data_destination_port: "53",
1037 + data_dns_type: "answer",
1038 + traffic_direction: "egress",
1039 + rule_id: "200300",
1040 + data_dns_question_class: "IN",
1041 + cluster_node: "ASHWZHMA.socfortress.local",
1042 + dst_port: "53",
1043 + "data_@timestamp": "2025-05-23T20:24:33.880Z",
1044 + data_event_duration: "17582186",
1045 + data_host_os_platform: "debian",
1046 + data_dns_flags_recursion_desired: "true",
1047 + data_host_name: "piHole",
1048 + data_dns_question_subdomain: "api",
1049 + gl2_remote_port: 39928,
1050 + data_host_os_type: "linux",
1051 + source: "10.255.255.13",
1052 + gl2_source_input: "660320f176ca320e8393f030",
1053 + rule_level: 3,
1054 + data_event_type: "connection, protocol",
1055 + data_host_os_family: "debian",
1056 + data_dns_additionals_count: "0",
1057 + data_dns_flags_authentic_data: "false",
1058 + protocol: "udp",
1059 + data_dns_answers:
1060 + "{type=AAAA, class=IN, ttl=300, data=2606:4700:4400::6812:230f, name=api.coinbase.com}, {ttl=300, data=2606:4700:4400::ac40:98f1, name=api.coinbase.com, type=AAAA, class=IN}",
1061 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1062 + data_event_start: "2025-05-23T20:24:33.880Z",
1063 + rule_description: "Linux: DNS Query to api.coinbase.com",
1064 + data_agent_version: "8.7.1",
1065 + data_related_ip: "192.168.100.3, 1.1.1.3, 2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
1066 + data_status: "OK",
1067 + data_query: "class IN, type AAAA, api.coinbase.com",
1068 + "data_@metadata_type": "_doc",
1069 + data_server_ip: "1.1.1.3",
1070 + data_method: "QUERY",
1071 + data_dns_question_registered_domain: "coinbase.com",
1072 + gl2_message_id: "01JVZD3CX862P7A9S72EMX9GTA",
1073 + data_dns_answers_count: "2",
1074 + data_network_type: "ipv4",
1075 + data_dns_opt_ext_rcode: "NOERROR",
1076 + data_client_port: "52260",
1077 + data_network_bytes: "146",
1078 + data_dns_resolved_ip: "2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
1079 + data_host_containerized: "false",
1080 + true: 1748031876.954916,
1081 + data_host_hostname: "piHole",
1082 + rule_groups: "linux, packetbeat, dns",
1083 + data_client_bytes: "45",
1084 + data_dns_question_type: "AAAA",
1085 + data_destination_ip: "1.1.1.3",
1086 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1087 + rule_mitre_technique: "Application Layer Protocol",
1088 + rule_firedtimes: 293,
1089 + data_network_transport: "udp",
1090 + dst_ip: "1.1.1.3",
1091 + src_ip: "192.168.100.3",
1092 + decoder_name: "json",
1093 + syslog_level: "INFO",
1094 + data_dns_op_code: "QUERY",
1095 + data_host_os_version: "11 (bullseye)",
1096 + data_host_os_kernel: "5.10.0-21-amd64",
1097 + cluster_name: "socfortress",
1098 + data_source_bytes: "45",
1099 + gl2_processing_error:
1100 + 'Replaced invalid timestamp value in message <f2fac464-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:36.268+0000> caused exception: Invalid format: "2025-05-23T20:24:36.268+0000" is malformed at "T20:24:36.268+0000".',
1101 + data_dns_opt_do: "true",
1102 + data_dns_authorities_count: "0",
1103 + data_dns_question_name: "api.coinbase.com",
1104 + message:
1105 + '{"true":1748031876.954916,"timestamp":"2025-05-23T20:24:36.268+0000","rule":{"level":3,"description":"Linux: DNS Query to api.coinbase.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":293,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031876.83784869","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:33.880Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"ip":"192.168.100.3","port":"52260","bytes":"45"},"server":{"ip":"1.1.1.3","port":"53","bytes":"101"},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"source":{"ip":"192.168.100.3","port":"52260","bytes":"45"},"method":"QUERY","type":"dns","related":{"ip":["192.168.100.3","1.1.1.3","2606:4700:4400::6812:230f","2606:4700:4400::ac40:98f1"]},"destination":{"ip":"1.1.1.3","port":"53","bytes":"101"},"resource":"api.coinbase.com","dns":{"authorities_count":"0","op_code":"QUERY","opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"},"additionals_count":"0","header_flags":["RD","RA","DO"],"resolved_ip":["2606:4700:4400::6812:230f","2606:4700:4400::ac40:98f1"],"flags":{"truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false"},"response_code":"NOERROR","question":{"name":"api.coinbase.com","type":"AAAA","class":"IN","etld_plus_one":"coinbase.com","registered_domain":"coinbase.com","top_level_domain":"com","subdomain":"api"},"answers":[{"type":"AAAA","class":"IN","ttl":"300","data":"2606:4700:4400::6812:230f","name":"api.coinbase.com"},{"ttl":"300","data":"2606:4700:4400::ac40:98f1","name":"api.coinbase.com","type":"AAAA","class":"IN"}],"type":"answer","id":"57215","answers_count":"2"},"ecs":{"version":"8.0.0"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:cHbmaBX78sZuvoLLR5j5BGNbP8s=","bytes":"146"},"query":"class IN, type AAAA, api.coinbase.com","event":{"end":"2025-05-23T20:24:33.897Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"17582186","start":"2025-05-23T20:24:33.880Z"},"host":{"hostname":"piHole","architecture":"x86_64","os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1106 + dns_answer: "2606:4700:4400::6812:230f, 2606:4700:4400::ac40:98f1",
1107 + data_dns_id: "57215",
1108 + src_port: "52260",
1109 + manager_name: "ASHWZHMA",
1110 + data_dns_question_top_level_domain: "com",
1111 + data_network_direction: "egress",
1112 + data_event_end: "2025-05-23T20:24:33.897Z",
1113 + data_agent_name: "piHole",
1114 + data_client_ip: "192.168.100.3",
1115 + data_server_bytes: "101",
1116 + data_dns_flags_authoritative: "false",
1117 + data_type: "dns",
1118 + data_dns_header_flags: "RD, RA, DO",
1119 + data_dns_flags_checking_disabled: "false",
1120 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1121 + "data_@metadata_version": "8.7.1",
1122 + data_host_os_name: "Debian GNU/Linux",
1123 + rule_group3: "dns",
1124 + msg_timestamp: "2025-05-23T20:24:36.268Z",
1125 + rule_group2: "packetbeat",
1126 + rule_group1: "linux"
1127 + },
1128 + {
1129 + data_source_ip: "192.168.100.1",
1130 + data_host_architecture: "x86_64",
1131 + agent_id: "032",
1132 + agent_name: "piHole",
1133 + gl2_remote_ip: "10.255.255.13",
1134 + data_resource: "github.com",
1135 + agent_labels_customer: "00001",
1136 + data_ecs_version: "8.0.0",
1137 + timestamp_utc: "2025-05-23T20:24:31.373Z",
1138 + data_host_os_codename: "bullseye",
1139 + syslog_type: "wazuh",
1140 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1141 + id: "1748031874.83778122",
1142 + data_dns_question_etld_plus_one: "github.com",
1143 + data_server_port: "53",
1144 + rule_mitre_tactic: "Command and Control",
1145 + gl2_accounted_message_size: 5977,
1146 + data_agent_type: "packetbeat",
1147 + streams: ["660320f176ca320e8393f057"],
1148 + rule_mitre_id: "T1071",
1149 + data_destination_bytes: "55",
1150 + data_event_dataset: "dns",
1151 + "data_@metadata_beat": "packetbeat",
1152 + agent_ip: "192.168.100.3",
1153 + data_source_port: "12080",
1154 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1155 + data_event_kind: "event",
1156 + data_network_protocol: "dns",
1157 + dns_response_code: "NOERROR",
1158 + dns_query: "github.com",
1159 + data_dns_response_code: "NOERROR",
1160 + data_network_community_id: "1:aPgg+uDBf3W03gGqIHpeYZ0dTWE=",
1161 + data_dns_flags_truncated_response: "false",
1162 + rule_mail: false,
1163 + data_dns_opt_udp_size: "1232",
1164 + data_event_category: "network",
1165 + data_dns_flags_recursion_available: "true",
1166 + data_dns_opt_version: "0",
1167 + timestamp: "2025-05-23 20:24:38.056",
1168 + data_host_mac: "00-0C-29-09-D5-9B",
1169 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1170 + data_destination_port: "53",
1171 + data_dns_type: "answer",
1172 + traffic_direction: "ingress",
1173 + rule_id: "200300",
1174 + data_dns_question_class: "IN",
1175 + cluster_node: "ASHWZHMA.socfortress.local",
1176 + dst_port: "53",
1177 + "data_@timestamp": "2025-05-23T20:24:31.373Z",
1178 + data_host_os_platform: "debian",
1179 + data_event_duration: "15844018",
1180 + data_host_name: "piHole",
1181 + data_dns_flags_recursion_desired: "true",
1182 + gl2_remote_port: 39928,
1183 + data_host_os_type: "linux",
1184 + source: "10.255.255.13",
1185 + gl2_source_input: "660320f176ca320e8393f030",
1186 + rule_level: 3,
1187 + data_event_type: "connection, protocol",
1188 + data_host_os_family: "debian",
1189 + data_dns_additionals_count: "0",
1190 + data_dns_flags_authentic_data: "false",
1191 + protocol: "udp",
1192 + data_dns_answers: "{ttl=54, data=140.82.114.4, name=github.com, type=A, class=IN}",
1193 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1194 + data_event_start: "2025-05-23T20:24:31.373Z",
1195 + rule_description: "Linux: DNS Query to github.com",
1196 + data_agent_version: "8.7.1",
1197 + data_related_ip: "192.168.100.1, 192.168.100.3, 140.82.114.4",
1198 + data_status: "OK",
1199 + data_query: "class IN, type A, github.com",
1200 + "data_@metadata_type": "_doc",
1201 + data_method: "QUERY",
1202 + data_dns_question_registered_domain: "github.com",
1203 + data_server_ip: "192.168.100.3",
1204 + gl2_message_id: "01JVZD3CX8DWEFZMWSK79H3XSX",
1205 + data_dns_answers_count: "1",
1206 + data_network_type: "ipv4",
1207 + data_dns_opt_ext_rcode: "NOERROR",
1208 + data_client_port: "12080",
1209 + data_network_bytes: "94",
1210 + data_dns_resolved_ip: "140.82.114.4",
1211 + data_host_containerized: "false",
1212 + true: 1748031874.954571,
1213 + data_host_hostname: "piHole",
1214 + rule_groups: "linux, packetbeat, dns",
1215 + data_client_bytes: "39",
1216 + data_dns_question_type: "A",
1217 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1218 + data_destination_ip: "192.168.100.3",
1219 + rule_mitre_technique: "Application Layer Protocol",
1220 + rule_firedtimes: 291,
1221 + data_network_transport: "udp",
1222 + dst_ip: "192.168.100.3",
1223 + src_ip: "192.168.100.1",
1224 + decoder_name: "json",
1225 + syslog_level: "INFO",
1226 + data_dns_op_code: "QUERY",
1227 + data_host_os_version: "11 (bullseye)",
1228 + data_host_os_kernel: "5.10.0-21-amd64",
1229 + cluster_name: "socfortress",
1230 + data_source_bytes: "39",
1231 + gl2_processing_error:
1232 + 'Replaced invalid timestamp value in message <f2fac461-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:34.266+0000> caused exception: Invalid format: "2025-05-23T20:24:34.266+0000" is malformed at "T20:24:34.266+0000".',
1233 + data_dns_opt_do: "true",
1234 + data_dns_authorities_count: "0",
1235 + data_dns_question_name: "github.com",
1236 + message:
1237 + '{"true":1748031874.954571,"timestamp":"2025-05-23T20:24:34.266+0000","rule":{"level":3,"description":"Linux: DNS Query to github.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":291,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031874.83778122","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:31.373Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"},"host":{"os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole","hostname":"piHole","architecture":"x86_64"},"type":"dns","destination":{"bytes":"55","ip":"192.168.100.3","port":"53"},"client":{"bytes":"39","ip":"192.168.100.1","port":"12080"},"method":"QUERY","dns":{"additionals_count":"0","type":"answer","flags":{"authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"},"header_flags":["RD","RA","DO"],"resolved_ip":["140.82.114.4"],"op_code":"QUERY","authorities_count":"0","question":{"name":"github.com","type":"A","class":"IN","etld_plus_one":"github.com","registered_domain":"github.com","top_level_domain":"com"},"opt":{"ext_rcode":"NOERROR","do":"true","version":"0","udp_size":"1232"},"answers_count":"1","answers":[{"ttl":"54","data":"140.82.114.4","name":"github.com","type":"A","class":"IN"}],"id":"15400","response_code":"NOERROR"},"ecs":{"version":"8.0.0"},"source":{"port":"12080","bytes":"39","ip":"192.168.100.1"},"network":{"protocol":"dns","direction":"ingress","community_id":"1:aPgg+uDBf3W03gGqIHpeYZ0dTWE=","bytes":"94","type":"ipv4","transport":"udp"},"query":"class IN, type A, github.com","resource":"github.com","event":{"start":"2025-05-23T20:24:31.373Z","end":"2025-05-23T20:24:31.389Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"15844018"},"server":{"ip":"192.168.100.3","port":"53","bytes":"55"},"related":{"ip":["192.168.100.1","192.168.100.3","140.82.114.4"]}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1238 + dns_answer: "140.82.114.4",
1239 + data_dns_id: "15400",
1240 + src_port: "12080",
1241 + manager_name: "ASHWZHMA",
1242 + data_dns_question_top_level_domain: "com",
1243 + data_network_direction: "ingress",
1244 + data_event_end: "2025-05-23T20:24:31.389Z",
1245 + data_agent_name: "piHole",
1246 + data_client_ip: "192.168.100.1",
1247 + data_dns_flags_authoritative: "false",
1248 + data_server_bytes: "55",
1249 + data_type: "dns",
1250 + data_dns_header_flags: "RD, RA, DO",
1251 + data_dns_flags_checking_disabled: "false",
1252 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1253 + "data_@metadata_version": "8.7.1",
1254 + data_host_os_name: "Debian GNU/Linux",
1255 + rule_group3: "dns",
1256 + msg_timestamp: "2025-05-23T20:24:34.266Z",
1257 + rule_group2: "packetbeat",
1258 + rule_group1: "linux"
1259 + },
1260 + {
1261 + data_source_ip: "192.168.100.1",
1262 + data_host_architecture: "x86_64",
1263 + agent_id: "032",
1264 + agent_name: "piHole",
1265 + gl2_remote_ip: "10.255.255.13",
1266 + data_resource: "default.exp-tas.com",
1267 + agent_labels_customer: "00001",
1268 + data_ecs_version: "8.0.0",
1269 + timestamp_utc: "2025-05-23T20:24:25.086Z",
1270 + data_host_os_codename: "bullseye",
1271 + syslog_type: "wazuh",
1272 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1273 + id: "1748031866.83767213",
1274 + data_dns_question_etld_plus_one: "exp-tas.com",
1275 + data_server_port: "53",
1276 + rule_mitre_tactic: "Command and Control",
1277 + gl2_accounted_message_size: 6100,
1278 + data_agent_type: "packetbeat",
1279 + streams: ["660320f176ca320e8393f057"],
1280 + rule_mitre_id: "T1071",
1281 + data_destination_bytes: "64",
1282 + data_event_dataset: "dns",
1283 + "data_@metadata_beat": "packetbeat",
1284 + agent_ip: "192.168.100.3",
1285 + data_source_port: "30943",
1286 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1287 + data_event_kind: "event",
1288 + data_network_protocol: "dns",
1289 + dns_response_code: "NOERROR",
1290 + dns_query: "default.exp-tas.com",
1291 + data_dns_response_code: "NOERROR",
1292 + data_network_community_id: "1:vnUwNaG0YFdp/V8rH3Gxab1UxfA=",
1293 + data_dns_flags_truncated_response: "false",
1294 + rule_mail: false,
1295 + data_dns_opt_udp_size: "1232",
1296 + data_event_category: "network",
1297 + data_dns_flags_recursion_available: "true",
1298 + data_dns_opt_version: "0",
1299 + timestamp: "2025-05-23 20:24:28.691",
1300 + data_host_mac: "00-0C-29-09-D5-9B",
1301 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1302 + data_destination_port: "53",
1303 + data_dns_type: "answer",
1304 + traffic_direction: "ingress",
1305 + rule_id: "200300",
1306 + data_dns_question_class: "IN",
1307 + cluster_node: "ASHWZHMA.socfortress.local",
1308 + dst_port: "53",
1309 + "data_@timestamp": "2025-05-23T20:24:25.086Z",
1310 + data_event_duration: "59506",
1311 + data_host_os_platform: "debian",
1312 + data_dns_flags_recursion_desired: "true",
1313 + data_host_name: "piHole",
1314 + data_dns_question_subdomain: "default",
1315 + gl2_remote_port: 40570,
1316 + data_host_os_type: "linux",
1317 + source: "10.255.255.13",
1318 + gl2_source_input: "660320f176ca320e8393f030",
1319 + rule_level: 3,
1320 + data_event_type: "connection, protocol",
1321 + data_host_os_family: "debian",
1322 + data_dns_additionals_count: "0",
1323 + data_dns_flags_authentic_data: "false",
1324 + protocol: "udp",
1325 + data_dns_answers: "{name=default.exp-tas.com, type=A, class=IN, ttl=2, data=0.0.0.0}",
1326 + data_event_start: "2025-05-23T20:24:25.086Z",
1327 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1328 + rule_description: "Linux: DNS Query to default.exp-tas.com",
1329 + data_related_ip: "192.168.100.1, 192.168.100.3, 0.0.0.0",
1330 + data_agent_version: "8.7.1",
1331 + data_status: "OK",
1332 + data_query: "class IN, type A, default.exp-tas.com",
1333 + "data_@metadata_type": "_doc",
1334 + data_dns_question_registered_domain: "exp-tas.com",
1335 + data_method: "QUERY",
1336 + data_server_ip: "192.168.100.3",
1337 + gl2_message_id: "01JVZD33RKQ2PMXYA8A89RSNK1",
1338 + data_dns_answers_count: "1",
1339 + data_network_type: "ipv4",
1340 + data_dns_opt_ext_rcode: "NOERROR",
1341 + data_client_port: "30943",
1342 + data_network_bytes: "112",
1343 + data_dns_resolved_ip: "0.0.0.0",
1344 + data_host_containerized: "false",
1345 + true: 1748031866.296917,
1346 + data_host_hostname: "piHole",
1347 + rule_groups: "linux, packetbeat, dns",
1348 + data_client_bytes: "48",
1349 + data_dns_question_type: "A",
1350 + data_destination_ip: "192.168.100.3",
1351 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1352 + rule_mitre_technique: "Application Layer Protocol",
1353 + rule_firedtimes: 287,
1354 + data_network_transport: "udp",
1355 + dst_ip: "192.168.100.3",
1356 + src_ip: "192.168.100.1",
1357 + decoder_name: "json",
1358 + syslog_level: "INFO",
1359 + data_dns_op_code: "QUERY",
1360 + data_host_os_version: "11 (bullseye)",
1361 + data_host_os_kernel: "5.10.0-21-amd64",
1362 + cluster_name: "socfortress",
1363 + data_source_bytes: "48",
1364 + gl2_processing_error:
1365 + 'Replaced invalid timestamp value in message <ed04bc54-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:26.259+0000> caused exception: Invalid format: "2025-05-23T20:24:26.259+0000" is malformed at "T20:24:26.259+0000".',
1366 + data_dns_opt_do: "true",
1367 + data_dns_authorities_count: "0",
1368 + data_dns_question_name: "default.exp-tas.com",
1369 + message:
1370 + '{"true":1748031866.296917,"timestamp":"2025-05-23T20:24:26.259+0000","rule":{"level":3,"description":"Linux: DNS Query to default.exp-tas.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":287,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031866.83767213","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:25.086Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"resource":"default.exp-tas.com","dns":{"answers":[{"name":"default.exp-tas.com","type":"A","class":"IN","ttl":"2","data":"0.0.0.0"}],"resolved_ip":["0.0.0.0"],"additionals_count":"0","flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"true","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"answers_count":"1","type":"answer","question":{"name":"default.exp-tas.com","type":"A","class":"IN","etld_plus_one":"exp-tas.com","registered_domain":"exp-tas.com","top_level_domain":"com","subdomain":"default"},"authorities_count":"0","id":"3874","response_code":"NOERROR","op_code":"QUERY","header_flags":["AA","RD","RA","DO"]},"query":"class IN, type A, default.exp-tas.com","network":{"transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:vnUwNaG0YFdp/V8rH3Gxab1UxfA=","bytes":"112","type":"ipv4"},"event":{"duration":"59506","start":"2025-05-23T20:24:25.086Z","end":"2025-05-23T20:24:25.086Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns"},"method":"QUERY","destination":{"ip":"192.168.100.3","port":"53","bytes":"64"},"client":{"bytes":"48","ip":"192.168.100.1","port":"30943"},"host":{"containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole","hostname":"piHole","architecture":"x86_64","os":{"type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye"},"id":"8986bcccef884a1ebe34f1ccd31b4f50"},"type":"dns","source":{"ip":"192.168.100.1","port":"30943","bytes":"48"},"ecs":{"version":"8.0.0"},"related":{"ip":["192.168.100.1","192.168.100.3","0.0.0.0"]},"agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"},"server":{"ip":"192.168.100.3","port":"53","bytes":"64"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1371 + dns_answer: "0.0.0.0",
1372 + data_dns_id: "3874",
1373 + src_port: "30943",
1374 + manager_name: "ASHWZHMA",
1375 + data_dns_question_top_level_domain: "com",
1376 + data_network_direction: "ingress",
1377 + data_event_end: "2025-05-23T20:24:25.086Z",
1378 + data_agent_name: "piHole",
1379 + data_dns_flags_authoritative: "true",
1380 + data_client_ip: "192.168.100.1",
1381 + data_server_bytes: "64",
1382 + data_dns_header_flags: "AA, RD, RA, DO",
1383 + data_type: "dns",
1384 + data_dns_flags_checking_disabled: "false",
1385 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1386 + "data_@metadata_version": "8.7.1",
1387 + data_host_os_name: "Debian GNU/Linux",
1388 + rule_group3: "dns",
1389 + msg_timestamp: "2025-05-23T20:24:26.259Z",
1390 + rule_group2: "packetbeat",
1391 + rule_group1: "linux"
1392 + },
1393 + {
1394 + data_source_ip: "192.168.100.3",
1395 + data_host_architecture: "x86_64",
1396 + agent_id: "032",
1397 + agent_name: "piHole",
1398 + gl2_remote_ip: "10.255.255.13",
1399 + data_resource: "api.github.com",
1400 + agent_labels_customer: "00001",
1401 + data_ecs_version: "8.0.0",
1402 + timestamp_utc: "2025-05-23T20:24:25.391Z",
1403 + data_host_os_codename: "bullseye",
1404 + syslog_type: "wazuh",
1405 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1406 + id: "1748031866.83769971",
1407 + data_server_port: "53",
1408 + data_dns_question_etld_plus_one: "github.com",
1409 + rule_mitre_tactic: "Command and Control",
1410 + gl2_accounted_message_size: 6026,
1411 + data_agent_type: "packetbeat",
1412 + streams: ["660320f176ca320e8393f057"],
1413 + rule_mitre_id: "T1071",
1414 + data_destination_bytes: "59",
1415 + data_event_dataset: "dns",
1416 + "data_@metadata_beat": "packetbeat",
1417 + agent_ip: "192.168.100.3",
1418 + data_source_port: "41851",
1419 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1420 + data_event_kind: "event",
1421 + data_network_protocol: "dns",
1422 + dns_response_code: "NOERROR",
1423 + dns_query: "api.github.com",
1424 + data_dns_response_code: "NOERROR",
1425 + data_network_community_id: "1:Qv+ZQxBe6Mp2YnOq4At/7f+jvHM=",
1426 + data_dns_flags_truncated_response: "false",
1427 + rule_mail: false,
1428 + data_dns_opt_udp_size: "1232",
1429 + data_event_category: "network",
1430 + data_dns_flags_recursion_available: "true",
1431 + data_dns_opt_version: "0",
1432 + timestamp: "2025-05-23 20:24:28.055",
1433 + data_host_mac: "00-0C-29-09-D5-9B",
1434 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1435 + data_destination_port: "53",
1436 + data_dns_type: "answer",
1437 + traffic_direction: "egress",
1438 + rule_id: "200300",
1439 + data_dns_question_class: "IN",
1440 + cluster_node: "ASHWZHMA.socfortress.local",
1441 + dst_port: "53",
1442 + "data_@timestamp": "2025-05-23T20:24:25.391Z",
1443 + data_host_os_platform: "debian",
1444 + data_event_duration: "12390708",
1445 + data_host_name: "piHole",
1446 + data_dns_flags_recursion_desired: "true",
1447 + data_dns_question_subdomain: "api",
1448 + gl2_remote_port: 40570,
1449 + data_host_os_type: "linux",
1450 + source: "10.255.255.13",
1451 + gl2_source_input: "660320f176ca320e8393f030",
1452 + rule_level: 3,
1453 + data_event_type: "connection, protocol",
1454 + data_host_os_family: "debian",
1455 + data_dns_additionals_count: "0",
1456 + data_dns_flags_authentic_data: "false",
1457 + protocol: "udp",
1458 + data_dns_answers: "{class=IN, ttl=45, data=140.82.112.6, name=api.github.com, type=A}",
1459 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1460 + data_event_start: "2025-05-23T20:24:25.391Z",
1461 + rule_description: "Linux: DNS Query to api.github.com",
1462 + data_agent_version: "8.7.1",
1463 + data_related_ip: "192.168.100.3, 1.1.1.3, 140.82.112.6",
1464 + data_status: "OK",
1465 + data_query: "class IN, type A, api.github.com",
1466 + "data_@metadata_type": "_doc",
1467 + data_method: "QUERY",
1468 + data_server_ip: "1.1.1.3",
1469 + data_dns_question_registered_domain: "github.com",
1470 + gl2_message_id: "01JVZD334QAK44WW31X0PRKNCW",
1471 + data_dns_answers_count: "1",
1472 + data_network_type: "ipv4",
1473 + data_dns_opt_ext_rcode: "NOERROR",
1474 + data_client_port: "41851",
1475 + data_network_bytes: "102",
1476 + data_dns_resolved_ip: "140.82.112.6",
1477 + data_host_containerized: "false",
1478 + true: 1748031866.297121,
1479 + data_host_hostname: "piHole",
1480 + rule_groups: "linux, packetbeat, dns",
1481 + data_client_bytes: "43",
1482 + data_dns_question_type: "A",
1483 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1484 + data_destination_ip: "1.1.1.3",
1485 + rule_mitre_technique: "Application Layer Protocol",
1486 + rule_firedtimes: 289,
1487 + data_network_transport: "udp",
1488 + dst_ip: "1.1.1.3",
1489 + src_ip: "192.168.100.3",
1490 + decoder_name: "json",
1491 + syslog_level: "INFO",
1492 + data_dns_op_code: "QUERY",
1493 + data_host_os_version: "11 (bullseye)",
1494 + data_host_os_kernel: "5.10.0-21-amd64",
1495 + cluster_name: "socfortress",
1496 + data_source_bytes: "43",
1497 + gl2_processing_error:
1498 + 'Replaced invalid timestamp value in message <ed04e360-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:26.296+0000> caused exception: Invalid format: "2025-05-23T20:24:26.296+0000" is malformed at "T20:24:26.296+0000".',
1499 + data_dns_opt_do: "true",
1500 + data_dns_authorities_count: "0",
1501 + data_dns_question_name: "api.github.com",
1502 + message:
1503 + '{"true":1748031866.297121,"timestamp":"2025-05-23T20:24:26.296+0000","rule":{"level":3,"description":"Linux: DNS Query to api.github.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":289,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031866.83769971","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:25.391Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"host":{"architecture":"x86_64","os":{"version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian"},"name":"piHole","id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole"},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"event":{"start":"2025-05-23T20:24:25.391Z","end":"2025-05-23T20:24:25.403Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"12390708"},"resource":"api.github.com","client":{"ip":"192.168.100.3","port":"41851","bytes":"43"},"related":{"ip":["192.168.100.3","1.1.1.3","140.82.112.6"]},"method":"QUERY","source":{"ip":"192.168.100.3","port":"41851","bytes":"43"},"server":{"ip":"1.1.1.3","port":"53","bytes":"59"},"ecs":{"version":"8.0.0"},"dns":{"additionals_count":"0","resolved_ip":["140.82.112.6"],"op_code":"QUERY","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"answers_count":"1","answers":[{"class":"IN","ttl":"45","data":"140.82.112.6","name":"api.github.com","type":"A"}],"authorities_count":"0","type":"answer","id":"21292","header_flags":["RD","RA","DO"],"question":{"registered_domain":"github.com","top_level_domain":"com","subdomain":"api","name":"api.github.com","type":"A","class":"IN","etld_plus_one":"github.com"},"response_code":"NOERROR"},"network":{"direction":"egress","community_id":"1:Qv+ZQxBe6Mp2YnOq4At/7f+jvHM=","bytes":"102","type":"ipv4","transport":"udp","protocol":"dns"},"type":"dns","destination":{"bytes":"59","ip":"1.1.1.3","port":"53"},"query":"class IN, type A, api.github.com"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1504 + dns_answer: "140.82.112.6",
1505 + data_dns_id: "21292",
1506 + src_port: "41851",
1507 + manager_name: "ASHWZHMA",
1508 + data_dns_question_top_level_domain: "com",
1509 + data_network_direction: "egress",
1510 + data_event_end: "2025-05-23T20:24:25.403Z",
1511 + data_agent_name: "piHole",
1512 + data_client_ip: "192.168.100.3",
1513 + data_server_bytes: "59",
1514 + data_dns_flags_authoritative: "false",
1515 + data_dns_header_flags: "RD, RA, DO",
1516 + data_type: "dns",
1517 + data_dns_flags_checking_disabled: "false",
1518 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1519 + "data_@metadata_version": "8.7.1",
1520 + data_host_os_name: "Debian GNU/Linux",
1521 + rule_group3: "dns",
1522 + msg_timestamp: "2025-05-23T20:24:26.296Z",
1523 + rule_group2: "packetbeat",
1524 + rule_group1: "linux"
1525 + },
1526 + {
1527 + data_source_ip: "192.168.100.1",
1528 + data_host_architecture: "x86_64",
1529 + agent_id: "032",
1530 + agent_name: "piHole",
1531 + gl2_remote_ip: "10.255.255.13",
1532 + data_resource: "api.github.com",
1533 + agent_labels_customer: "00001",
1534 + data_ecs_version: "8.0.0",
1535 + timestamp_utc: "2025-05-23T20:24:25.391Z",
1536 + data_host_os_codename: "bullseye",
1537 + syslog_type: "wazuh",
1538 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1539 + id: "1748031866.83772695",
1540 + data_dns_question_etld_plus_one: "github.com",
1541 + data_server_port: "53",
1542 + rule_mitre_tactic: "Command and Control",
1543 + gl2_accounted_message_size: 6069,
1544 + data_agent_type: "packetbeat",
1545 + streams: ["660320f176ca320e8393f057"],
1546 + rule_mitre_id: "T1071",
1547 + data_destination_bytes: "59",
1548 + data_event_dataset: "dns",
1549 + "data_@metadata_beat": "packetbeat",
1550 + agent_ip: "192.168.100.3",
1551 + data_source_port: "16098",
1552 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1553 + data_event_kind: "event",
1554 + data_network_protocol: "dns",
1555 + dns_response_code: "NOERROR",
1556 + dns_query: "api.github.com",
1557 + data_dns_response_code: "NOERROR",
1558 + data_network_community_id: "1:SAwm+c+9j+fNsGX6uGF/2a4zktU=",
1559 + data_dns_flags_truncated_response: "false",
1560 + rule_mail: false,
1561 + data_dns_opt_udp_size: "1232",
1562 + data_event_category: "network",
1563 + data_dns_flags_recursion_available: "true",
1564 + data_dns_opt_version: "0",
1565 + timestamp: "2025-05-23 20:24:28.055",
1566 + data_host_mac: "00-0C-29-09-D5-9B",
1567 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1568 + data_destination_port: "53",
1569 + data_dns_type: "answer",
1570 + traffic_direction: "ingress",
1571 + rule_id: "200300",
1572 + data_dns_question_class: "IN",
1573 + cluster_node: "ASHWZHMA.socfortress.local",
1574 + dst_port: "53",
1575 + "data_@timestamp": "2025-05-23T20:24:25.391Z",
1576 + data_event_duration: "12538930",
1577 + data_host_os_platform: "debian",
1578 + data_dns_flags_recursion_desired: "true",
1579 + data_host_name: "piHole",
1580 + data_dns_question_subdomain: "api",
1581 + gl2_remote_port: 40570,
1582 + data_host_os_type: "linux",
1583 + source: "10.255.255.13",
1584 + gl2_source_input: "660320f176ca320e8393f030",
1585 + rule_level: 3,
1586 + data_event_type: "connection, protocol",
1587 + data_host_os_family: "debian",
1588 + data_dns_additionals_count: "0",
1589 + data_dns_flags_authentic_data: "false",
1590 + protocol: "udp",
1591 + data_dns_answers: "{data=140.82.112.6, name=api.github.com, type=A, class=IN, ttl=45}",
1592 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1593 + data_event_start: "2025-05-23T20:24:25.391Z",
1594 + rule_description: "Linux: DNS Query to api.github.com",
1595 + data_agent_version: "8.7.1",
1596 + data_related_ip: "192.168.100.1, 192.168.100.3, 140.82.112.6",
1597 + data_status: "OK",
1598 + data_query: "class IN, type A, api.github.com",
1599 + "data_@metadata_type": "_doc",
1600 + data_method: "QUERY",
1601 + data_dns_question_registered_domain: "github.com",
1602 + data_server_ip: "192.168.100.3",
1603 + gl2_message_id: "01JVZD334Q5T1XWE1HMBFF0DVX",
1604 + data_dns_answers_count: "1",
1605 + data_network_type: "ipv4",
1606 + data_dns_opt_ext_rcode: "NOERROR",
1607 + data_client_port: "16098",
1608 + data_network_bytes: "102",
1609 + data_dns_resolved_ip: "140.82.112.6",
1610 + data_host_containerized: "false",
1611 + true: 1748031866.953483,
1612 + data_host_hostname: "piHole",
1613 + rule_groups: "linux, packetbeat, dns",
1614 + data_client_bytes: "43",
1615 + data_dns_question_type: "A",
1616 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1617 + data_destination_ip: "192.168.100.3",
1618 + rule_mitre_technique: "Application Layer Protocol",
1619 + rule_firedtimes: 288,
1620 + data_network_transport: "udp",
1621 + dst_ip: "192.168.100.3",
1622 + src_ip: "192.168.100.1",
1623 + decoder_name: "json",
1624 + syslog_level: "INFO",
1625 + data_dns_op_code: "QUERY",
1626 + data_host_os_version: "11 (bullseye)",
1627 + data_host_os_kernel: "5.10.0-21-amd64",
1628 + cluster_name: "socfortress",
1629 + data_source_bytes: "43",
1630 + gl2_processing_error:
1631 + 'Replaced invalid timestamp value in message <ed04e361-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:26.296+0000> caused exception: Invalid format: "2025-05-23T20:24:26.296+0000" is malformed at "T20:24:26.296+0000".',
1632 + data_dns_opt_do: "true",
1633 + data_dns_authorities_count: "0",
1634 + data_dns_question_name: "api.github.com",
1635 + message:
1636 + '{"true":1748031866.953483,"timestamp":"2025-05-23T20:24:26.296+0000","rule":{"level":3,"description":"Linux: DNS Query to api.github.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":288,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031866.83772695","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:25.391Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"type":"dns","agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"method":"QUERY","dns":{"header_flags":["RD","RA","DO"],"additionals_count":"0","id":"1842","question":{"etld_plus_one":"github.com","registered_domain":"github.com","top_level_domain":"com","subdomain":"api","name":"api.github.com","type":"A","class":"IN"},"answers":[{"data":"140.82.112.6","name":"api.github.com","type":"A","class":"IN","ttl":"45"}],"op_code":"QUERY","response_code":"NOERROR","answers_count":"1","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"resolved_ip":["140.82.112.6"],"authorities_count":"0","type":"answer","opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"}},"resource":"api.github.com","network":{"protocol":"dns","direction":"ingress","community_id":"1:SAwm+c+9j+fNsGX6uGF/2a4zktU=","bytes":"102","type":"ipv4","transport":"udp"},"query":"class IN, type A, api.github.com","source":{"ip":"192.168.100.1","port":"16098","bytes":"43"},"related":{"ip":["192.168.100.1","192.168.100.3","140.82.112.6"]},"event":{"dataset":"dns","duration":"12538930","start":"2025-05-23T20:24:25.391Z","end":"2025-05-23T20:24:25.403Z","kind":"event","category":["network"],"type":["connection","protocol"]},"server":{"port":"53","bytes":"59","ip":"192.168.100.3"},"ecs":{"version":"8.0.0"},"host":{"ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","name":"piHole"},"destination":{"ip":"192.168.100.3","port":"53","bytes":"59"},"client":{"port":"16098","bytes":"43","ip":"192.168.100.1"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1637 + dns_answer: "140.82.112.6",
1638 + data_dns_id: "1842",
1639 + src_port: "16098",
1640 + manager_name: "ASHWZHMA",
1641 + data_dns_question_top_level_domain: "com",
1642 + data_network_direction: "ingress",
1643 + data_event_end: "2025-05-23T20:24:25.403Z",
1644 + data_agent_name: "piHole",
1645 + data_dns_flags_authoritative: "false",
1646 + data_server_bytes: "59",
1647 + data_client_ip: "192.168.100.1",
1648 + data_type: "dns",
1649 + data_dns_header_flags: "RD, RA, DO",
1650 + data_dns_flags_checking_disabled: "false",
1651 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1652 + "data_@metadata_version": "8.7.1",
1653 + data_host_os_name: "Debian GNU/Linux",
1654 + rule_group3: "dns",
1655 + msg_timestamp: "2025-05-23T20:24:26.296Z",
1656 + rule_group2: "packetbeat",
1657 + rule_group1: "linux"
1658 + },
1659 + {
1660 + data_source_ip: "192.168.100.3",
1661 + data_host_architecture: "x86_64",
1662 + agent_id: "032",
1663 + agent_name: "piHole",
1664 + gl2_remote_ip: "10.255.255.13",
1665 + data_resource: "clientservices.googleapis.com",
1666 + agent_labels_customer: "00001",
1667 + data_ecs_version: "8.0.0",
1668 + timestamp_utc: "2025-05-23T20:24:16.968Z",
1669 + data_host_os_codename: "bullseye",
1670 + syslog_type: "wazuh",
1671 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1672 + id: "1748031858.83757535",
1673 + data_dns_question_etld_plus_one: "clientservices.googleapis.com",
1674 + data_server_port: "53",
1675 + rule_mitre_tactic: "Command and Control",
1676 + gl2_accounted_message_size: 6255,
1677 + data_agent_type: "packetbeat",
1678 + streams: ["660320f176ca320e8393f057"],
1679 + rule_mitre_id: "T1071",
1680 + data_destination_bytes: "74",
1681 + data_event_dataset: "dns",
1682 + "data_@metadata_beat": "packetbeat",
1683 + agent_ip: "192.168.100.3",
1684 + data_source_port: "39875",
1685 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1686 + data_event_kind: "event",
1687 + data_network_protocol: "dns",
1688 + dns_response_code: "NOERROR",
1689 + dns_query: "clientservices.googleapis.com",
1690 + data_dns_response_code: "NOERROR",
1691 + data_network_community_id: "1:gqNtlcfR7YF76W/Vl1c5Rfg8Tyk=",
1692 + data_dns_flags_truncated_response: "false",
1693 + rule_mail: false,
1694 + data_dns_opt_udp_size: "1232",
1695 + data_event_category: "network",
1696 + data_dns_flags_recursion_available: "true",
1697 + data_dns_opt_version: "0",
1698 + timestamp: "2025-05-23 20:24:23.055",
1699 + data_host_mac: "00-0C-29-09-D5-9B",
1700 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1701 + data_destination_port: "53",
1702 + data_dns_type: "answer",
1703 + traffic_direction: "egress",
1704 + rule_id: "200300",
1705 + data_dns_question_class: "IN",
1706 + cluster_node: "ASHWZHMA.socfortress.local",
1707 + dst_port: "53",
1708 + "data_@timestamp": "2025-05-23T20:24:16.968Z",
1709 + data_event_duration: "12495689",
1710 + data_host_os_platform: "debian",
1711 + data_dns_flags_recursion_desired: "true",
1712 + data_host_name: "piHole",
1713 + gl2_remote_port: 51720,
1714 + data_host_os_type: "linux",
1715 + source: "10.255.255.13",
1716 + gl2_source_input: "660320f176ca320e8393f030",
1717 + rule_level: 3,
1718 + data_event_type: "connection, protocol",
1719 + data_host_os_family: "debian",
1720 + data_dns_additionals_count: "0",
1721 + data_dns_flags_authentic_data: "false",
1722 + protocol: "udp",
1723 + data_dns_answers: "{class=IN, ttl=203, data=142.251.186.94, name=clientservices.googleapis.com, type=A}",
1724 + data_event_start: "2025-05-23T20:24:16.968Z",
1725 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1726 + rule_description: "Linux: DNS Query to clientservices.googleapis.com",
1727 + data_related_ip: "192.168.100.3, 1.1.1.3, 142.251.186.94",
1728 + data_agent_version: "8.7.1",
1729 + data_status: "OK",
1730 + data_query: "class IN, type A, clientservices.googleapis.com",
1731 + "data_@metadata_type": "_doc",
1732 + data_dns_question_registered_domain: "clientservices.googleapis.com",
1733 + data_server_ip: "1.1.1.3",
1734 + data_method: "QUERY",
1735 + gl2_message_id: "01JVZD2Y8F9QG7T66B5765KXZ6",
1736 + data_dns_answers_count: "1",
1737 + data_network_type: "ipv4",
1738 + data_dns_opt_ext_rcode: "NOERROR",
1739 + data_client_port: "39875",
1740 + data_network_bytes: "132",
1741 + data_dns_resolved_ip: "142.251.186.94",
1742 + data_host_containerized: "false",
1743 + true: 1748031858.256838,
1744 + data_host_hostname: "piHole",
1745 + rule_groups: "linux, packetbeat, dns",
1746 + data_client_bytes: "58",
1747 + data_dns_question_type: "A",
1748 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1749 + data_destination_ip: "1.1.1.3",
1750 + rule_mitre_technique: "Application Layer Protocol",
1751 + rule_firedtimes: 284,
1752 + data_network_transport: "udp",
1753 + dst_ip: "1.1.1.3",
1754 + src_ip: "192.168.100.3",
1755 + decoder_name: "json",
1756 + syslog_level: "INFO",
1757 + data_dns_op_code: "QUERY",
1758 + data_host_os_version: "11 (bullseye)",
1759 + data_host_os_kernel: "5.10.0-21-amd64",
1760 + cluster_name: "socfortress",
1761 + data_source_bytes: "58",
1762 + gl2_processing_error:
1763 + 'Replaced invalid timestamp value in message <ea09cbd3-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:18.256+0000> caused exception: Invalid format: "2025-05-23T20:24:18.256+0000" is malformed at "T20:24:18.256+0000".',
1764 + data_dns_opt_do: "true",
1765 + data_dns_authorities_count: "0",
1766 + data_dns_question_name: "clientservices.googleapis.com",
1767 + message:
1768 + '{"true":1748031858.256838,"timestamp":"2025-05-23T20:24:18.256+0000","rule":{"level":3,"description":"Linux: DNS Query to clientservices.googleapis.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":284,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031858.83757535","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:16.968Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"event":{"duration":"12495689","start":"2025-05-23T20:24:16.968Z","end":"2025-05-23T20:24:16.981Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns"},"related":{"ip":["192.168.100.3","1.1.1.3","142.251.186.94"]},"network":{"bytes":"132","type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:gqNtlcfR7YF76W/Vl1c5Rfg8Tyk="},"client":{"ip":"192.168.100.3","port":"39875","bytes":"58"},"ecs":{"version":"8.0.0"},"source":{"ip":"192.168.100.3","port":"39875","bytes":"58"},"query":"class IN, type A, clientservices.googleapis.com","dns":{"authorities_count":"0","op_code":"QUERY","opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"flags":{"recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true"},"header_flags":["RD","RA","DO"],"answers_count":"1","response_code":"NOERROR","resolved_ip":["142.251.186.94"],"id":"9779","question":{"name":"clientservices.googleapis.com","type":"A","class":"IN","etld_plus_one":"clientservices.googleapis.com","registered_domain":"clientservices.googleapis.com","top_level_domain":"googleapis.com"},"answers":[{"class":"IN","ttl":"203","data":"142.251.186.94","name":"clientservices.googleapis.com","type":"A"}],"additionals_count":"0","type":"answer"},"host":{"architecture":"x86_64","os":{"platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole","hostname":"piHole"},"agent":{"version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat"},"server":{"bytes":"74","ip":"1.1.1.3","port":"53"},"destination":{"ip":"1.1.1.3","port":"53","bytes":"74"},"type":"dns","resource":"clientservices.googleapis.com","method":"QUERY"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1769 + dns_answer: "142.251.186.94",
1770 + data_dns_id: "9779",
1771 + src_port: "39875",
1772 + manager_name: "ASHWZHMA",
1773 + data_network_direction: "egress",
1774 + data_dns_question_top_level_domain: "googleapis.com",
1775 + data_event_end: "2025-05-23T20:24:16.981Z",
1776 + data_agent_name: "piHole",
1777 + data_client_ip: "192.168.100.3",
1778 + data_dns_flags_authoritative: "false",
1779 + data_server_bytes: "74",
1780 + data_dns_header_flags: "RD, RA, DO",
1781 + data_type: "dns",
1782 + data_dns_flags_checking_disabled: "false",
1783 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1784 + "data_@metadata_version": "8.7.1",
1785 + data_host_os_name: "Debian GNU/Linux",
1786 + rule_group3: "dns",
1787 + msg_timestamp: "2025-05-23T20:24:18.256Z",
1788 + rule_group2: "packetbeat",
1789 + rule_group1: "linux"
1790 + },
1791 + {
1792 + data_source_ip: "192.168.100.3",
1793 + data_host_architecture: "x86_64",
1794 + agent_id: "032",
1795 + agent_name: "piHole",
1796 + gl2_remote_ip: "10.255.255.13",
1797 + data_resource: "clientservices.googleapis.com",
1798 + agent_labels_customer: "00001",
1799 + data_ecs_version: "8.0.0",
1800 + timestamp_utc: "2025-05-23T20:24:16.968Z",
1801 + data_host_os_codename: "bullseye",
1802 + syslog_type: "wazuh",
1803 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1804 + id: "1748031858.83763262",
1805 + data_server_port: "53",
1806 + data_dns_question_etld_plus_one: "clientservices.googleapis.com",
1807 + rule_mitre_tactic: "Command and Control",
1808 + gl2_accounted_message_size: 6336,
1809 + data_agent_type: "packetbeat",
1810 + streams: ["660320f176ca320e8393f057"],
1811 + rule_mitre_id: "T1071",
1812 + data_destination_bytes: "86",
1813 + data_event_dataset: "dns",
1814 + "data_@metadata_beat": "packetbeat",
1815 + agent_ip: "192.168.100.3",
1816 + data_source_port: "58871",
1817 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1818 + data_event_kind: "event",
1819 + data_network_protocol: "dns",
1820 + dns_response_code: "NOERROR",
1821 + dns_query: "clientservices.googleapis.com",
1822 + data_dns_response_code: "NOERROR",
1823 + data_network_community_id: "1:ykrdpoGjkUiCgojr1rKBDgiEppw=",
1824 + data_dns_flags_truncated_response: "false",
1825 + rule_mail: false,
1826 + data_dns_opt_udp_size: "1232",
1827 + data_event_category: "network",
1828 + data_dns_flags_recursion_available: "true",
1829 + data_dns_opt_version: "0",
1830 + timestamp: "2025-05-23 20:24:23.055",
1831 + data_host_mac: "00-0C-29-09-D5-9B",
1832 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1833 + data_destination_port: "53",
1834 + data_dns_type: "answer",
1835 + traffic_direction: "egress",
1836 + rule_id: "200300",
1837 + data_dns_question_class: "IN",
1838 + cluster_node: "ASHWZHMA.socfortress.local",
1839 + dst_port: "53",
1840 + "data_@timestamp": "2025-05-23T20:24:16.968Z",
1841 + data_host_os_platform: "debian",
1842 + data_event_duration: "10913100",
1843 + data_dns_flags_recursion_desired: "true",
1844 + data_host_name: "piHole",
1845 + gl2_remote_port: 51720,
1846 + data_host_os_type: "linux",
1847 + source: "10.255.255.13",
1848 + gl2_source_input: "660320f176ca320e8393f030",
1849 + rule_level: 3,
1850 + data_event_type: "connection, protocol",
1851 + data_host_os_family: "debian",
1852 + data_dns_additionals_count: "0",
1853 + data_dns_flags_authentic_data: "false",
1854 + protocol: "udp",
1855 + data_dns_answers:
1856 + "{name=clientservices.googleapis.com, type=AAAA, class=IN, ttl=54, data=2607:f8b0:4023:1006::5e}",
1857 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1858 + data_event_start: "2025-05-23T20:24:16.968Z",
1859 + rule_description: "Linux: DNS Query to clientservices.googleapis.com",
1860 + data_agent_version: "8.7.1",
1861 + data_related_ip: "192.168.100.3, 1.1.1.3, 2607:f8b0:4023:1006::5e",
1862 + data_status: "OK",
1863 + data_query: "class IN, type AAAA, clientservices.googleapis.com",
1864 + "data_@metadata_type": "_doc",
1865 + data_server_ip: "1.1.1.3",
1866 + data_dns_question_registered_domain: "clientservices.googleapis.com",
1867 + data_method: "QUERY",
1868 + gl2_message_id: "01JVZD2Y8F3NKJF9TQN2STXTRP",
1869 + data_dns_answers_count: "1",
1870 + data_network_type: "ipv4",
1871 + data_dns_opt_ext_rcode: "NOERROR",
1872 + data_client_port: "58871",
1873 + data_network_bytes: "144",
1874 + data_dns_resolved_ip: "2607:f8b0:4023:1006::5e",
1875 + data_host_containerized: "false",
1876 + true: 1748031858.952529,
1877 + data_host_hostname: "piHole",
1878 + rule_groups: "linux, packetbeat, dns",
1879 + data_client_bytes: "58",
1880 + data_dns_question_type: "AAAA",
1881 + data_destination_ip: "1.1.1.3",
1882 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
1883 + rule_mitre_technique: "Application Layer Protocol",
1884 + rule_firedtimes: 286,
1885 + data_network_transport: "udp",
1886 + dst_ip: "1.1.1.3",
1887 + src_ip: "192.168.100.3",
1888 + decoder_name: "json",
1889 + syslog_level: "INFO",
1890 + data_dns_op_code: "QUERY",
1891 + data_host_os_version: "11 (bullseye)",
1892 + data_host_os_kernel: "5.10.0-21-amd64",
1893 + cluster_name: "socfortress",
1894 + data_source_bytes: "58",
1895 + gl2_processing_error:
1896 + 'Replaced invalid timestamp value in message <ea09cbd5-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:18.255+0000> caused exception: Invalid format: "2025-05-23T20:24:18.255+0000" is malformed at "T20:24:18.255+0000".',
1897 + data_dns_opt_do: "true",
1898 + data_dns_authorities_count: "0",
1899 + data_dns_question_name: "clientservices.googleapis.com",
1900 + message:
1901 + '{"true":1748031858.952529,"timestamp":"2025-05-23T20:24:18.255+0000","rule":{"level":3,"description":"Linux: DNS Query to clientservices.googleapis.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":286,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031858.83763262","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:16.968Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"destination":{"bytes":"86","ip":"1.1.1.3","port":"53"},"server":{"ip":"1.1.1.3","port":"53","bytes":"86"},"dns":{"additionals_count":"0","id":"48715","opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"answers":[{"name":"clientservices.googleapis.com","type":"AAAA","class":"IN","ttl":"54","data":"2607:f8b0:4023:1006::5e"}],"flags":{"recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true"},"answers_count":"1","authorities_count":"0","resolved_ip":["2607:f8b0:4023:1006::5e"],"type":"answer","header_flags":["RD","RA","DO"],"question":{"top_level_domain":"googleapis.com","name":"clientservices.googleapis.com","type":"AAAA","class":"IN","etld_plus_one":"clientservices.googleapis.com","registered_domain":"clientservices.googleapis.com"},"op_code":"QUERY","response_code":"NOERROR"},"ecs":{"version":"8.0.0"},"host":{"containerized":"false","name":"piHole","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50"},"agent":{"id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3"},"method":"QUERY","query":"class IN, type AAAA, clientservices.googleapis.com","related":{"ip":["192.168.100.3","1.1.1.3","2607:f8b0:4023:1006::5e"]},"client":{"port":"58871","bytes":"58","ip":"192.168.100.3"},"resource":"clientservices.googleapis.com","type":"dns","network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:ykrdpoGjkUiCgojr1rKBDgiEppw=","bytes":"144"},"event":{"start":"2025-05-23T20:24:16.968Z","end":"2025-05-23T20:24:16.979Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"10913100"},"source":{"ip":"192.168.100.3","port":"58871","bytes":"58"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
1902 + dns_answer: "2607:f8b0:4023:1006::5e",
1903 + data_dns_id: "48715",
1904 + src_port: "58871",
1905 + manager_name: "ASHWZHMA",
1906 + data_dns_question_top_level_domain: "googleapis.com",
1907 + data_network_direction: "egress",
1908 + data_event_end: "2025-05-23T20:24:16.979Z",
1909 + data_agent_name: "piHole",
1910 + data_server_bytes: "86",
1911 + data_dns_flags_authoritative: "false",
1912 + data_client_ip: "192.168.100.3",
1913 + data_dns_header_flags: "RD, RA, DO",
1914 + data_type: "dns",
1915 + data_dns_flags_checking_disabled: "false",
1916 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
1917 + "data_@metadata_version": "8.7.1",
1918 + data_host_os_name: "Debian GNU/Linux",
1919 + rule_group3: "dns",
1920 + msg_timestamp: "2025-05-23T20:24:18.255Z",
1921 + rule_group2: "packetbeat",
1922 + rule_group1: "linux"
1923 + },
1924 + {
1925 + data_source_ip: "192.168.100.1",
1926 + data_host_architecture: "x86_64",
1927 + agent_id: "032",
1928 + agent_name: "piHole",
1929 + gl2_remote_ip: "10.255.255.13",
1930 + data_resource: "clientservices.googleapis.com",
1931 + agent_labels_customer: "00001",
1932 + data_ecs_version: "8.0.0",
1933 + timestamp_utc: "2025-05-23T20:24:16.968Z",
1934 + data_host_os_codename: "bullseye",
1935 + syslog_type: "wazuh",
1936 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
1937 + id: "1748031858.83760371",
1938 + data_dns_question_etld_plus_one: "clientservices.googleapis.com",
1939 + data_server_port: "53",
1940 + rule_mitre_tactic: "Command and Control",
1941 + gl2_accounted_message_size: 6381,
1942 + data_agent_type: "packetbeat",
1943 + streams: ["660320f176ca320e8393f057"],
1944 + rule_mitre_id: "T1071",
1945 + data_destination_bytes: "86",
1946 + data_event_dataset: "dns",
1947 + "data_@metadata_beat": "packetbeat",
1948 + agent_ip: "192.168.100.3",
1949 + data_source_port: "43099",
1950 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
1951 + data_event_kind: "event",
1952 + data_network_protocol: "dns",
1953 + dns_response_code: "NOERROR",
1954 + dns_query: "clientservices.googleapis.com",
1955 + data_dns_response_code: "NOERROR",
1956 + data_network_community_id: "1:T5KKxFzRKrYGd3zpS/XejHoi9AM=",
1957 + data_dns_flags_truncated_response: "false",
1958 + rule_mail: false,
1959 + data_dns_opt_udp_size: "1232",
1960 + data_event_category: "network",
1961 + data_dns_flags_recursion_available: "true",
1962 + data_dns_opt_version: "0",
1963 + timestamp: "2025-05-23 20:24:23.055",
1964 + data_host_mac: "00-0C-29-09-D5-9B",
1965 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
1966 + data_destination_port: "53",
1967 + data_dns_type: "answer",
1968 + traffic_direction: "ingress",
1969 + rule_id: "200300",
1970 + data_dns_question_class: "IN",
1971 + cluster_node: "ASHWZHMA.socfortress.local",
1972 + dst_port: "53",
1973 + "data_@timestamp": "2025-05-23T20:24:16.968Z",
1974 + data_event_duration: "11235860",
1975 + data_host_os_platform: "debian",
1976 + data_dns_flags_recursion_desired: "true",
1977 + data_host_name: "piHole",
1978 + gl2_remote_port: 51720,
1979 + data_host_os_type: "linux",
1980 + source: "10.255.255.13",
1981 + gl2_source_input: "660320f176ca320e8393f030",
1982 + rule_level: 3,
1983 + data_event_type: "connection, protocol",
1984 + data_host_os_family: "debian",
1985 + data_dns_additionals_count: "0",
1986 + data_dns_flags_authentic_data: "false",
1987 + protocol: "udp",
1988 + data_dns_answers:
1989 + "{data=2607:f8b0:4023:1006::5e, name=clientservices.googleapis.com, type=AAAA, class=IN, ttl=54}",
1990 + data_event_start: "2025-05-23T20:24:16.968Z",
1991 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
1992 + rule_description: "Linux: DNS Query to clientservices.googleapis.com",
1993 + data_related_ip: "192.168.100.1, 192.168.100.3, 2607:f8b0:4023:1006::5e",
1994 + data_agent_version: "8.7.1",
1995 + data_status: "OK",
1996 + data_query: "class IN, type AAAA, clientservices.googleapis.com",
1997 + "data_@metadata_type": "_doc",
1998 + data_dns_question_registered_domain: "clientservices.googleapis.com",
1999 + data_server_ip: "192.168.100.3",
2000 + data_method: "QUERY",
2001 + gl2_message_id: "01JVZD2Y8F8T46KKT8KDH9EYB0",
2002 + data_dns_answers_count: "1",
2003 + data_network_type: "ipv4",
2004 + data_dns_opt_ext_rcode: "NOERROR",
2005 + data_client_port: "43099",
2006 + data_network_bytes: "144",
2007 + data_dns_resolved_ip: "2607:f8b0:4023:1006::5e",
2008 + data_host_containerized: "false",
2009 + true: 1748031858.257044,
2010 + data_host_hostname: "piHole",
2011 + rule_groups: "linux, packetbeat, dns",
2012 + data_client_bytes: "58",
2013 + data_dns_question_type: "AAAA",
2014 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2015 + data_destination_ip: "192.168.100.3",
2016 + rule_mitre_technique: "Application Layer Protocol",
2017 + rule_firedtimes: 285,
2018 + data_network_transport: "udp",
2019 + dst_ip: "192.168.100.3",
2020 + src_ip: "192.168.100.1",
2021 + decoder_name: "json",
2022 + syslog_level: "INFO",
2023 + data_dns_op_code: "QUERY",
2024 + data_host_os_version: "11 (bullseye)",
2025 + data_host_os_kernel: "5.10.0-21-amd64",
2026 + cluster_name: "socfortress",
2027 + data_source_bytes: "58",
2028 + gl2_processing_error:
2029 + 'Replaced invalid timestamp value in message <ea09cbd4-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:18.255+0000> caused exception: Invalid format: "2025-05-23T20:24:18.255+0000" is malformed at "T20:24:18.255+0000".',
2030 + data_dns_opt_do: "true",
2031 + data_dns_authorities_count: "0",
2032 + data_dns_question_name: "clientservices.googleapis.com",
2033 + message:
2034 + '{"true":1748031858.257044,"timestamp":"2025-05-23T20:24:18.255+0000","rule":{"level":3,"description":"Linux: DNS Query to clientservices.googleapis.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":285,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031858.83760371","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:16.968Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"ip":"192.168.100.1","port":"43099","bytes":"58"},"event":{"duration":"11235860","start":"2025-05-23T20:24:16.968Z","end":"2025-05-23T20:24:16.979Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns"},"dns":{"resolved_ip":["2607:f8b0:4023:1006::5e"],"id":"37478","header_flags":["RD","RA","DO"],"answers":[{"data":"2607:f8b0:4023:1006::5e","name":"clientservices.googleapis.com","type":"AAAA","class":"IN","ttl":"54"}],"answers_count":"1","response_code":"NOERROR","question":{"type":"AAAA","class":"IN","etld_plus_one":"clientservices.googleapis.com","registered_domain":"clientservices.googleapis.com","top_level_domain":"googleapis.com","name":"clientservices.googleapis.com"},"opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"op_code":"QUERY","authorities_count":"0","additionals_count":"0","type":"answer","flags":{"authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"}},"related":{"ip":["192.168.100.1","192.168.100.3","2607:f8b0:4023:1006::5e"]},"host":{"architecture":"x86_64","os":{"kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"name":"piHole","mac":["00-0C-29-09-D5-9B"],"hostname":"piHole"},"agent":{"id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3"},"query":"class IN, type AAAA, clientservices.googleapis.com","source":{"bytes":"58","ip":"192.168.100.1","port":"43099"},"server":{"ip":"192.168.100.3","port":"53","bytes":"86"},"type":"dns","network":{"protocol":"dns","direction":"ingress","community_id":"1:T5KKxFzRKrYGd3zpS/XejHoi9AM=","bytes":"144","type":"ipv4","transport":"udp"},"destination":{"bytes":"86","ip":"192.168.100.3","port":"53"},"ecs":{"version":"8.0.0"},"method":"QUERY","resource":"clientservices.googleapis.com"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2035 + dns_answer: "2607:f8b0:4023:1006::5e",
2036 + data_dns_id: "37478",
2037 + src_port: "43099",
2038 + manager_name: "ASHWZHMA",
2039 + data_dns_question_top_level_domain: "googleapis.com",
2040 + data_network_direction: "ingress",
2041 + data_event_end: "2025-05-23T20:24:16.979Z",
2042 + data_agent_name: "piHole",
2043 + data_client_ip: "192.168.100.1",
2044 + data_dns_flags_authoritative: "false",
2045 + data_server_bytes: "86",
2046 + data_dns_header_flags: "RD, RA, DO",
2047 + data_type: "dns",
2048 + data_dns_flags_checking_disabled: "false",
2049 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2050 + "data_@metadata_version": "8.7.1",
2051 + data_host_os_name: "Debian GNU/Linux",
2052 + rule_group3: "dns",
2053 + msg_timestamp: "2025-05-23T20:24:18.255Z",
2054 + rule_group2: "packetbeat",
2055 + rule_group1: "linux"
2056 + },
2057 + {
2058 + data_source_ip: "192.168.100.1",
2059 + data_host_architecture: "x86_64",
2060 + agent_id: "032",
2061 + agent_name: "piHole",
2062 + gl2_remote_ip: "10.255.255.13",
2063 + data_resource: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2064 + agent_labels_customer: "00001",
2065 + data_ecs_version: "8.0.0",
2066 + timestamp_utc: "2025-05-23T20:24:05.953Z",
2067 + data_host_os_codename: "bullseye",
2068 + syslog_type: "wazuh",
2069 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2070 + id: "1748031848.83751517",
2071 + data_server_port: "53",
2072 + data_dns_question_etld_plus_one: "sharepoint.com",
2073 + rule_mitre_tactic: "Command and Control",
2074 + gl2_accounted_message_size: 6754,
2075 + data_agent_type: "packetbeat",
2076 + streams: ["660320f176ca320e8393f057"],
2077 + rule_mitre_id: "T1071",
2078 + data_destination_bytes: "130",
2079 + data_event_dataset: "dns",
2080 + "data_@metadata_beat": "packetbeat",
2081 + agent_ip: "192.168.100.3",
2082 + data_source_port: "23048",
2083 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2084 + data_event_kind: "event",
2085 + data_network_protocol: "dns",
2086 + dns_response_code: "NOERROR",
2087 + dns_query: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2088 + data_dns_response_code: "NOERROR",
2089 + data_network_community_id: "1:m9QwZxOBfLQh63euZxFGEUKc91E=",
2090 + data_dns_flags_truncated_response: "false",
2091 + rule_mail: false,
2092 + data_dns_opt_udp_size: "1232",
2093 + data_event_category: "network",
2094 + data_dns_flags_recursion_available: "true",
2095 + data_dns_opt_version: "0",
2096 + timestamp: "2025-05-23 20:24:13.652",
2097 + data_host_mac: "00-0C-29-09-D5-9B",
2098 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2099 + data_destination_port: "53",
2100 + data_dns_type: "answer",
2101 + traffic_direction: "ingress",
2102 + rule_id: "200300",
2103 + data_dns_question_class: "IN",
2104 + cluster_node: "ASHWZHMA.socfortress.local",
2105 + dst_port: "53",
2106 + "data_@timestamp": "2025-05-23T20:24:05.953Z",
2107 + data_host_os_platform: "debian",
2108 + data_event_duration: "26399654",
2109 + data_host_name: "piHole",
2110 + data_dns_flags_recursion_desired: "true",
2111 + data_dns_question_subdomain: "192071-ipv4.gr.global.aa-rt",
2112 + gl2_remote_port: 53306,
2113 + data_host_os_type: "linux",
2114 + source: "10.255.255.13",
2115 + gl2_source_input: "660320f176ca320e8393f030",
2116 + rule_level: 3,
2117 + data_event_type: "connection, protocol",
2118 + data_host_os_family: "debian",
2119 + data_dns_additionals_count: "0",
2120 + data_dns_flags_authentic_data: "false",
2121 + protocol: "udp",
2122 + data_dns_answers:
2123 + "{name=192071-ipv4.gr.global.aa-rt.sharepoint.com, type=CNAME, class=IN, ttl=59, data=192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com}, {class=IN, ttl=3599, data=52.104.26.41, name=192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com, type=A}",
2124 + data_event_start: "2025-05-23T20:24:05.953Z",
2125 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2126 + rule_description: "Linux: DNS Query to 192071-ipv4.gr.global.aa-rt.sharepoint.com",
2127 + data_related_ip: "192.168.100.1, 192.168.100.3, 52.104.26.41",
2128 + data_agent_version: "8.7.1",
2129 + data_status: "OK",
2130 + data_query: "class IN, type A, 192071-ipv4.gr.global.aa-rt.sharepoint.com",
2131 + "data_@metadata_type": "_doc",
2132 + data_method: "QUERY",
2133 + data_server_ip: "192.168.100.3",
2134 + data_dns_question_registered_domain: "sharepoint.com",
2135 + gl2_message_id: "01JVZD2N2MRENTMM587X0BVQEJ",
2136 + data_dns_answers_count: "2",
2137 + data_network_type: "ipv4",
2138 + data_dns_opt_ext_rcode: "NOERROR",
2139 + data_client_port: "23048",
2140 + data_network_bytes: "201",
2141 + data_dns_resolved_ip: "52.104.26.41",
2142 + data_host_containerized: "false",
2143 + true: 1748031848.951349,
2144 + data_host_hostname: "piHole",
2145 + rule_groups: "linux, packetbeat, dns",
2146 + data_client_bytes: "71",
2147 + data_dns_question_type: "A",
2148 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2149 + data_destination_ip: "192.168.100.3",
2150 + rule_mitre_technique: "Application Layer Protocol",
2151 + rule_firedtimes: 281,
2152 + data_network_transport: "udp",
2153 + dst_ip: "192.168.100.3",
2154 + src_ip: "192.168.100.1",
2155 + decoder_name: "json",
2156 + syslog_level: "INFO",
2157 + data_dns_op_code: "QUERY",
2158 + data_host_os_version: "11 (bullseye)",
2159 + data_host_os_kernel: "5.10.0-21-amd64",
2160 + cluster_name: "socfortress",
2161 + data_source_bytes: "71",
2162 + gl2_processing_error:
2163 + 'Replaced invalid timestamp value in message <e41411e2-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:08.282+0000> caused exception: Invalid format: "2025-05-23T20:24:08.282+0000" is malformed at "T20:24:08.282+0000".',
2164 + data_dns_opt_do: "true",
2165 + data_dns_authorities_count: "0",
2166 + data_dns_question_name: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2167 + message:
2168 + '{"true":1748031848.951349,"timestamp":"2025-05-23T20:24:08.282+0000","rule":{"level":3,"description":"Linux: DNS Query to 192071-ipv4.gr.global.aa-rt.sharepoint.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":281,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031848.83751517","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.953Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"method":"QUERY","server":{"port":"53","bytes":"130","ip":"192.168.100.3"},"host":{"ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","name":"piHole","os":{"type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false"},"event":{"dataset":"dns","duration":"26399654","start":"2025-05-23T20:24:05.953Z","end":"2025-05-23T20:24:05.980Z","kind":"event","category":["network"],"type":["connection","protocol"]},"query":"class IN, type A, 192071-ipv4.gr.global.aa-rt.sharepoint.com","source":{"bytes":"71","ip":"192.168.100.1","port":"23048"},"related":{"ip":["192.168.100.1","192.168.100.3","52.104.26.41"]},"network":{"direction":"ingress","community_id":"1:m9QwZxOBfLQh63euZxFGEUKc91E=","bytes":"201","type":"ipv4","transport":"udp","protocol":"dns"},"destination":{"ip":"192.168.100.3","port":"53","bytes":"130"},"type":"dns","agent":{"type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole"},"dns":{"opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"},"op_code":"QUERY","additionals_count":"0","answers_count":"2","response_code":"NOERROR","flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"header_flags":["RD","RA","DO"],"question":{"registered_domain":"sharepoint.com","top_level_domain":"com","subdomain":"192071-ipv4.gr.global.aa-rt","name":"192071-ipv4.gr.global.aa-rt.sharepoint.com","type":"A","class":"IN","etld_plus_one":"sharepoint.com"},"resolved_ip":["52.104.26.41"],"authorities_count":"0","id":"57613","answers":[{"name":"192071-ipv4.gr.global.aa-rt.sharepoint.com","type":"CNAME","class":"IN","ttl":"59","data":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com"},{"class":"IN","ttl":"3599","data":"52.104.26.41","name":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com","type":"A"}],"type":"answer"},"client":{"bytes":"71","ip":"192.168.100.1","port":"23048"},"ecs":{"version":"8.0.0"},"resource":"192071-ipv4.gr.global.aa-rt.sharepoint.com"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2169 + dns_answer: "52.104.26.41",
2170 + data_dns_id: "57613",
2171 + src_port: "23048",
2172 + manager_name: "ASHWZHMA",
2173 + data_network_direction: "ingress",
2174 + data_dns_question_top_level_domain: "com",
2175 + data_event_end: "2025-05-23T20:24:05.980Z",
2176 + data_agent_name: "piHole",
2177 + data_server_bytes: "130",
2178 + data_dns_flags_authoritative: "false",
2179 + data_client_ip: "192.168.100.1",
2180 + data_type: "dns",
2181 + data_dns_header_flags: "RD, RA, DO",
2182 + data_dns_flags_checking_disabled: "false",
2183 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2184 + "data_@metadata_version": "8.7.1",
2185 + data_host_os_name: "Debian GNU/Linux",
2186 + rule_group3: "dns",
2187 + msg_timestamp: "2025-05-23T20:24:08.282Z",
2188 + rule_group2: "packetbeat",
2189 + rule_group1: "linux"
2190 + },
2191 + {
2192 + data_source_ip: "192.168.100.3",
2193 + data_host_architecture: "x86_64",
2194 + agent_id: "032",
2195 + agent_name: "piHole",
2196 + gl2_remote_ip: "10.255.255.13",
2197 + data_resource: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2198 + agent_labels_customer: "00001",
2199 + data_ecs_version: "8.0.0",
2200 + timestamp_utc: "2025-05-23T20:24:05.925Z",
2201 + data_host_os_codename: "bullseye",
2202 + syslog_type: "wazuh",
2203 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2204 + id: "1748031848.83748458",
2205 + data_server_port: "53",
2206 + data_dns_question_etld_plus_one: "sharepoint.com",
2207 + rule_mitre_tactic: "Command and Control",
2208 + gl2_accounted_message_size: 6709,
2209 + data_agent_type: "packetbeat",
2210 + streams: ["660320f176ca320e8393f057"],
2211 + rule_mitre_id: "T1071",
2212 + data_destination_bytes: "130",
2213 + data_event_dataset: "dns",
2214 + "data_@metadata_beat": "packetbeat",
2215 + agent_ip: "192.168.100.3",
2216 + data_source_port: "36086",
2217 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2218 + data_event_kind: "event",
2219 + data_network_protocol: "dns",
2220 + dns_response_code: "NOERROR",
2221 + dns_query: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2222 + data_dns_response_code: "NOERROR",
2223 + data_network_community_id: "1:5iZvTrF7flgUj6breYQizRYkGeA=",
2224 + data_dns_flags_truncated_response: "false",
2225 + rule_mail: false,
2226 + data_dns_opt_udp_size: "1232",
2227 + data_event_category: "network",
2228 + data_dns_flags_recursion_available: "true",
2229 + data_dns_opt_version: "0",
2230 + timestamp: "2025-05-23 20:24:13.652",
2231 + data_host_mac: "00-0C-29-09-D5-9B",
2232 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2233 + data_destination_port: "53",
2234 + data_dns_type: "answer",
2235 + traffic_direction: "egress",
2236 + rule_id: "200300",
2237 + data_dns_question_class: "IN",
2238 + cluster_node: "ASHWZHMA.socfortress.local",
2239 + dst_port: "53",
2240 + "data_@timestamp": "2025-05-23T20:24:05.925Z",
2241 + data_event_duration: "54290460",
2242 + data_host_os_platform: "debian",
2243 + data_host_name: "piHole",
2244 + data_dns_flags_recursion_desired: "true",
2245 + data_dns_question_subdomain: "192071-ipv4.gr.global.aa-rt",
2246 + gl2_remote_port: 53306,
2247 + data_host_os_type: "linux",
2248 + source: "10.255.255.13",
2249 + gl2_source_input: "660320f176ca320e8393f030",
2250 + rule_level: 3,
2251 + data_event_type: "connection, protocol",
2252 + data_host_os_family: "debian",
2253 + data_dns_additionals_count: "0",
2254 + data_dns_flags_authentic_data: "false",
2255 + protocol: "udp",
2256 + data_dns_answers:
2257 + "{name=192071-ipv4.gr.global.aa-rt.sharepoint.com, type=CNAME, class=IN, ttl=59, data=192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com}, {type=A, class=IN, ttl=3599, data=52.104.26.41, name=192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com}",
2258 + data_event_start: "2025-05-23T20:24:05.925Z",
2259 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2260 + rule_description: "Linux: DNS Query to 192071-ipv4.gr.global.aa-rt.sharepoint.com",
2261 + data_related_ip: "192.168.100.3, 1.1.1.3, 52.104.26.41",
2262 + data_agent_version: "8.7.1",
2263 + data_status: "OK",
2264 + data_query: "class IN, type A, 192071-ipv4.gr.global.aa-rt.sharepoint.com",
2265 + "data_@metadata_type": "_doc",
2266 + data_server_ip: "1.1.1.3",
2267 + data_method: "QUERY",
2268 + data_dns_question_registered_domain: "sharepoint.com",
2269 + gl2_message_id: "01JVZD2N2MHH1Q2XGV51KGCEMC",
2270 + data_dns_answers_count: "2",
2271 + data_network_type: "ipv4",
2272 + data_dns_opt_ext_rcode: "NOERROR",
2273 + data_client_port: "36086",
2274 + data_network_bytes: "201",
2275 + data_dns_resolved_ip: "52.104.26.41",
2276 + data_host_containerized: "false",
2277 + true: 1748031848.283055,
2278 + data_host_hostname: "piHole",
2279 + rule_groups: "linux, packetbeat, dns",
2280 + data_client_bytes: "71",
2281 + data_dns_question_type: "A",
2282 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2283 + data_destination_ip: "1.1.1.3",
2284 + rule_mitre_technique: "Application Layer Protocol",
2285 + rule_firedtimes: 282,
2286 + data_network_transport: "udp",
2287 + dst_ip: "1.1.1.3",
2288 + src_ip: "192.168.100.3",
2289 + decoder_name: "json",
2290 + syslog_level: "INFO",
2291 + data_dns_op_code: "QUERY",
2292 + data_host_os_version: "11 (bullseye)",
2293 + data_host_os_kernel: "5.10.0-21-amd64",
2294 + cluster_name: "socfortress",
2295 + data_source_bytes: "71",
2296 + gl2_processing_error:
2297 + 'Replaced invalid timestamp value in message <e41411e1-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:08.281+0000> caused exception: Invalid format: "2025-05-23T20:24:08.281+0000" is malformed at "T20:24:08.281+0000".',
2298 + data_dns_opt_do: "true",
2299 + data_dns_authorities_count: "0",
2300 + data_dns_question_name: "192071-ipv4.gr.global.aa-rt.sharepoint.com",
2301 + message:
2302 + '{"true":1748031848.283055,"timestamp":"2025-05-23T20:24:08.281+0000","rule":{"level":3,"description":"Linux: DNS Query to 192071-ipv4.gr.global.aa-rt.sharepoint.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":282,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031848.83748458","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.925Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"server":{"bytes":"130","ip":"1.1.1.3","port":"53"},"event":{"category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"54290460","start":"2025-05-23T20:24:05.925Z","end":"2025-05-23T20:24:05.980Z","kind":"event"},"method":"QUERY","related":{"ip":["192.168.100.3","1.1.1.3","52.104.26.41"]},"query":"class IN, type A, 192071-ipv4.gr.global.aa-rt.sharepoint.com","host":{"ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole","hostname":"piHole","architecture":"x86_64","os":{"platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false"},"source":{"port":"36086","bytes":"71","ip":"192.168.100.3"},"destination":{"ip":"1.1.1.3","port":"53","bytes":"130"},"network":{"transport":"udp","protocol":"dns","direction":"egress","community_id":"1:5iZvTrF7flgUj6breYQizRYkGeA=","bytes":"201","type":"ipv4"},"dns":{"answers":[{"name":"192071-ipv4.gr.global.aa-rt.sharepoint.com","type":"CNAME","class":"IN","ttl":"59","data":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com"},{"type":"A","class":"IN","ttl":"3599","data":"52.104.26.41","name":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com"}],"resolved_ip":["52.104.26.41"],"question":{"registered_domain":"sharepoint.com","top_level_domain":"com","subdomain":"192071-ipv4.gr.global.aa-rt","name":"192071-ipv4.gr.global.aa-rt.sharepoint.com","type":"A","class":"IN","etld_plus_one":"sharepoint.com"},"answers_count":"2","additionals_count":"0","flags":{"authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"},"type":"answer","op_code":"QUERY","header_flags":["RD","RA","DO"],"id":"17463","response_code":"NOERROR","opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"authorities_count":"0"},"client":{"ip":"192.168.100.3","port":"36086","bytes":"71"},"resource":"192071-ipv4.gr.global.aa-rt.sharepoint.com","agent":{"type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole"},"ecs":{"version":"8.0.0"},"type":"dns"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2303 + dns_answer: "52.104.26.41",
2304 + data_dns_id: "17463",
2305 + src_port: "36086",
2306 + manager_name: "ASHWZHMA",
2307 + data_network_direction: "egress",
2308 + data_dns_question_top_level_domain: "com",
2309 + data_event_end: "2025-05-23T20:24:05.980Z",
2310 + data_agent_name: "piHole",
2311 + data_server_bytes: "130",
2312 + data_dns_flags_authoritative: "false",
2313 + data_client_ip: "192.168.100.3",
2314 + data_dns_header_flags: "RD, RA, DO",
2315 + data_type: "dns",
2316 + data_dns_flags_checking_disabled: "false",
2317 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2318 + "data_@metadata_version": "8.7.1",
2319 + data_host_os_name: "Debian GNU/Linux",
2320 + rule_group3: "dns",
2321 + msg_timestamp: "2025-05-23T20:24:08.281Z",
2322 + rule_group2: "packetbeat",
2323 + rule_group1: "linux"
2324 + },
2325 + {
2326 + data_source_ip: "192.168.100.3",
2327 + data_host_architecture: "x86_64",
2328 + agent_id: "032",
2329 + agent_name: "piHole",
2330 + gl2_remote_ip: "10.255.255.13",
2331 + data_resource: "192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com",
2332 + agent_labels_customer: "00001",
2333 + data_ecs_version: "8.0.0",
2334 + timestamp_utc: "2025-05-23T20:24:05.980Z",
2335 + data_host_os_codename: "bullseye",
2336 + syslog_type: "wazuh",
2337 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2338 + id: "1748031848.83754595",
2339 + data_dns_question_etld_plus_one: "sharepoint.com",
2340 + data_server_port: "53",
2341 + rule_mitre_tactic: "Command and Control",
2342 + gl2_accounted_message_size: 6493,
2343 + data_agent_type: "packetbeat",
2344 + streams: ["660320f176ca320e8393f057"],
2345 + rule_mitre_id: "T1071",
2346 + data_destination_bytes: "94",
2347 + data_event_dataset: "dns",
2348 + "data_@metadata_beat": "packetbeat",
2349 + agent_ip: "192.168.100.3",
2350 + data_source_port: "33365",
2351 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2352 + data_event_kind: "event",
2353 + data_network_protocol: "dns",
2354 + dns_response_code: "NOERROR",
2355 + dns_query: "192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com",
2356 + data_dns_response_code: "NOERROR",
2357 + data_network_community_id: "1:8sjmsqnhAWFl5tsJDVLyv/9bmRA=",
2358 + data_dns_flags_truncated_response: "false",
2359 + rule_mail: false,
2360 + data_dns_opt_udp_size: "1232",
2361 + data_event_category: "network",
2362 + data_dns_flags_recursion_available: "true",
2363 + data_dns_opt_version: "0",
2364 + timestamp: "2025-05-23 20:24:13.532",
2365 + data_host_mac: "00-0C-29-09-D5-9B",
2366 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2367 + data_destination_port: "53",
2368 + data_dns_type: "answer",
2369 + traffic_direction: "egress",
2370 + rule_id: "200300",
2371 + data_dns_question_class: "IN",
2372 + cluster_node: "ASHWZHMA.socfortress.local",
2373 + dst_port: "53",
2374 + "data_@timestamp": "2025-05-23T20:24:05.980Z",
2375 + data_event_duration: "44621509",
2376 + data_host_os_platform: "debian",
2377 + data_dns_flags_recursion_desired: "true",
2378 + data_host_name: "piHole",
2379 + data_dns_question_subdomain: "192071-ipv4.farm.dprodmgd105.aa-rt",
2380 + gl2_remote_port: 53306,
2381 + data_host_os_type: "linux",
2382 + source: "10.255.255.13",
2383 + gl2_source_input: "660320f176ca320e8393f030",
2384 + rule_level: 3,
2385 + data_event_type: "connection, protocol",
2386 + data_host_os_family: "debian",
2387 + data_dns_additionals_count: "0",
2388 + data_dns_flags_authentic_data: "false",
2389 + protocol: "udp",
2390 + data_dns_answers:
2391 + "{name=192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com, type=A, class=IN, ttl=3600, data=52.104.26.41}",
2392 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2393 + data_event_start: "2025-05-23T20:24:05.980Z",
2394 + rule_description: "Linux: DNS Query to 192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com",
2395 + data_related_ip: "192.168.100.3, 1.1.1.3, 52.104.26.41",
2396 + data_agent_version: "8.7.1",
2397 + data_status: "OK",
2398 + data_query: "class IN, type A, 192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com",
2399 + "data_@metadata_type": "_doc",
2400 + data_method: "QUERY",
2401 + data_dns_question_registered_domain: "sharepoint.com",
2402 + data_server_ip: "1.1.1.3",
2403 + gl2_message_id: "01JVZD2MYW83NXNFSK6RC1FV7V",
2404 + data_dns_answers_count: "1",
2405 + data_network_type: "ipv4",
2406 + data_dns_opt_ext_rcode: "NOERROR",
2407 + data_client_port: "33365",
2408 + data_network_bytes: "172",
2409 + data_dns_resolved_ip: "52.104.26.41",
2410 + data_host_containerized: "false",
2411 + true: 1748031848.951426,
2412 + data_host_hostname: "piHole",
2413 + rule_groups: "linux, packetbeat, dns",
2414 + data_client_bytes: "78",
2415 + data_dns_question_type: "A",
2416 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2417 + data_destination_ip: "1.1.1.3",
2418 + rule_mitre_technique: "Application Layer Protocol",
2419 + rule_firedtimes: 283,
2420 + data_network_transport: "udp",
2421 + dst_ip: "1.1.1.3",
2422 + src_ip: "192.168.100.3",
2423 + decoder_name: "json",
2424 + syslog_level: "INFO",
2425 + data_dns_op_code: "QUERY",
2426 + data_host_os_version: "11 (bullseye)",
2427 + data_host_os_kernel: "5.10.0-21-amd64",
2428 + cluster_name: "socfortress",
2429 + data_source_bytes: "78",
2430 + gl2_processing_error:
2431 + 'Replaced invalid timestamp value in message <e41438f0-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:08.282+0000> caused exception: Invalid format: "2025-05-23T20:24:08.282+0000" is malformed at "T20:24:08.282+0000".',
2432 + data_dns_opt_do: "true",
2433 + data_dns_authorities_count: "0",
2434 + data_dns_question_name: "192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com",
2435 + message:
2436 + '{"true":1748031848.951426,"timestamp":"2025-05-23T20:24:08.282+0000","rule":{"level":3,"description":"Linux: DNS Query to 192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":283,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031848.83754595","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.980Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"source":{"bytes":"78","ip":"192.168.100.3","port":"33365"},"method":"QUERY","query":"class IN, type A, 192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com","dns":{"answers_count":"1","answers":[{"name":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com","type":"A","class":"IN","ttl":"3600","data":"52.104.26.41"}],"response_code":"NOERROR","authorities_count":"0","additionals_count":"0","type":"answer","id":"60845","resolved_ip":["52.104.26.41"],"flags":{"recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true"},"question":{"class":"IN","etld_plus_one":"sharepoint.com","registered_domain":"sharepoint.com","top_level_domain":"com","subdomain":"192071-ipv4.farm.dprodmgd105.aa-rt","name":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com","type":"A"},"opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"op_code":"QUERY","header_flags":["RD","RA","DO"]},"related":{"ip":["192.168.100.3","1.1.1.3","52.104.26.41"]},"client":{"ip":"192.168.100.3","port":"33365","bytes":"78"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:8sjmsqnhAWFl5tsJDVLyv/9bmRA=","bytes":"172"},"agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"},"ecs":{"version":"8.0.0"},"event":{"end":"2025-05-23T20:24:06.025Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"44621509","start":"2025-05-23T20:24:05.980Z"},"type":"dns","server":{"port":"53","bytes":"94","ip":"1.1.1.3"},"host":{"hostname":"piHole","architecture":"x86_64","os":{"version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole"},"destination":{"ip":"1.1.1.3","port":"53","bytes":"94"},"resource":"192071-ipv4.farm.dprodmgd105.aa-rt.sharepoint.com"},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2437 + dns_answer: "52.104.26.41",
2438 + data_dns_id: "60845",
2439 + src_port: "33365",
2440 + manager_name: "ASHWZHMA",
2441 + data_dns_question_top_level_domain: "com",
2442 + data_network_direction: "egress",
2443 + data_event_end: "2025-05-23T20:24:06.025Z",
2444 + data_agent_name: "piHole",
2445 + data_dns_flags_authoritative: "false",
2446 + data_client_ip: "192.168.100.3",
2447 + data_server_bytes: "94",
2448 + data_dns_header_flags: "RD, RA, DO",
2449 + data_type: "dns",
2450 + data_dns_flags_checking_disabled: "false",
2451 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2452 + "data_@metadata_version": "8.7.1",
2453 + data_host_os_name: "Debian GNU/Linux",
2454 + rule_group3: "dns",
2455 + msg_timestamp: "2025-05-23T20:24:08.282Z",
2456 + rule_group2: "packetbeat",
2457 + rule_group1: "linux"
2458 + },
2459 + {
2460 + data_source_ip: "192.168.100.1",
2461 + data_host_architecture: "x86_64",
2462 + agent_id: "032",
2463 + agent_name: "piHole",
2464 + gl2_remote_ip: "10.255.255.13",
2465 + data_resource: "browser-intake-datadoghq.com",
2466 + agent_labels_customer: "00001",
2467 + data_ecs_version: "8.0.0",
2468 + timestamp_utc: "2025-05-23T20:24:05.363Z",
2469 + data_host_os_codename: "bullseye",
2470 + syslog_type: "wazuh",
2471 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2472 + id: "1748031848.83745642",
2473 + data_dns_question_etld_plus_one: "browser-intake-datadoghq.com",
2474 + data_server_port: "53",
2475 + rule_mitre_tactic: "Command and Control",
2476 + gl2_accounted_message_size: 6213,
2477 + data_agent_type: "packetbeat",
2478 + streams: ["660320f176ca320e8393f057"],
2479 + rule_mitre_id: "T1071",
2480 + data_destination_bytes: "73",
2481 + data_event_dataset: "dns",
2482 + "data_@metadata_beat": "packetbeat",
2483 + agent_ip: "192.168.100.3",
2484 + data_source_port: "62861",
2485 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2486 + data_event_kind: "event",
2487 + data_network_protocol: "dns",
2488 + dns_response_code: "NOERROR",
2489 + dns_query: "browser-intake-datadoghq.com",
2490 + data_dns_response_code: "NOERROR",
2491 + data_network_community_id: "1:I5jTWyK/ZK6S56G3s+cDVNVF6+s=",
2492 + data_dns_flags_truncated_response: "false",
2493 + rule_mail: false,
2494 + data_dns_opt_udp_size: "1232",
2495 + data_event_category: "network",
2496 + data_dns_flags_recursion_available: "true",
2497 + data_dns_opt_version: "0",
2498 + timestamp: "2025-05-23 20:24:13.532",
2499 + data_host_mac: "00-0C-29-09-D5-9B",
2500 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2501 + data_destination_port: "53",
2502 + data_dns_type: "answer",
2503 + traffic_direction: "ingress",
2504 + rule_id: "200300",
2505 + data_dns_question_class: "IN",
2506 + cluster_node: "ASHWZHMA.socfortress.local",
2507 + dst_port: "53",
2508 + "data_@timestamp": "2025-05-23T20:24:05.363Z",
2509 + data_event_duration: "119080",
2510 + data_host_os_platform: "debian",
2511 + data_dns_flags_recursion_desired: "true",
2512 + data_host_name: "piHole",
2513 + gl2_remote_port: 53306,
2514 + data_host_os_type: "linux",
2515 + source: "10.255.255.13",
2516 + gl2_source_input: "660320f176ca320e8393f030",
2517 + rule_level: 3,
2518 + data_event_type: "connection, protocol",
2519 + data_host_os_family: "debian",
2520 + data_dns_additionals_count: "0",
2521 + data_dns_flags_authentic_data: "false",
2522 + protocol: "udp",
2523 + data_dns_answers: "{name=browser-intake-datadoghq.com, type=A, class=IN, ttl=2, data=0.0.0.0}",
2524 + data_event_start: "2025-05-23T20:24:05.363Z",
2525 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2526 + rule_description: "Linux: DNS Query to browser-intake-datadoghq.com",
2527 + data_related_ip: "192.168.100.1, 192.168.100.3, 0.0.0.0",
2528 + data_agent_version: "8.7.1",
2529 + data_status: "OK",
2530 + data_query: "class IN, type A, browser-intake-datadoghq.com",
2531 + "data_@metadata_type": "_doc",
2532 + data_dns_question_registered_domain: "browser-intake-datadoghq.com",
2533 + data_method: "QUERY",
2534 + data_server_ip: "192.168.100.3",
2535 + gl2_message_id: "01JVZD2MYW05N49ASCDWBHBBM2",
2536 + data_dns_answers_count: "1",
2537 + data_network_type: "ipv4",
2538 + data_dns_opt_ext_rcode: "NOERROR",
2539 + data_client_port: "62861",
2540 + data_network_bytes: "130",
2541 + data_dns_resolved_ip: "0.0.0.0",
2542 + data_host_containerized: "false",
2543 + true: 1748031848.282895,
2544 + data_host_hostname: "piHole",
2545 + rule_groups: "linux, packetbeat, dns",
2546 + data_client_bytes: "57",
2547 + data_dns_question_type: "A",
2548 + data_destination_ip: "192.168.100.3",
2549 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2550 + rule_mitre_technique: "Application Layer Protocol",
2551 + rule_firedtimes: 280,
2552 + data_network_transport: "udp",
2553 + dst_ip: "192.168.100.3",
2554 + src_ip: "192.168.100.1",
2555 + decoder_name: "json",
2556 + syslog_level: "INFO",
2557 + data_dns_op_code: "QUERY",
2558 + data_host_os_version: "11 (bullseye)",
2559 + data_host_os_kernel: "5.10.0-21-amd64",
2560 + cluster_name: "socfortress",
2561 + data_source_bytes: "57",
2562 + gl2_processing_error:
2563 + 'Replaced invalid timestamp value in message <e41411e0-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:08.240+0000> caused exception: Invalid format: "2025-05-23T20:24:08.240+0000" is malformed at "T20:24:08.240+0000".',
2564 + data_dns_opt_do: "true",
2565 + data_dns_authorities_count: "0",
2566 + data_dns_question_name: "browser-intake-datadoghq.com",
2567 + message:
2568 + '{"true":1748031848.282895,"timestamp":"2025-05-23T20:24:08.240+0000","rule":{"level":3,"description":"Linux: DNS Query to browser-intake-datadoghq.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":280,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031848.83745642","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.363Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"ip":"192.168.100.1","port":"62861","bytes":"57"},"network":{"transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:I5jTWyK/ZK6S56G3s+cDVNVF6+s=","bytes":"130","type":"ipv4"},"event":{"duration":"119080","start":"2025-05-23T20:24:05.363Z","end":"2025-05-23T20:24:05.364Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns"},"type":"dns","ecs":{"version":"8.0.0"},"dns":{"additionals_count":"0","flags":{"authoritative":"true","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"},"id":"4301","response_code":"NOERROR","resolved_ip":["0.0.0.0"],"header_flags":["AA","RD","RA","DO"],"answers_count":"1","op_code":"QUERY","question":{"class":"IN","etld_plus_one":"browser-intake-datadoghq.com","registered_domain":"browser-intake-datadoghq.com","top_level_domain":"com","name":"browser-intake-datadoghq.com","type":"A"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"answers":[{"name":"browser-intake-datadoghq.com","type":"A","class":"IN","ttl":"2","data":"0.0.0.0"}],"authorities_count":"0","type":"answer"},"source":{"ip":"192.168.100.1","port":"62861","bytes":"57"},"query":"class IN, type A, browser-intake-datadoghq.com","resource":"browser-intake-datadoghq.com","destination":{"port":"53","bytes":"73","ip":"192.168.100.3"},"method":"QUERY","host":{"architecture":"x86_64","os":{"family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","name":"piHole"},"related":{"ip":["192.168.100.1","192.168.100.3","0.0.0.0"]},"server":{"ip":"192.168.100.3","port":"53","bytes":"73"},"agent":{"id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2569 + dns_answer: "0.0.0.0",
2570 + data_dns_id: "4301",
2571 + src_port: "62861",
2572 + manager_name: "ASHWZHMA",
2573 + data_network_direction: "ingress",
2574 + data_dns_question_top_level_domain: "com",
2575 + data_event_end: "2025-05-23T20:24:05.364Z",
2576 + data_agent_name: "piHole",
2577 + data_client_ip: "192.168.100.1",
2578 + data_dns_flags_authoritative: "true",
2579 + data_server_bytes: "73",
2580 + data_type: "dns",
2581 + data_dns_header_flags: "AA, RD, RA, DO",
2582 + data_dns_flags_checking_disabled: "false",
2583 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2584 + "data_@metadata_version": "8.7.1",
2585 + data_host_os_name: "Debian GNU/Linux",
2586 + rule_group3: "dns",
2587 + msg_timestamp: "2025-05-23T20:24:08.240Z",
2588 + rule_group2: "packetbeat",
2589 + rule_group1: "linux"
2590 + },
2591 + {
2592 + data_source_ip: "192.168.100.1",
2593 + data_host_architecture: "x86_64",
2594 + agent_id: "032",
2595 + agent_name: "piHole",
2596 + gl2_remote_ip: "10.255.255.13",
2597 + data_resource: "www.tm.v4.a.prd.aadg.akadns.net",
2598 + agent_labels_customer: "00001",
2599 + data_ecs_version: "8.0.0",
2600 + timestamp_utc: "2025-05-23T20:24:05.033Z",
2601 + data_host_os_codename: "bullseye",
2602 + syslog_type: "wazuh",
2603 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2604 + id: "1748031846.83734359",
2605 + data_server_port: "53",
2606 + data_dns_question_etld_plus_one: "akadns.net",
2607 + rule_mitre_tactic: "Command and Control",
2608 + gl2_accounted_message_size: 8100,
2609 + data_agent_type: "packetbeat",
2610 + streams: ["660320f176ca320e8393f057"],
2611 + rule_mitre_id: "T1071",
2612 + data_destination_bytes: "188",
2613 + data_event_dataset: "dns",
2614 + "data_@metadata_beat": "packetbeat",
2615 + agent_ip: "192.168.100.3",
2616 + data_source_port: "38616",
2617 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2618 + data_event_kind: "event",
2619 + data_network_protocol: "dns",
2620 + dns_response_code: "NOERROR",
2621 + dns_query: "www.tm.v4.a.prd.aadg.akadns.net",
2622 + data_dns_response_code: "NOERROR",
2623 + data_network_community_id: "1:d5Hlw2X6vZE+Qn/Ex1rZR9GqtxA=",
2624 + data_dns_flags_truncated_response: "false",
2625 + rule_mail: false,
2626 + data_dns_opt_udp_size: "1232",
2627 + data_event_category: "network",
2628 + data_dns_flags_recursion_available: "true",
2629 + data_dns_opt_version: "0",
2630 + timestamp: "2025-05-23 20:24:09.408",
2631 + data_host_mac: "00-0C-29-09-D5-9B",
2632 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2633 + data_destination_port: "53",
2634 + data_dns_type: "answer",
2635 + traffic_direction: "ingress",
2636 + rule_id: "200300",
2637 + data_dns_question_class: "IN",
2638 + cluster_node: "ASHWZHMA.socfortress.local",
2639 + dst_port: "53",
2640 + "data_@timestamp": "2025-05-23T20:24:05.033Z",
2641 + data_host_os_platform: "debian",
2642 + data_event_duration: "63234444",
2643 + data_host_name: "piHole",
2644 + data_dns_flags_recursion_desired: "true",
2645 + data_dns_question_subdomain: "www.tm.v4.a.prd.aadg",
2646 + gl2_remote_port: 53290,
2647 + data_host_os_type: "linux",
2648 + source: "10.255.255.13",
2649 + gl2_source_input: "660320f176ca320e8393f030",
2650 + rule_level: 3,
2651 + data_event_type: "connection, protocol",
2652 + data_host_os_family: "debian",
2653 + data_dns_additionals_count: "0",
2654 + data_dns_flags_authentic_data: "false",
2655 + protocol: "udp",
2656 + data_dns_answers:
2657 + "{data=20.190.135.17, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93}, {class=IN, ttl=93, data=20.190.135.6, name=www.tm.v4.a.prd.aadg.akadns.net, type=A}, {type=A, class=IN, ttl=93, data=40.126.7.35, name=www.tm.v4.a.prd.aadg.akadns.net}, {ttl=93, data=40.126.28.23, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {class=IN, ttl=93, data=40.126.28.19, name=www.tm.v4.a.prd.aadg.akadns.net, type=A}, {type=A, class=IN, ttl=93, data=20.190.135.16, name=www.tm.v4.a.prd.aadg.akadns.net}, {data=40.126.28.11, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93}, {name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93, data=20.190.135.7}",
2658 + data_event_start: "2025-05-23T20:24:05.033Z",
2659 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2660 + rule_description: "Linux: DNS Query to www.tm.v4.a.prd.aadg.akadns.net",
2661 + data_related_ip:
2662 + "192.168.100.1, 192.168.100.3, 20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2663 + data_agent_version: "8.7.1",
2664 + data_status: "OK",
2665 + data_query: "class IN, type A, www.tm.v4.a.prd.aadg.akadns.net",
2666 + "data_@metadata_type": "_doc",
2667 + data_server_ip: "192.168.100.3",
2668 + data_method: "QUERY",
2669 + data_dns_question_registered_domain: "akadns.net",
2670 + gl2_message_id: "01JVZD2GY0JG6V9D7S7RB24AKN",
2671 + data_dns_answers_count: "8",
2672 + data_network_type: "ipv4",
2673 + data_dns_opt_ext_rcode: "NOERROR",
2674 + data_client_port: "38616",
2675 + data_network_bytes: "248",
2676 + data_dns_resolved_ip:
2677 + "20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2678 + data_host_containerized: "false",
2679 + true: 1748031846.313782,
2680 + data_host_hostname: "piHole",
2681 + rule_groups: "linux, packetbeat, dns",
2682 + data_client_bytes: "60",
2683 + data_dns_question_type: "A",
2684 + data_destination_ip: "192.168.100.3",
2685 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2686 + rule_mitre_technique: "Application Layer Protocol",
2687 + rule_firedtimes: 278,
2688 + data_network_transport: "udp",
2689 + dst_ip: "192.168.100.3",
2690 + src_ip: "192.168.100.1",
2691 + decoder_name: "json",
2692 + syslog_level: "INFO",
2693 + data_dns_op_code: "QUERY",
2694 + data_host_os_version: "11 (bullseye)",
2695 + data_host_os_kernel: "5.10.0-21-amd64",
2696 + cluster_name: "socfortress",
2697 + data_source_bytes: "60",
2698 + gl2_processing_error:
2699 + 'Replaced invalid timestamp value in message <e18f89e0-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.312+0000> caused exception: Invalid format: "2025-05-23T20:24:06.312+0000" is malformed at "T20:24:06.312+0000".',
2700 + data_dns_opt_do: "true",
2701 + data_dns_authorities_count: "0",
2702 + data_dns_question_name: "www.tm.v4.a.prd.aadg.akadns.net",
2703 + message:
2704 + '{"true":1748031846.313782,"timestamp":"2025-05-23T20:24:06.312+0000","rule":{"level":3,"description":"Linux: DNS Query to www.tm.v4.a.prd.aadg.akadns.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":278,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83734359","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.033Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"network":{"bytes":"248","type":"ipv4","transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:d5Hlw2X6vZE+Qn/Ex1rZR9GqtxA="},"destination":{"bytes":"188","ip":"192.168.100.3","port":"53"},"ecs":{"version":"8.0.0"},"client":{"ip":"192.168.100.1","port":"38616","bytes":"60"},"query":"class IN, type A, www.tm.v4.a.prd.aadg.akadns.net","host":{"name":"piHole","architecture":"x86_64","os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole"},"server":{"ip":"192.168.100.3","port":"53","bytes":"188"},"method":"QUERY","related":{"ip":["192.168.100.1","192.168.100.3","20.190.135.17","20.190.135.6","40.126.7.35","40.126.28.23","40.126.28.19","20.190.135.16","40.126.28.11","20.190.135.7"]},"event":{"category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"63234444","start":"2025-05-23T20:24:05.033Z","end":"2025-05-23T20:24:05.096Z","kind":"event"},"type":"dns","source":{"ip":"192.168.100.1","port":"38616","bytes":"60"},"dns":{"op_code":"QUERY","authorities_count":"0","additionals_count":"0","question":{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","etld_plus_one":"akadns.net","registered_domain":"akadns.net","top_level_domain":"net","subdomain":"www.tm.v4.a.prd.aadg"},"header_flags":["RD","RA","DO"],"opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"},"resolved_ip":["20.190.135.17","20.190.135.6","40.126.7.35","40.126.28.23","40.126.28.19","20.190.135.16","40.126.28.11","20.190.135.7"],"id":"1767","flags":{"authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false"},"response_code":"NOERROR","answers":[{"data":"20.190.135.17","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93"},{"class":"IN","ttl":"93","data":"20.190.135.6","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A"},{"type":"A","class":"IN","ttl":"93","data":"40.126.7.35","name":"www.tm.v4.a.prd.aadg.akadns.net"},{"ttl":"93","data":"40.126.28.23","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"class":"IN","ttl":"93","data":"40.126.28.19","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A"},{"type":"A","class":"IN","ttl":"93","data":"20.190.135.16","name":"www.tm.v4.a.prd.aadg.akadns.net"},{"data":"40.126.28.11","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93"},{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93","data":"20.190.135.7"}],"type":"answer","answers_count":"8"},"resource":"www.tm.v4.a.prd.aadg.akadns.net","agent":{"version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2705 + dns_answer:
2706 + "20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2707 + data_dns_id: "1767",
2708 + src_port: "38616",
2709 + manager_name: "ASHWZHMA",
2710 + data_network_direction: "ingress",
2711 + data_dns_question_top_level_domain: "net",
2712 + data_event_end: "2025-05-23T20:24:05.096Z",
2713 + data_agent_name: "piHole",
2714 + data_client_ip: "192.168.100.1",
2715 + data_server_bytes: "188",
2716 + data_dns_flags_authoritative: "false",
2717 + data_type: "dns",
2718 + data_dns_header_flags: "RD, RA, DO",
2719 + data_dns_flags_checking_disabled: "false",
2720 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2721 + "data_@metadata_version": "8.7.1",
2722 + data_host_os_name: "Debian GNU/Linux",
2723 + rule_group3: "dns",
2724 + msg_timestamp: "2025-05-23T20:24:06.312Z",
2725 + rule_group2: "packetbeat",
2726 + rule_group1: "linux"
2727 + },
2728 + {
2729 + data_source_ip: "192.168.100.3",
2730 + data_host_architecture: "x86_64",
2731 + agent_id: "032",
2732 + agent_name: "piHole",
2733 + gl2_remote_ip: "10.255.255.13",
2734 + data_resource: "www.tm.v4.a.prd.aadg.akadns.net",
2735 + agent_labels_customer: "00001",
2736 + data_ecs_version: "8.0.0",
2737 + timestamp_utc: "2025-05-23T20:24:05.033Z",
2738 + data_host_os_codename: "bullseye",
2739 + syslog_type: "wazuh",
2740 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2741 + id: "1748031846.83738118",
2742 + data_dns_question_etld_plus_one: "akadns.net",
2743 + data_server_port: "53",
2744 + rule_mitre_tactic: "Command and Control",
2745 + gl2_accounted_message_size: 8057,
2746 + data_agent_type: "packetbeat",
2747 + streams: ["660320f176ca320e8393f057"],
2748 + rule_mitre_id: "T1071",
2749 + data_destination_bytes: "188",
2750 + data_event_dataset: "dns",
2751 + "data_@metadata_beat": "packetbeat",
2752 + agent_ip: "192.168.100.3",
2753 + data_source_port: "35015",
2754 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2755 + data_event_kind: "event",
2756 + data_network_protocol: "dns",
2757 + dns_response_code: "NOERROR",
2758 + dns_query: "www.tm.v4.a.prd.aadg.akadns.net",
2759 + data_dns_response_code: "NOERROR",
2760 + data_network_community_id: "1:oWVDnNzsSDgmenqSFSwrd2TfgeM=",
2761 + data_dns_flags_truncated_response: "false",
2762 + rule_mail: false,
2763 + data_dns_opt_udp_size: "1232",
2764 + data_event_category: "network",
2765 + data_dns_flags_recursion_available: "true",
2766 + data_dns_opt_version: "0",
2767 + timestamp: "2025-05-23 20:24:09.408",
2768 + data_host_mac: "00-0C-29-09-D5-9B",
2769 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2770 + data_destination_port: "53",
2771 + data_dns_type: "answer",
2772 + traffic_direction: "egress",
2773 + rule_id: "200300",
2774 + data_dns_question_class: "IN",
2775 + cluster_node: "ASHWZHMA.socfortress.local",
2776 + dst_port: "53",
2777 + "data_@timestamp": "2025-05-23T20:24:05.033Z",
2778 + data_host_os_platform: "debian",
2779 + data_event_duration: "63064417",
2780 + data_dns_flags_recursion_desired: "true",
2781 + data_host_name: "piHole",
2782 + data_dns_question_subdomain: "www.tm.v4.a.prd.aadg",
2783 + gl2_remote_port: 53290,
2784 + data_host_os_type: "linux",
2785 + source: "10.255.255.13",
2786 + gl2_source_input: "660320f176ca320e8393f030",
2787 + rule_level: 3,
2788 + data_event_type: "connection, protocol",
2789 + data_host_os_family: "debian",
2790 + data_dns_additionals_count: "0",
2791 + data_dns_flags_authentic_data: "false",
2792 + protocol: "udp",
2793 + data_dns_answers:
2794 + "{name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93, data=20.190.135.17}, {name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93, data=20.190.135.6}, {ttl=93, data=40.126.7.35, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {data=40.126.28.23, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93}, {ttl=93, data=40.126.28.19, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {data=20.190.135.16, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=93}, {type=A, class=IN, ttl=93, data=40.126.28.11, name=www.tm.v4.a.prd.aadg.akadns.net}, {ttl=93, data=20.190.135.7, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}",
2795 + data_event_start: "2025-05-23T20:24:05.033Z",
2796 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2797 + rule_description: "Linux: DNS Query to www.tm.v4.a.prd.aadg.akadns.net",
2798 + data_related_ip:
2799 + "192.168.100.3, 1.1.1.3, 20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2800 + data_agent_version: "8.7.1",
2801 + data_status: "OK",
2802 + data_query: "class IN, type A, www.tm.v4.a.prd.aadg.akadns.net",
2803 + "data_@metadata_type": "_doc",
2804 + data_dns_question_registered_domain: "akadns.net",
2805 + data_method: "QUERY",
2806 + data_server_ip: "1.1.1.3",
2807 + gl2_message_id: "01JVZD2GY0QX7GK1F7ZY7JBJTR",
2808 + data_dns_answers_count: "8",
2809 + data_network_type: "ipv4",
2810 + data_dns_opt_ext_rcode: "NOERROR",
2811 + data_client_port: "35015",
2812 + data_network_bytes: "248",
2813 + data_dns_resolved_ip:
2814 + "20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2815 + data_host_containerized: "false",
2816 + true: 1748031846.950923,
2817 + data_host_hostname: "piHole",
2818 + rule_groups: "linux, packetbeat, dns",
2819 + data_client_bytes: "60",
2820 + data_dns_question_type: "A",
2821 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2822 + data_destination_ip: "1.1.1.3",
2823 + rule_mitre_technique: "Application Layer Protocol",
2824 + rule_firedtimes: 279,
2825 + data_network_transport: "udp",
2826 + dst_ip: "1.1.1.3",
2827 + src_ip: "192.168.100.3",
2828 + decoder_name: "json",
2829 + syslog_level: "INFO",
2830 + data_dns_op_code: "QUERY",
2831 + data_host_os_version: "11 (bullseye)",
2832 + data_host_os_kernel: "5.10.0-21-amd64",
2833 + cluster_name: "socfortress",
2834 + data_source_bytes: "60",
2835 + gl2_processing_error:
2836 + 'Replaced invalid timestamp value in message <e18fd800-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.312+0000> caused exception: Invalid format: "2025-05-23T20:24:06.312+0000" is malformed at "T20:24:06.312+0000".',
2837 + data_dns_opt_do: "true",
2838 + data_dns_authorities_count: "0",
2839 + data_dns_question_name: "www.tm.v4.a.prd.aadg.akadns.net",
2840 + message:
2841 + '{"true":1748031846.950923,"timestamp":"2025-05-23T20:24:06.312+0000","rule":{"level":3,"description":"Linux: DNS Query to www.tm.v4.a.prd.aadg.akadns.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":279,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83738118","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:05.033Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"port":"35015","bytes":"60","ip":"192.168.100.3"},"dns":{"op_code":"QUERY","answers":[{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93","data":"20.190.135.17"},{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93","data":"20.190.135.6"},{"ttl":"93","data":"40.126.7.35","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"data":"40.126.28.23","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93"},{"ttl":"93","data":"40.126.28.19","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"data":"20.190.135.16","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"93"},{"type":"A","class":"IN","ttl":"93","data":"40.126.28.11","name":"www.tm.v4.a.prd.aadg.akadns.net"},{"ttl":"93","data":"20.190.135.7","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"}],"additionals_count":"0","question":{"class":"IN","etld_plus_one":"akadns.net","registered_domain":"akadns.net","top_level_domain":"net","subdomain":"www.tm.v4.a.prd.aadg","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"type":"answer","id":"11576","answers_count":"8","resolved_ip":["20.190.135.17","20.190.135.6","40.126.7.35","40.126.28.23","40.126.28.19","20.190.135.16","40.126.28.11","20.190.135.7"],"authorities_count":"0","flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"response_code":"NOERROR","header_flags":["RD","RA","DO"]},"host":{"name":"piHole","mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","os":{"version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"]},"destination":{"bytes":"188","ip":"1.1.1.3","port":"53"},"event":{"end":"2025-05-23T20:24:05.096Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"63064417","start":"2025-05-23T20:24:05.033Z"},"method":"QUERY","query":"class IN, type A, www.tm.v4.a.prd.aadg.akadns.net","server":{"ip":"1.1.1.3","port":"53","bytes":"188"},"related":{"ip":["192.168.100.3","1.1.1.3","20.190.135.17","20.190.135.6","40.126.7.35","40.126.28.23","40.126.28.19","20.190.135.16","40.126.28.11","20.190.135.7"]},"resource":"www.tm.v4.a.prd.aadg.akadns.net","agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"},"type":"dns","source":{"ip":"192.168.100.3","port":"35015","bytes":"60"},"network":{"direction":"egress","community_id":"1:oWVDnNzsSDgmenqSFSwrd2TfgeM=","bytes":"248","type":"ipv4","transport":"udp","protocol":"dns"},"ecs":{"version":"8.0.0"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2842 + dns_answer:
2843 + "20.190.135.17, 20.190.135.6, 40.126.7.35, 40.126.28.23, 40.126.28.19, 20.190.135.16, 40.126.28.11, 20.190.135.7",
2844 + data_dns_id: "11576",
2845 + src_port: "35015",
2846 + manager_name: "ASHWZHMA",
2847 + data_dns_question_top_level_domain: "net",
2848 + data_network_direction: "egress",
2849 + data_event_end: "2025-05-23T20:24:05.096Z",
2850 + data_agent_name: "piHole",
2851 + data_client_ip: "192.168.100.3",
2852 + data_dns_flags_authoritative: "false",
2853 + data_server_bytes: "188",
2854 + data_dns_header_flags: "RD, RA, DO",
2855 + data_type: "dns",
2856 + data_dns_flags_checking_disabled: "false",
2857 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2858 + "data_@metadata_version": "8.7.1",
2859 + data_host_os_name: "Debian GNU/Linux",
2860 + rule_group3: "dns",
2861 + msg_timestamp: "2025-05-23T20:24:06.312Z",
2862 + rule_group2: "packetbeat",
2863 + rule_group1: "linux"
2864 + },
2865 + {
2866 + data_source_ip: "192.168.100.1",
2867 + data_host_architecture: "x86_64",
2868 + agent_id: "032",
2869 + agent_name: "piHole",
2870 + gl2_remote_ip: "10.255.255.13",
2871 + data_resource: "www.tm.lg.prod.aadmsa.trafficmanager.net",
2872 + agent_labels_customer: "00001",
2873 + data_ecs_version: "8.0.0",
2874 + timestamp_utc: "2025-05-23T20:24:04.870Z",
2875 + data_host_os_codename: "bullseye",
2876 + syslog_type: "wazuh",
2877 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
2878 + id: "1748031846.83726440",
2879 + data_dns_question_etld_plus_one: "trafficmanager.net",
2880 + data_server_port: "53",
2881 + rule_mitre_tactic: "Command and Control",
2882 + gl2_accounted_message_size: 8706,
2883 + data_agent_type: "packetbeat",
2884 + streams: ["660320f176ca320e8393f057"],
2885 + rule_mitre_id: "T1071",
2886 + data_destination_bytes: "279",
2887 + data_event_dataset: "dns",
2888 + "data_@metadata_beat": "packetbeat",
2889 + agent_ip: "192.168.100.3",
2890 + data_source_port: "10699",
2891 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
2892 + data_event_kind: "event",
2893 + data_network_protocol: "dns",
2894 + dns_response_code: "NOERROR",
2895 + dns_query: "www.tm.lg.prod.aadmsa.trafficmanager.net",
2896 + data_dns_response_code: "NOERROR",
2897 + data_network_community_id: "1:rRbPmhPceaU7J6cD1EfgYg23n5U=",
2898 + data_dns_flags_truncated_response: "false",
2899 + rule_mail: false,
2900 + data_dns_opt_udp_size: "1232",
2901 + data_event_category: "network",
2902 + data_dns_flags_recursion_available: "true",
2903 + data_dns_opt_version: "0",
2904 + timestamp: "2025-05-23 20:24:09.407",
2905 + data_host_mac: "00-0C-29-09-D5-9B",
2906 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
2907 + data_destination_port: "53",
2908 + data_dns_type: "answer",
2909 + traffic_direction: "ingress",
2910 + rule_id: "200300",
2911 + data_dns_question_class: "IN",
2912 + cluster_node: "ASHWZHMA.socfortress.local",
2913 + dst_port: "53",
2914 + "data_@timestamp": "2025-05-23T20:24:04.870Z",
2915 + data_event_duration: "50793434",
2916 + data_host_os_platform: "debian",
2917 + data_dns_flags_recursion_desired: "true",
2918 + data_host_name: "piHole",
2919 + data_dns_question_subdomain: "www.tm.lg.prod.aadmsa",
2920 + gl2_remote_port: 53290,
2921 + data_host_os_type: "linux",
2922 + source: "10.255.255.13",
2923 + gl2_source_input: "660320f176ca320e8393f030",
2924 + rule_level: 3,
2925 + data_event_type: "connection, protocol",
2926 + data_host_os_family: "debian",
2927 + data_dns_additionals_count: "0",
2928 + data_dns_flags_authentic_data: "false",
2929 + protocol: "udp",
2930 + data_dns_answers:
2931 + "{ttl=271, data=prdv4a.aadg.msidentity.com, name=www.tm.lg.prod.aadmsa.trafficmanager.net, type=CNAME, class=IN}, {class=IN, ttl=271, data=www.tm.v4.a.prd.aadg.akadns.net, name=prdv4a.aadg.msidentity.com, type=CNAME}, {name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=271, data=40.126.29.10}, {ttl=271, data=40.126.29.7, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=271, data=20.190.157.14}, {class=IN, ttl=271, data=20.190.157.12, name=www.tm.v4.a.prd.aadg.akadns.net, type=A}, {data=20.190.157.1, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=271}, {data=20.190.157.11, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=271}, {data=20.190.157.4, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=271}, {ttl=271, data=40.126.29.11, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}",
2932 + data_event_start: "2025-05-23T20:24:04.870Z",
2933 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
2934 + rule_description: "Linux: DNS Query to www.tm.lg.prod.aadmsa.trafficmanager.net",
2935 + data_agent_version: "8.7.1",
2936 + data_related_ip:
2937 + "192.168.100.1, 192.168.100.3, 40.126.29.10, 40.126.29.7, 20.190.157.14, 20.190.157.12, 20.190.157.1, 20.190.157.11, 20.190.157.4, 40.126.29.11",
2938 + data_status: "OK",
2939 + data_query: "class IN, type A, www.tm.lg.prod.aadmsa.trafficmanager.net",
2940 + "data_@metadata_type": "_doc",
2941 + data_dns_question_registered_domain: "trafficmanager.net",
2942 + data_server_ip: "192.168.100.3",
2943 + data_method: "QUERY",
2944 + gl2_message_id: "01JVZD2GXZZKVQKRG4WAY9N6VG",
2945 + data_dns_answers_count: "10",
2946 + data_network_type: "ipv4",
2947 + data_dns_opt_ext_rcode: "NOERROR",
2948 + data_client_port: "10699",
2949 + data_network_bytes: "348",
2950 + data_dns_resolved_ip:
2951 + "40.126.29.10, 40.126.29.7, 20.190.157.14, 20.190.157.12, 20.190.157.1, 20.190.157.11, 20.190.157.4, 40.126.29.11",
2952 + data_host_containerized: "false",
2953 + true: 1748031846.313229,
2954 + data_host_hostname: "piHole",
2955 + rule_groups: "linux, packetbeat, dns",
2956 + data_client_bytes: "69",
2957 + data_dns_question_type: "A",
2958 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
2959 + data_destination_ip: "192.168.100.3",
2960 + rule_mitre_technique: "Application Layer Protocol",
2961 + rule_firedtimes: 276,
2962 + data_network_transport: "udp",
2963 + dst_ip: "192.168.100.3",
2964 + src_ip: "192.168.100.1",
2965 + decoder_name: "json",
2966 + syslog_level: "INFO",
2967 + data_dns_op_code: "QUERY",
2968 + data_host_os_version: "11 (bullseye)",
2969 + data_host_os_kernel: "5.10.0-21-amd64",
2970 + cluster_name: "socfortress",
2971 + data_source_bytes: "69",
2972 + gl2_processing_error:
2973 + 'Replaced invalid timestamp value in message <e18f62d1-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.276+0000> caused exception: Invalid format: "2025-05-23T20:24:06.276+0000" is malformed at "T20:24:06.276+0000".',
2974 + data_dns_opt_do: "true",
2975 + data_dns_authorities_count: "0",
2976 + data_dns_question_name: "www.tm.lg.prod.aadmsa.trafficmanager.net",
2977 + message:
2978 + '{"true":1748031846.313229,"timestamp":"2025-05-23T20:24:06.276+0000","rule":{"level":3,"description":"Linux: DNS Query to www.tm.lg.prod.aadmsa.trafficmanager.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":276,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83726440","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.870Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"port":"10699","bytes":"69","ip":"192.168.100.1"},"dns":{"additionals_count":"0","op_code":"QUERY","response_code":"NOERROR","resolved_ip":["40.126.29.10","40.126.29.7","20.190.157.14","20.190.157.12","20.190.157.1","20.190.157.11","20.190.157.4","40.126.29.11"],"authorities_count":"0","type":"answer","id":"17026","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"header_flags":["RD","RA","DO"],"answers":[{"ttl":"271","data":"prdv4a.aadg.msidentity.com","name":"www.tm.lg.prod.aadmsa.trafficmanager.net","type":"CNAME","class":"IN"},{"class":"IN","ttl":"271","data":"www.tm.v4.a.prd.aadg.akadns.net","name":"prdv4a.aadg.msidentity.com","type":"CNAME"},{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"271","data":"40.126.29.10"},{"ttl":"271","data":"40.126.29.7","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"271","data":"20.190.157.14"},{"class":"IN","ttl":"271","data":"20.190.157.12","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A"},{"data":"20.190.157.1","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"271"},{"data":"20.190.157.11","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"271"},{"data":"20.190.157.4","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"271"},{"ttl":"271","data":"40.126.29.11","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"}],"answers_count":"10","question":{"name":"www.tm.lg.prod.aadmsa.trafficmanager.net","type":"A","class":"IN","etld_plus_one":"trafficmanager.net","registered_domain":"trafficmanager.net","top_level_domain":"net","subdomain":"www.tm.lg.prod.aadmsa"}},"server":{"bytes":"279","ip":"192.168.100.3","port":"53"},"resource":"www.tm.lg.prod.aadmsa.trafficmanager.net","ecs":{"version":"8.0.0"},"event":{"dataset":"dns","duration":"50793434","start":"2025-05-23T20:24:04.870Z","end":"2025-05-23T20:24:04.921Z","kind":"event","category":["network"],"type":["connection","protocol"]},"host":{"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","name":"piHole","os":{"kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"]},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"related":{"ip":["192.168.100.1","192.168.100.3","40.126.29.10","40.126.29.7","20.190.157.14","20.190.157.12","20.190.157.1","20.190.157.11","20.190.157.4","40.126.29.11"]},"network":{"direction":"ingress","community_id":"1:rRbPmhPceaU7J6cD1EfgYg23n5U=","bytes":"348","type":"ipv4","transport":"udp","protocol":"dns"},"type":"dns","query":"class IN, type A, www.tm.lg.prod.aadmsa.trafficmanager.net","source":{"port":"10699","bytes":"69","ip":"192.168.100.1"},"method":"QUERY","destination":{"ip":"192.168.100.3","port":"53","bytes":"279"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
2979 + dns_answer:
2980 + "40.126.29.10, 40.126.29.7, 20.190.157.14, 20.190.157.12, 20.190.157.1, 20.190.157.11, 20.190.157.4, 40.126.29.11",
2981 + data_dns_id: "17026",
2982 + src_port: "10699",
2983 + manager_name: "ASHWZHMA",
2984 + data_dns_question_top_level_domain: "net",
2985 + data_network_direction: "ingress",
2986 + data_event_end: "2025-05-23T20:24:04.921Z",
2987 + data_agent_name: "piHole",
2988 + data_client_ip: "192.168.100.1",
2989 + data_dns_flags_authoritative: "false",
2990 + data_server_bytes: "279",
2991 + data_dns_header_flags: "RD, RA, DO",
2992 + data_type: "dns",
2993 + data_dns_flags_checking_disabled: "false",
2994 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
2995 + "data_@metadata_version": "8.7.1",
2996 + data_host_os_name: "Debian GNU/Linux",
2997 + rule_group3: "dns",
2998 + msg_timestamp: "2025-05-23T20:24:06.276Z",
2999 + rule_group2: "packetbeat",
3000 + rule_group1: "linux"
3001 + },
3002 + {
3003 + data_source_ip: "192.168.100.3",
3004 + data_host_architecture: "x86_64",
3005 + agent_id: "032",
3006 + agent_name: "piHole",
3007 + gl2_remote_ip: "10.255.255.13",
3008 + data_resource: "login.msa.msidentity.com",
3009 + agent_labels_customer: "00001",
3010 + data_ecs_version: "8.0.0",
3011 + timestamp_utc: "2025-05-23T20:24:04.842Z",
3012 + data_host_os_codename: "bullseye",
3013 + syslog_type: "wazuh",
3014 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
3015 + id: "1748031846.83718115",
3016 + data_server_port: "53",
3017 + data_dns_question_etld_plus_one: "msidentity.com",
3018 + rule_mitre_tactic: "Command and Control",
3019 + gl2_accounted_message_size: 8828,
3020 + data_agent_type: "packetbeat",
3021 + streams: ["660320f176ca320e8393f057"],
3022 + rule_mitre_id: "T1071",
3023 + data_destination_bytes: "296",
3024 + data_event_dataset: "dns",
3025 + "data_@metadata_beat": "packetbeat",
3026 + agent_ip: "192.168.100.3",
3027 + data_source_port: "43412",
3028 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
3029 + data_event_kind: "event",
3030 + data_network_protocol: "dns",
3031 + dns_response_code: "NOERROR",
3032 + dns_query: "login.msa.msidentity.com",
3033 + data_dns_response_code: "NOERROR",
3034 + data_network_community_id: "1:wrZWjvynVtKm0XboVC0Mpa+kPsA=",
3035 + data_dns_flags_truncated_response: "false",
3036 + rule_mail: false,
3037 + data_dns_opt_udp_size: "1232",
3038 + data_event_category: "network",
3039 + data_dns_flags_recursion_available: "true",
3040 + data_dns_opt_version: "0",
3041 + timestamp: "2025-05-23 20:24:09.328",
3042 + data_host_mac: "00-0C-29-09-D5-9B",
3043 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
3044 + data_destination_port: "53",
3045 + data_dns_type: "answer",
3046 + traffic_direction: "egress",
3047 + rule_id: "200300",
3048 + data_dns_question_class: "IN",
3049 + cluster_node: "ASHWZHMA.socfortress.local",
3050 + dst_port: "53",
3051 + "data_@timestamp": "2025-05-23T20:24:04.842Z",
3052 + data_host_os_platform: "debian",
3053 + data_event_duration: "27378247",
3054 + data_host_name: "piHole",
3055 + data_dns_flags_recursion_desired: "true",
3056 + data_dns_question_subdomain: "login.msa",
3057 + gl2_remote_port: 53290,
3058 + data_host_os_type: "linux",
3059 + source: "10.255.255.13",
3060 + gl2_source_input: "660320f176ca320e8393f030",
3061 + rule_level: 3,
3062 + data_event_type: "connection, protocol",
3063 + data_host_os_family: "debian",
3064 + data_dns_additionals_count: "0",
3065 + data_dns_flags_authentic_data: "false",
3066 + protocol: "udp",
3067 + data_dns_answers:
3068 + "{class=IN, ttl=88, data=www.tm.lg.prod.aadmsa.trafficmanager.net, name=login.msa.msidentity.com, type=CNAME}, {type=CNAME, class=IN, ttl=88, data=prdv4a.aadg.msidentity.com, name=www.tm.lg.prod.aadmsa.trafficmanager.net}, {data=www.tm.v4.a.prd.aadg.trafficmanager.net, name=prdv4a.aadg.msidentity.com, type=CNAME, class=IN, ttl=88}, {data=40.126.28.20, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}, {class=IN, ttl=88, data=40.126.28.23, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A}, {ttl=88, data=20.190.135.16, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN}, {class=IN, ttl=88, data=20.190.135.3, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A}, {name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88, data=40.126.28.18}, {type=A, class=IN, ttl=88, data=20.190.135.19, name=www.tm.v4.a.prd.aadg.trafficmanager.net}, {data=40.126.28.13, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}, {ttl=88, data=40.126.7.32, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN}",
3069 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
3070 + data_event_start: "2025-05-23T20:24:04.842Z",
3071 + rule_description: "Linux: DNS Query to login.msa.msidentity.com",
3072 + data_related_ip:
3073 + "192.168.100.3, 1.1.1.3, 40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3074 + data_agent_version: "8.7.1",
3075 + data_status: "OK",
3076 + data_query: "class IN, type A, login.msa.msidentity.com",
3077 + "data_@metadata_type": "_doc",
3078 + data_method: "QUERY",
3079 + data_server_ip: "1.1.1.3",
3080 + data_dns_question_registered_domain: "msidentity.com",
3081 + gl2_message_id: "01JVZD2GVGY1C7C1BJ4D9YJ6CY",
3082 + data_dns_answers_count: "11",
3083 + data_network_type: "ipv4",
3084 + data_dns_opt_ext_rcode: "NOERROR",
3085 + data_client_port: "43412",
3086 + data_network_bytes: "349",
3087 + data_dns_resolved_ip:
3088 + "40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3089 + data_host_containerized: "false",
3090 + true: 1748031846.27769,
3091 + data_host_hostname: "piHole",
3092 + rule_groups: "linux, packetbeat, dns",
3093 + data_client_bytes: "53",
3094 + data_dns_question_type: "A",
3095 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
3096 + data_destination_ip: "1.1.1.3",
3097 + rule_mitre_technique: "Application Layer Protocol",
3098 + rule_firedtimes: 274,
3099 + data_network_transport: "udp",
3100 + dst_ip: "1.1.1.3",
3101 + src_ip: "192.168.100.3",
3102 + decoder_name: "json",
3103 + syslog_level: "INFO",
3104 + data_dns_op_code: "QUERY",
3105 + data_host_os_version: "11 (bullseye)",
3106 + data_host_os_kernel: "5.10.0-21-amd64",
3107 + cluster_name: "socfortress",
3108 + data_source_bytes: "53",
3109 + gl2_processing_error:
3110 + 'Replaced invalid timestamp value in message <e13c87e2-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.276+0000> caused exception: Invalid format: "2025-05-23T20:24:06.276+0000" is malformed at "T20:24:06.276+0000".',
3111 + data_dns_opt_do: "true",
3112 + data_dns_authorities_count: "0",
3113 + data_dns_question_name: "login.msa.msidentity.com",
3114 + message:
3115 + '{"true":1748031846.27769,"timestamp":"2025-05-23T20:24:06.276+0000","rule":{"level":3,"description":"Linux: DNS Query to login.msa.msidentity.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":274,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83718115","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.842Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"method":"QUERY","related":{"ip":["192.168.100.3","1.1.1.3","40.126.28.20","40.126.28.23","20.190.135.16","20.190.135.3","40.126.28.18","20.190.135.19","40.126.28.13","40.126.7.32"]},"ecs":{"version":"8.0.0"},"source":{"bytes":"53","ip":"192.168.100.3","port":"43412"},"host":{"hostname":"piHole","architecture":"x86_64","os":{"family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","name":"piHole","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"]},"query":"class IN, type A, login.msa.msidentity.com","resource":"login.msa.msidentity.com","client":{"port":"43412","bytes":"53","ip":"192.168.100.3"},"server":{"ip":"1.1.1.3","port":"53","bytes":"296"},"agent":{"type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole"},"type":"dns","destination":{"ip":"1.1.1.3","port":"53","bytes":"296"},"event":{"end":"2025-05-23T20:24:04.869Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"27378247","start":"2025-05-23T20:24:04.842Z"},"dns":{"answers":[{"class":"IN","ttl":"88","data":"www.tm.lg.prod.aadmsa.trafficmanager.net","name":"login.msa.msidentity.com","type":"CNAME"},{"type":"CNAME","class":"IN","ttl":"88","data":"prdv4a.aadg.msidentity.com","name":"www.tm.lg.prod.aadmsa.trafficmanager.net"},{"data":"www.tm.v4.a.prd.aadg.trafficmanager.net","name":"prdv4a.aadg.msidentity.com","type":"CNAME","class":"IN","ttl":"88"},{"data":"40.126.28.20","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"},{"class":"IN","ttl":"88","data":"40.126.28.23","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A"},{"ttl":"88","data":"20.190.135.16","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN"},{"class":"IN","ttl":"88","data":"20.190.135.3","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A"},{"name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88","data":"40.126.28.18"},{"type":"A","class":"IN","ttl":"88","data":"20.190.135.19","name":"www.tm.v4.a.prd.aadg.trafficmanager.net"},{"data":"40.126.28.13","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"},{"ttl":"88","data":"40.126.7.32","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN"}],"resolved_ip":["40.126.28.20","40.126.28.23","20.190.135.16","20.190.135.3","40.126.28.18","20.190.135.19","40.126.28.13","40.126.7.32"],"op_code":"QUERY","id":"21047","answers_count":"11","additionals_count":"0","flags":{"checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false"},"header_flags":["RD","RA","DO"],"question":{"registered_domain":"msidentity.com","top_level_domain":"com","subdomain":"login.msa","name":"login.msa.msidentity.com","type":"A","class":"IN","etld_plus_one":"msidentity.com"},"opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"response_code":"NOERROR","authorities_count":"0","type":"answer"},"network":{"protocol":"dns","direction":"egress","community_id":"1:wrZWjvynVtKm0XboVC0Mpa+kPsA=","bytes":"349","type":"ipv4","transport":"udp"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
3116 + dns_answer:
3117 + "40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3118 + data_dns_id: "21047",
3119 + src_port: "43412",
3120 + manager_name: "ASHWZHMA",
3121 + data_dns_question_top_level_domain: "com",
3122 + data_network_direction: "egress",
3123 + data_event_end: "2025-05-23T20:24:04.869Z",
3124 + data_agent_name: "piHole",
3125 + data_client_ip: "192.168.100.3",
3126 + data_server_bytes: "296",
3127 + data_dns_flags_authoritative: "false",
3128 + data_type: "dns",
3129 + data_dns_header_flags: "RD, RA, DO",
3130 + data_dns_flags_checking_disabled: "false",
3131 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
3132 + "data_@metadata_version": "8.7.1",
3133 + data_host_os_name: "Debian GNU/Linux",
3134 + rule_group3: "dns",
3135 + msg_timestamp: "2025-05-23T20:24:06.276Z",
3136 + rule_group2: "packetbeat",
3137 + rule_group1: "linux"
3138 + },
3139 + {
3140 + data_source_ip: "192.168.100.1",
3141 + data_host_architecture: "x86_64",
3142 + agent_id: "032",
3143 + agent_name: "piHole",
3144 + gl2_remote_ip: "10.255.255.13",
3145 + data_resource: "login.msa.msidentity.com",
3146 + agent_labels_customer: "00001",
3147 + data_ecs_version: "8.0.0",
3148 + timestamp_utc: "2025-05-23T20:24:04.842Z",
3149 + data_host_os_codename: "bullseye",
3150 + syslog_type: "wazuh",
3151 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
3152 + id: "1748031846.83722268",
3153 + data_server_port: "53",
3154 + data_dns_question_etld_plus_one: "msidentity.com",
3155 + rule_mitre_tactic: "Command and Control",
3156 + gl2_accounted_message_size: 8874,
3157 + data_agent_type: "packetbeat",
3158 + streams: ["660320f176ca320e8393f057"],
3159 + rule_mitre_id: "T1071",
3160 + data_destination_bytes: "296",
3161 + data_event_dataset: "dns",
3162 + "data_@metadata_beat": "packetbeat",
3163 + agent_ip: "192.168.100.3",
3164 + data_source_port: "28861",
3165 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
3166 + data_event_kind: "event",
3167 + data_network_protocol: "dns",
3168 + dns_response_code: "NOERROR",
3169 + dns_query: "login.msa.msidentity.com",
3170 + data_dns_response_code: "NOERROR",
3171 + data_network_community_id: "1:BnSWks/M1fOeIzHRcaJbP28aEFM=",
3172 + data_dns_flags_truncated_response: "false",
3173 + rule_mail: false,
3174 + data_dns_opt_udp_size: "1232",
3175 + data_event_category: "network",
3176 + data_dns_flags_recursion_available: "true",
3177 + data_dns_opt_version: "0",
3178 + timestamp: "2025-05-23 20:24:09.328",
3179 + data_host_mac: "00-0C-29-09-D5-9B",
3180 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
3181 + data_destination_port: "53",
3182 + data_dns_type: "answer",
3183 + traffic_direction: "ingress",
3184 + rule_id: "200300",
3185 + data_dns_question_class: "IN",
3186 + cluster_node: "ASHWZHMA.socfortress.local",
3187 + dst_port: "53",
3188 + "data_@timestamp": "2025-05-23T20:24:04.842Z",
3189 + data_host_os_platform: "debian",
3190 + data_event_duration: "27608350",
3191 + data_host_name: "piHole",
3192 + data_dns_flags_recursion_desired: "true",
3193 + data_dns_question_subdomain: "login.msa",
3194 + gl2_remote_port: 53290,
3195 + data_host_os_type: "linux",
3196 + source: "10.255.255.13",
3197 + gl2_source_input: "660320f176ca320e8393f030",
3198 + rule_level: 3,
3199 + data_event_type: "connection, protocol",
3200 + data_host_os_family: "debian",
3201 + data_dns_additionals_count: "0",
3202 + data_dns_flags_authentic_data: "false",
3203 + protocol: "udp",
3204 + data_dns_answers:
3205 + "{ttl=88, data=www.tm.lg.prod.aadmsa.trafficmanager.net, name=login.msa.msidentity.com, type=CNAME, class=IN}, {name=www.tm.lg.prod.aadmsa.trafficmanager.net, type=CNAME, class=IN, ttl=88, data=prdv4a.aadg.msidentity.com}, {type=CNAME, class=IN, ttl=88, data=www.tm.v4.a.prd.aadg.trafficmanager.net, name=prdv4a.aadg.msidentity.com}, {class=IN, ttl=88, data=40.126.28.20, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A}, {name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88, data=40.126.28.23}, {class=IN, ttl=88, data=20.190.135.16, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A}, {name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88, data=20.190.135.3}, {data=40.126.28.18, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}, {data=20.190.135.19, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}, {data=40.126.28.13, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}, {data=40.126.7.32, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=88}",
3206 + data_event_start: "2025-05-23T20:24:04.842Z",
3207 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
3208 + rule_description: "Linux: DNS Query to login.msa.msidentity.com",
3209 + data_related_ip:
3210 + "192.168.100.1, 192.168.100.3, 40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3211 + data_agent_version: "8.7.1",
3212 + data_status: "OK",
3213 + data_query: "class IN, type A, login.msa.msidentity.com",
3214 + "data_@metadata_type": "_doc",
3215 + data_method: "QUERY",
3216 + data_server_ip: "192.168.100.3",
3217 + data_dns_question_registered_domain: "msidentity.com",
3218 + gl2_message_id: "01JVZD2GVGJB77P3V6563YFA75",
3219 + data_dns_answers_count: "11",
3220 + data_network_type: "ipv4",
3221 + data_dns_opt_ext_rcode: "NOERROR",
3222 + data_client_port: "28861",
3223 + data_network_bytes: "349",
3224 + data_dns_resolved_ip:
3225 + "40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3226 + data_host_containerized: "false",
3227 + true: 1748031846.277803,
3228 + data_host_hostname: "piHole",
3229 + rule_groups: "linux, packetbeat, dns",
3230 + data_client_bytes: "53",
3231 + data_dns_question_type: "A",
3232 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
3233 + data_destination_ip: "192.168.100.3",
3234 + rule_mitre_technique: "Application Layer Protocol",
3235 + rule_firedtimes: 275,
3236 + data_network_transport: "udp",
3237 + dst_ip: "192.168.100.3",
3238 + src_ip: "192.168.100.1",
3239 + decoder_name: "json",
3240 + syslog_level: "INFO",
3241 + data_dns_op_code: "QUERY",
3242 + data_host_os_version: "11 (bullseye)",
3243 + data_host_os_kernel: "5.10.0-21-amd64",
3244 + cluster_name: "socfortress",
3245 + data_source_bytes: "53",
3246 + gl2_processing_error:
3247 + 'Replaced invalid timestamp value in message <e18f62d0-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.276+0000> caused exception: Invalid format: "2025-05-23T20:24:06.276+0000" is malformed at "T20:24:06.276+0000".',
3248 + data_dns_opt_do: "true",
3249 + data_dns_authorities_count: "0",
3250 + data_dns_question_name: "login.msa.msidentity.com",
3251 + message:
3252 + '{"true":1748031846.277803,"timestamp":"2025-05-23T20:24:06.276+0000","rule":{"level":3,"description":"Linux: DNS Query to login.msa.msidentity.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":275,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83722268","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.842Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"host":{"architecture":"x86_64","os":{"name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"name":"piHole","hostname":"piHole"},"destination":{"ip":"192.168.100.3","port":"53","bytes":"296"},"method":"QUERY","related":{"ip":["192.168.100.1","192.168.100.3","40.126.28.20","40.126.28.23","20.190.135.16","20.190.135.3","40.126.28.18","20.190.135.19","40.126.28.13","40.126.7.32"]},"resource":"login.msa.msidentity.com","client":{"ip":"192.168.100.1","port":"28861","bytes":"53"},"event":{"kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"27608350","start":"2025-05-23T20:24:04.842Z","end":"2025-05-23T20:24:04.869Z"},"type":"dns","query":"class IN, type A, login.msa.msidentity.com","network":{"direction":"ingress","community_id":"1:BnSWks/M1fOeIzHRcaJbP28aEFM=","bytes":"349","type":"ipv4","transport":"udp","protocol":"dns"},"agent":{"name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b"},"ecs":{"version":"8.0.0"},"server":{"ip":"192.168.100.3","port":"53","bytes":"296"},"dns":{"flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"header_flags":["RD","RA","DO"],"resolved_ip":["40.126.28.20","40.126.28.23","20.190.135.16","20.190.135.3","40.126.28.18","20.190.135.19","40.126.28.13","40.126.7.32"],"response_code":"NOERROR","answers":[{"ttl":"88","data":"www.tm.lg.prod.aadmsa.trafficmanager.net","name":"login.msa.msidentity.com","type":"CNAME","class":"IN"},{"name":"www.tm.lg.prod.aadmsa.trafficmanager.net","type":"CNAME","class":"IN","ttl":"88","data":"prdv4a.aadg.msidentity.com"},{"type":"CNAME","class":"IN","ttl":"88","data":"www.tm.v4.a.prd.aadg.trafficmanager.net","name":"prdv4a.aadg.msidentity.com"},{"class":"IN","ttl":"88","data":"40.126.28.20","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A"},{"name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88","data":"40.126.28.23"},{"class":"IN","ttl":"88","data":"20.190.135.16","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A"},{"name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88","data":"20.190.135.3"},{"data":"40.126.28.18","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"},{"data":"20.190.135.19","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"},{"data":"40.126.28.13","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"},{"data":"40.126.7.32","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"88"}],"authorities_count":"0","answers_count":"11","type":"answer","opt":{"udp_size":"1232","ext_rcode":"NOERROR","do":"true","version":"0"},"additionals_count":"0","id":"33835","op_code":"QUERY","question":{"registered_domain":"msidentity.com","top_level_domain":"com","subdomain":"login.msa","name":"login.msa.msidentity.com","type":"A","class":"IN","etld_plus_one":"msidentity.com"}},"source":{"port":"28861","bytes":"53","ip":"192.168.100.1"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
3253 + dns_answer:
3254 + "40.126.28.20, 40.126.28.23, 20.190.135.16, 20.190.135.3, 40.126.28.18, 20.190.135.19, 40.126.28.13, 40.126.7.32",
3255 + data_dns_id: "33835",
3256 + src_port: "28861",
3257 + manager_name: "ASHWZHMA",
3258 + data_network_direction: "ingress",
3259 + data_dns_question_top_level_domain: "com",
3260 + data_event_end: "2025-05-23T20:24:04.869Z",
3261 + data_agent_name: "piHole",
3262 + data_client_ip: "192.168.100.1",
3263 + data_server_bytes: "296",
3264 + data_dns_flags_authoritative: "false",
3265 + data_type: "dns",
3266 + data_dns_header_flags: "RD, RA, DO",
3267 + data_dns_flags_checking_disabled: "false",
3268 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
3269 + "data_@metadata_version": "8.7.1",
3270 + data_host_os_name: "Debian GNU/Linux",
3271 + rule_group3: "dns",
3272 + msg_timestamp: "2025-05-23T20:24:06.276Z",
3273 + rule_group2: "packetbeat",
3274 + rule_group1: "linux"
3275 + },
3276 + {
3277 + data_source_ip: "192.168.100.3",
3278 + data_host_architecture: "x86_64",
3279 + agent_id: "032",
3280 + agent_name: "piHole",
3281 + gl2_remote_ip: "10.255.255.13",
3282 + data_resource: "prdv4a.aadg.msidentity.com",
3283 + agent_labels_customer: "00001",
3284 + data_ecs_version: "8.0.0",
3285 + timestamp_utc: "2025-05-23T20:24:04.995Z",
3286 + data_host_os_codename: "bullseye",
3287 + syslog_type: "wazuh",
3288 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
3289 + id: "1748031846.83730512",
3290 + data_dns_question_etld_plus_one: "msidentity.com",
3291 + data_server_port: "53",
3292 + rule_mitre_tactic: "Command and Control",
3293 + gl2_accounted_message_size: 8249,
3294 + data_agent_type: "packetbeat",
3295 + streams: ["660320f176ca320e8393f057"],
3296 + rule_mitre_id: "T1071",
3297 + data_destination_bytes: "228",
3298 + data_event_dataset: "dns",
3299 + "data_@metadata_beat": "packetbeat",
3300 + agent_ip: "192.168.100.3",
3301 + data_source_port: "38863",
3302 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
3303 + data_event_kind: "event",
3304 + data_network_protocol: "dns",
3305 + dns_response_code: "NOERROR",
3306 + dns_query: "prdv4a.aadg.msidentity.com",
3307 + data_dns_response_code: "NOERROR",
3308 + data_network_community_id: "1:owkn6wop0ljZlI813Huqub9Sj0A=",
3309 + data_dns_flags_truncated_response: "false",
3310 + rule_mail: false,
3311 + data_dns_opt_udp_size: "1232",
3312 + data_event_category: "network",
3313 + data_dns_flags_recursion_available: "true",
3314 + data_dns_opt_version: "0",
3315 + timestamp: "2025-05-23 20:24:08.831",
3316 + data_host_mac: "00-0C-29-09-D5-9B",
3317 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
3318 + data_destination_port: "53",
3319 + data_dns_type: "answer",
3320 + traffic_direction: "egress",
3321 + rule_id: "200300",
3322 + data_dns_question_class: "IN",
3323 + cluster_node: "ASHWZHMA.socfortress.local",
3324 + dst_port: "53",
3325 + "data_@timestamp": "2025-05-23T20:24:04.995Z",
3326 + data_host_os_platform: "debian",
3327 + data_event_duration: "36713343",
3328 + data_host_name: "piHole",
3329 + data_dns_flags_recursion_desired: "true",
3330 + data_dns_question_subdomain: "prdv4a.aadg",
3331 + gl2_remote_port: 53290,
3332 + data_host_os_type: "linux",
3333 + source: "10.255.255.13",
3334 + gl2_source_input: "660320f176ca320e8393f030",
3335 + rule_level: 3,
3336 + data_event_type: "connection, protocol",
3337 + data_host_os_family: "debian",
3338 + data_dns_additionals_count: "0",
3339 + data_dns_flags_authentic_data: "false",
3340 + protocol: "udp",
3341 + data_dns_answers:
3342 + "{ttl=251, data=www.tm.v4.a.prd.aadg.akadns.net, name=prdv4a.aadg.msidentity.com, type=CNAME, class=IN}, {type=A, class=IN, ttl=251, data=40.126.29.8, name=www.tm.v4.a.prd.aadg.akadns.net}, {data=40.126.29.7, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=251}, {data=40.126.29.11, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=251}, {data=40.126.29.12, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=251}, {ttl=251, data=20.190.157.12, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {type=A, class=IN, ttl=251, data=20.190.157.11, name=www.tm.v4.a.prd.aadg.akadns.net}, {ttl=251, data=20.190.157.14, name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN}, {name=www.tm.v4.a.prd.aadg.akadns.net, type=A, class=IN, ttl=251, data=20.190.157.4}",
3343 + data_event_start: "2025-05-23T20:24:04.995Z",
3344 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
3345 + rule_description: "Linux: DNS Query to prdv4a.aadg.msidentity.com",
3346 + data_related_ip:
3347 + "192.168.100.3, 1.1.1.3, 40.126.29.8, 40.126.29.7, 40.126.29.11, 40.126.29.12, 20.190.157.12, 20.190.157.11, 20.190.157.14, 20.190.157.4",
3348 + data_agent_version: "8.7.1",
3349 + data_status: "OK",
3350 + data_query: "class IN, type A, prdv4a.aadg.msidentity.com",
3351 + "data_@metadata_type": "_doc",
3352 + data_dns_question_registered_domain: "msidentity.com",
3353 + data_method: "QUERY",
3354 + data_server_ip: "1.1.1.3",
3355 + gl2_message_id: "01JVZD2GBZBZKK1FQWFEC4ATJ6",
3356 + data_dns_answers_count: "9",
3357 + data_network_type: "ipv4",
3358 + data_dns_opt_ext_rcode: "NOERROR",
3359 + data_client_port: "38863",
3360 + data_network_bytes: "283",
3361 + data_dns_resolved_ip:
3362 + "40.126.29.8, 40.126.29.7, 40.126.29.11, 40.126.29.12, 20.190.157.12, 20.190.157.11, 20.190.157.14, 20.190.157.4",
3363 + data_host_containerized: "false",
3364 + true: 1748031846.313568,
3365 + data_host_hostname: "piHole",
3366 + rule_groups: "linux, packetbeat, dns",
3367 + data_client_bytes: "55",
3368 + data_dns_question_type: "A",
3369 + data_destination_ip: "1.1.1.3",
3370 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
3371 + rule_mitre_technique: "Application Layer Protocol",
3372 + rule_firedtimes: 277,
3373 + data_network_transport: "udp",
3374 + dst_ip: "1.1.1.3",
3375 + src_ip: "192.168.100.3",
3376 + decoder_name: "json",
3377 + syslog_level: "INFO",
3378 + data_dns_op_code: "QUERY",
3379 + data_host_os_version: "11 (bullseye)",
3380 + data_host_os_kernel: "5.10.0-21-amd64",
3381 + cluster_name: "socfortress",
3382 + data_source_bytes: "55",
3383 + gl2_processing_error:
3384 + 'Replaced invalid timestamp value in message <e18f62d2-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.312+0000> caused exception: Invalid format: "2025-05-23T20:24:06.312+0000" is malformed at "T20:24:06.312+0000".',
3385 + data_dns_opt_do: "true",
3386 + data_dns_authorities_count: "0",
3387 + data_dns_question_name: "prdv4a.aadg.msidentity.com",
3388 + message:
3389 + '{"true":1748031846.313568,"timestamp":"2025-05-23T20:24:06.312+0000","rule":{"level":3,"description":"Linux: DNS Query to prdv4a.aadg.msidentity.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":277,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83730512","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.995Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"resource":"prdv4a.aadg.msidentity.com","destination":{"ip":"1.1.1.3","port":"53","bytes":"228"},"ecs":{"version":"8.0.0"},"host":{"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","name":"piHole","os":{"type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"]},"client":{"ip":"192.168.100.3","port":"38863","bytes":"55"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:owkn6wop0ljZlI813Huqub9Sj0A=","bytes":"283"},"dns":{"opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"type":"answer","flags":{"truncated_response":"false","recursion_desired":"true","recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false"},"op_code":"QUERY","additionals_count":"0","id":"60335","header_flags":["RD","RA","DO"],"question":{"class":"IN","etld_plus_one":"msidentity.com","registered_domain":"msidentity.com","top_level_domain":"com","subdomain":"prdv4a.aadg","name":"prdv4a.aadg.msidentity.com","type":"A"},"answers_count":"9","resolved_ip":["40.126.29.8","40.126.29.7","40.126.29.11","40.126.29.12","20.190.157.12","20.190.157.11","20.190.157.14","20.190.157.4"],"response_code":"NOERROR","answers":[{"ttl":"251","data":"www.tm.v4.a.prd.aadg.akadns.net","name":"prdv4a.aadg.msidentity.com","type":"CNAME","class":"IN"},{"type":"A","class":"IN","ttl":"251","data":"40.126.29.8","name":"www.tm.v4.a.prd.aadg.akadns.net"},{"data":"40.126.29.7","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"251"},{"data":"40.126.29.11","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"251"},{"data":"40.126.29.12","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"251"},{"ttl":"251","data":"20.190.157.12","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"type":"A","class":"IN","ttl":"251","data":"20.190.157.11","name":"www.tm.v4.a.prd.aadg.akadns.net"},{"ttl":"251","data":"20.190.157.14","name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN"},{"name":"www.tm.v4.a.prd.aadg.akadns.net","type":"A","class":"IN","ttl":"251","data":"20.190.157.4"}],"authorities_count":"0"},"type":"dns","source":{"ip":"192.168.100.3","port":"38863","bytes":"55"},"query":"class IN, type A, prdv4a.aadg.msidentity.com","event":{"dataset":"dns","duration":"36713343","start":"2025-05-23T20:24:04.995Z","end":"2025-05-23T20:24:05.032Z","kind":"event","category":["network"],"type":["connection","protocol"]},"related":{"ip":["192.168.100.3","1.1.1.3","40.126.29.8","40.126.29.7","40.126.29.11","40.126.29.12","20.190.157.12","20.190.157.11","20.190.157.14","20.190.157.4"]},"method":"QUERY","server":{"ip":"1.1.1.3","port":"53","bytes":"228"},"agent":{"version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
3390 + dns_answer:
3391 + "40.126.29.8, 40.126.29.7, 40.126.29.11, 40.126.29.12, 20.190.157.12, 20.190.157.11, 20.190.157.14, 20.190.157.4",
3392 + data_dns_id: "60335",
3393 + src_port: "38863",
3394 + manager_name: "ASHWZHMA",
3395 + data_network_direction: "egress",
3396 + data_dns_question_top_level_domain: "com",
3397 + data_event_end: "2025-05-23T20:24:05.032Z",
3398 + data_agent_name: "piHole",
3399 + data_client_ip: "192.168.100.3",
3400 + data_dns_flags_authoritative: "false",
3401 + data_server_bytes: "228",
3402 + data_dns_header_flags: "RD, RA, DO",
3403 + data_type: "dns",
3404 + data_dns_flags_checking_disabled: "false",
3405 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
3406 + "data_@metadata_version": "8.7.1",
3407 + data_host_os_name: "Debian GNU/Linux",
3408 + rule_group3: "dns",
3409 + msg_timestamp: "2025-05-23T20:24:06.312Z",
3410 + rule_group2: "packetbeat",
3411 + rule_group1: "linux"
3412 + },
3413 + {
3414 + data_source_ip: "192.168.100.3",
3415 + data_host_architecture: "x86_64",
3416 + agent_id: "032",
3417 + agent_name: "piHole",
3418 + gl2_remote_ip: "10.255.255.13",
3419 + data_resource: "login.live.com",
3420 + agent_labels_customer: "00001",
3421 + data_ecs_version: "8.0.0",
3422 + timestamp_utc: "2025-05-23T20:24:04.815Z",
3423 + data_host_os_codename: "bullseye",
3424 + syslog_type: "wazuh",
3425 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
3426 + id: "1748031846.83713929",
3427 + data_dns_question_etld_plus_one: "live.com",
3428 + data_server_port: "53",
3429 + rule_mitre_tactic: "Command and Control",
3430 + gl2_accounted_message_size: 8868,
3431 + data_agent_type: "packetbeat",
3432 + streams: ["660320f176ca320e8393f057"],
3433 + rule_mitre_id: "T1071",
3434 + data_destination_bytes: "328",
3435 + data_event_dataset: "dns",
3436 + "data_@metadata_beat": "packetbeat",
3437 + agent_ip: "192.168.100.3",
3438 + data_source_port: "60286",
3439 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
3440 + data_event_kind: "event",
3441 + data_network_protocol: "dns",
3442 + dns_response_code: "NOERROR",
3443 + dns_query: "login.live.com",
3444 + data_dns_response_code: "NOERROR",
3445 + data_network_community_id: "1:1GvoZkkegqS2kWj0nbkXnzAb1QQ=",
3446 + data_dns_flags_truncated_response: "false",
3447 + rule_mail: false,
3448 + data_dns_opt_udp_size: "1232",
3449 + data_event_category: "network",
3450 + data_dns_flags_recursion_available: "true",
3451 + data_dns_opt_version: "0",
3452 + timestamp: "2025-05-23 20:24:08.830",
3453 + data_host_mac: "00-0C-29-09-D5-9B",
3454 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
3455 + data_destination_port: "53",
3456 + data_dns_type: "answer",
3457 + traffic_direction: "egress",
3458 + rule_id: "200300",
3459 + data_dns_question_class: "IN",
3460 + cluster_node: "ASHWZHMA.socfortress.local",
3461 + dst_port: "53",
3462 + "data_@timestamp": "2025-05-23T20:24:04.815Z",
3463 + data_host_os_platform: "debian",
3464 + data_event_duration: "25965908",
3465 + data_dns_flags_recursion_desired: "true",
3466 + data_host_name: "piHole",
3467 + data_dns_question_subdomain: "login",
3468 + gl2_remote_port: 53290,
3469 + data_host_os_type: "linux",
3470 + source: "10.255.255.13",
3471 + gl2_source_input: "660320f176ca320e8393f030",
3472 + rule_level: 3,
3473 + data_event_type: "connection, protocol",
3474 + data_host_os_family: "debian",
3475 + data_dns_additionals_count: "0",
3476 + data_dns_flags_authentic_data: "false",
3477 + protocol: "udp",
3478 + data_dns_answers:
3479 + "{class=IN, ttl=295, data=login.msa.msidentity.com, name=login.live.com, type=CNAME}, {data=www.tm.lg.prod.aadmsa.akadns.net, name=login.msa.msidentity.com, type=CNAME, class=IN, ttl=295}, {class=IN, ttl=295, data=prdv4a.aadg.msidentity.com, name=www.tm.lg.prod.aadmsa.akadns.net, type=CNAME}, {type=CNAME, class=IN, ttl=295, data=www.tm.v4.a.prd.aadg.trafficmanager.net, name=prdv4a.aadg.msidentity.com}, {data=40.126.29.7, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295}, {class=IN, ttl=295, data=40.126.29.15, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A}, {data=40.126.29.10, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295}, {type=A, class=IN, ttl=295, data=20.190.157.14, name=www.tm.v4.a.prd.aadg.trafficmanager.net}, {data=20.190.157.9, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295}, {name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295, data=40.126.29.5}, {data=20.190.157.4, name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295}, {name=www.tm.v4.a.prd.aadg.trafficmanager.net, type=A, class=IN, ttl=295, data=20.190.157.0}",
3480 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
3481 + data_event_start: "2025-05-23T20:24:04.815Z",
3482 + rule_description: "Linux: DNS Query to login.live.com",
3483 + data_related_ip:
3484 + "192.168.100.3, 1.1.1.3, 40.126.29.7, 40.126.29.15, 40.126.29.10, 20.190.157.14, 20.190.157.9, 40.126.29.5, 20.190.157.4, 20.190.157.0",
3485 + data_agent_version: "8.7.1",
3486 + data_status: "OK",
3487 + data_query: "class IN, type A, login.live.com",
3488 + "data_@metadata_type": "_doc",
3489 + data_method: "QUERY",
3490 + data_dns_question_registered_domain: "live.com",
3491 + data_server_ip: "1.1.1.3",
3492 + gl2_message_id: "01JVZD2GBY1TFG35WJZT5ME05R",
3493 + data_dns_answers_count: "12",
3494 + data_network_type: "ipv4",
3495 + data_dns_opt_ext_rcode: "NOERROR",
3496 + data_client_port: "60286",
3497 + data_network_bytes: "371",
3498 + data_dns_resolved_ip:
3499 + "40.126.29.7, 40.126.29.15, 40.126.29.10, 20.190.157.14, 20.190.157.9, 40.126.29.5, 20.190.157.4, 20.190.157.0",
3500 + data_host_containerized: "false",
3501 + true: 1748031846.277626,
3502 + data_host_hostname: "piHole",
3503 + rule_groups: "linux, packetbeat, dns",
3504 + data_client_bytes: "43",
3505 + data_dns_question_type: "A",
3506 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
3507 + data_destination_ip: "1.1.1.3",
3508 + rule_mitre_technique: "Application Layer Protocol",
3509 + rule_firedtimes: 273,
3510 + data_network_transport: "udp",
3511 + dst_ip: "1.1.1.3",
3512 + src_ip: "192.168.100.3",
3513 + decoder_name: "json",
3514 + syslog_level: "INFO",
3515 + data_dns_op_code: "QUERY",
3516 + data_host_os_version: "11 (bullseye)",
3517 + data_host_os_kernel: "5.10.0-21-amd64",
3518 + cluster_name: "socfortress",
3519 + data_source_bytes: "43",
3520 + gl2_processing_error:
3521 + 'Replaced invalid timestamp value in message <e13c87e1-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.276+0000> caused exception: Invalid format: "2025-05-23T20:24:06.276+0000" is malformed at "T20:24:06.276+0000".',
3522 + data_dns_opt_do: "true",
3523 + data_dns_authorities_count: "0",
3524 + data_dns_question_name: "login.live.com",
3525 + message:
3526 + '{"true":1748031846.277626,"timestamp":"2025-05-23T20:24:06.276+0000","rule":{"level":3,"description":"Linux: DNS Query to login.live.com","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":273,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83713929","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.815Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"client":{"bytes":"43","ip":"192.168.100.3","port":"60286"},"method":"QUERY","related":{"ip":["192.168.100.3","1.1.1.3","40.126.29.7","40.126.29.15","40.126.29.10","20.190.157.14","20.190.157.9","40.126.29.5","20.190.157.4","20.190.157.0"]},"dns":{"flags":{"recursion_available":"true","authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true"},"authorities_count":"0","header_flags":["RD","RA","DO"],"resolved_ip":["40.126.29.7","40.126.29.15","40.126.29.10","20.190.157.14","20.190.157.9","40.126.29.5","20.190.157.4","20.190.157.0"],"op_code":"QUERY","opt":{"do":"true","version":"0","udp_size":"1232","ext_rcode":"NOERROR"},"id":"56796","response_code":"NOERROR","question":{"name":"login.live.com","type":"A","class":"IN","etld_plus_one":"live.com","registered_domain":"live.com","top_level_domain":"com","subdomain":"login"},"answers_count":"12","answers":[{"class":"IN","ttl":"295","data":"login.msa.msidentity.com","name":"login.live.com","type":"CNAME"},{"data":"www.tm.lg.prod.aadmsa.akadns.net","name":"login.msa.msidentity.com","type":"CNAME","class":"IN","ttl":"295"},{"class":"IN","ttl":"295","data":"prdv4a.aadg.msidentity.com","name":"www.tm.lg.prod.aadmsa.akadns.net","type":"CNAME"},{"type":"CNAME","class":"IN","ttl":"295","data":"www.tm.v4.a.prd.aadg.trafficmanager.net","name":"prdv4a.aadg.msidentity.com"},{"data":"40.126.29.7","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295"},{"class":"IN","ttl":"295","data":"40.126.29.15","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A"},{"data":"40.126.29.10","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295"},{"type":"A","class":"IN","ttl":"295","data":"20.190.157.14","name":"www.tm.v4.a.prd.aadg.trafficmanager.net"},{"data":"20.190.157.9","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295"},{"name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295","data":"40.126.29.5"},{"data":"20.190.157.4","name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295"},{"name":"www.tm.v4.a.prd.aadg.trafficmanager.net","type":"A","class":"IN","ttl":"295","data":"20.190.157.0"}],"type":"answer","additionals_count":"0"},"host":{"os":{"codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian","name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false","ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","name":"piHole","architecture":"x86_64"},"agent":{"id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1","ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3"},"resource":"login.live.com","query":"class IN, type A, login.live.com","network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"egress","community_id":"1:1GvoZkkegqS2kWj0nbkXnzAb1QQ=","bytes":"371"},"server":{"ip":"1.1.1.3","port":"53","bytes":"328"},"event":{"end":"2025-05-23T20:24:04.841Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"25965908","start":"2025-05-23T20:24:04.815Z"},"type":"dns","destination":{"ip":"1.1.1.3","port":"53","bytes":"328"},"ecs":{"version":"8.0.0"},"source":{"ip":"192.168.100.3","port":"60286","bytes":"43"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
3527 + dns_answer:
3528 + "40.126.29.7, 40.126.29.15, 40.126.29.10, 20.190.157.14, 20.190.157.9, 40.126.29.5, 20.190.157.4, 20.190.157.0",
3529 + data_dns_id: "56796",
3530 + src_port: "60286",
3531 + manager_name: "ASHWZHMA",
3532 + data_dns_question_top_level_domain: "com",
3533 + data_network_direction: "egress",
3534 + data_event_end: "2025-05-23T20:24:04.841Z",
3535 + data_agent_name: "piHole",
3536 + data_client_ip: "192.168.100.3",
3537 + data_dns_flags_authoritative: "false",
3538 + data_server_bytes: "328",
3539 + data_dns_header_flags: "RD, RA, DO",
3540 + data_type: "dns",
3541 + data_dns_flags_checking_disabled: "false",
3542 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
3543 + "data_@metadata_version": "8.7.1",
3544 + data_host_os_name: "Debian GNU/Linux",
3545 + rule_group3: "dns",
3546 + msg_timestamp: "2025-05-23T20:24:06.276Z",
3547 + rule_group2: "packetbeat",
3548 + rule_group1: "linux"
3549 + },
3550 + {
3551 + data_source_ip: "192.168.100.1",
3552 + data_host_architecture: "x86_64",
3553 + agent_id: "032",
3554 + agent_name: "piHole",
3555 + gl2_remote_ip: "10.255.255.13",
3556 + data_resource: "wns.notify.trafficmanager.net",
3557 + agent_labels_customer: "00001",
3558 + data_ecs_version: "8.0.0",
3559 + timestamp_utc: "2025-05-23T20:24:04.324Z",
3560 + data_host_os_codename: "bullseye",
3561 + syslog_type: "wazuh",
3562 + gl2_source_node: "3b68efa4-3319-4885-a38f-c944f0fcf191",
3563 + id: "1748031846.83705408",
3564 + data_dns_question_etld_plus_one: "trafficmanager.net",
3565 + data_server_port: "53",
3566 + rule_mitre_tactic: "Command and Control",
3567 + gl2_accounted_message_size: 6296,
3568 + data_agent_type: "packetbeat",
3569 + streams: ["660320f176ca320e8393f057"],
3570 + rule_mitre_id: "T1071",
3571 + data_destination_bytes: "74",
3572 + data_event_dataset: "dns",
3573 + "data_@metadata_beat": "packetbeat",
3574 + agent_ip: "192.168.100.3",
3575 + data_source_port: "10467",
3576 + data_host_id: "8986bcccef884a1ebe34f1ccd31b4f50",
3577 + data_event_kind: "event",
3578 + data_network_protocol: "dns",
3579 + dns_response_code: "NOERROR",
3580 + dns_query: "wns.notify.trafficmanager.net",
3581 + data_dns_response_code: "NOERROR",
3582 + data_network_community_id: "1:RAgDkVIAbVNgcEH1gw0uw34FTTc=",
3583 + data_dns_flags_truncated_response: "false",
3584 + rule_mail: false,
3585 + data_dns_opt_udp_size: "1232",
3586 + data_event_category: "network",
3587 + data_dns_flags_recursion_available: "true",
3588 + data_dns_opt_version: "0",
3589 + timestamp: "2025-05-23 20:24:08.829",
3590 + data_host_mac: "00-0C-29-09-D5-9B",
3591 + data_agent_id: "9d8db289-3bc9-40d3-92cb-2bd2d9f9434b",
3592 + data_destination_port: "53",
3593 + data_dns_type: "answer",
3594 + traffic_direction: "ingress",
3595 + rule_id: "200300",
3596 + data_dns_question_class: "IN",
3597 + cluster_node: "ASHWZHMA.socfortress.local",
3598 + dst_port: "53",
3599 + "data_@timestamp": "2025-05-23T20:24:04.324Z",
3600 + data_event_duration: "8268226",
3601 + data_host_os_platform: "debian",
3602 + data_dns_flags_recursion_desired: "true",
3603 + data_host_name: "piHole",
3604 + data_dns_question_subdomain: "wns.notify",
3605 + gl2_remote_port: 53290,
3606 + data_host_os_type: "linux",
3607 + source: "10.255.255.13",
3608 + gl2_source_input: "660320f176ca320e8393f030",
3609 + rule_level: 3,
3610 + data_event_type: "connection, protocol",
3611 + data_host_os_family: "debian",
3612 + data_dns_additionals_count: "0",
3613 + data_dns_flags_authentic_data: "false",
3614 + protocol: "udp",
3615 + data_dns_answers: "{data=104.208.203.90, name=wns.notify.trafficmanager.net, type=A, class=IN, ttl=100}",
3616 + data_agent_ephemeral_id: "f64f34f9-15e3-4717-8349-bc5e342d07c3",
3617 + data_event_start: "2025-05-23T20:24:04.324Z",
3618 + rule_description: "Linux: DNS Query to wns.notify.trafficmanager.net",
3619 + data_agent_version: "8.7.1",
3620 + data_related_ip: "192.168.100.1, 192.168.100.3, 104.208.203.90",
3621 + data_status: "OK",
3622 + data_query: "class IN, type A, wns.notify.trafficmanager.net",
3623 + "data_@metadata_type": "_doc",
3624 + data_dns_question_registered_domain: "trafficmanager.net",
3625 + data_method: "QUERY",
3626 + data_server_ip: "192.168.100.3",
3627 + gl2_message_id: "01JVZD2GBXAENHVG3BRH7X6GJF",
3628 + data_dns_answers_count: "1",
3629 + data_network_type: "ipv4",
3630 + data_dns_opt_ext_rcode: "NOERROR",
3631 + data_client_port: "10467",
3632 + data_network_bytes: "132",
3633 + data_dns_resolved_ip: "104.208.203.90",
3634 + data_host_containerized: "false",
3635 + true: 1748031846.242808,
3636 + data_host_hostname: "piHole",
3637 + rule_groups: "linux, packetbeat, dns",
3638 + data_client_bytes: "58",
3639 + data_dns_question_type: "A",
3640 + data_destination_ip: "192.168.100.3",
3641 + data_host_ip: "192.168.100.3, fe80::20c:29ff:fe09:d59b",
3642 + rule_mitre_technique: "Application Layer Protocol",
3643 + rule_firedtimes: 270,
3644 + data_network_transport: "udp",
3645 + dst_ip: "192.168.100.3",
3646 + src_ip: "192.168.100.1",
3647 + decoder_name: "json",
3648 + syslog_level: "INFO",
3649 + data_dns_op_code: "QUERY",
3650 + data_host_os_version: "11 (bullseye)",
3651 + data_host_os_kernel: "5.10.0-21-amd64",
3652 + cluster_name: "socfortress",
3653 + data_source_bytes: "58",
3654 + gl2_processing_error:
3655 + 'Replaced invalid timestamp value in message <e13c12b0-3813-11f0-91aa-8600007a2218> with current time - Value <2025-05-23T20:24:06.242+0000> caused exception: Invalid format: "2025-05-23T20:24:06.242+0000" is malformed at "T20:24:06.242+0000".',
3656 + data_dns_opt_do: "true",
3657 + data_dns_authorities_count: "0",
3658 + data_dns_question_name: "wns.notify.trafficmanager.net",
3659 + message:
3660 + '{"true":1748031846.242808,"timestamp":"2025-05-23T20:24:06.242+0000","rule":{"level":3,"description":"Linux: DNS Query to wns.notify.trafficmanager.net","id":"200300","mitre":{"id":["T1071"],"tactic":["Command and Control"],"technique":["Application Layer Protocol"]},"firedtimes":270,"mail":false,"groups":["linux","packetbeat","dns"]},"agent":{"id":"032","name":"piHole","ip":"192.168.100.3","labels":{"customer":"00001"}},"manager":{"name":"ASHWZHMA"},"id":"1748031846.83705408","cluster":{"name":"socfortress","node":"ASHWZHMA.socfortress.local"},"decoder":{"name":"json"},"data":{"status":"OK","@timestamp":"2025-05-23T20:24:04.324Z","@metadata":{"beat":"packetbeat","type":"_doc","version":"8.7.1"},"agent":{"ephemeral_id":"f64f34f9-15e3-4717-8349-bc5e342d07c3","id":"9d8db289-3bc9-40d3-92cb-2bd2d9f9434b","name":"piHole","type":"packetbeat","version":"8.7.1"},"dns":{"additionals_count":"0","id":"36071","answers_count":"1","authorities_count":"0","type":"answer","op_code":"QUERY","resolved_ip":["104.208.203.90"],"response_code":"NOERROR","header_flags":["RD","RA","DO"],"question":{"subdomain":"wns.notify","name":"wns.notify.trafficmanager.net","type":"A","class":"IN","etld_plus_one":"trafficmanager.net","registered_domain":"trafficmanager.net","top_level_domain":"net"},"flags":{"authentic_data":"false","checking_disabled":"false","authoritative":"false","truncated_response":"false","recursion_desired":"true","recursion_available":"true"},"opt":{"version":"0","udp_size":"1232","ext_rcode":"NOERROR","do":"true"},"answers":[{"data":"104.208.203.90","name":"wns.notify.trafficmanager.net","type":"A","class":"IN","ttl":"100"}]},"method":"QUERY","event":{"start":"2025-05-23T20:24:04.324Z","end":"2025-05-23T20:24:04.332Z","kind":"event","category":["network"],"type":["connection","protocol"],"dataset":"dns","duration":"8268226"},"source":{"ip":"192.168.100.1","port":"10467","bytes":"58"},"destination":{"ip":"192.168.100.3","port":"53","bytes":"74"},"client":{"ip":"192.168.100.1","port":"10467","bytes":"58"},"type":"dns","related":{"ip":["192.168.100.1","192.168.100.3","104.208.203.90"]},"host":{"ip":["192.168.100.3","fe80::20c:29ff:fe09:d59b"],"mac":["00-0C-29-09-D5-9B"],"hostname":"piHole","architecture":"x86_64","name":"piHole","os":{"name":"Debian GNU/Linux","kernel":"5.10.0-21-amd64","codename":"bullseye","type":"linux","platform":"debian","version":"11 (bullseye)","family":"debian"},"id":"8986bcccef884a1ebe34f1ccd31b4f50","containerized":"false"},"network":{"type":"ipv4","transport":"udp","protocol":"dns","direction":"ingress","community_id":"1:RAgDkVIAbVNgcEH1gw0uw34FTTc=","bytes":"132"},"resource":"wns.notify.trafficmanager.net","server":{"ip":"192.168.100.3","port":"53","bytes":"74"},"query":"class IN, type A, wns.notify.trafficmanager.net","ecs":{"version":"8.0.0"}},"location":"/tmp/packetbeat/packetbeat-20250523-90.ndjson"}',
3661 + dns_answer: "104.208.203.90",
3662 + data_dns_id: "36071",
3663 + src_port: "10467",
3664 + manager_name: "ASHWZHMA",
3665 + data_dns_question_top_level_domain: "net",
3666 + data_network_direction: "ingress",
3667 + data_event_end: "2025-05-23T20:24:04.332Z",
3668 + data_agent_name: "piHole",
3669 + data_dns_flags_authoritative: "false",
3670 + data_client_ip: "192.168.100.1",
3671 + data_server_bytes: "74",
3672 + data_dns_header_flags: "RD, RA, DO",
3673 + data_type: "dns",
3674 + data_dns_flags_checking_disabled: "false",
3675 + location: "/tmp/packetbeat/packetbeat-20250523-90.ndjson",
3676 + "data_@metadata_version": "8.7.1",
3677 + data_host_os_name: "Debian GNU/Linux",
3678 + rule_group3: "dns",
3679 + msg_timestamp: "2025-05-23T20:24:06.242Z",
3680 + rule_group2: "packetbeat",
3681 + rule_group1: "linux"
3682 + }
3683 + ] as unknown as MitreEventDetails[],
3684 + field_used: "rule_mitre_id",
3685 + time_range: "now-24h",
3686 + page: 1,
3687 + page_size: 25,
3688 + total_pages: 678
3689 +}
frontend/src/components/monitoringAlerts/Item.vue
+1 -1
@@ -46,11 +46,11 @@
46
47 <script setup lang="ts">
48 import type { MonitoringAlert } from "@/types/monitoringAlerts.d"
49 +import { computed, ref } from "vue"
50 import Badge from "@/components/common/Badge.vue"
51 import CardEntity from "@/components/common/cards/CardEntity.vue"
52 import Icon from "@/components/common/Icon.vue"
53 import { useGoto } from "@/composables/useGoto"
53 -import { computed, ref } from "vue"
54 import AlertActions from "./ItemActions.vue"
55
56 const { alert, embedded } = defineProps<{
frontend/src/components/monitoringAlerts/ItemActions.vue
+3 -3
@@ -16,12 +16,12 @@
16 </template>
17
18 <script setup lang="ts">
19 -import type { MonitoringAlert } from "@/types/monitoringAlerts.d"
19 import type { Size } from "naive-ui/es/button/src/interface"
21 -import Api from "@/api"
22 -import Icon from "@/components/common/Icon.vue"
20 +import type { MonitoringAlert } from "@/types/monitoringAlerts.d"
21 import { NButton, useDialog, useMessage } from "naive-ui"
22 import { computed, ref, watch } from "vue"
23 +import Api from "@/api"
24 +import Icon from "@/components/common/Icon.vue"
25
26 const { alert, size } = defineProps<{
27 alert: MonitoringAlert
frontend/src/components/monitoringAlerts/List.vue
+2 -2
@@ -75,11 +75,11 @@
75
76 <script setup lang="ts">
77 import type { MonitoringAlert } from "@/types/monitoringAlerts.d"
78 -import Api from "@/api"
79 -import Icon from "@/components/common/Icon.vue"
78 import { useResizeObserver } from "@vueuse/core"
79 import { NButton, NEmpty, NPagination, NPopover, NSpin, useDialog, useMessage } from "naive-ui"
80 import { computed, onBeforeMount, ref } from "vue"
81 +import Api from "@/api"
82 +import Icon from "@/components/common/Icon.vue"
83 import Alert from "./Item.vue"
84
85 const dialog = useDialog()
frontend/src/components/networkConnectors/NetworkConnectorsList.vue
+2 -2
@@ -13,10 +13,10 @@
13
14 <script setup lang="ts">
15 import type { ServiceItemData } from "../services/types"
16 -import Api from "@/api"
17 -import ServicesList from "@/components/services/List.vue"
16 import { useMessage } from "naive-ui"
17 import { onBeforeMount, ref } from "vue"
18 +import Api from "@/api"
19 +import ServicesList from "@/components/services/List.vue"
20
21 const { embedded, hideTotals, selectable, disabledIdsList } = defineProps<{
22 embedded?: boolean
frontend/src/components/overview/AgentsCard.vue
+2 -2
@@ -11,13 +11,13 @@
11 <script setup lang="ts">
12 import type { ItemProps } from "@/components/common/cards/CardStatsMulti.vue"
13 import type { Agent } from "@/types/agents.d"
14 +import { NSpin, useMessage } from "naive-ui"
15 +import { computed, onBeforeMount, ref } from "vue"
16 import Api from "@/api"
17 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
18 import CardStatsMulti from "@/components/common/cards/CardStatsMulti.vue"
19 import { useGoto } from "@/composables/useGoto"
20 import { AgentStatus } from "@/types/agents.d"
19 -import { NSpin, useMessage } from "naive-ui"
20 -import { computed, onBeforeMount, ref } from "vue"
21
22 const AgentsIcon = "carbon:network-3"
23 const { gotoAgent } = useGoto()
frontend/src/components/overview/CustomersCard.vue
+2 -2
@@ -16,12 +16,12 @@
16
17 <script setup lang="ts">
18 import type { Customer } from "@/types/customers.d"
19 +import { NSpin, useMessage } from "naive-ui"
20 +import { computed, onBeforeMount, ref } from "vue"
21 import Api from "@/api"
22 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
23 import CardStatsMulti from "@/components/common/cards/CardStatsMulti.vue"
24 import { useGoto } from "@/composables/useGoto"
23 -import { NSpin, useMessage } from "naive-ui"
24 -import { computed, onBeforeMount, ref } from "vue"
25
26 const CustomersIcon = "carbon:user-multiple"
27 const { gotoCustomer } = useGoto()
frontend/src/components/overview/HealthcheckCard.vue
+2 -2
@@ -16,14 +16,14 @@
16 <script setup lang="ts">
17 import type { ItemProps } from "@/components/common/cards/CardStatsMulti.vue"
18 import type { InfluxDBAlert } from "@/types/healthchecks.d"
19 +import { NSpin, useMessage } from "naive-ui"
20 +import { computed, onBeforeMount, ref } from "vue"
21 import Api from "@/api"
22 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
23 import CardStatsMulti from "@/components/common/cards/CardStatsMulti.vue"
24 import { useGoto } from "@/composables/useGoto"
25 import { useThemeStore } from "@/stores/theme"
26 import { InfluxDBAlertLevel } from "@/types/healthchecks.d"
25 -import { NSpin, useMessage } from "naive-ui"
26 -import { computed, onBeforeMount, ref } from "vue"
27
28 const HealthcheckIcon = "ph:heartbeat"
29 const { gotoHealthcheck } = useGoto()
frontend/src/components/overview/IncidentAlerts.vue
+2 -2
@@ -16,12 +16,12 @@
16
17 <script setup lang="ts">
18 import type { ItemProps } from "@/components/common/cards/CardStatsBars.vue"
19 +import { NSpin, useMessage } from "naive-ui"
20 +import { computed, onBeforeMount, ref } from "vue"
21 import Api from "@/api"
22 import CardStatsBars from "@/components/common/cards/CardStatsBars.vue"
23 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
24 import { useGoto } from "@/composables/useGoto"
23 -import { NSpin, useMessage } from "naive-ui"
24 -import { computed, onBeforeMount, ref } from "vue"
25
26 const AlertsIcon = "carbon:warning-hex"
27 const { gotoIncidentManagementAlerts } = useGoto()
frontend/src/components/overview/IncidentCases.vue
+2 -2
@@ -17,12 +17,12 @@
17 <script setup lang="ts">
18 import type { ItemProps } from "@/components/common/cards/CardStatsBars.vue"
19 import type { Case } from "@/types/incidentManagement/cases"
20 +import { NSpin, useMessage } from "naive-ui"
21 +import { computed, onBeforeMount, ref } from "vue"
22 import Api from "@/api"
23 import CardStatsBars from "@/components/common/cards/CardStatsBars.vue"
24 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
25 import { useGoto } from "@/composables/useGoto"
24 -import { NSpin, useMessage } from "naive-ui"
25 -import { computed, onBeforeMount, ref } from "vue"
26
27 const CasesIcon = "carbon:ibm-secure-infrastructure-on-vpc-for-regulated-industries"
28 const { gotoIncidentManagementCases } = useGoto()
frontend/src/components/overview/SocAlertsCard.vue
+2 -2
@@ -17,12 +17,12 @@
17
18 <script setup lang="ts">
19 import type { SocAlert } from "@/types/soc/alert.d"
20 +import { NSpin, useMessage } from "naive-ui"
21 +import { computed, onBeforeMount, ref, toRefs } from "vue"
22 import Api from "@/api"
23 import CardStats from "@/components/common/cards/CardStats.vue"
24 import CardStatsIcon from "@/components/common/cards/CardStatsIcon.vue"
25 import { useGoto } from "@/composables/useGoto"
24 -import { NSpin, useMessage } from "naive-ui"
25 -import { computed, onBeforeMount, ref, toRefs } from "vue"
26
27 const props = defineProps<{
28 vertical?: boolean
frontend/src/components/profile/ProfileSettings.vue
+2 -2
@@ -27,10 +27,10 @@
27
28 <script setup lang="ts">
29 import type { FormInst, FormValidationError } from "naive-ui"
30 -import { useSettingsStore } from "@/stores/settings"
31 -import dayjs from "@/utils/dayjs"
30 import { NButton, NCard, NForm, NFormItem, NRadio, NRadioGroup, NSelect, NSpin, useMessage } from "naive-ui"
31 import { ref } from "vue"
32 +import { useSettingsStore } from "@/stores/settings"
33 +import dayjs from "@/utils/dayjs"
34
35 const settingsStore = useSettingsStore()
36
frontend/src/components/reportCreation/Panels.vue
+5 -5
@@ -196,19 +196,19 @@
196 </template>
197
198 <script setup lang="ts">
199 +import type { PrintSettingsData } from "./PrintSettings.vue"
200 import type { GenerateReportPayload, ReportTimeRange } from "@/api/endpoints/reporting"
201 import type { Dashboard, Org, Panel } from "@/types/reporting.d"
201 -import type { PrintSettingsData } from "./PrintSettings.vue"
202 -import Api from "@/api"
203 -import Icon from "@/components/common/Icon.vue"
204 -import { useSettingsStore } from "@/stores/settings"
205 -import { formatDate } from "@/utils"
202 import { useStorage } from "@vueuse/core"
203 import { saveAs } from "file-saver"
204 import _kebabCase from "lodash/kebabCase"
205 import { NButton, NDrawer, NDrawerContent, NPopover, NScrollbar, NSpin, NSwitch, NTooltip, useMessage } from "naive-ui"
206 import { computed, onMounted, ref, toRefs, watch } from "vue"
207 import draggable from "vuedraggable"
208 +import Api from "@/api"
209 +import Icon from "@/components/common/Icon.vue"
210 +import { useSettingsStore } from "@/stores/settings"
211 +import { formatDate } from "@/utils"
212 import * as defaultSettings from "./defaultSettings"
213 import PrintSettings from "./PrintSettings.vue"
214
frontend/src/components/reportCreation/PrintSettings.vue
+2 -2
@@ -38,11 +38,11 @@
38
39 <script setup lang="ts">
40 import type { ImageCropperResult } from "@/components/common/ImageCropper.vue"
41 -import Icon from "@/components/common/Icon.vue"
42 -import ImageCropper from "@/components/common/ImageCropper.vue"
41 import { useStorage } from "@vueuse/core"
42 import { NAvatar, NButton, NFormItem, NInput, NRadioButton, NRadioGroup, NSwitch } from "naive-ui"
43 import { onMounted, watch } from "vue"
44 +import Icon from "@/components/common/Icon.vue"
45 +import ImageCropper from "@/components/common/ImageCropper.vue"
46 import * as defaultSettings from "./defaultSettings"
47
48 export interface PrintSettingsData {
frontend/src/components/reportCreation/Wizard.vue
+1 -1
@@ -52,10 +52,10 @@
52 <script setup lang="ts">
53 import type { ReportTimeRange, RowPanelTimeUnit } from "@/api/endpoints/reporting"
54 import type { Dashboard, Org, Panel } from "@/types/reporting.d"
55 -import Api from "@/api"
55 import { useStorage } from "@vueuse/core"
56 import { NForm, NFormItem, NInputGroup, NInputNumber, NSelect, NSpin, useMessage } from "naive-ui"
57 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
58 +import Api from "@/api"
59
60 const props = defineProps<{
61 hidePanelsSelect?: boolean
frontend/src/components/scheduler/Item.vue
+1 -1
@@ -45,12 +45,12 @@
45
46 <script setup lang="ts">
47 import type { Job } from "@/types/scheduler.d"
48 +import { NTooltip } from "naive-ui"
49 import Badge from "@/components/common/Badge.vue"
50 import CardEntity from "@/components/common/cards/CardEntity.vue"
51 import Icon from "@/components/common/Icon.vue"
52 import { useSettingsStore } from "@/stores/settings"
53 import { formatDate } from "@/utils"
53 -import { NTooltip } from "naive-ui"
54 import JobActions from "./JobActions.vue"
55 import NextJobTimeTooltip from "./NextJobTimeTooltip.vue"
56
frontend/src/components/scheduler/JobActions.vue
+3 -3
@@ -44,13 +44,13 @@
44 </template>
45
46 <script setup lang="ts">
47 +import type { Size } from "naive-ui/es/button/src/interface"
48 import type { UpdateJobPayload } from "@/api/endpoints/scheduler"
49 import type { Job } from "@/types/scheduler.d"
49 -import type { Size } from "naive-ui/es/button/src/interface"
50 -import Api from "@/api"
51 -import Icon from "@/components/common/Icon.vue"
50 import { NButton, NModal, useMessage } from "naive-ui"
51 import { ref, toRefs } from "vue"
52 +import Api from "@/api"
53 +import Icon from "@/components/common/Icon.vue"
54 import JobForm from "./JobForm.vue"
55
56 const props = defineProps<{ job: Job; size?: Size; inline?: boolean }>()
frontend/src/components/scheduler/JobForm.vue
+2 -2
@@ -29,14 +29,14 @@
29 </template>
30
31 <script setup lang="ts">
32 +import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
33 import type { UpdateJobPayload } from "@/api/endpoints/scheduler"
34 import type { Job } from "@/types/scheduler.d"
34 -import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
35 -import Api from "@/api"
35 import _get from "lodash/get"
36 import _trim from "lodash/trim"
37 import { NButton, NForm, NFormItem, NInputNumber, NSpin, useMessage } from "naive-ui"
38 import { computed, ref, toRefs } from "vue"
39 +import Api from "@/api"
40
41 const props = defineProps<{ job: Job }>()
42 const emit = defineEmits<{
frontend/src/components/scheduler/List.vue
+1 -1
@@ -15,9 +15,9 @@
15
16 <script setup lang="ts">
17 import type { Job } from "@/types/scheduler.d"
18 -import Api from "@/api"
18 import { NEmpty, NSpin, useMessage } from "naive-ui"
19 import { computed, onBeforeMount, ref } from "vue"
20 +import Api from "@/api"
21 import JobCard from "./Item.vue"
22
23 const message = useMessage()
frontend/src/components/scheduler/NextJobTimeTooltip.vue
+2 -2
@@ -14,12 +14,12 @@
14 </template>
15
16 <script setup lang="ts">
17 +import { NSpin, NTooltip, useMessage } from "naive-ui"
18 +import { ref, toRefs } from "vue"
19 import Api from "@/api"
20 import Icon from "@/components/common/Icon.vue"
21 import { useSettingsStore } from "@/stores/settings"
22 import { formatDate } from "@/utils"
21 -import { NSpin, NTooltip, useMessage } from "naive-ui"
22 -import { ref, toRefs } from "vue"
23
24 const props = defineProps<{ jobId: string }>()
25 const { jobId } = toRefs(props)
frontend/src/components/services/Item.vue
+2 -2
@@ -52,11 +52,11 @@
52
53 <script setup lang="ts">
54 import type { ServiceItemData, ServiceItemType } from "./types"
55 +import { NButton, NModal, NRadio } from "naive-ui"
56 +import { defineAsyncComponent, ref, toRefs } from "vue"
57 import Badge from "@/components/common/Badge.vue"
58 import CardEntity from "@/components/common/cards/CardEntity.vue"
59 import Icon from "@/components/common/Icon.vue"
58 -import { NButton, NModal, NRadio } from "naive-ui"
59 -import { defineAsyncComponent, ref, toRefs } from "vue"
60
61 const props = defineProps<{
62 data: ServiceItemData
frontend/src/components/sigma/QueriesActions.vue
+1 -1
@@ -48,8 +48,8 @@
48 </template>
49
50 <script setup lang="ts">
51 -import Icon from "@/components/common/Icon.vue"
51 import { NButton } from "naive-ui"
52 +import Icon from "@/components/common/Icon.vue"
53 import QueryActiveAllForm from "./actionsProviders/QueryActiveAllForm.vue"
54 import QueryDeleteAll from "./actionsProviders/QueryDeleteAll.vue"
55 import QueryDownloadAll from "./actionsProviders/QueryDownloadAll.vue"
frontend/src/components/sigma/QueriesList.vue
+3 -3
@@ -128,14 +128,14 @@
128
129 <script setup lang="ts">
130 import type { SigmaQuery } from "@/types/sigma.d"
131 -import Api from "@/api"
132 -import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
133 -import Icon from "@/components/common/Icon.vue"
131 import { useResizeObserver, useStorage } from "@vueuse/core"
132 import _cloneDeep from "lodash/cloneDeep"
133 import _orderBy from "lodash/orderBy"
134 import { NBadge, NButton, NEmpty, NPagination, NPopover, NSelect, NSpin, useMessage } from "naive-ui"
135 import { computed, onBeforeMount, ref, watch } from "vue"
136 +import Api from "@/api"
137 +import CollapseKeepAlive from "@/components/common/CollapseKeepAlive.vue"
138 +import Icon from "@/components/common/Icon.vue"
139 import QueriesActions from "./QueriesActions.vue"
140 import QueryItem from "./QueryItem.vue"
141
frontend/src/components/sigma/QueryItem.vue
+2 -2
@@ -92,13 +92,13 @@
92
93 <script setup lang="ts">
94 import type { SigmaQuery } from "@/types/sigma.d"
95 +import { NButton, NCard, NModal, NSpin } from "naive-ui"
96 +import { ref, toRefs } from "vue"
97 import Badge from "@/components/common/Badge.vue"
98 import CardEntity from "@/components/common/cards/CardEntity.vue"
99 import Icon from "@/components/common/Icon.vue"
100 import { useSettingsStore } from "@/stores/settings"
101 import { formatDate } from "@/utils"
100 -import { NButton, NCard, NModal, NSpin } from "naive-ui"
101 -import { ref, toRefs } from "vue"
102 import QueryDeleteOne from "./actionsProviders/QueryDeleteOne.vue"
103 import QueryTimeIntervalForm from "./actionsProviders/QueryTimeIntervalForm.vue"
104 import QueryDetails from "./QueryDetails.vue"
frontend/src/components/sigma/QueryOverview.vue
+2 -2
@@ -128,12 +128,12 @@
128
129 <script setup lang="ts">
130 import type { SigmaQuery } from "@/types/sigma.d"
131 +import { NButton, NSpin } from "naive-ui"
132 +import { ref, toRefs } from "vue"
133 import CardKV from "@/components/common/cards/CardKV.vue"
134 import Icon from "@/components/common/Icon.vue"
135 import { useSettingsStore } from "@/stores/settings"
136 import { formatDate } from "@/utils"
135 -import { NButton, NSpin } from "naive-ui"
136 -import { ref, toRefs } from "vue"
137 import QueryActiveForm from "./actionsProviders/QueryActiveForm.vue"
138 import QueryDeleteOne from "./actionsProviders/QueryDeleteOne.vue"
139 import QueryTimeIntervalForm from "./actionsProviders/QueryTimeIntervalForm.vue"
frontend/src/components/sigma/actionsProviders/QueryActiveAllForm.vue
+1 -1
@@ -20,9 +20,9 @@
20 </template>
21
22 <script setup lang="ts">
23 -import Api from "@/api"
23 import { NButton, NPopover, useMessage } from "naive-ui"
24 import { ref } from "vue"
25 +import Api from "@/api"
26
27 const emit = defineEmits<{
28 (e: "updated"): void
frontend/src/components/sigma/actionsProviders/QueryActiveForm.vue
+1 -1
@@ -22,9 +22,9 @@
22
23 <script setup lang="ts">
24 import type { SigmaQuery } from "@/types/sigma.d"
25 -import Api from "@/api"
25 import { NButton, NPopover, NSwitch, useMessage } from "naive-ui"
26 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
27 +import Api from "@/api"
28
29 const props = defineProps<{
30 query: SigmaQuery
frontend/src/components/sigma/actionsProviders/QueryDeleteAll.vue
+1 -1
@@ -18,9 +18,9 @@
18 </template>
19
20 <script setup lang="ts">
21 -import Api from "@/api"
21 import { NButton, NPopover, useMessage } from "naive-ui"
22 import { ref } from "vue"
23 +import Api from "@/api"
24
25 const emit = defineEmits<{
26 (e: "updated"): void
frontend/src/components/sigma/actionsProviders/QueryDeleteOne.vue
+2 -2
@@ -26,10 +26,10 @@
26
27 <script setup lang="ts">
28 import type { SigmaQuery } from "@/types/sigma.d"
29 -import Api from "@/api"
30 -import Icon from "@/components/common/Icon.vue"
29 import { NButton, NPopover, useMessage } from "naive-ui"
30 import { ref, toRefs } from "vue"
31 +import Api from "@/api"
32 +import Icon from "@/components/common/Icon.vue"
33
34 const props = defineProps<{
35 query: SigmaQuery
frontend/src/components/sigma/actionsProviders/QueryDownloadAll.vue
+1 -1
@@ -16,9 +16,9 @@
16 </template>
17
18 <script setup lang="ts">
19 -import Api from "@/api"
19 import { NButton, NPopover, useMessage } from "naive-ui"
20 import { ref } from "vue"
21 +import Api from "@/api"
22
23 const emit = defineEmits<{
24 (e: "updated"): void
frontend/src/components/sigma/actionsProviders/QueryTimeIntervalForm.vue
+1 -1
@@ -43,9 +43,9 @@
43
44 <script setup lang="ts">
45 import type { SigmaQuery, SigmaTimeInterval, SigmaTimeIntervalUnit } from "@/types/sigma.d"
46 -import Api from "@/api"
46 import { NButton, NInputGroup, NInputNumber, NPopover, NSelect, useMessage } from "naive-ui"
47 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
48 +import Api from "@/api"
49
50 const props = defineProps<{
51 query: SigmaQuery
frontend/src/components/sigma/actionsProviders/QueryUploadDB.vue
+1 -1
@@ -26,9 +26,9 @@
26
27 <script setup lang="ts">
28 import type { SigmaRuleLevels } from "@/types/sigma.d"
29 -import Api from "@/api"
29 import { NButton, NCheckbox, NCheckboxGroup, NPopover, useMessage } from "naive-ui"
30 import { computed, ref } from "vue"
31 +import Api from "@/api"
32
33 const emit = defineEmits<{
34 (e: "updated"): void
frontend/src/components/sigma/actionsProviders/QueryUploadFile.vue
+2 -2
@@ -32,10 +32,10 @@
32
33 <script setup lang="ts">
34 import type { UploadFileInfo } from "naive-ui"
35 -import Api from "@/api"
36 -import Icon from "@/components/common/Icon.vue"
35 import { NButton, NPopover, NUpload, NUploadDragger, useMessage } from "naive-ui"
36 import { computed, ref } from "vue"
37 +import Api from "@/api"
38 +import Icon from "@/components/common/Icon.vue"
39
40 const emit = defineEmits<{
41 (e: "updated"): void
frontend/src/components/soc/SocAlerts/SocAlertAssets/SocAlertAssetsItem.vue
+3 -3
@@ -142,6 +142,9 @@
142
143 <script setup lang="ts">
144 import type { SocAlertAsset } from "@/types/soc/asset.d"
145 +import _omit from "lodash/omit"
146 +import { NModal, NTabPane, NTabs } from "naive-ui"
147 +import { computed, defineAsyncComponent, ref } from "vue"
148 import Badge from "@/components/common/Badge.vue"
149 import CardEntity from "@/components/common/cards/CardEntity.vue"
150 import CardKV from "@/components/common/cards/CardKV.vue"
@@ -150,9 +153,6 @@ import { useGoto } from "@/composables/useGoto"
153 import { useSettingsStore } from "@/stores/settings"
154 import { isUrlLike } from "@/utils"
155 import dayjs from "@/utils/dayjs"
153 -import _omit from "lodash/omit"
154 -import { NModal, NTabPane, NTabs } from "naive-ui"
155 -import { computed, defineAsyncComponent, ref } from "vue"
156
157 const { asset } = defineProps<{ asset: SocAlertAsset }>()
158
frontend/src/components/soc/SocAlerts/SocAlertAssets/SocAlertAssetsList.vue
+1 -1
@@ -13,9 +13,9 @@
13
14 <script setup lang="ts">
15 import type { SocAlertAsset } from "@/types/soc/asset.d"
16 -import Api from "@/api"
16 import { NEmpty, NSpin, useMessage } from "naive-ui"
17 import { onBeforeMount, ref } from "vue"
18 +import Api from "@/api"
19 import SocAlertAssetsItem from "./SocAlertAssetsItem.vue"
20
21 const { alertId } = defineProps<{ alertId: string | number }>()
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItem.vue
+2 -2
@@ -110,11 +110,11 @@
110 import type { Alert } from "@/types/alerts.d"
111 import type { SocAlert } from "@/types/soc/alert.d"
112 import type { SocUser } from "@/types/soc/user.d"
113 +import { NCheckbox, NCollapse, NCollapseItem, NCollapseTransition, NModal, useMessage } from "naive-ui"
114 +import { computed, defineAsyncComponent, onBeforeMount, ref, toRefs, watch } from "vue"
115 import Api from "@/api"
116 import CardEntity from "@/components/common/cards/CardEntity.vue"
117 import Icon from "@/components/common/Icon.vue"
116 -import { NCheckbox, NCollapse, NCollapseItem, NCollapseTransition, NModal, useMessage } from "naive-ui"
117 -import { computed, defineAsyncComponent, onBeforeMount, ref, toRefs, watch } from "vue"
118 import SocAlertItemActions from "./SocAlertItemActions.vue"
119 import SocAlertItemBookmarkToggler from "./SocAlertItemBookmarkToggler.vue"
120 import SocAlertItemTime from "./SocAlertItemTime.vue"
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemActions.vue
+2 -2
@@ -58,11 +58,11 @@
58
59 <script setup lang="ts">
60 import type { Size } from "naive-ui/es/button/src/interface"
61 +import { NButton, NModal, useDialog, useMessage } from "naive-ui"
62 +import { computed, ref, watch } from "vue"
63 import Api from "@/api"
64 import Icon from "@/components/common/Icon.vue"
65 import SocCaseItem from "@/components/soc/SocCases/SocCaseItem.vue"
64 -import { NButton, NModal, useDialog, useMessage } from "naive-ui"
65 -import { computed, ref, watch } from "vue"
66
67 const { alertId, caseId, size } = defineProps<{
68 alertId?: string | number | null
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemBadges.vue
+2 -2
@@ -86,11 +86,11 @@
86 <script setup lang="ts">
87 import type { SocAlert } from "@/types/soc/alert.d"
88 import type { SocUser } from "@/types/soc/user.d"
89 +import { NSpin, NTooltip } from "naive-ui"
90 +import { computed, toRefs } from "vue"
91 import Badge from "@/components/common/Badge.vue"
92 import Icon from "@/components/common/Icon.vue"
93 import { useGoto } from "@/composables/useGoto"
92 -import { NSpin, NTooltip } from "naive-ui"
93 -import { computed, toRefs } from "vue"
94 import SocAssignUser from "./SocAssignUser.vue"
95
96 const props = defineProps<{
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemBookmarkToggler.vue
+2 -2
@@ -10,10 +10,10 @@
10
11 <script setup lang="ts">
12 import type { SocAlert } from "@/types/soc/alert.d"
13 -import Api from "@/api"
14 -import Icon from "@/components/common/Icon.vue"
13 import { useMessage } from "naive-ui"
14 import { ref, toRefs } from "vue"
15 +import Api from "@/api"
16 +import Icon from "@/components/common/Icon.vue"
17
18 const props = defineProps<{
19 alert: SocAlert
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemContext.vue
+2 -2
@@ -35,13 +35,13 @@
35
36 <script setup lang="ts">
37 import type { SocAlert } from "@/types/soc/alert.d"
38 -import CardKV from "@/components/common/cards/CardKV.vue"
39 -import Icon from "@/components/common/Icon.vue"
38 import _compact from "lodash/compact"
39 import _split from "lodash/split"
40 import _uniq from "lodash/uniq"
41 import { NInput } from "naive-ui"
42 import { computed, defineAsyncComponent, ref } from "vue"
43 +import CardKV from "@/components/common/cards/CardKV.vue"
44 +import Icon from "@/components/common/Icon.vue"
45
46 const { alert } = defineProps<{
47 alert: SocAlert
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemDetails.vue
+3 -3
@@ -90,13 +90,13 @@
90 <script setup lang="ts">
91 import type { SocAlert } from "@/types/soc/alert.d"
92 import type { SocUser } from "@/types/soc/user.d"
93 +import { NSpin, NTabPane, NTabs } from "naive-ui"
94 +import { computed, defineAsyncComponent } from "vue"
95 +import { SimpleJsonViewer } from "vue-sjv"
96 import Badge from "@/components/common/Badge.vue"
97 import CardKV from "@/components/common/cards/CardKV.vue"
98 import Icon from "@/components/common/Icon.vue"
99 import { useGoto } from "@/composables/useGoto"
97 -import { NSpin, NTabPane, NTabs } from "naive-ui"
98 -import { computed, defineAsyncComponent } from "vue"
99 -import { SimpleJsonViewer } from "vue-sjv"
100 import "@/assets/scss/overrides/vuesjv-override.scss"
101
102 const { alert } = defineProps<{
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemTime.vue
+2 -2
@@ -16,11 +16,11 @@
16
17 <script setup lang="ts">
18 import type { SocAlert } from "@/types/soc/alert.d"
19 +import { NPopover } from "naive-ui"
20 +import { toRefs } from "vue"
21 import Icon from "@/components/common/Icon.vue"
22 import { useSettingsStore } from "@/stores/settings"
23 import dayjs from "@/utils/dayjs"
22 -import { NPopover } from "naive-ui"
23 -import { toRefs } from "vue"
24 import SocAlertItemTimeline from "./SocAlertItemTimeline.vue"
25
26 const props = defineProps<{
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAlertItemTimeline.vue
+2 -2
@@ -13,11 +13,11 @@
13
14 <script setup lang="ts">
15 import type { SocAlert } from "@/types/soc/alert.d"
16 -import { useSettingsStore } from "@/stores/settings"
17 -import dayjs from "@/utils/dayjs"
16 import _toNumber from "lodash/toSafeInteger"
17 import { NTimeline, NTimelineItem } from "naive-ui"
18 import { onBeforeMount, ref } from "vue"
19 +import { useSettingsStore } from "@/stores/settings"
20 +import dayjs from "@/utils/dayjs"
21
22 const { alert } = defineProps<{ alert: SocAlert }>()
23
frontend/src/components/soc/SocAlerts/SocAlertItem/SocAssignUser.vue
+1 -1
@@ -15,9 +15,9 @@
15 <script setup lang="ts">
16 import type { SocAlert } from "@/types/soc/alert.d"
17 import type { SocUser } from "@/types/soc/user.d"
18 -import Api from "@/api"
18 import { NPopselect, useMessage } from "naive-ui"
19 import { computed, onBeforeMount, ref, toRefs, watch } from "vue"
20 +import Api from "@/api"
21
22 const props = defineProps<{
23 alert: SocAlert
frontend/src/components/soc/SocAlerts/SocAlertsBookmarks.vue
+1 -1
@@ -34,10 +34,10 @@
34 <script setup lang="ts">
35 import type { SocAlert } from "@/types/soc/alert.d"
36 import type { SocUser } from "@/types/soc/user.d"
37 -import Api from "@/api"
37 import axios from "axios"
38 import { NEmpty, NSpin, useMessage } from "naive-ui"
39 import { onBeforeMount, onBeforeUnmount, onMounted, ref, toRefs } from "vue"
40 +import Api from "@/api"
41 import SocAlertItem from "./SocAlertItem/SocAlertItem.vue"
42
43 const props = defineProps<{
frontend/src/components/soc/SocAlerts/SocAlertsFullList.vue
+2 -2
@@ -81,11 +81,11 @@
81 <script setup lang="ts">
82 import type { SocAlert } from "@/types/soc/alert.d"
83 import type { SocUser } from "@/types/soc/user.d"
84 -import Api from "@/api"
85 -import Icon from "@/components/common/Icon.vue"
84 import { useResizeObserver } from "@vueuse/core"
85 import { NBackTop, NButton, NDrawer, NDrawerContent, NSplit, useMessage } from "naive-ui"
86 import { onBeforeMount, ref, toRefs } from "vue"
87 +import Api from "@/api"
88 +import Icon from "@/components/common/Icon.vue"
89 import SocAlertsBookmarks from "./SocAlertsBookmarks.vue"
90 import SocAlertsList from "./SocAlertsList.vue"
91
frontend/src/components/soc/SocAlerts/SocAlertsList.vue
+3 -3
@@ -92,13 +92,13 @@
92 import type { AlertsFilter } from "@/api/endpoints/soc"
93 import type { SocAlert } from "@/types/soc/alert.d"
94 import type { SocUser } from "@/types/soc/user.d"
95 -import Api from "@/api"
96 -import Icon from "@/components/common/Icon.vue"
97 -import PaginationIndeterminate from "@/components/common/PaginationIndeterminate.vue"
95 import { useResizeObserver, watchDebounced } from "@vueuse/core"
96 import axios from "axios"
97 import { NButton, NEmpty, NInput, NPopover, NSpin, useDialog, useMessage } from "naive-ui"
98 import { computed, nextTick, onBeforeMount, onBeforeUnmount, onMounted, ref, toRefs, watch } from "vue"
99 +import Api from "@/api"
100 +import Icon from "@/components/common/Icon.vue"
101 +import PaginationIndeterminate from "@/components/common/PaginationIndeterminate.vue"
102 import SocAlertItem from "./SocAlertItem/SocAlertItem.vue"
103 // MOCK
104 // import { alerts as alertsMock } from "./mock"
frontend/src/components/soc/SocCases/SocCaseAssetLink.vue
+2 -2
@@ -67,14 +67,14 @@
67 <script setup lang="ts">
68 import type { SocCaseAssetLink } from "@/types/soc/asset.d"
69 import type { SocCase } from "@/types/soc/case.d"
70 +import { NCollapse, NCollapseItem, NEmpty, NSpin, useMessage } from "naive-ui"
71 +import { ref } from "vue"
72 import Api from "@/api"
73 import Badge from "@/components/common/Badge.vue"
74 import CardEntity from "@/components/common/cards/CardEntity.vue"
75 import Icon from "@/components/common/Icon.vue"
76 import { useSettingsStore } from "@/stores/settings"
77 import dayjs from "@/utils/dayjs"
76 -import { NCollapse, NCollapseItem, NEmpty, NSpin, useMessage } from "naive-ui"
77 -import { ref } from "vue"
78 import SocCaseItem from "./SocCaseItem.vue"
79
80 const { link } = defineProps<{ link: SocCaseAssetLink }>()
frontend/src/components/soc/SocCases/SocCaseAssetsItem.vue
+5 -5
@@ -113,16 +113,16 @@
113
114 <script setup lang="ts">
115 import type { SocCaseAsset } from "@/types/soc/asset.d"
116 -import Badge from "@/components/common/Badge.vue"
117 -import CardEntity from "@/components/common/cards/CardEntity.vue"
118 -import CardKV from "@/components/common/cards/CardKV.vue"
119 -import Icon from "@/components/common/Icon.vue"
120 -import { isUrlLike } from "@/utils"
116 import _omit from "lodash/omit"
117 import _split from "lodash/split"
118 import _upperFirst from "lodash/upperFirst"
119 import { NEmpty, NModal, NTabPane, NTabs } from "naive-ui"
120 import { computed, defineAsyncComponent, ref } from "vue"
121 +import Badge from "@/components/common/Badge.vue"
122 +import CardEntity from "@/components/common/cards/CardEntity.vue"
123 +import CardKV from "@/components/common/cards/CardKV.vue"
124 +import Icon from "@/components/common/Icon.vue"
125 +import { isUrlLike } from "@/utils"
126
127 const { asset } = defineProps<{ asset: SocCaseAsset }>()
128
frontend/src/components/soc/SocCases/SocCaseAssetsList.vue
+2 -2
@@ -23,11 +23,11 @@
23
24 <script setup lang="ts">
25 import type { SocCaseAsset, SocCaseAssetsState } from "@/types/soc/asset.d"
26 +import { NEmpty, NSpin, useMessage } from "naive-ui"
27 +import { onBeforeMount, ref } from "vue"
28 import Api from "@/api"
29 import { useSettingsStore } from "@/stores/settings"
30 import dayjs from "@/utils/dayjs"
29 -import { NEmpty, NSpin, useMessage } from "naive-ui"
30 -import { onBeforeMount, ref } from "vue"
31 import SocCaseAssetsItem from "./SocCaseAssetsItem.vue"
32
33 const { caseId } = defineProps<{ caseId: string | number }>()
frontend/src/components/soc/SocCases/SocCaseItem.vue
+9 -9
@@ -233,15 +233,6 @@
233
234 <script setup lang="ts">
235 import type { SocCase, SocCaseExt } from "@/types/soc/case.d"
236 -import Api from "@/api"
237 -import Badge from "@/components/common/Badge.vue"
238 -import CardEntity from "@/components/common/cards/CardEntity.vue"
239 -import CardKV from "@/components/common/cards/CardKV.vue"
240 -import Icon from "@/components/common/Icon.vue"
241 -import { useGoto } from "@/composables/useGoto"
242 -import { useSettingsStore } from "@/stores/settings"
243 -import { StateName } from "@/types/soc/case.d"
244 -import dayjs from "@/utils/dayjs"
236 import _omit from "lodash/omit"
237 import _split from "lodash/split"
238 import {
@@ -259,6 +250,15 @@ import {
250 useMessage
251 } from "naive-ui"
252 import { computed, defineAsyncComponent, onBeforeMount, ref, watch } from "vue"
253 +import Api from "@/api"
254 +import Badge from "@/components/common/Badge.vue"
255 +import CardEntity from "@/components/common/cards/CardEntity.vue"
256 +import CardKV from "@/components/common/cards/CardKV.vue"
257 +import Icon from "@/components/common/Icon.vue"
258 +import { useGoto } from "@/composables/useGoto"
259 +import { useSettingsStore } from "@/stores/settings"
260 +import { StateName } from "@/types/soc/case.d"
261 +import dayjs from "@/utils/dayjs"
262
263 const { caseData, caseId, embedded, hideSocCaseAction, hideSocAlertLink } = defineProps<{
264 caseData?: SocCase
frontend/src/components/soc/SocCases/SocCaseItemActions.vue
+3 -3
@@ -29,13 +29,13 @@
29 </template>
30
31 <script setup lang="ts">
32 -import type { SocCase, SocCaseExt } from "@/types/soc/case.d"
32 import type { Size } from "naive-ui/es/button/src/interface"
33 +import type { SocCase, SocCaseExt } from "@/types/soc/case.d"
34 +import { NButton, useDialog, useMessage } from "naive-ui"
35 +import { computed, ref, watch } from "vue"
36 import Api from "@/api"
37 import Icon from "@/components/common/Icon.vue"
38 import { StateName } from "@/types/soc/case.d"
37 -import { NButton, useDialog, useMessage } from "naive-ui"
38 -import { computed, ref, watch } from "vue"
39
40 const { caseData, size } = defineProps<{
41 caseData: SocCase | SocCaseExt | null
frontend/src/components/soc/SocCases/SocCaseNote.vue
+3 -3
@@ -96,14 +96,14 @@
96
97 <script setup lang="ts">
98 import type { SocNote } from "@/types/soc/note.d"
99 +import _omit from "lodash/omit"
100 +import { NInput, NModal, NPopover, NTabPane, NTabs } from "naive-ui"
101 +import { computed, defineAsyncComponent, ref } from "vue"
102 import CardEntity from "@/components/common/cards/CardEntity.vue"
103 import CardKV from "@/components/common/cards/CardKV.vue"
104 import Icon from "@/components/common/Icon.vue"
105 import { useSettingsStore } from "@/stores/settings"
106 import dayjs from "@/utils/dayjs"
104 -import _omit from "lodash/omit"
105 -import { NInput, NModal, NPopover, NTabPane, NTabs } from "naive-ui"
106 -import { computed, defineAsyncComponent, ref } from "vue"
107
108 const { note } = defineProps<{ note: SocNote }>()
109
frontend/src/components/soc/SocCases/SocCaseNoteForm.vue
+1 -1
@@ -24,9 +24,9 @@
24
25 <script setup lang="ts">
26 import type { SocNewNote } from "@/types/soc/note.d"
27 -import Api from "@/api"
27 import { NButton, NInput, NSpin, useMessage } from "naive-ui"
28 import { ref } from "vue"
29 +import Api from "@/api"
30
31 const { caseId } = defineProps<{ caseId: string | number }>()
32
frontend/src/components/soc/SocCases/SocCaseNoteTimeline.vue
+2 -2
@@ -13,10 +13,10 @@
13
14 <script setup lang="ts">
15 import type { SocNote } from "@/types/soc/note.d"
16 -import { useSettingsStore } from "@/stores/settings"
17 -import dayjs from "@/utils/dayjs"
16 import { NTimeline, NTimelineItem } from "naive-ui"
17 import { onBeforeMount, ref } from "vue"
18 +import { useSettingsStore } from "@/stores/settings"
19 +import dayjs from "@/utils/dayjs"
20
21 const { note } = defineProps<{ note: SocNote }>()
22
frontend/src/components/soc/SocCases/SocCaseNotesList.vue
+1 -1
@@ -16,11 +16,11 @@
16
17 <script setup lang="ts">
18 import type { SocNote } from "@/types/soc/note.d"
19 -import Api from "@/api"
19 import { refDebounced } from "@vueuse/core"
20 import axios from "axios"
21 import { NEmpty, NInput, NSpin, useMessage } from "naive-ui"
22 import { onBeforeMount, ref, toRefs, watch } from "vue"
23 +import Api from "@/api"
24 import SocCaseNote from "./SocCaseNote.vue"
25
26 const props = defineProps<{ caseId: string | number }>()
frontend/src/components/soc/SocCases/SocCaseTimeline.vue
+2 -2
@@ -13,11 +13,11 @@
13
14 <script setup lang="ts">
15 import type { SocCaseExt } from "@/types/soc/case.d"
16 -import { useSettingsStore } from "@/stores/settings"
17 -import dayjs from "@/utils/dayjs"
16 import _toNumber from "lodash/toSafeInteger"
17 import { NTimeline, NTimelineItem } from "naive-ui"
18 import { onBeforeMount, ref } from "vue"
19 +import { useSettingsStore } from "@/stores/settings"
20 +import dayjs from "@/utils/dayjs"
21
22 const { caseData } = defineProps<{ caseData: SocCaseExt }>()
23
frontend/src/components/soc/SocCases/SocCasesList.vue
+3 -3
@@ -114,9 +114,6 @@
114 <script setup lang="ts">
115 import type { CasesFilter } from "@/api/endpoints/soc"
116 import type { DateFormatted, SocCase } from "@/types/soc/case.d"
117 -import Api from "@/api"
118 -import Icon from "@/components/common/Icon.vue"
119 -import dayjs from "@/utils/dayjs"
117 import { useResizeObserver } from "@vueuse/core"
118 import _cloneDeep from "lodash/cloneDeep"
119 import _orderBy from "lodash/orderBy"
@@ -134,6 +131,9 @@ import {
131 useMessage
132 } from "naive-ui"
133 import { computed, onBeforeMount, ref, watch } from "vue"
134 +import Api from "@/api"
135 +import Icon from "@/components/common/Icon.vue"
136 +import dayjs from "@/utils/dayjs"
137 import SocCaseItem from "./SocCaseItem.vue"
138
139 const dialog = useDialog()
frontend/src/components/soc/SocUsers/SocUserAlerts.vue
+1 -1
@@ -39,10 +39,10 @@
39
40 <script setup lang="ts">
41 import type { SocAlert } from "@/types/soc/alert.d"
42 -import Api from "@/api"
42 import axios from "axios"
43 import { NModal, NSpin, NTooltip, useMessage } from "naive-ui"
44 import { onBeforeMount, onBeforeUnmount, ref } from "vue"
45 +import Api from "@/api"
46 import SocAlertItem from "../SocAlerts/SocAlertItem/SocAlertItem.vue"
47
48 const { userId } = defineProps<{
frontend/src/components/soc/SocUsers/SocUsersList.vue
+2 -2
@@ -57,10 +57,10 @@
57 <script setup lang="ts">
58 import type { SocAlert } from "@/types/soc/alert.d"
59 import type { SocUser } from "@/types/soc/user.d"
60 -import Api from "@/api"
61 -import Icon from "@/components/common/Icon.vue"
60 import { NScrollbar, NSpin, NTable, NTooltip, useMessage } from "naive-ui"
61 import { onBeforeMount, ref, toRefs } from "vue"
62 +import Api from "@/api"
63 +import Icon from "@/components/common/Icon.vue"
64 import SocUserAlerts from "./SocUserAlerts.vue"
65
66 const props = defineProps<{ highlight: string | null | undefined }>()
frontend/src/components/stackProvisioning/StackProvisioningButton.vue
+1 -1
@@ -21,9 +21,9 @@
21
22 <script setup lang="ts">
23 import type { Size, Type } from "naive-ui/es/button/src/interface"
24 -import Icon from "@/components/common/Icon.vue"
24 import { NButton, NModal } from "naive-ui"
25 import { ref } from "vue"
26 +import Icon from "@/components/common/Icon.vue"
27 import StackProvisioningList from "./StackProvisioningList.vue"
28
29 const { type, size } = defineProps<{
frontend/src/components/stackProvisioning/StackProvisioningItem.vue
+2 -2
@@ -25,11 +25,11 @@
25
26 <script setup lang="ts">
27 import type { AvailableContentPack } from "@/types/stackProvisioning.d"
28 +import { NButton, useMessage } from "naive-ui"
29 +import { ref } from "vue"
30 import Api from "@/api"
31 import CardEntity from "@/components/common/cards/CardEntity.vue"
32 import Icon from "@/components/common/Icon.vue"
31 -import { NButton, useMessage } from "naive-ui"
32 -import { ref } from "vue"
33
34 const { contentPack } = defineProps<{ contentPack: AvailableContentPack }>()
35
frontend/src/components/stackProvisioning/StackProvisioningList.vue
+1 -1
@@ -15,9 +15,9 @@
15
16 <script setup lang="ts">
17 import type { AvailableContentPack } from "@/types/stackProvisioning.d"
18 -import Api from "@/api"
18 import { NEmpty, NSpin, useMessage } from "naive-ui"
19 import { computed, onBeforeMount, ref } from "vue"
20 +import Api from "@/api"
21 import StackProvisioningItem from "./StackProvisioningItem.vue"
22
23 const message = useMessage()
frontend/src/components/threatIntel/AIAnalystButton.vue
+3 -3
@@ -98,13 +98,13 @@
98 </template>
99
100 <script setup lang="ts">
101 -import type { AiAnalysisResponse } from "@/types/threatIntel.d"
101 import type { Size } from "naive-ui/es/button/src/interface"
102 +import type { AiAnalysisResponse } from "@/types/threatIntel.d"
103 +import { NButton, NModal, NTabPane, NTabs, useMessage } from "naive-ui"
104 +import { defineAsyncComponent, ref, watchEffect } from "vue"
105 import Api from "@/api"
106 import Icon from "@/components/common/Icon.vue"
107 import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
106 -import { NButton, NModal, NTabPane, NTabs, useMessage } from "naive-ui"
107 -import { defineAsyncComponent, ref, watchEffect } from "vue"
108
109 const {
110 indexName,
frontend/src/components/threatIntel/AIVelociraptorArtifactRecommendationButton.vue
+3 -3
@@ -67,14 +67,14 @@
67 </template>
68
69 <script setup lang="ts">
70 -import type { AiVelociraptorArtifactRecommendationResponse } from "@/types/threatIntel.d"
70 import type { Size } from "naive-ui/es/button/src/interface"
71 +import type { AiVelociraptorArtifactRecommendationResponse } from "@/types/threatIntel.d"
72 +import { NButton, NEmpty, NModal, useMessage } from "naive-ui"
73 +import { ref, watchEffect } from "vue"
74 import Api from "@/api"
75 import CardEntity from "@/components/common/cards/CardEntity.vue"
76 import Icon from "@/components/common/Icon.vue"
77 import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
76 -import { NButton, NEmpty, NModal, useMessage } from "naive-ui"
77 -import { ref, watchEffect } from "vue"
78
79 const {
80 indexName,
frontend/src/components/threatIntel/AIWazuhExclusionRuleButton.vue
+3 -3
@@ -60,13 +60,13 @@
60 </template>
61
62 <script setup lang="ts">
63 -import type { AiWazuhExclusionRuleResponse } from "@/types/threatIntel.d"
63 import type { Size } from "naive-ui/es/button/src/interface"
64 +import type { AiWazuhExclusionRuleResponse } from "@/types/threatIntel.d"
65 +import { NButton, NEmpty, NModal, useMessage } from "naive-ui"
66 +import { defineAsyncComponent, ref, watchEffect } from "vue"
67 import Api from "@/api"
68 import Icon from "@/components/common/Icon.vue"
69 import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
68 -import { NButton, NEmpty, NModal, useMessage } from "naive-ui"
69 -import { defineAsyncComponent, ref, watchEffect } from "vue"
70
71 const {
72 indexName,
frontend/src/components/threatIntel/ThreatIntelButton.vue
+1 -1
@@ -21,9 +21,9 @@
21
22 <script setup lang="ts">
23 import type { Size, Type } from "naive-ui/es/button/src/interface"
24 -import Icon from "@/components/common/Icon.vue"
24 import { NButton, NDrawer, NDrawerContent } from "naive-ui"
25 import { ref, watch } from "vue"
26 +import Icon from "@/components/common/Icon.vue"
27 import ThreatIntelForm from "./ThreatIntelForm.vue"
28
29 const { type, size } = defineProps<{
frontend/src/components/threatIntel/ThreatIntelEpssScore.vue
+3 -3
@@ -46,13 +46,13 @@
46
47 <script setup lang="ts">
48 import type { EpssScore } from "@/types/threatIntel.d"
49 +import { NCard, NEmpty, NSpin, NStatistic, useMessage } from "naive-ui"
50 +import { nanoid } from "nanoid"
51 +import { onBeforeMount, ref } from "vue"
52 import Api from "@/api"
53 import CardKV from "@/components/common/cards/CardKV.vue"
54 import { useSettingsStore } from "@/stores/settings"
55 import { formatDate } from "@/utils"
53 -import { NCard, NEmpty, NSpin, NStatistic, useMessage } from "naive-ui"
54 -import { nanoid } from "nanoid"
55 -import { onBeforeMount, ref } from "vue"
56
57 interface EpssScoreExt extends EpssScore {
58 ___id?: string
frontend/src/components/threatIntel/ThreatIntelForm.vue
+3 -3
@@ -75,12 +75,12 @@
75
76 <script setup lang="ts">
77 import type { ThreatIntelResponse } from "@/types/threatIntel.d"
78 -import Api from "@/api"
79 -import { useSettingsStore } from "@/stores/settings"
80 -import { formatDate } from "@/utils"
78 import _trim from "lodash/trim"
79 import { NButton, NInput, NSpin, useMessage } from "naive-ui"
80 import { computed, onMounted, ref } from "vue"
81 +import Api from "@/api"
82 +import { useSettingsStore } from "@/stores/settings"
83 +import { formatDate } from "@/utils"
84
85 const emit = defineEmits<{
86 (
frontend/src/components/threatIntel/ThreatIntelProcessEvaluationProvider.vue
+1 -1
@@ -87,10 +87,10 @@
87
88 <script setup lang="ts">
89 import type { EvaluationData } from "@/types/threatIntel.d"
90 -import Api from "@/api"
90 import _toSafeInteger from "lodash/toSafeInteger"
91 import { NCard, NEmpty, NInput, NModal, NSpin, NStatistic, NTabPane, NTabs, useMessage } from "naive-ui"
92 import { computed, defineAsyncComponent, ref } from "vue"
93 +import Api from "@/api"
94
95 const { processName } = defineProps<{
96 processName: string
frontend/src/components/threatIntel/VirusTotalEnrichmentButton.vue
+4 -4
@@ -532,16 +532,16 @@
532 </template>
533
534 <script setup lang="ts">
535 +import type { Size } from "naive-ui/es/button/src/interface"
536 import type { ItemProps } from "@/components/common/cards/CardStatsBars.vue"
537 import type { VirusTotalData } from "@/types/threatIntel.d"
537 -import type { Size } from "naive-ui/es/button/src/interface"
538 +import _pick from "lodash/pick"
539 +import { NButton, NEmpty, NInput, NModal, NStatistic, NTable, NTabPane, NTabs, useMessage } from "naive-ui"
540 +import { computed, defineAsyncComponent, ref } from "vue"
541 import Api from "@/api"
542 import Icon from "@/components/common/Icon.vue"
543 import { useSettingsStore } from "@/stores/settings"
544 import { formatDate } from "@/utils"
542 -import _pick from "lodash/pick"
543 -import { NButton, NEmpty, NInput, NModal, NStatistic, NTable, NTabPane, NTabs, useMessage } from "naive-ui"
544 -import { computed, defineAsyncComponent, ref } from "vue"
545
546 const { iocValue, size } = defineProps<{
547 iocValue: string
frontend/src/components/users/ChangePassword.vue
+4 -4
@@ -53,15 +53,15 @@
53 </template>
54
55 <script setup lang="ts">
56 -import type { User } from "@/types/user"
56 import type { FormInst, FormItemRule, FormRules, FormValidationError } from "naive-ui"
57 import type { Size, Type } from "naive-ui/es/button/src/interface"
59 -import Api from "@/api"
60 -import Icon from "@/components/common/Icon.vue"
61 -import { useAuthStore } from "@/stores/auth"
58 +import type { User } from "@/types/user"
59 import { NButton, NDrawer, NDrawerContent, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
60 import PasswordValidator from "password-validator"
61 import { computed, ref, watch } from "vue"
62 +import Api from "@/api"
63 +import Icon from "@/components/common/Icon.vue"
64 +import { useAuthStore } from "@/stores/auth"
65
66 interface ModelType {
67 password: string | null
frontend/src/components/users/DeleteUser.vue
+3 -3
@@ -8,12 +8,12 @@
8 </template>
9
10 <script setup lang="ts">
11 -import type { User } from "@/types/user"
11 import type { Size, Type } from "naive-ui/es/button/src/interface"
13 -import Api from "@/api"
14 -import Icon from "@/components/common/Icon.vue"
12 +import type { User } from "@/types/user"
13 import { NButton, useDialog, useMessage } from "naive-ui"
14 import { computed, h, ref, watch } from "vue"
15 +import Api from "@/api"
16 +import Icon from "@/components/common/Icon.vue"
17
18 const {
19 type = "error",
frontend/src/components/users/UsersList.vue
+2 -2
@@ -84,11 +84,11 @@
84
85 <script setup lang="ts">
86 import type { User } from "@/types/user.d"
87 +import { NButton, NDropdown, NModal, NScrollbar, NSpin, NTable, useMessage } from "naive-ui"
88 +import { computed, defineAsyncComponent, h, onBeforeMount, ref } from "vue"
89 import Api from "@/api"
90 import Icon from "@/components/common/Icon.vue"
91 import { useAuthStore } from "@/stores/auth"
90 -import { NButton, NDropdown, NModal, NScrollbar, NSpin, NTable, useMessage } from "naive-ui"
91 -import { computed, defineAsyncComponent, h, onBeforeMount, ref } from "vue"
92
93 const { highlight } = defineProps<{ highlight: string | null | undefined }>()
94 const ChangePassword = defineAsyncComponent(() => import("./ChangePassword.vue"))
frontend/src/components/webVulnerabilityAssessment/ReportsItem.vue
+2 -2
@@ -40,10 +40,10 @@
40
41 <script setup lang="ts">
42 import type { NucleiReport } from "@/types/webVulnerabilityAssessment.d"
43 -import Api from "@/api"
44 -import CardEntity from "@/components/common/cards/CardEntity.vue"
43 import { NButton, NEmpty, NModal, NPageHeader, NPopconfirm, NSpin, useMessage } from "naive-ui"
44 import { computed, defineAsyncComponent, ref, watch } from "vue"
45 +import Api from "@/api"
46 +import CardEntity from "@/components/common/cards/CardEntity.vue"
47
48 const { report } = defineProps<{ report: NucleiReport }>()
49
frontend/src/components/webVulnerabilityAssessment/ReportsList.vue
+2 -2
@@ -62,10 +62,10 @@
62
63 <script setup lang="ts">
64 import type { NucleiReport } from "@/types/webVulnerabilityAssessment.d"
65 -import Api from "@/api"
66 -import Icon from "@/components/common/Icon.vue"
65 import { NButton, NEmpty, NModal, NPopover, NSpin, useMessage } from "naive-ui"
66 import { computed, onBeforeMount, ref, watch } from "vue"
67 +import Api from "@/api"
68 +import Icon from "@/components/common/Icon.vue"
69 import ReportsItem from "./ReportsItem.vue"
70 import ScanHostForm from "./ScanHostForm.vue"
71
frontend/src/components/webVulnerabilityAssessment/ScanHostForm.vue
+2 -2
@@ -25,12 +25,12 @@
25 </template>
26
27 <script setup lang="ts">
28 -import type { ScanHostPayload } from "@/types/webVulnerabilityAssessment.d"
28 import type { FormInst, FormItemRule, FormRules, FormValidationError, MessageReactive } from "naive-ui"
30 -import Api from "@/api"
29 +import type { ScanHostPayload } from "@/types/webVulnerabilityAssessment.d"
30 import { NButton, NForm, NFormItem, NInput, NSpin, useMessage } from "naive-ui"
31 import isURL from "validator/es/lib/isURL"
32 import { computed, onMounted, ref } from "vue"
33 +import Api from "@/api"
34
35 type FormPayload = ScanHostPayload
36
frontend/src/components/webVulnerabilityAssessment/WebVulnerabilityAssessmentButton.vue
+1 -1
@@ -9,9 +9,9 @@
9
10 <script setup lang="ts">
11 import type { Size, Type } from "naive-ui/es/button/src/interface"
12 -import Icon from "@/components/common/Icon.vue"
12 import { NButton } from "naive-ui"
13 import { useRouter } from "vue-router"
14 +import Icon from "@/components/common/Icon.vue"
15
16 const { type, size } = defineProps<{
17 size?: Size
frontend/src/composables/useHealthchecksNotify.ts
+2 -2
@@ -1,8 +1,8 @@
1 import type { Notification } from "./useNotifications"
2 -import { usHealthcheckStore } from "@/stores/healthcheck"
3 -import { IndexHealth } from "@/types/indices.d"
2 import _capitalize from "lodash/capitalize"
3 import { computed, watch } from "vue"
4 +import { usHealthcheckStore } from "@/stores/healthcheck"
5 +import { IndexHealth } from "@/types/indices.d"
6 import { useGoto } from "./useGoto"
7 import { useNotifications } from "./useNotifications"
8
frontend/src/composables/useHideLayoutFooter.ts
+1 -1
@@ -1,5 +1,5 @@
1 -import { useThemeStore } from "@/stores/theme"
1 import { onBeforeMount, onBeforeUnmount } from "vue"
2 +import { useThemeStore } from "@/stores/theme"
3
4 // :has() CSS relational pseudo-class not yet supported by Firefox
5 // (https://caniuse.com/css-has)
frontend/src/composables/useLoadingBarSetup.ts
+1 -1
@@ -1,7 +1,7 @@
1 -import { useMainStore } from "@/stores/main"
1 import { useLoadingBar } from "naive-ui"
2 import { onMounted } from "vue"
3 import { useRouter } from "vue-router"
4 +import { useMainStore } from "@/stores/main"
5
6 export function useLoadingBarSetup() {
7 const router = useRouter()
frontend/src/composables/useNotifications.ts
+2 -2
@@ -1,10 +1,10 @@
1 import type { NotificationObject } from "./useGlobalActions"
2 -import { useSettingsStore } from "@/stores/settings"
3 -import dayjs from "@/utils/dayjs"
2 import { useStorage } from "@vueuse/core"
3 import _uniqBy from "lodash/uniqBy"
4 import { NButton } from "naive-ui"
5 import { computed, h } from "vue"
6 +import { useSettingsStore } from "@/stores/settings"
7 +import dayjs from "@/utils/dayjs"
8 import { useGlobalActions } from "./useGlobalActions"
9
10 export type NotificationCategory = "alert"
frontend/src/directives/v-shiki.ts
+1 -1
@@ -1,6 +1,6 @@
1 -import { codeThemes, getHighlighter } from "@/utils/highlighter"
1 import flourite from "flourite"
2 import { decode } from "html-entities"
3 +import { codeThemes, getHighlighter } from "@/utils/highlighter"
4
5 const vShiki = {
6 created: async (
frontend/src/lang/config.ts
+1 -1
@@ -1,5 +1,5 @@
1 -import type { RecursiveKeyOf } from "@/types/common"
1 import type { I18nOptions } from "vue-i18n"
2 +import type { RecursiveKeyOf } from "@/types/common"
3 import * as locales from "./locales"
4
5 export type LocaleCodes = keyof typeof locales
frontend/src/main.ts
+3 -3
@@ -1,9 +1,9 @@
1 -import App from "@/App.vue"
2 -import i18n from "@/lang"
3 -import router from "@/router"
1 import { createPinia } from "pinia"
2 import { createPersistedState } from "pinia-plugin-persistedstate"
3 import { createApp } from "vue"
4 +import App from "@/App.vue"
5 +import i18n from "@/lang"
6 +import router from "@/router"
7 import "@/assets/scss/index.scss"
8 import "./tailwind.css"
9
frontend/src/router/index.ts
+26 -4
@@ -1,10 +1,10 @@
1 import type { FormType } from "@/components/auth/types.d"
2 +import { createRouter, createWebHistory } from "vue-router"
3 import { RouteRole } from "@/types/auth.d"
4 import { Layout } from "@/types/theme.d"
5 import { authCheck } from "@/utils/auth"
6 import AuthPage from "@/views/Auth.vue"
7 import OverviewPage from "@/views/Overview.vue"
7 -import { createRouter, createWebHistory } from "vue-router"
8
9 const router = createRouter({
10 history: createWebHistory(import.meta.env.BASE_URL),
@@ -88,9 +88,31 @@ const router = createRouter({
88 },
89 {
90 path: "/alerts",
91 - name: "Alerts",
92 - component: () => import("@/views/AlertsGraylog.vue"),
93 - meta: { title: "Alerts", auth: true, roles: RouteRole.All }
91 + redirect: "/alerts/siem",
92 + meta: {
93 + auth: true,
94 + roles: RouteRole.All
95 + },
96 + children: [
97 + {
98 + path: "siem",
99 + name: "Alerts-SIEM",
100 + component: () => import("@/views/alerts/AlertsGraylog.vue"),
101 + meta: { title: "SIEM" }
102 + },
103 + {
104 + path: "mitre",
105 + name: "Alerts-Mitre",
106 + component: () => import("@/views/alerts/Mitre.vue"),
107 + meta: { title: "MITRE ATT&CK" }
108 + },
109 + {
110 + path: "atomic-red-team",
111 + name: "Alerts-AtomicRedTeam",
112 + component: () => import("@/views/alerts/AtomicRedTeam.vue"),
113 + meta: { title: "Atomic Red Team" }
114 + }
115 + ]
116 },
117 {
118 path: "/artifacts",
frontend/src/stores/auth.ts
+4 -4
@@ -1,15 +1,15 @@
1 import type { AuthUser, JWTPayload, LoginPayload, RouteMetaAuthRole } from "@/types/auth.d"
2 import type { ApiError } from "@/types/common.d"
3 -import Api from "@/api"
4 -import { AuthUserRole, RouteRole } from "@/types/auth.d"
5 -import { getAvatar, getNameInitials } from "@/utils"
6 -import { jwtRoleToUserRole } from "@/utils/auth"
3 import * as jose from "jose"
4 import _castArray from "lodash/castArray"
5 import _toLower from "lodash/toLower"
6 import _toNumber from "lodash/toNumber"
7 import { acceptHMRUpdate, defineStore } from "pinia"
8 import SecureLS from "secure-ls"
9 +import Api from "@/api"
10 +import { AuthUserRole, RouteRole } from "@/types/auth.d"
11 +import { getAvatar, getNameInitials } from "@/utils"
12 +import { jwtRoleToUserRole } from "@/utils/auth"
13
14 const ls = new SecureLS({ encodingType: "aes", isCompression: false })
15
frontend/src/stores/caseReportTemplate.ts
+2 -2
@@ -1,7 +1,7 @@
1 -import type { FlaskBaseResponse } from "@/types/flask"
1 import type { AxiosResponse } from "axios"
3 -import Api from "@/api"
2 +import type { FlaskBaseResponse } from "@/types/flask"
3 import { acceptHMRUpdate, defineStore } from "pinia"
4 +import Api from "@/api"
5
6 export const useCaseReportTemplateStore = defineStore("caseReportTemplate", {
7 state: () => ({
frontend/src/stores/healthcheck.ts
+2 -2
@@ -1,9 +1,9 @@
1 import type { InfluxDBAlert } from "@/types/healthchecks.d"
2 +import _toNumber from "lodash/toNumber"
3 +import { acceptHMRUpdate, defineStore } from "pinia"
4 import Api from "@/api"
5 import { InfluxDBAlertLevel } from "@/types/healthchecks.d"
6 import { IndexHealth } from "@/types/indices.d"
5 -import _toNumber from "lodash/toNumber"
6 -import { acceptHMRUpdate, defineStore } from "pinia"
7
8 export const usHealthcheckStore = defineStore("healthcheck", {
9 state: () => ({
frontend/src/stores/i18n.ts
+2 -2
@@ -1,7 +1,6 @@
1 -import type { LocaleCodes } from "@/lang/config"
1 import type { NDateLocale, NLocale } from "naive-ui"
2 import type { WritableComputedRef } from "vue"
4 -import dayjs from "@/utils/dayjs"
3 +import type { LocaleCodes } from "@/lang/config"
4 import {
5 dateDeDE,
6 dateEnUS,
@@ -19,6 +18,7 @@ import {
18 import { acceptHMRUpdate, defineStore } from "pinia"
19 import { nextTick } from "vue"
20 import { useI18n } from "vue-i18n"
21 +import dayjs from "@/utils/dayjs"
22
23 export const useLocalesStore = defineStore("i18n", {
24 state: () => {
frontend/src/stores/theme.ts
+3 -3
@@ -1,14 +1,14 @@
1 -import type { Layout, RouterTransition } from "@/types/theme.d"
1 import type { GlobalThemeOverrides, ThemeCommonVars } from "naive-ui"
2 import type { BuiltInGlobalTheme } from "naive-ui/es/themes/interface"
4 -import { getCssVars, getDefaultState, getThemeOverrides } from "@/theme"
5 -import { ThemeNameEnum } from "@/types/theme.d"
3 +import type { Layout, RouterTransition } from "@/types/theme.d"
4 import { useWindowSize } from "@vueuse/core"
5 import _get from "lodash/get"
6 import _set from "lodash/set"
7 import { darkTheme, lightTheme } from "naive-ui"
8 import { acceptHMRUpdate, defineStore } from "pinia"
9 import { watch } from "vue"
10 +import { getCssVars, getDefaultState, getThemeOverrides } from "@/theme"
11 +import { ThemeNameEnum } from "@/types/theme.d"
12
13 export const useThemeStore = defineStore("theme", {
14 state: () => getDefaultState(),
frontend/src/tailwind.css
+1
@@ -35,6 +35,7 @@
35 --text-color-tertiary: var(--fg-tertiary-color);
36
37 --breakpoint-xs: 460px;
38 + --breakpoint-mobile: 701px;
39
40 --animate-fade: fade 0.3s forwards;
41
frontend/src/theme/index.ts
+1 -1
@@ -1,8 +1,8 @@
1 import type { GlobalThemeOverrides, ThemeCommonVars } from "naive-ui"
2 +import { useOsTheme } from "naive-ui"
3 import tokens from "@/design-tokens.json"
4 import { Layout, RouterTransition, ThemeNameEnum } from "@/types/theme.d"
5 import { colorToArray, expandPattern, getThemeColors, getTypeValue } from "@/utils/theme"
5 -import { useOsTheme } from "naive-ui"
6
7 type ThemeState = ReturnType<typeof getDefaultState>
8
frontend/src/types/mitre.d.ts new
+259
@@ -0,0 +1,259 @@
1 +export interface MitreTechnique {
2 + technique_id: string
3 + technique_name: string
4 + count: number
5 + last_seen: string
6 + tactics: MitreTactic[]
7 +}
8 +
9 +export interface MitreTactic {
10 + id: string
11 + name: string
12 + short_name: string
13 +}
14 +
15 +export interface MitreTechniqueDetails {
16 + description: string
17 + name: string
18 + id: string
19 + modified_time: Date
20 + created_time: Date
21 + tactics: string[]
22 + url: string
23 + source: string
24 + external_id: string
25 + references: MitreReference[]
26 + mitigations: string[]
27 + subtechnique_of: string | null
28 + techniques: string[] | null
29 + groups: string[]
30 + software: string[]
31 + mitre_detection: string
32 + mitre_version: string
33 + deprecated: number
34 + remote_support: number
35 + network_requirements: number
36 + platforms: string[]
37 + data_sources: string[]
38 + is_subtechnique: boolean
39 +}
40 +
41 +export interface MitreReference {
42 + url: string
43 + description: string
44 + source: string
45 +}
46 +
47 +export interface MitreMitigationDetails {
48 + mitre_version: string
49 + deprecated: number
50 + description: string
51 + name: string
52 + id: string
53 + modified_time: Date
54 + created_time: Date
55 + techniques: string[]
56 + references: MitreReference[]
57 + url: string
58 + source: string
59 + external_id: string
60 +}
61 +
62 +export interface MitreSoftwareDetails {
63 + mitre_version: string
64 + deprecated: number
65 + description: string
66 + name: string
67 + id: string
68 + modified_time: Date
69 + created_time: Date
70 + groups: string[]
71 + techniques: string[]
72 + references: MitreReference[]
73 + url: string
74 + source: string
75 + external_id: string
76 + platforms: null | string[]
77 + aliases: null | string[]
78 + type: null | string
79 +}
80 +
81 +export interface MitreTacticDetails {
82 + description: string
83 + name: string
84 + id: string
85 + modified_time: Date
86 + created_time: Date
87 + short_name: string
88 + techniques: string[]
89 + references: MitreReference[]
90 + url: string
91 + source: string
92 + external_id: string
93 +}
94 +
95 +export interface MitreGroupDetails {
96 + mitre_version: string
97 + deprecated: number
98 + description: string
99 + name: string
100 + id: string
101 + modified_time: Date
102 + created_time: Date
103 + software: string[]
104 + techniques: string[]
105 + references: MitreReference[]
106 + url: string
107 + source: string
108 + external_id: string
109 + aliases: null | string[]
110 + country: null | string
111 +}
112 +
113 +export type MitreTechniquesDetails = any
114 +
115 +export interface MitreEventDetails {
116 + data_source_ip: string
117 + data_host_architecture: string
118 + agent_id: string
119 + agent_name: string
120 + gl2_remote_ip: string
121 + data_resource: string
122 + agent_labels_customer: string
123 + data_ecs_version: string
124 + timestamp_utc: Date
125 + data_host_os_codename: string
126 + syslog_type: string
127 + gl2_source_node: string
128 + id: string
129 + data_dns_question_etld_plus_one: string
130 + data_server_port: string
131 + rule_mitre_tactic: string
132 + gl2_accounted_message_size: number
133 + data_agent_type: string
134 + streams: string[]
135 + rule_mitre_id: string
136 + data_destination_bytes: string
137 + data_event_dataset: string
138 + "data_@metadata_beat": string
139 + agent_ip: string
140 + data_source_port: string
141 + data_host_id: string
142 + data_event_kind: string
143 + data_network_protocol: string
144 + dns_response_code: string
145 + dns_query: string
146 + data_dns_response_code: string
147 + data_network_community_id: string
148 + data_dns_flags_truncated_response: string
149 + rule_mail: boolean
150 + data_dns_opt_udp_size: string
151 + data_event_category: string
152 + data_dns_flags_recursion_available: string
153 + data_dns_opt_version: string
154 + timestamp: Date
155 + data_host_mac: string
156 + data_agent_id: string
157 + data_destination_port: string
158 + data_dns_type: string
159 + traffic_direction: string
160 + rule_id: string
161 + data_dns_question_class: string
162 + cluster_node: string
163 + dst_port: string
164 + "data_@timestamp": Date
165 + data_event_duration: string
166 + data_host_os_platform: string
167 + data_host_name: string
168 + data_dns_flags_recursion_desired: string
169 + data_dns_question_subdomain: string
170 + gl2_remote_port: number
171 + data_host_os_type: string
172 + source: string
173 + gl2_source_input: string
174 + rule_level: number
175 + data_event_type: string
176 + data_host_os_family: string
177 + data_dns_additionals_count: string
178 + data_dns_flags_authentic_data: string
179 + protocol: string
180 + data_dns_answers: string
181 + data_event_start: Date
182 + data_agent_ephemeral_id: string
183 + rule_description: string
184 + data_related_ip: string
185 + data_agent_version: string
186 + data_status: string
187 + data_query: string
188 + "data_@metadata_type": string
189 + data_method: string
190 + data_dns_question_registered_domain: string
191 + data_server_ip: string
192 + gl2_message_id: string
193 + data_dns_answers_count: string
194 + data_network_type: string
195 + data_dns_opt_ext_rcode: string
196 + data_client_port: string
197 + data_network_bytes: string
198 + data_dns_resolved_ip: string
199 + data_host_containerized: string
200 + true: number
201 + data_host_hostname: string
202 + rule_groups: string
203 + data_client_bytes: string
204 + data_dns_question_type: string
205 + data_host_ip: string
206 + data_destination_ip: string
207 + rule_mitre_technique: string
208 + rule_firedtimes: number
209 + data_network_transport: string
210 + dst_ip: string
211 + src_ip: string
212 + decoder_name: string
213 + syslog_level: string
214 + data_dns_op_code: string
215 + data_host_os_version: string
216 + data_host_os_kernel: string
217 + cluster_name: string
218 + data_source_bytes: string
219 + gl2_processing_error: string
220 + data_dns_opt_do: string
221 + data_dns_authorities_count: string
222 + data_dns_question_name: string
223 + message: string
224 + dns_answer: string
225 + data_dns_id: string
226 + src_port: string
227 + manager_name: string
228 + data_network_direction: string
229 + data_dns_question_top_level_domain: string
230 + data_event_end: Date
231 + data_agent_name: string
232 + data_client_ip: string
233 + data_dns_flags_authoritative: string
234 + data_server_bytes: string
235 + data_type: string
236 + data_dns_header_flags: string
237 + data_dns_flags_checking_disabled: string
238 + location: string
239 + "data_@metadata_version": string
240 + data_host_os_name: string
241 + rule_group3: string
242 + msg_timestamp: Date
243 + rule_group2: string
244 + rule_group1: string
245 +}
246 +
247 +export interface MitreAtomicTest {
248 + technique_id: string
249 + technique_name: string
250 + test_count: number
251 + categories: MitreAtomicTestCategory[]
252 + has_prerequisites: boolean
253 +}
254 +
255 +export enum MitreAtomicTestCategory {
256 + Linux = "linux",
257 + Macos = "macos",
258 + Windows = "windows"
259 +}
frontend/src/utils/auth.ts
+3 -3
@@ -1,10 +1,10 @@
1 -import type { JWTRole, RouteMetaAuth } from "@/types/auth.d"
1 import type { RouteLocationNormalized } from "vue-router"
3 -import { useAuthStore } from "@/stores/auth"
4 -import { AuthUserRole } from "@/types/auth.d"
2 +import type { JWTRole, RouteMetaAuth } from "@/types/auth.d"
3 import { decodeJwt } from "jose"
4 import _castArray from "lodash/castArray"
5 import _toNumber from "lodash/toNumber"
6 +import { useAuthStore } from "@/stores/auth"
7 +import { AuthUserRole } from "@/types/auth.d"
8
9 export function isDebounceTimeOver(lastCheck: Date | null) {
10 const debounceTime = useAuthStore().tokenDebounceTime
frontend/src/utils/highlighter.ts
+1
@@ -22,6 +22,7 @@ export async function getHighlighter() {
22 import("shiki/langs/http.mjs"),
23 import("shiki/langs/sql.mjs"),
24 import("shiki/langs/lua.mjs"),
25 + import("shiki/langs/vb.mjs"),
26 import("shiki/langs/php.mjs")
27 ],
28 engine: createOnigurumaEngine(() => import("shiki/wasm"))
frontend/src/utils/index.ts
+3 -3
@@ -1,12 +1,12 @@
1 -import type { OsTypesFull } from "@/types/common.d"
1 import type { Component } from "vue"
2 +import type { OsTypesFull } from "@/types/common.d"
3 import process from "node:process"
4 -import Icon from "@/components/common/Icon.vue"
5 -import dayjs from "@/utils/dayjs"
4 import { isMobile as detectMobile } from "detect-touch-device"
5 import { md5 } from "js-md5"
6 import _trim from "lodash/trim"
7 import { h } from "vue"
8 +import Icon from "@/components/common/Icon.vue"
9 +import dayjs from "@/utils/dayjs"
10
11 // Transform File Instance in base64 string
12 export function file2Base64(blob: Blob): Promise<string> {
frontend/src/views/Auth.vue
+2 -2
@@ -17,11 +17,11 @@
17
18 <script lang="ts" setup>
19 import type { FormType } from "@/components/auth/types.d"
20 +import { computed, onBeforeMount, ref, toRefs } from "vue"
21 +import { useRoute } from "vue-router"
22 import AuthForm from "@/components/auth/AuthForm.vue"
23 import { useAuthStore } from "@/stores/auth"
24 import { useThemeStore } from "@/stores/theme"
23 -import { computed, onBeforeMount, ref, toRefs } from "vue"
24 -import { useRoute } from "vue-router"
25
26 type Align = "left" | "center" | "right"
27
frontend/src/views/Customers.vue
+2 -2
@@ -23,12 +23,12 @@
23 </template>
24
25 <script setup lang="ts">
26 +import { onBeforeMount, onMounted, onUnmounted, ref } from "vue"
27 +import { useRoute, useRouter } from "vue-router"
28 import CustomerCreationButton from "@/components/customers/CustomerCreationButton.vue"
29 import CustomersList from "@/components/customers/CustomersList.vue"
30 import CustomerDefaultSettingsButton from "@/components/customers/provision/CustomerDefaultSettingsButton.vue"
31 import { emitter } from "@/emitter"
30 -import { onBeforeMount, onMounted, onUnmounted, ref } from "vue"
31 -import { useRoute, useRouter } from "vue-router"
32
33 const route = useRoute()
34 const router = useRouter()
frontend/src/views/Indices.vue
+3 -3
@@ -34,15 +34,15 @@
34
35 <script lang="ts" setup>
36 import type { IndexStats } from "@/types/indices.d"
37 +import { NCard, useMessage } from "naive-ui"
38 +import { defineAsyncComponent, onBeforeMount, ref } from "vue"
39 +import { useRoute } from "vue-router"
40 import Api from "@/api"
41 import ClusterHealth from "@/components/indices/ClusterHealth.vue"
42 import Details from "@/components/indices/Details.vue"
43 import IndicesMarquee from "@/components/indices/Marquee.vue"
44 import NodeAllocation from "@/components/indices/NodeAllocation.vue"
45 import UnhealthyIndices from "@/components/indices/UnhealthyIndices.vue"
43 -import { NCard, useMessage } from "naive-ui"
44 -import { defineAsyncComponent, onBeforeMount, ref } from "vue"
45 -import { useRoute } from "vue-router"
46
47 const TopIndices = defineAsyncComponent(() => import("@/components/indices/TopIndices.vue"))
48
frontend/src/views/Logs.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import LogsList from "@/components/logs/LogsList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import LogsList from "@/components/logs/LogsList.vue"
11
12 const route = useRoute()
13
frontend/src/views/Overview.vue
+3 -3
@@ -76,6 +76,9 @@
76 </template>
77
78 <script setup lang="ts">
79 +import { useResizeObserver } from "@vueuse/core"
80 +import { NButton, NDrawer, NDrawerContent } from "naive-ui"
81 +import { defineAsyncComponent, ref } from "vue"
82 import ActiveResponseWizardButton from "@/components/activeResponse/ActiveResponseWizardButton.vue"
83 import CloudSecurityAssessmentButton from "@/components/cloudSecurityAssessment/CloudSecurityAssessmentButton.vue"
84 import Icon from "@/components/common/Icon.vue"
@@ -91,9 +94,6 @@ import IncidentCases from "@/components/overview/IncidentCases.vue"
94 import StackProvisioningButton from "@/components/stackProvisioning/StackProvisioningButton.vue"
95 import WebVulnerabilityAssessmentButton from "@/components/webVulnerabilityAssessment/WebVulnerabilityAssessmentButton.vue"
96 import { useGoto } from "@/composables/useGoto"
94 -import { useResizeObserver } from "@vueuse/core"
95 -import { NButton, NDrawer, NDrawerContent } from "naive-ui"
96 -import { defineAsyncComponent, ref } from "vue"
97
98 const ThreatIntelButton = defineAsyncComponent(() => import("@/components/threatIntel/ThreatIntelButton.vue"))
99
frontend/src/views/Profile.vue
+2 -2
@@ -70,13 +70,13 @@
70
71 <script lang="ts" setup>
72 import type { ImageCropperResult } from "@/components/common/ImageCropper.vue"
73 +import { NAvatar, NButton, NCard, NTab, NTabPane, NTabs, NTooltip } from "naive-ui"
74 +import { ref } from "vue"
75 import Icon from "@/components/common/Icon.vue"
76 import ImageCropper from "@/components/common/ImageCropper.vue"
77 import ProfileSettings from "@/components/profile/ProfileSettings.vue"
78 import ChangePassword from "@/components/users/ChangePassword.vue"
79 import { useAuthStore } from "@/stores/auth"
78 -import { NAvatar, NButton, NCard, NTab, NTabPane, NTabs, NTooltip } from "naive-ui"
79 -import { ref } from "vue"
80
81 const propicEnabled = false
82
frontend/src/views/ReportCreation.vue
+2 -2
@@ -43,12 +43,12 @@
43 <script setup lang="ts">
44 import type { ReportTimeRange } from "@/api/endpoints/reporting"
45 import type { Dashboard, Org, Panel } from "@/types/reporting.d"
46 +import { NAlert, NSpin } from "naive-ui"
47 +import { ref } from "vue"
48 import Icon from "@/components/common/Icon.vue"
49 import LicenseFeatureCheck from "@/components/license/LicenseFeatureCheck.vue"
50 import ReportPanels from "@/components/reportCreation/Panels.vue"
51 import ReportWizard from "@/components/reportCreation/Wizard.vue"
50 -import { NAlert, NSpin } from "naive-ui"
51 -import { ref } from "vue"
52
53 const AlertIcon = "mdi:alert-outline"
54 const timerange = ref<ReportTimeRange | null>(null)
frontend/src/views/Users.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import UsersList from "@/components/users/UsersList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import UsersList from "@/components/users/UsersList.vue"
11
12 const route = useRoute()
13
frontend/src/views/agents/Agents.vue
+4 -4
@@ -56,15 +56,15 @@
56
57 <script setup lang="ts">
58 import type { Agent } from "@/types/agents.d"
59 +import _debounce from "lodash/debounce"
60 +import _split from "lodash/split"
61 +import { NEmpty, NPagination, NScrollbar, NSpin, useMessage } from "naive-ui"
62 +import { computed, onBeforeMount, ref, watch } from "vue"
63 import Api from "@/api"
64 import AgentCard from "@/components/agents/AgentCard.vue"
65 import AgentToolbar from "@/components/agents/AgentToolbar.vue"
66 import { useGoto } from "@/composables/useGoto"
67 import { AgentStatus } from "@/types/agents.d"
64 -import _debounce from "lodash/debounce"
65 -import _split from "lodash/split"
66 -import { NEmpty, NPagination, NScrollbar, NSpin, useMessage } from "naive-ui"
67 -import { computed, onBeforeMount, ref, watch } from "vue"
68
69 const message = useMessage()
70 const { gotoAgent } = useGoto()
frontend/src/views/agents/Overview.vue
+3 -3
@@ -143,15 +143,15 @@
143 <script setup lang="ts">
144 import type { Agent } from "@/types/agents.d"
145 import type { Artifact } from "@/types/artifacts.d"
146 +import { NButton, NCard, NSpin, NTabPane, NTabs, NTag, NTooltip, useDialog, useMessage } from "naive-ui"
147 +import { computed, defineAsyncComponent, nextTick, onBeforeMount, ref } from "vue"
148 +import { useRoute, useRouter } from "vue-router"
149 import Api from "@/api"
150 import { handleDeleteAgent, toggleAgentCritical } from "@/components/agents/utils"
151 import CardEntity from "@/components/common/cards/CardEntity.vue"
152 import Icon from "@/components/common/Icon.vue"
153 import { useGoto } from "@/composables/useGoto"
154 import { AgentStatus } from "@/types/agents.d"
152 -import { NButton, NCard, NSpin, NTabPane, NTabs, NTag, NTooltip, useDialog, useMessage } from "naive-ui"
153 -import { computed, defineAsyncComponent, nextTick, onBeforeMount, ref } from "vue"
154 -import { useRoute, useRouter } from "vue-router"
155
156 const VulnerabilitiesGrid = defineAsyncComponent(
157 () => import("@/components/agents/vulnerabilities/VulnerabilitiesGrid.vue")
frontend/src/views/agents/SysmonConfig.vue
+4 -4
@@ -127,19 +127,19 @@
127 </template>
128
129 <script setup lang="ts">
130 +import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface"
131 import type { XMLEditorCtx } from "@/components/common/XMLEditor.vue"
132 import type { Customer } from "@/types/customers"
133 import type { ConfigContent } from "@/types/sysmonConfig.d"
133 -import type { DropdownMixedOption } from "naive-ui/es/dropdown/src/interface"
134 +import _clone from "lodash/cloneDeep"
135 +import { NButton, NDropdown, NEmpty, NSpin, useMessage } from "naive-ui"
136 +import { computed, h, onBeforeMount, ref } from "vue"
137 import Api from "@/api"
138 import CardEntity from "@/components/common/cards/CardEntity.vue"
139 import Icon from "@/components/common/Icon.vue"
140 import SegmentedPage from "@/components/common/SegmentedPage.vue"
141 import XMLEditor from "@/components/common/XMLEditor.vue"
142 import { useGoto } from "@/composables/useGoto"
140 -import _clone from "lodash/cloneDeep"
141 -import { NButton, NDropdown, NEmpty, NSpin, useMessage } from "naive-ui"
142 -import { computed, h, onBeforeMount, ref } from "vue"
143
144 const message = useMessage()
145 const { gotoCustomer } = useGoto()
frontend/src/views/alerts/AlertsGraylog.vue renamed
frontend/src/views/alerts/AlertsOld.vue renamed
frontend/src/views/alerts/AtomicRedTeam.vue new
+9
@@ -0,0 +1,9 @@
1 +<template>
2 + <div class="page">
3 + <List />
4 + </div>
5 +</template>
6 +
7 +<script setup lang="ts">
8 +import List from "@/components/mitre/AtomicTests/List.vue"
9 +</script>
frontend/src/views/alerts/Mitre.vue new
+16
@@ -0,0 +1,16 @@
1 +<template>
2 + <div class="page page-wrapped page-mobile-full page-without-footer flex flex-col">
3 + <div class="relative flex h-full grow flex-col gap-4 overflow-hidden">
4 + <Filters class="max-mobile:px-5" @update="filters = $event" />
5 + <List :filters class="grow" />
6 + </div>
7 + </div>
8 +</template>
9 +
10 +<script setup lang="ts">
11 +import { ref } from "vue"
12 +import Filters from "@/components/mitre/TechniquesAlerts/Filters.vue"
13 +import List from "@/components/mitre/TechniquesAlerts/List.vue"
14 +
15 +const filters = ref<{ type: string; value: string }[]>([])
16 +</script>
frontend/src/views/graylog/Metrics.vue
+3 -3
@@ -40,15 +40,15 @@
40
41 <script setup lang="ts">
42 import type { ThroughputMetric } from "@/types/graylog/metrics.d"
43 +import { useStorage } from "@vueuse/core"
44 +import { NButton, NSelect, useMessage } from "naive-ui"
45 +import { computed, nextTick, onBeforeMount, onBeforeUnmount, ref, watch } from "vue"
46 import Api from "@/api"
47 import Icon from "@/components/common/Icon.vue"
48 import MetricsList from "@/components/graylog/Metrics/List.vue"
49 import UncommittedEntries from "@/components/graylog/Metrics/UncommittedEntries.vue"
50 import { useSettingsStore } from "@/stores/settings"
51 import { formatDate } from "@/utils"
49 -import { useStorage } from "@vueuse/core"
50 -import { NButton, NSelect, useMessage } from "naive-ui"
51 -import { computed, nextTick, onBeforeMount, onBeforeUnmount, ref, watch } from "vue"
52
53 const UpdatedIcon = "carbon:update-now"
54 const StopIcon = "carbon:stop"
frontend/src/views/graylog/Pipelines.vue
+3 -3
@@ -43,13 +43,13 @@
43
44 <script setup lang="ts">
45 import type { PipelineFull } from "@/types/graylog/pipelines.d"
46 +import { NButton, NDrawer, NDrawerContent, NModal } from "naive-ui"
47 +import { onBeforeMount, ref, watch } from "vue"
48 +import { useRoute } from "vue-router"
49 import Icon from "@/components/common/Icon.vue"
50 import PipeInfo from "@/components/graylog/Pipelines/PipeInfo.vue"
51 import PipeList from "@/components/graylog/Pipelines/PipeList.vue"
52 import RulesList from "@/components/graylog/Pipelines/RulesList.vue"
50 -import { NButton, NDrawer, NDrawerContent, NModal } from "naive-ui"
51 -import { onBeforeMount, ref, watch } from "vue"
52 -import { useRoute } from "vue-router"
53
54 const RulesIcon = "ic:outline-swipe-right-alt"
55
frontend/src/views/incidentManagement/Alerts.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import AlertsList from "@/components/incidentManagement/alerts/AlertsList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import AlertsList from "@/components/incidentManagement/alerts/AlertsList.vue"
11
12 const route = useRoute()
13
frontend/src/views/incidentManagement/Cases.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import CasesList from "@/components/incidentManagement/cases/CasesList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import CasesList from "@/components/incidentManagement/cases/CasesList.vue"
11
12 const route = useRoute()
13
frontend/src/views/incidentManagement/Sources.vue
+4 -4
@@ -41,15 +41,15 @@
41 </template>
42
43 <script setup lang="ts">
44 +import { useResizeObserver } from "@vueuse/core"
45 +import { NTabPane, NTabs } from "naive-ui"
46 +import { ref } from "vue"
47 import ExclusionRulesList from "@/components/incidentManagement/exclusionRules/ExclusionRulesList.vue"
48 +
49 import NewExclusionRuleButton from "@/components/incidentManagement/exclusionRules/NewExclusionRuleButton.vue"
50 import ConfiguredSourcesList from "@/components/incidentManagement/sources/ConfiguredSourcesList.vue"
51 import NewConfiguredSourceButton from "@/components/incidentManagement/sources/NewConfiguredSourceButton.vue"
52
49 -import { useResizeObserver } from "@vueuse/core"
50 -import { NTabPane, NTabs } from "naive-ui"
51 -import { ref } from "vue"
52 -
53 const configuredSourcesListTotal = ref(0)
54 const configuredSourcesListCTX = ref<{ reload: () => void } | null>(null)
55 const exclusionRulesListCTX = ref<{ reload: () => void } | null>(null)
frontend/src/views/license/License.vue
+1 -1
@@ -10,8 +10,8 @@
10
11 <script setup lang="ts">
12 import type { LicenseKey } from "@/types/license.d"
13 -import LicenseViewer from "@/components/license/LicenseViewer.vue"
13 import { ref } from "vue"
14 +import LicenseViewer from "@/components/license/LicenseViewer.vue"
15
16 const licenseKey = ref<LicenseKey | undefined>(undefined)
17 </script>
frontend/src/views/license/Success.vue
+1 -1
@@ -5,8 +5,8 @@
5 </template>
6
7 <script setup lang="ts">
8 -import LicenseCheckoutResponse from "@/components/license/LicenseCheckoutResponse.vue"
8 import { useRoute } from "vue-router"
9 +import LicenseCheckoutResponse from "@/components/license/LicenseCheckoutResponse.vue"
10
11 const route = useRoute()
12 </script>
frontend/src/views/soc/Alerts.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import SocAlertsFullList from "@/components/soc/SocAlerts/SocAlertsFullList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import SocAlertsFullList from "@/components/soc/SocAlerts/SocAlertsFullList.vue"
11
12 const route = useRoute()
13
frontend/src/views/soc/Users.vue
+1 -1
@@ -5,9 +5,9 @@
5 </template>
6
7 <script setup lang="ts">
8 -import SocUsersList from "@/components/soc/SocUsers/SocUsersList.vue"
8 import { onBeforeMount, ref } from "vue"
9 import { useRoute } from "vue-router"
10 +import SocUsersList from "@/components/soc/SocUsers/SocUsersList.vue"
11
12 const route = useRoute()
13