Shuffle singul2 (#463)
* Update IP address in Singul integration to use 1.1.1.1 * feat: add app-auth-search page * refactor: update router * feat: add validation for manager_orgs field in DetailedOrganization model --------- Co-authored-by: Davide Di Modica <webmaster.ddm@gmail.com>
taylor_socfortress committed
Jun 25, 2025 at 14:41 UTC
24f5c013c21ab99f6478e4aa07ede13f35bf0377
13 files changed
+532
-190
.vscode/settings.json
+1
@@ -56,6 +56,7 @@
56
"shikijs",
57
"SIEM",
58
"signin",
59
+ "Singul",
60
"Socfortress",
61
"sparkline",
62
"Sysmon",
backend/app/connectors/shuffle/schema/organizations.py
+24
@@ -6,6 +6,7 @@ from typing import Optional
6
7
from pydantic import BaseModel
8
from pydantic import Field
9
+from pydantic import validator
10
11
12
class SyncConfig(BaseModel):
@@ -102,6 +103,29 @@ class DetailedOrganization(BaseModel):
103
region_url: str = ""
104
tutorials: List[Any] = []
105
106
+ @validator("manager_orgs", pre=True, always=True)
107
+ def validate_manager_orgs(cls, v):
108
+ """
109
+ Validate and normalize manager_orgs field.
110
+ Handles various input types and converts them to proper format or None.
111
+ """
112
+ if v is None:
113
+ return None
114
+
115
+ # If it's already a list, validate each item is a string
116
+ if isinstance(v, list):
117
+ try:
118
+ return [str(item) for item in v if item is not None]
119
+ except Exception:
120
+ return None
121
+
122
+ # If it's a single value, convert to list
123
+ if isinstance(v, (str, int)):
124
+ return [str(v)]
125
+
126
+ # For any other type, return None
127
+ return None
128
+
129
130
class DetailedOrganizationResponse(BaseModel):
131
success: bool
backend/app/connectors/shuffle/services/singul.py
+1
-1
@@ -64,7 +64,7 @@ async def execute_singul(
64
response = singul.intel.get_ioc(
65
app="opencti_dcon",
66
org_id=await get_shuffle_org_id(),
67
- fields=[{"key": "ip", "value": "8.8.8.8"}],
67
+ fields=[{"key": "ip", "value": "1.1.1.1"}],
68
)
69
logger.info(f"Singul response: {response}")
70
logger.info(f"Singul response success: {response.get('success', 'unknown')}")
frontend/package.json
+5
-4
@@ -3,7 +3,7 @@
3
"type": "module",
4
"version": "1.0.0",
5
"private": true,
6
- "packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac",
6
+ "packageManager": "pnpm@10.12.2+sha512.a32540185b964ee30bb4e979e405adc6af59226b438ee4cc19f9e8773667a66d302f5bfee60a39d3cac69e35e4b96e708a71dd002b7e9359c4112a1722ac323f",
7
"engines": {
8
"node": ">=18.0.0"
9
},
@@ -46,6 +46,7 @@
46
"@fontsource/lexend": "^5.2.9",
47
"@fontsource/public-sans": "^5.2.6",
48
"@shikijs/markdown-it": "^3.7.0",
49
+ "@singulio/app-auth-search": "^0.0.3",
50
"@vueuse/core": "^13.4.0",
51
"@vueuse/motion": "^3.0.3",
52
"axios": "^1.10.0",
@@ -74,7 +75,7 @@
75
"vue-advanced-cropper": "^2.8.9",
76
"vue-codemirror": "^6.1.1",
77
"vue-highlight-words": "^3.0.1",
77
- "vue-i18n": "^11.1.6",
78
+ "vue-i18n": "^11.1.7",
79
"vue-router": "^4.5.1",
80
"vue-sjv": "^0.0.6",
81
"vue3-apexcharts": "^1.8.0",
@@ -87,7 +88,7 @@
88
"vueuc": "^0.4.64"
89
},
90
"devDependencies": {
90
- "@antfu/eslint-config": "^4.15.0",
91
+ "@antfu/eslint-config": "^4.16.1",
92
"@clack/prompts": "^0.11.0",
93
"@iconify/vue": "^5.0.0",
94
"@tailwindcss/vite": "^4.1.10",
@@ -111,7 +112,7 @@
112
"fs-extra": "^11.3.0",
113
"jsdom": "^26.1.0",
114
"npm-run-all2": "^8.0.4",
114
- "prettier": "^3.5.3",
115
+ "prettier": "^3.6.0",
116
"prettier-plugin-tailwindcss": "^0.6.13",
117
"sass": "^1.89.2",
118
"start-server-and-test": "^2.0.12",
frontend/pnpm-lock.yaml
+227
-180
@@ -38,6 +38,9 @@ importers:
38
'@shikijs/markdown-it':
39
specifier: ^3.7.0
40
version: 3.7.0
41
+ '@singulio/app-auth-search':
42
+ specifier: ^0.0.3
43
+ version: 0.0.3
44
'@vueuse/core':
45
specifier: ^13.4.0
46
version: 13.4.0(vue@3.5.17(typescript@5.8.3))
@@ -123,8 +126,8 @@ importers:
126
specifier: ^3.0.1
127
version: 3.0.1(vue@3.5.17(typescript@5.8.3))
128
vue-i18n:
126
- specifier: ^11.1.6
127
- version: 11.1.6(vue@3.5.17(typescript@5.8.3))
129
+ specifier: ^11.1.7
130
+ version: 11.1.7(vue@3.5.17(typescript@5.8.3))
131
vue-router:
132
specifier: ^4.5.1
133
version: 4.5.1(vue@3.5.17(typescript@5.8.3))
@@ -142,8 +145,8 @@ importers:
145
version: 4.1.0(vue@3.5.17(typescript@5.8.3))
146
devDependencies:
147
'@antfu/eslint-config':
145
- specifier: ^4.15.0
146
- version: 4.15.0(@vue/compiler-sfc@3.5.17)(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))
148
+ specifier: ^4.16.1
149
+ version: 4.16.1(@vue/compiler-sfc@3.5.17)(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))
150
'@clack/prompts':
151
specifier: ^0.11.0
152
version: 0.11.0
@@ -214,11 +217,11 @@ importers:
217
specifier: ^8.0.4
218
version: 8.0.4
219
prettier:
217
- specifier: ^3.5.3
218
- version: 3.5.3
220
+ specifier: ^3.6.0
221
+ version: 3.6.0
222
prettier-plugin-tailwindcss:
223
specifier: ^0.6.13
221
- version: 0.6.13(prettier@3.5.3)
224
+ version: 0.6.13(prettier@3.6.0)
225
sass:
226
specifier: ^1.89.2
227
version: 1.89.2
@@ -271,12 +274,64 @@ packages:
274
'@ajoelp/json-to-formdata@1.5.0':
275
resolution: {integrity: sha512-nrlfeTSL0X0dtx5r2KpzPiqLSIQquiiJjUKsQAKzWaCmO2QoYZCyb5ENZwF3YoffKronOCJr25mxaD8JRJmK8w==}
276
277
+ '@algolia/client-abtesting@5.29.0':
278
+ resolution: {integrity: sha512-AM/6LYMSTnZvAT5IarLEKjYWOdV+Fb+LVs8JRq88jn8HH6bpVUtjWdOZXqX1hJRXuCAY8SdQfb7F8uEiMNXdYQ==}
279
+ engines: {node: '>= 14.0.0'}
280
+
281
+ '@algolia/client-analytics@5.29.0':
282
+ resolution: {integrity: sha512-La34HJh90l0waw3wl5zETO8TuukeUyjcXhmjYZL3CAPLggmKv74mobiGRIb+mmBENybiFDXf/BeKFLhuDYWMMQ==}
283
+ engines: {node: '>= 14.0.0'}
284
+
285
+ '@algolia/client-common@5.29.0':
286
+ resolution: {integrity: sha512-T0lzJH/JiCxQYtCcnWy7Jf1w/qjGDXTi2npyF9B9UsTvXB97GRC6icyfXxe21mhYvhQcaB1EQ/J2575FXxi2rA==}
287
+ engines: {node: '>= 14.0.0'}
288
+
289
+ '@algolia/client-insights@5.29.0':
290
+ resolution: {integrity: sha512-A39F1zmHY9aev0z4Rt3fTLcGN5AG1VsVUkVWy6yQG5BRDScktH+U5m3zXwThwniBTDV1HrPgiGHZeWb67GkR2Q==}
291
+ engines: {node: '>= 14.0.0'}
292
+
293
+ '@algolia/client-personalization@5.29.0':
294
+ resolution: {integrity: sha512-ibxmh2wKKrzu5du02gp8CLpRMeo+b/75e4ORct98CT7mIxuYFXowULwCd6cMMkz/R0LpKXIbTUl15UL5soaiUQ==}
295
+ engines: {node: '>= 14.0.0'}
296
+
297
+ '@algolia/client-query-suggestions@5.29.0':
298
+ resolution: {integrity: sha512-VZq4/AukOoJC2WSwF6J5sBtt+kImOoBwQc1nH3tgI+cxJBg7B77UsNC+jT6eP2dQCwGKBBRTmtPLUTDDnHpMgA==}
299
+ engines: {node: '>= 14.0.0'}
300
+
301
+ '@algolia/client-search@5.29.0':
302
+ resolution: {integrity: sha512-cZ0Iq3OzFUPpgszzDr1G1aJV5UMIZ4VygJ2Az252q4Rdf5cQMhYEIKArWY/oUjMhQmosM8ygOovNq7gvA9CdCg==}
303
+ engines: {node: '>= 14.0.0'}
304
+
305
+ '@algolia/ingestion@1.29.0':
306
+ resolution: {integrity: sha512-scBXn0wO5tZCxmO6evfa7A3bGryfyOI3aoXqSQBj5SRvNYXaUlFWQ/iKI70gRe/82ICwE0ICXbHT/wIvxOW7vw==}
307
+ engines: {node: '>= 14.0.0'}
308
+
309
+ '@algolia/monitoring@1.29.0':
310
+ resolution: {integrity: sha512-FGWWG9jLFhsKB7YiDjM2dwQOYnWu//7Oxrb2vT96N7+s+hg1mdHHfHNRyEudWdxd4jkMhBjeqNA21VbTiOIPVg==}
311
+ engines: {node: '>= 14.0.0'}
312
+
313
+ '@algolia/recommend@5.29.0':
314
+ resolution: {integrity: sha512-xte5+mpdfEARAu61KXa4ewpjchoZuJlAlvQb8ptK6hgHlBHDnYooy1bmOFpokaAICrq/H9HpoqNUX71n+3249A==}
315
+ engines: {node: '>= 14.0.0'}
316
+
317
+ '@algolia/requester-browser-xhr@5.29.0':
318
+ resolution: {integrity: sha512-og+7Em75aPHhahEUScq2HQ3J7ULN63Levtd87BYMpn6Im5d5cNhaC4QAUsXu6LWqxRPgh4G+i+wIb6tVhDhg2A==}
319
+ engines: {node: '>= 14.0.0'}
320
+
321
+ '@algolia/requester-fetch@5.29.0':
322
+ resolution: {integrity: sha512-JCxapz7neAy8hT/nQpCvOrI5JO8VyQ1kPvBiaXWNC1prVq0UMYHEL52o1BsPvtXfdQ7BVq19OIq6TjOI06mV/w==}
323
+ engines: {node: '>= 14.0.0'}
324
+
325
+ '@algolia/requester-node-http@5.29.0':
326
+ resolution: {integrity: sha512-lVBD81RBW5VTdEYgnzCz7Pf9j2H44aymCP+/eHGJu4vhU+1O8aKf3TVBgbQr5UM6xoe8IkR/B112XY6YIG2vtg==}
327
+ engines: {node: '>= 14.0.0'}
328
+
329
'@ampproject/remapping@2.3.0':
330
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
331
engines: {node: '>=6.0.0'}
332
278
- '@antfu/eslint-config@4.15.0':
279
- resolution: {integrity: sha512-wNn8eDUR+L48nGqX0j8uS19+lHjlhjJsTuhOIbp5aUtnNzAqUuzeoGa7S7rfIbK3XnzcRXJ1AW+xWXsMSGu0YA==}
333
+ '@antfu/eslint-config@4.16.1':
334
+ resolution: {integrity: sha512-20hA+bjnEmYnZChnQFM9ugPF+FR5N2yd6UNUjhZSmTeYpaKnkJ1EvZyEWxnmVGKC5O5HNDEJY3BXUQymdOoftQ==}
335
hasBin: true
336
peerDependencies:
337
'@eslint-react/eslint-plugin': ^1.38.4
@@ -769,8 +824,8 @@ packages:
824
resolution: {integrity: sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==}
825
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
826
772
- '@eslint/markdown@6.5.0':
773
- resolution: {integrity: sha512-oSkF0p8X21vKEEAGTZASi7q3tbdTvlGduQ02Xz2A1AFncUP4RLVcNz27XurxVW4fs1JXuh0xBtvokXdtp/nN+Q==}
827
+ '@eslint/markdown@6.6.0':
828
+ resolution: {integrity: sha512-IsWPy2jU3gaQDlioDC4sT4I4kG1hX1OMWs/q2sWwJrPoMASHW/Z4SDw+6Aql6EsHejGbagYuJbFq9Zvx+Y1b1Q==}
829
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
830
831
'@eslint/object-schema@2.1.6':
@@ -833,16 +888,16 @@ packages:
888
peerDependencies:
889
vue: '>=3'
890
836
- '@intlify/core-base@11.1.6':
837
- resolution: {integrity: sha512-gfMLnoWGiQkA1BwK6Qbrog/e3I6Lnkhqk08XObJb0lMq6sLG1Ggl2MazVaMfGnv/E1Td8pCS5UwR54Ys+fOxmQ==}
891
+ '@intlify/core-base@11.1.7':
892
+ resolution: {integrity: sha512-gYiGnQeJVp3kNBeXQ73m1uFOak0ry4av8pn+IkEWigyyPWEMGzB+xFeQdmGMFn49V+oox6294oGVff8bYOhtOw==}
893
engines: {node: '>= 16'}
894
840
- '@intlify/message-compiler@11.1.6':
841
- resolution: {integrity: sha512-w0LYo5sqgQZF3vEmjLlx+5PYk5EEiB+uigsBkka/DKoAIH2c5xlXcjAxhTgSw35Vrck+GOGriahFsfbHL+ZjPw==}
895
+ '@intlify/message-compiler@11.1.7':
896
+ resolution: {integrity: sha512-0ezkep1AT30NyuKj8QbRlmvMORCCRlOIIu9v8RNU8SwDjjTiFCZzczCORMns2mCH4HZ1nXgrfkKzYUbfjNRmng==}
897
engines: {node: '>= 16'}
898
844
- '@intlify/shared@11.1.6':
845
- resolution: {integrity: sha512-G1Pe4UILhiGOItuehRW+Pk9/NlnRaMFsdnhZ1fwBjiHvrzitmPNZdLx7Eo3GPfRrsk1mdkilZSfgH8SnM419vA==}
899
+ '@intlify/shared@11.1.7':
900
+ resolution: {integrity: sha512-4yZeMt2Aa/7n5Ehy4KalUlvt3iRLcg1tq9IBVfOgkyWFArN4oygn6WxgGIFibP3svpaH8DarbNaottq+p0gUZQ==}
901
engines: {node: '>= 16'}
902
903
'@isaacs/cliui@8.0.2':
@@ -1170,8 +1225,11 @@ packages:
1225
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
1226
engines: {node: '>=18'}
1227
1173
- '@stylistic/eslint-plugin@5.0.0-beta.5':
1174
- resolution: {integrity: sha512-hYoTE1AuPKkF8gN6nwJVnBovUEkt3UGiE3zu8nNmFi3yw7F36l1/tU/VRg16CZC804rnAhUwsYTHqKnAPqICxg==}
1228
+ '@singulio/app-auth-search@0.0.3':
1229
+ resolution: {integrity: sha512-4U/of6Gry5hal3CdZoMkrdfbSYza43ZcvlJoh4pJ1UCm16Vpegmw3MwmbrZHjg8wiFWe+f5WnX/WkgQpuuZnHw==}
1230
+
1231
+ '@stylistic/eslint-plugin@5.0.0':
1232
+ resolution: {integrity: sha512-nVV2FSzeTJ3oFKw+3t9gQYQcrgbopgCASSY27QOtkhEGgSfdQQjDmzZd41NeT1myQ8Wc6l+pZllST9qIu4NKzg==}
1233
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1234
peerDependencies:
1235
eslint: '>=9.0.0'
@@ -1403,32 +1461,16 @@ packages:
1461
eslint: ^8.57.0 || ^9.0.0
1462
typescript: '>=4.8.4 <5.9.0'
1463
1406
- '@typescript-eslint/project-service@8.33.1':
1407
- resolution: {integrity: sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==}
1408
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1409
- peerDependencies:
1410
- typescript: '>=4.8.4 <5.9.0'
1411
-
1464
'@typescript-eslint/project-service@8.34.1':
1465
resolution: {integrity: sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==}
1466
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1467
peerDependencies:
1468
typescript: '>=4.8.4 <5.9.0'
1469
1418
- '@typescript-eslint/scope-manager@8.33.1':
1419
- resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==}
1420
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1421
-
1470
'@typescript-eslint/scope-manager@8.34.1':
1471
resolution: {integrity: sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==}
1472
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1473
1426
- '@typescript-eslint/tsconfig-utils@8.33.1':
1427
- resolution: {integrity: sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==}
1428
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1429
- peerDependencies:
1430
- typescript: '>=4.8.4 <5.9.0'
1431
-
1474
'@typescript-eslint/tsconfig-utils@8.34.1':
1475
resolution: {integrity: sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==}
1476
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1442,33 +1484,16 @@ packages:
1484
eslint: ^8.57.0 || ^9.0.0
1485
typescript: '>=4.8.4 <5.9.0'
1486
1445
- '@typescript-eslint/types@8.33.1':
1446
- resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==}
1447
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1448
-
1487
'@typescript-eslint/types@8.34.1':
1488
resolution: {integrity: sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==}
1489
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1490
1453
- '@typescript-eslint/typescript-estree@8.33.1':
1454
- resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==}
1455
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1456
- peerDependencies:
1457
- typescript: '>=4.8.4 <5.9.0'
1458
-
1491
'@typescript-eslint/typescript-estree@8.34.1':
1492
resolution: {integrity: sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==}
1493
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1494
peerDependencies:
1495
typescript: '>=4.8.4 <5.9.0'
1496
1465
- '@typescript-eslint/utils@8.33.1':
1466
- resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==}
1467
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1468
- peerDependencies:
1469
- eslint: ^8.57.0 || ^9.0.0
1470
- typescript: '>=4.8.4 <5.9.0'
1471
-
1497
'@typescript-eslint/utils@8.34.1':
1498
resolution: {integrity: sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==}
1499
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1476,10 +1501,6 @@ packages:
1501
eslint: ^8.57.0 || ^9.0.0
1502
typescript: '>=4.8.4 <5.9.0'
1503
1479
- '@typescript-eslint/visitor-keys@8.33.1':
1480
- resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==}
1481
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1482
-
1504
'@typescript-eslint/visitor-keys@8.34.1':
1505
resolution: {integrity: sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==}
1506
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -1724,6 +1745,10 @@ packages:
1745
ajv@6.12.6:
1746
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
1747
1748
+ algoliasearch@5.29.0:
1749
+ resolution: {integrity: sha512-E2l6AlTWGznM2e7vEE6T6hzObvEyXukxMOlBmVlMyixZyK1umuO/CiVc6sDBbzVH0oEviCE5IfVY1oZBmccYPQ==}
1750
+ engines: {node: '>= 14.0.0'}
1751
+
1752
alien-signals@1.0.13:
1753
resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==}
1754
@@ -2401,8 +2426,8 @@ packages:
2426
peerDependencies:
2427
eslint: '*'
2428
2404
- eslint-plugin-command@3.2.1:
2405
- resolution: {integrity: sha512-PcpzWe8dvAPaBobxE9zgz1w94fO4JYvzciDzw6thlUb9Uqf5e2/gJz97itOGxvdq+mFeudi71m1OGFgvWmb93w==}
2429
+ eslint-plugin-command@3.3.1:
2430
+ resolution: {integrity: sha512-fBVTXQ2y48TVLT0+4A6PFINp7GcdIailHAXbvPBixE7x+YpYnNQhFZxTdvnb+aWk+COgNebQKen/7m4dmgyWAw==}
2431
peerDependencies:
2432
eslint: '*'
2433
@@ -2422,8 +2447,8 @@ packages:
2447
typescript:
2448
optional: true
2449
2425
- eslint-plugin-jsdoc@51.1.2:
2426
- resolution: {integrity: sha512-xLg40KhRnlaOX6W+YLofVavGTajOUn6VCSoVC5eWKbsaMMM/aznFAqVXysuk76wSQZJMiBOfC4V6beseIk6eOg==}
2450
+ eslint-plugin-jsdoc@51.2.1:
2451
+ resolution: {integrity: sha512-iE2qpG/kaA9xXfEcTNSsxNvH5O8+o38VBGLwl2oZisQaM1JRGftTLJAGQrj7YZjSkp3n9VCrNTjOpo3ONhTApQ==}
2452
engines: {node: '>=20.11.0'}
2453
peerDependencies:
2454
eslint: ^7.0.0 || ^8.0.0 || ^9.0.0
@@ -2501,10 +2526,6 @@ packages:
2526
'@vue/compiler-sfc': ^3.3.0
2527
eslint: '>=9.0.0'
2528
2504
- eslint-scope@8.3.0:
2505
- resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==}
2506
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2507
-
2529
eslint-scope@8.4.0:
2530
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
2531
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2513,10 +2534,6 @@ packages:
2534
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
2535
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
2536
2516
- eslint-visitor-keys@4.2.0:
2517
- resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==}
2518
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2519
-
2537
eslint-visitor-keys@4.2.1:
2538
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
2539
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2531,10 +2548,6 @@ packages:
2548
jiti:
2549
optional: true
2550
2534
- espree@10.3.0:
2535
- resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
2536
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
2537
-
2551
espree@10.4.0:
2552
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
2553
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -2780,6 +2793,9 @@ packages:
2793
resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==}
2794
hasBin: true
2795
2796
+ github-slugger@2.0.0:
2797
+ resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==}
2798
+
2799
glob-parent@5.1.2:
2800
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
2801
engines: {node: '>= 6'}
@@ -3881,8 +3897,8 @@ packages:
3897
prettier-plugin-svelte:
3898
optional: true
3899
3884
- prettier@3.5.3:
3885
- resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
3900
+ prettier@3.6.0:
3901
+ resolution: {integrity: sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw==}
3902
engines: {node: '>=14'}
3903
hasBin: true
3904
@@ -4650,8 +4666,8 @@ packages:
4666
peerDependencies:
4667
vue: ^3.0.0
4668
4653
- vue-i18n@11.1.6:
4654
- resolution: {integrity: sha512-+IbsW/sTZHj7U1w0rPOYJbuSB0/7DeO1nvUo3BxvO20OQgHs+ukJ3QeLqvoUA6DiLk+8SA9+djRmKC9+FC6cAg==}
4669
+ vue-i18n@11.1.7:
4670
+ resolution: {integrity: sha512-CDrU7Cmyh1AxJjerQmipV9nVa//exVBdhTcWGlbfcDCN8bKp/uAe7Le6IoN4//5emIikbsSKe9Uofmf/xXkhOA==}
4671
engines: {node: '>= 16'}
4672
peerDependencies:
4673
vue: ^3.0.0
@@ -4857,18 +4873,95 @@ snapshots:
4873
dependencies:
4874
lodash: 4.17.21
4875
4876
+ '@algolia/client-abtesting@5.29.0':
4877
+ dependencies:
4878
+ '@algolia/client-common': 5.29.0
4879
+ '@algolia/requester-browser-xhr': 5.29.0
4880
+ '@algolia/requester-fetch': 5.29.0
4881
+ '@algolia/requester-node-http': 5.29.0
4882
+
4883
+ '@algolia/client-analytics@5.29.0':
4884
+ dependencies:
4885
+ '@algolia/client-common': 5.29.0
4886
+ '@algolia/requester-browser-xhr': 5.29.0
4887
+ '@algolia/requester-fetch': 5.29.0
4888
+ '@algolia/requester-node-http': 5.29.0
4889
+
4890
+ '@algolia/client-common@5.29.0': {}
4891
+
4892
+ '@algolia/client-insights@5.29.0':
4893
+ dependencies:
4894
+ '@algolia/client-common': 5.29.0
4895
+ '@algolia/requester-browser-xhr': 5.29.0
4896
+ '@algolia/requester-fetch': 5.29.0
4897
+ '@algolia/requester-node-http': 5.29.0
4898
+
4899
+ '@algolia/client-personalization@5.29.0':
4900
+ dependencies:
4901
+ '@algolia/client-common': 5.29.0
4902
+ '@algolia/requester-browser-xhr': 5.29.0
4903
+ '@algolia/requester-fetch': 5.29.0
4904
+ '@algolia/requester-node-http': 5.29.0
4905
+
4906
+ '@algolia/client-query-suggestions@5.29.0':
4907
+ dependencies:
4908
+ '@algolia/client-common': 5.29.0
4909
+ '@algolia/requester-browser-xhr': 5.29.0
4910
+ '@algolia/requester-fetch': 5.29.0
4911
+ '@algolia/requester-node-http': 5.29.0
4912
+
4913
+ '@algolia/client-search@5.29.0':
4914
+ dependencies:
4915
+ '@algolia/client-common': 5.29.0
4916
+ '@algolia/requester-browser-xhr': 5.29.0
4917
+ '@algolia/requester-fetch': 5.29.0
4918
+ '@algolia/requester-node-http': 5.29.0
4919
+
4920
+ '@algolia/ingestion@1.29.0':
4921
+ dependencies:
4922
+ '@algolia/client-common': 5.29.0
4923
+ '@algolia/requester-browser-xhr': 5.29.0
4924
+ '@algolia/requester-fetch': 5.29.0
4925
+ '@algolia/requester-node-http': 5.29.0
4926
+
4927
+ '@algolia/monitoring@1.29.0':
4928
+ dependencies:
4929
+ '@algolia/client-common': 5.29.0
4930
+ '@algolia/requester-browser-xhr': 5.29.0
4931
+ '@algolia/requester-fetch': 5.29.0
4932
+ '@algolia/requester-node-http': 5.29.0
4933
+
4934
+ '@algolia/recommend@5.29.0':
4935
+ dependencies:
4936
+ '@algolia/client-common': 5.29.0
4937
+ '@algolia/requester-browser-xhr': 5.29.0
4938
+ '@algolia/requester-fetch': 5.29.0
4939
+ '@algolia/requester-node-http': 5.29.0
4940
+
4941
+ '@algolia/requester-browser-xhr@5.29.0':
4942
+ dependencies:
4943
+ '@algolia/client-common': 5.29.0
4944
+
4945
+ '@algolia/requester-fetch@5.29.0':
4946
+ dependencies:
4947
+ '@algolia/client-common': 5.29.0
4948
+
4949
+ '@algolia/requester-node-http@5.29.0':
4950
+ dependencies:
4951
+ '@algolia/client-common': 5.29.0
4952
+
4953
'@ampproject/remapping@2.3.0':
4954
dependencies:
4955
'@jridgewell/gen-mapping': 0.3.8
4956
'@jridgewell/trace-mapping': 0.3.25
4957
4865
- '@antfu/eslint-config@4.15.0(@vue/compiler-sfc@3.5.17)(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))':
4958
+ '@antfu/eslint-config@4.16.1(@vue/compiler-sfc@3.5.17)(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))':
4959
dependencies:
4960
'@antfu/install-pkg': 1.1.0
4961
'@clack/prompts': 0.11.0
4962
'@eslint-community/eslint-plugin-eslint-comments': 4.5.0(eslint@9.29.0(jiti@2.4.2))
4870
- '@eslint/markdown': 6.5.0
4871
- '@stylistic/eslint-plugin': 5.0.0-beta.5(eslint@9.29.0(jiti@2.4.2))
4963
+ '@eslint/markdown': 6.6.0
4964
+ '@stylistic/eslint-plugin': 5.0.0(eslint@9.29.0(jiti@2.4.2))
4965
'@typescript-eslint/eslint-plugin': 8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
4966
'@typescript-eslint/parser': 8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
4967
'@vitest/eslint-plugin': 1.2.7(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))
@@ -4879,9 +4972,9 @@ snapshots:
4972
eslint-flat-config-utils: 2.1.0
4973
eslint-merge-processors: 2.0.0(eslint@9.29.0(jiti@2.4.2))
4974
eslint-plugin-antfu: 3.1.1(eslint@9.29.0(jiti@2.4.2))
4882
- eslint-plugin-command: 3.2.1(eslint@9.29.0(jiti@2.4.2))
4975
+ eslint-plugin-command: 3.3.1(eslint@9.29.0(jiti@2.4.2))
4976
eslint-plugin-import-lite: 0.3.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
4884
- eslint-plugin-jsdoc: 51.1.2(eslint@9.29.0(jiti@2.4.2))
4977
+ eslint-plugin-jsdoc: 51.2.1(eslint@9.29.0(jiti@2.4.2))
4978
eslint-plugin-jsonc: 2.20.1(eslint@9.29.0(jiti@2.4.2))
4979
eslint-plugin-n: 17.20.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
4980
eslint-plugin-no-only-tests: 3.3.0
@@ -5265,8 +5358,8 @@ snapshots:
5358
5359
'@es-joy/jsdoccomment@0.50.2':
5360
dependencies:
5268
- '@types/estree': 1.0.7
5269
- '@typescript-eslint/types': 8.33.1
5361
+ '@types/estree': 1.0.8
5362
+ '@typescript-eslint/types': 8.34.1
5363
comment-parser: 1.4.1
5364
esquery: 1.6.0
5365
jsdoc-type-pratt-parser: 4.1.0
@@ -5405,10 +5498,11 @@ snapshots:
5498
5499
'@eslint/js@9.29.0': {}
5500
5408
- '@eslint/markdown@6.5.0':
5501
+ '@eslint/markdown@6.6.0':
5502
dependencies:
5503
'@eslint/core': 0.14.0
5504
'@eslint/plugin-kit': 0.3.1
5505
+ github-slugger: 2.0.0
5506
mdast-util-from-markdown: 2.0.2
5507
mdast-util-frontmatter: 2.0.1
5508
mdast-util-gfm: 3.1.0
@@ -5466,17 +5560,17 @@ snapshots:
5560
'@iconify/types': 2.0.0
5561
vue: 3.5.17(typescript@5.8.3)
5562
5469
- '@intlify/core-base@11.1.6':
5563
+ '@intlify/core-base@11.1.7':
5564
dependencies:
5471
- '@intlify/message-compiler': 11.1.6
5472
- '@intlify/shared': 11.1.6
5565
+ '@intlify/message-compiler': 11.1.7
5566
+ '@intlify/shared': 11.1.7
5567
5474
- '@intlify/message-compiler@11.1.6':
5568
+ '@intlify/message-compiler@11.1.7':
5569
dependencies:
5476
- '@intlify/shared': 11.1.6
5570
+ '@intlify/shared': 11.1.7
5571
source-map-js: 1.2.1
5572
5479
- '@intlify/shared@11.1.6': {}
5573
+ '@intlify/shared@11.1.7': {}
5574
5575
'@isaacs/cliui@8.0.2':
5576
dependencies:
@@ -5770,13 +5864,17 @@ snapshots:
5864
5865
'@sindresorhus/merge-streams@4.0.0': {}
5866
5773
- '@stylistic/eslint-plugin@5.0.0-beta.5(eslint@9.29.0(jiti@2.4.2))':
5867
+ '@singulio/app-auth-search@0.0.3':
5868
+ dependencies:
5869
+ algoliasearch: 5.29.0
5870
+
5871
+ '@stylistic/eslint-plugin@5.0.0(eslint@9.29.0(jiti@2.4.2))':
5872
dependencies:
5873
'@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2))
5776
- '@typescript-eslint/types': 8.33.1
5874
+ '@typescript-eslint/types': 8.34.1
5875
eslint: 9.29.0(jiti@2.4.2)
5778
- eslint-visitor-keys: 4.2.0
5779
- espree: 10.3.0
5876
+ eslint-visitor-keys: 4.2.1
5877
+ espree: 10.4.0
5878
estraverse: 5.3.0
5879
picomatch: 4.0.2
5880
@@ -5990,15 +6088,6 @@ snapshots:
6088
transitivePeerDependencies:
6089
- supports-color
6090
5993
- '@typescript-eslint/project-service@8.33.1(typescript@5.8.3)':
5994
- dependencies:
5995
- '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3)
5996
- '@typescript-eslint/types': 8.33.1
5997
- debug: 4.4.1(supports-color@8.1.1)
5998
- typescript: 5.8.3
5999
- transitivePeerDependencies:
6000
- - supports-color
6001
-
6091
'@typescript-eslint/project-service@8.34.1(typescript@5.8.3)':
6092
dependencies:
6093
'@typescript-eslint/tsconfig-utils': 8.34.1(typescript@5.8.3)
@@ -6008,20 +6097,11 @@ snapshots:
6097
transitivePeerDependencies:
6098
- supports-color
6099
6011
- '@typescript-eslint/scope-manager@8.33.1':
6012
- dependencies:
6013
- '@typescript-eslint/types': 8.33.1
6014
- '@typescript-eslint/visitor-keys': 8.33.1
6015
-
6100
'@typescript-eslint/scope-manager@8.34.1':
6101
dependencies:
6102
'@typescript-eslint/types': 8.34.1
6103
'@typescript-eslint/visitor-keys': 8.34.1
6104
6021
- '@typescript-eslint/tsconfig-utils@8.33.1(typescript@5.8.3)':
6022
- dependencies:
6023
- typescript: 5.8.3
6024
-
6105
'@typescript-eslint/tsconfig-utils@8.34.1(typescript@5.8.3)':
6106
dependencies:
6107
typescript: 5.8.3
@@ -6037,26 +6117,8 @@ snapshots:
6117
transitivePeerDependencies:
6118
- supports-color
6119
6040
- '@typescript-eslint/types@8.33.1': {}
6041
-
6120
'@typescript-eslint/types@8.34.1': {}
6121
6044
- '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)':
6045
- dependencies:
6046
- '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3)
6047
- '@typescript-eslint/tsconfig-utils': 8.33.1(typescript@5.8.3)
6048
- '@typescript-eslint/types': 8.33.1
6049
- '@typescript-eslint/visitor-keys': 8.33.1
6050
- debug: 4.4.1(supports-color@8.1.1)
6051
- fast-glob: 3.3.3
6052
- is-glob: 4.0.3
6053
- minimatch: 9.0.5
6054
- semver: 7.7.2
6055
- ts-api-utils: 2.1.0(typescript@5.8.3)
6056
- typescript: 5.8.3
6057
- transitivePeerDependencies:
6058
- - supports-color
6059
-
6122
'@typescript-eslint/typescript-estree@8.34.1(typescript@5.8.3)':
6123
dependencies:
6124
'@typescript-eslint/project-service': 8.34.1(typescript@5.8.3)
@@ -6073,17 +6135,6 @@ snapshots:
6135
transitivePeerDependencies:
6136
- supports-color
6137
6076
- '@typescript-eslint/utils@8.33.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)':
6077
- dependencies:
6078
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2))
6079
- '@typescript-eslint/scope-manager': 8.33.1
6080
- '@typescript-eslint/types': 8.33.1
6081
- '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
6082
- eslint: 9.29.0(jiti@2.4.2)
6083
- typescript: 5.8.3
6084
- transitivePeerDependencies:
6085
- - supports-color
6086
-
6138
'@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)':
6139
dependencies:
6140
'@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2))
@@ -6095,11 +6146,6 @@ snapshots:
6146
transitivePeerDependencies:
6147
- supports-color
6148
6098
- '@typescript-eslint/visitor-keys@8.33.1':
6099
- dependencies:
6100
- '@typescript-eslint/types': 8.33.1
6101
- eslint-visitor-keys: 4.2.0
6102
-
6149
'@typescript-eslint/visitor-keys@8.34.1':
6150
dependencies:
6151
'@typescript-eslint/types': 8.34.1
@@ -6125,7 +6171,7 @@ snapshots:
6171
6172
'@vitest/eslint-plugin@1.2.7(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.3)(jiti@2.4.2)(jsdom@26.1.0)(lightningcss@1.30.1)(sass@1.89.2)(yaml@2.8.0))':
6173
dependencies:
6128
- '@typescript-eslint/utils': 8.33.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
6174
+ '@typescript-eslint/utils': 8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
6175
eslint: 9.29.0(jiti@2.4.2)
6176
optionalDependencies:
6177
typescript: 5.8.3
@@ -6426,10 +6472,6 @@ snapshots:
6472
6473
abbrev@2.0.0: {}
6474
6429
- acorn-jsx@5.3.2(acorn@8.14.1):
6430
- dependencies:
6431
- acorn: 8.14.1
6432
-
6475
acorn-jsx@5.3.2(acorn@8.15.0):
6476
dependencies:
6477
acorn: 8.15.0
@@ -6452,6 +6494,22 @@ snapshots:
6494
json-schema-traverse: 0.4.1
6495
uri-js: 4.4.1
6496
6497
+ algoliasearch@5.29.0:
6498
+ dependencies:
6499
+ '@algolia/client-abtesting': 5.29.0
6500
+ '@algolia/client-analytics': 5.29.0
6501
+ '@algolia/client-common': 5.29.0
6502
+ '@algolia/client-insights': 5.29.0
6503
+ '@algolia/client-personalization': 5.29.0
6504
+ '@algolia/client-query-suggestions': 5.29.0
6505
+ '@algolia/client-search': 5.29.0
6506
+ '@algolia/ingestion': 1.29.0
6507
+ '@algolia/monitoring': 1.29.0
6508
+ '@algolia/recommend': 5.29.0
6509
+ '@algolia/requester-browser-xhr': 5.29.0
6510
+ '@algolia/requester-fetch': 5.29.0
6511
+ '@algolia/requester-node-http': 5.29.0
6512
+
6513
alien-signals@1.0.13: {}
6514
6515
ansi-colors@4.1.3: {}
@@ -7136,7 +7194,7 @@ snapshots:
7194
dependencies:
7195
eslint: 9.29.0(jiti@2.4.2)
7196
7139
- eslint-plugin-command@3.2.1(eslint@9.29.0(jiti@2.4.2)):
7197
+ eslint-plugin-command@3.3.1(eslint@9.29.0(jiti@2.4.2)):
7198
dependencies:
7199
'@es-joy/jsdoccomment': 0.50.2
7200
eslint: 9.29.0(jiti@2.4.2)
@@ -7156,7 +7214,7 @@ snapshots:
7214
optionalDependencies:
7215
typescript: 5.8.3
7216
7159
- eslint-plugin-jsdoc@51.1.2(eslint@9.29.0(jiti@2.4.2)):
7217
+ eslint-plugin-jsdoc@51.2.1(eslint@9.29.0(jiti@2.4.2)):
7218
dependencies:
7219
'@es-joy/jsdoccomment': 0.52.0
7220
are-docs-informative: 0.0.2
@@ -7178,7 +7236,7 @@ snapshots:
7236
eslint: 9.29.0(jiti@2.4.2)
7237
eslint-compat-utils: 0.6.5(eslint@9.29.0(jiti@2.4.2))
7238
eslint-json-compat-utils: 0.2.1(eslint@9.29.0(jiti@2.4.2))(jsonc-eslint-parser@2.4.0)
7181
- espree: 10.3.0
7239
+ espree: 10.4.0
7240
graphemer: 1.4.0
7241
jsonc-eslint-parser: 2.4.0
7242
natural-compare: 1.4.0
@@ -7189,7 +7247,7 @@ snapshots:
7247
eslint-plugin-n@17.20.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3):
7248
dependencies:
7249
'@eslint-community/eslint-utils': 4.7.0(eslint@9.29.0(jiti@2.4.2))
7192
- '@typescript-eslint/utils': 8.33.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
7250
+ '@typescript-eslint/utils': 8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
7251
enhanced-resolve: 5.18.1
7252
eslint: 9.29.0(jiti@2.4.2)
7253
eslint-plugin-es-x: 7.8.0(eslint@9.29.0(jiti@2.4.2))
@@ -7300,11 +7358,6 @@ snapshots:
7358
'@vue/compiler-sfc': 3.5.17
7359
eslint: 9.29.0(jiti@2.4.2)
7360
7303
- eslint-scope@8.3.0:
7304
- dependencies:
7305
- esrecurse: 4.3.0
7306
- estraverse: 5.3.0
7307
-
7361
eslint-scope@8.4.0:
7362
dependencies:
7363
esrecurse: 4.3.0
@@ -7312,8 +7365,6 @@ snapshots:
7365
7366
eslint-visitor-keys@3.4.3: {}
7367
7315
- eslint-visitor-keys@4.2.0: {}
7316
-
7368
eslint-visitor-keys@4.2.1: {}
7369
7370
eslint@9.29.0(jiti@2.4.2):
@@ -7358,12 +7409,6 @@ snapshots:
7409
transitivePeerDependencies:
7410
- supports-color
7411
7361
- espree@10.3.0:
7362
- dependencies:
7363
- acorn: 8.14.1
7364
- acorn-jsx: 5.3.2(acorn@8.14.1)
7365
- eslint-visitor-keys: 4.2.0
7366
-
7412
espree@10.4.0:
7413
dependencies:
7414
acorn: 8.15.0
@@ -7372,8 +7417,8 @@ snapshots:
7417
7418
espree@9.6.1:
7419
dependencies:
7375
- acorn: 8.14.1
7376
- acorn-jsx: 5.3.2(acorn@8.14.1)
7420
+ acorn: 8.15.0
7421
+ acorn-jsx: 5.3.2(acorn@8.15.0)
7422
eslint-visitor-keys: 3.4.3
7423
7424
esprima@4.0.1: {}
@@ -7646,6 +7691,8 @@ snapshots:
7691
nypm: 0.6.0
7692
pathe: 2.0.3
7693
7694
+ github-slugger@2.0.0: {}
7695
+
7696
glob-parent@5.1.2:
7697
dependencies:
7698
is-glob: 4.0.3
@@ -7977,7 +8024,7 @@ snapshots:
8024
8025
jsonc-eslint-parser@2.4.0:
8026
dependencies:
7980
- acorn: 8.14.1
8027
+ acorn: 8.15.0
8028
eslint-visitor-keys: 3.4.3
8029
espree: 9.6.1
8030
semver: 7.7.2
@@ -8824,11 +8871,11 @@ snapshots:
8871
8872
prelude-ls@1.2.1: {}
8873
8827
- prettier-plugin-tailwindcss@0.6.13(prettier@3.5.3):
8874
+ prettier-plugin-tailwindcss@0.6.13(prettier@3.6.0):
8875
dependencies:
8829
- prettier: 3.5.3
8876
+ prettier: 3.6.0
8877
8831
- prettier@3.5.3: {}
8878
+ prettier@3.6.0: {}
8879
8880
pretty-bytes@5.6.0: {}
8881
@@ -9656,9 +9703,9 @@ snapshots:
9703
dependencies:
9704
debug: 4.4.1(supports-color@8.1.1)
9705
eslint: 9.29.0(jiti@2.4.2)
9659
- eslint-scope: 8.3.0
9660
- eslint-visitor-keys: 4.2.0
9661
- espree: 10.3.0
9706
+ eslint-scope: 8.4.0
9707
+ eslint-visitor-keys: 4.2.1
9708
+ espree: 10.4.0
9709
esquery: 1.6.0
9710
lodash: 4.17.21
9711
semver: 7.7.2
@@ -9670,10 +9717,10 @@ snapshots:
9717
highlight-words-core: 1.2.3
9718
vue: 3.5.17(typescript@5.8.3)
9719
9673
- vue-i18n@11.1.6(vue@3.5.17(typescript@5.8.3)):
9720
+ vue-i18n@11.1.7(vue@3.5.17(typescript@5.8.3)):
9721
dependencies:
9675
- '@intlify/core-base': 11.1.6
9676
- '@intlify/shared': 11.1.6
9722
+ '@intlify/core-base': 11.1.7
9723
+ '@intlify/shared': 11.1.7
9724
'@vue/devtools-api': 6.6.4
9725
vue: 3.5.17(typescript@5.8.3)
9726
frontend/src/App.vue
+7
-4
@@ -26,6 +26,7 @@
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 { defineCustomElements } from "@singulio/app-auth-search/loader"
30
import { computed, onBeforeMount, ref, watch } from "vue"
31
import { useRoute, useRouter } from "vue-router"
32
import Blank from "@/app-layouts/Blank"
@@ -37,15 +38,17 @@ import { useAuthStore } from "@/stores/auth"
38
import { useMainStore } from "@/stores/main"
39
import { useThemeStore } from "@/stores/theme"
40
40
-const router = useRouter()
41
-const route = useRoute()
42
-const loading = ref(true)
43
-
41
const layoutComponents = {
42
HorizontalNav,
43
Blank
44
}
45
46
+defineCustomElements()
47
+
48
+const router = useRouter()
49
+const route = useRoute()
50
+const loading = ref(true)
51
+
52
const themeStore = useThemeStore()
53
const mainStore = useMainStore()
54
const authStore = useAuthStore()
frontend/src/api/endpoints/shuffle.ts
new
+16
@@ -0,0 +1,16 @@
1
+import type { FlaskBaseResponse } from "@/types/flask.d"
2
+import type { Organization } from "@/types/shuffle.d"
3
+import { HttpClient } from "../httpClient"
4
+
5
+export default {
6
+ getOrganizations() {
7
+ return HttpClient.get<FlaskBaseResponse & { data: Organization[]; total_count: number }>(
8
+ `/shuffle/organizations/organizations?connector_name=Shuffle`
9
+ )
10
+ },
11
+ getOrganization(organizationId: string) {
12
+ return HttpClient.get<FlaskBaseResponse & { data: Organization }>(
13
+ `/shuffle/organizations/organizations/${organizationId}?connector_name=Shuffle`
14
+ )
15
+ }
16
+}
frontend/src/api/index.ts
+3
-1
@@ -21,6 +21,7 @@ import networkConnectors from "./endpoints/networkConnectors"
21
import portainer from "./endpoints/portainer"
22
import reporting from "./endpoints/reporting"
23
import scheduler from "./endpoints/scheduler"
24
+import shuffle from "./endpoints/shuffle"
25
import sigma from "./endpoints/sigma"
26
import soc from "./endpoints/soc"
27
import stackProvisioning from "./endpoints/stackProvisioning"
@@ -59,5 +60,6 @@ export default {
60
users,
61
sysmonConfig,
62
mitre,
62
- portainer
63
+ portainer,
64
+ shuffle
65
}
frontend/src/app-layouts/common/Navbar/items.tsx
+13
@@ -380,6 +380,19 @@ export default function getItems(): MenuMixedOption[] {
380
{ default: () => "Network Connectors" }
381
),
382
key: "ExternalServices-NetworkConnectors"
383
+ },
384
+ {
385
+ label: () =>
386
+ h(
387
+ RouterLink,
388
+ {
389
+ to: {
390
+ name: "ExternalServices-SingulAppAuth"
391
+ }
392
+ },
393
+ { default: () => "Singul App Auth" }
394
+ ),
395
+ key: "ExternalServices-SingulAppAuth"
396
}
397
]
398
},
frontend/src/router/index.ts
+6
@@ -233,6 +233,12 @@ const router = createRouter({
233
name: "ExternalServices-NetworkConnectors",
234
component: () => import("@/views/externalServices/NetworkConnectors.vue"),
235
meta: { title: "Network Connectors" }
236
+ },
237
+ {
238
+ path: "singul-app-auth",
239
+ name: "ExternalServices-SingulAppAuth",
240
+ component: () => import("@/views/externalServices/SingulAppAuth.vue"),
241
+ meta: { title: "Singul App Auth" }
242
}
243
]
244
},
frontend/src/types/shuffle.d.ts
new
+92
@@ -0,0 +1,92 @@
1
+export interface Organization {
2
+ name: string
3
+ description: string | null
4
+ company_type: string
5
+ id: string
6
+ org: string | null
7
+ org_auth: OrgAuth
8
+ users: string[] | null
9
+ role: string
10
+ roles: string[]
11
+ active_apps: string[]
12
+ cloud_sync: boolean
13
+ cloud_sync_active: boolean
14
+ sync_config: OrgSyncConfig
15
+ sync_features: OrgSyncFeatures
16
+ invites: string[] | null
17
+ child_orgs?: string[] | null
18
+ manager_orgs: string[] | null
19
+ creator_org: string
20
+ disabled: boolean
21
+ partner_info: OrgPartnerInfo
22
+ sso_config: OrgSsoConfig
23
+ main_priority: string
24
+ region: string
25
+ region_url: string
26
+ tutorials: OrgTutorial[]
27
+ image?: string
28
+}
29
+
30
+export interface OrgAuth {
31
+ token: string
32
+ expires: Date | null
33
+}
34
+
35
+export interface OrgPartnerInfo {
36
+ reseller: boolean
37
+ reseller_level: string
38
+}
39
+
40
+export interface OrgSsoConfig {
41
+ sso_entrypoint: string
42
+ sso_certificate: string
43
+ client_id: string
44
+ client_secret: string
45
+ openid_authorization: string
46
+ openid_token: string
47
+}
48
+
49
+export interface OrgSyncConfig {
50
+ interval: number
51
+ api_key: string
52
+ source: string
53
+}
54
+
55
+export interface OrgSyncFeatures {
56
+ editing: boolean
57
+ mail_sent: null | boolean
58
+ app_executions: OrgSyncFeature
59
+ multi_env: OrgSyncFeature
60
+ multi_tenant: OrgSyncFeature
61
+ multi_region: OrgSyncFeature
62
+ webhook: OrgSyncFeature
63
+ schedules: OrgSyncFeature
64
+ user_input: OrgSyncFeature
65
+ send_mail: OrgSyncFeature
66
+ send_sms: OrgSyncFeature
67
+ updates: OrgSyncFeature
68
+ email_trigger: OrgSyncFeature
69
+ notifications: OrgSyncFeature
70
+ workflows: OrgSyncFeature
71
+ autocomplete: OrgSyncFeature
72
+ workflow_executions: OrgSyncFeature
73
+ authentication: OrgSyncFeature
74
+ schedule: OrgSyncFeature
75
+ apps: OrgSyncFeature
76
+ shuffle_gpt: OrgSyncFeature
77
+}
78
+
79
+export interface OrgSyncFeature {
80
+ active: boolean
81
+ description?: string
82
+ usage: number
83
+ limit: number
84
+}
85
+
86
+export interface OrgTutorial {
87
+ name: string
88
+ description: string
89
+ link: string
90
+ done: boolean
91
+ active: boolean
92
+}
frontend/src/views/externalServices/SingulAppAuth.vue
new
+132
@@ -0,0 +1,132 @@
1
+<template>
2
+ <div class="flex flex-col gap-2">
3
+ <n-select
4
+ v-model:value="selectedOrganization"
5
+ :options="organizationsOptions"
6
+ :loading="loadingList"
7
+ :disabled="loadingList"
8
+ placeholder="Select an Organization..."
9
+ />
10
+
11
+ <n-spin v-if="selectedOrganization" :show="loadingToken" :size="14" class="app-auth-search-spinner">
12
+ <n-el>
13
+ <app-search-bar
14
+ class="app-auth-search"
15
+ :auth="organization?.org_auth.token"
16
+ placeholder="Find an app..."
17
+ :custom-styles="JSON.stringify({ height: '100px' })"
18
+ ></app-search-bar>
19
+ </n-el>
20
+ </n-spin>
21
+ </div>
22
+</template>
23
+
24
+<script setup lang="ts">
25
+import type { Organization } from "@/types/shuffle.d"
26
+import { NEl, NSelect, NSpin, useMessage } from "naive-ui"
27
+import { computed, onBeforeMount, ref, watch } from "vue"
28
+import Api from "@/api"
29
+
30
+const loadingList = ref(false)
31
+const loadingToken = ref(false)
32
+const message = useMessage()
33
+const organizations = ref<Organization[]>([])
34
+const organization = ref<Organization | null>(null)
35
+const selectedOrganization = ref<string | null>(null)
36
+const organizationsOptions = computed(() => organizations.value.map(o => ({ value: o.id, label: o.name })))
37
+
38
+function getOrganizations() {
39
+ loadingList.value = true
40
+
41
+ Api.shuffle
42
+ .getOrganizations()
43
+ .then(res => {
44
+ if (res.data.success) {
45
+ organizations.value = res.data?.data || []
46
+ } else {
47
+ message.warning(res.data?.message || "An error occurred. Please try again later.")
48
+ }
49
+ })
50
+ .catch(err => {
51
+ message.error(err.response?.data?.message || "An error occurred. Please try again later.")
52
+ })
53
+ .finally(() => {
54
+ loadingList.value = false
55
+ })
56
+}
57
+
58
+function getOrganization(id: string) {
59
+ loadingToken.value = true
60
+
61
+ Api.shuffle
62
+ .getOrganization(id)
63
+ .then(res => {
64
+ if (res.data.success) {
65
+ organization.value = res.data?.data || null
66
+ } else {
67
+ message.warning(res.data?.message || "An error occurred. Please try again later.")
68
+ }
69
+ })
70
+ .catch(err => {
71
+ message.error(err.response?.data?.message || "An error occurred. Please try again later.")
72
+ })
73
+ .finally(() => {
74
+ loadingToken.value = false
75
+ })
76
+}
77
+
78
+watch(selectedOrganization, val => {
79
+ if (val) {
80
+ getOrganization(val)
81
+ } else {
82
+ organization.value = null
83
+ }
84
+})
85
+
86
+onBeforeMount(() => {
87
+ getOrganizations()
88
+})
89
+</script>
90
+
91
+<style lang="scss" scoped>
92
+.app-auth-search {
93
+ --search-input-bg: var(--input-color);
94
+ --search-input-font-size: var(--font-size-medium);
95
+ --search-input-border: 1px solid transparent;
96
+ --search-input-border-radius: var(--border-radius);
97
+ --search-input-padding: 7px 12px 6px 12px;
98
+ --search-input-color: var(--text-color-base);
99
+ --search-input-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0);
100
+ --search-input-focus-border: var(--primary-color);
101
+ --search-input-focus-shadow: 0 0 8px 0 rgba(var(--primary-color-rgb) / 0.4);
102
+ --search-input-line-height: 1.3;
103
+ --search-placeholder-color: var(--placeholder-color);
104
+ --search-icon-color: var(--icon-color);
105
+ --search-font-family: var(--font-family);
106
+ --search-spinner-border: 1px solid transparent;
107
+ --search-spinner-border-top: 1px solid rgba(var(--primary-color-rgb) / 0.4);
108
+ --dropdown-bg: var(--input-color);
109
+ --dropdown-border: 1px solid transparent;
110
+ --dropdown-border-radius: var(--border-radius);
111
+ --dropdown-item-border: 1px solid var(--divider-color);
112
+ --dropdown-item-hover-bg: var(--button-color-2-hover);
113
+ --app-icon-size: 40px;
114
+ --app-icon-border: 1px solid var(--border-color);
115
+ --app-icon-border-radius: var(--border-radius-small);
116
+ --app-name-color: var(--text-color-base);
117
+ --app-name-font-size: var(--font-size-medium);
118
+ --empty-state-color: var(--placeholder-color);
119
+ --empty-state-font-size: var(--font-size-medium);
120
+}
121
+.app-auth-search-spinner {
122
+ :deep() {
123
+ .n-spin-body .n-base-loading {
124
+ position: relative;
125
+ margin-top: 0;
126
+ transform: translateY(-7px);
127
+ justify-content: flex-end;
128
+ padding-right: 16px;
129
+ }
130
+ }
131
+}
132
+</style>
frontend/vite.config.ts
+5
@@ -21,6 +21,11 @@ export default defineConfig(({ mode }) => {
21
vue({
22
script: {
23
defineModel: true
24
+ },
25
+ template: {
26
+ compilerOptions: {
27
+ isCustomElement: (tag: string) => tag === "app-search-bar"
28
+ }
29
}
30
}),
31
vueJsx(),