@cyvest/cyvest-js 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -45,7 +45,6 @@ __export(index_exports, {
45
45
  findExternalObservables: () => findExternalObservables,
46
46
  findInternalObservables: () => findInternalObservables,
47
47
  findLeafObservables: () => findLeafObservables,
48
- findManuallyScored: () => findManuallyScored,
49
48
  findObservablesAtLeast: () => findObservablesAtLeast,
50
49
  findObservablesByLevel: () => findObservablesByLevel,
51
50
  findObservablesByType: () => findObservablesByType,
@@ -140,6 +139,97 @@ var import_ajv_formats = __toESM(require("ajv-formats"));
140
139
  // ../../../schema/cyvest.schema.json
141
140
  var cyvest_schema_default = {
142
141
  $defs: {
142
+ AuditEvent: {
143
+ additionalProperties: true,
144
+ description: "Centralized audit event for investigation-level changes.",
145
+ properties: {
146
+ event_id: {
147
+ title: "Event Id",
148
+ type: "string"
149
+ },
150
+ timestamp: {
151
+ format: "date-time",
152
+ title: "Timestamp",
153
+ type: "string"
154
+ },
155
+ event_type: {
156
+ title: "Event Type",
157
+ type: "string"
158
+ },
159
+ actor: {
160
+ anyOf: [
161
+ {
162
+ type: "string"
163
+ },
164
+ {
165
+ type: "null"
166
+ }
167
+ ],
168
+ default: null,
169
+ title: "Actor"
170
+ },
171
+ reason: {
172
+ anyOf: [
173
+ {
174
+ type: "string"
175
+ },
176
+ {
177
+ type: "null"
178
+ }
179
+ ],
180
+ default: null,
181
+ title: "Reason"
182
+ },
183
+ tool: {
184
+ anyOf: [
185
+ {
186
+ type: "string"
187
+ },
188
+ {
189
+ type: "null"
190
+ }
191
+ ],
192
+ default: null,
193
+ title: "Tool"
194
+ },
195
+ object_type: {
196
+ anyOf: [
197
+ {
198
+ type: "string"
199
+ },
200
+ {
201
+ type: "null"
202
+ }
203
+ ],
204
+ default: null,
205
+ title: "Object Type"
206
+ },
207
+ object_key: {
208
+ anyOf: [
209
+ {
210
+ type: "string"
211
+ },
212
+ {
213
+ type: "null"
214
+ }
215
+ ],
216
+ default: null,
217
+ title: "Object Key"
218
+ },
219
+ details: {
220
+ additionalProperties: true,
221
+ title: "Details",
222
+ type: "object"
223
+ }
224
+ },
225
+ required: [
226
+ "event_id",
227
+ "timestamp",
228
+ "event_type"
229
+ ],
230
+ title: "AuditEvent",
231
+ type: "object"
232
+ },
143
233
  Check: {
144
234
  description: "Represents a verification step in the investigation.\n\nA check validates a specific aspect of the data under investigation\nand contributes to the overall investigation score.",
145
235
  properties: {
@@ -171,20 +261,25 @@ var cyvest_schema_default = {
171
261
  level: {
172
262
  $ref: "#/$defs/Level"
173
263
  },
174
- observables: {
264
+ origin_investigation_id: {
265
+ title: "Origin Investigation Id",
266
+ type: "string"
267
+ },
268
+ observable_links: {
175
269
  items: {
176
- type: "string"
270
+ $ref: "#/$defs/ObservableLink"
177
271
  },
178
- title: "Observables",
272
+ title: "Observable Links",
179
273
  type: "array"
180
274
  },
181
- score_policy: {
182
- $ref: "#/$defs/CheckScorePolicy",
183
- default: "auto"
184
- },
185
275
  key: {
186
276
  title: "Key",
187
277
  type: "string"
278
+ },
279
+ score_display: {
280
+ readOnly: true,
281
+ title: "Score Display",
282
+ type: "string"
188
283
  }
189
284
  },
190
285
  required: [
@@ -195,21 +290,14 @@ var cyvest_schema_default = {
195
290
  "extra",
196
291
  "score",
197
292
  "level",
198
- "observables",
199
- "key"
293
+ "origin_investigation_id",
294
+ "observable_links",
295
+ "key",
296
+ "score_display"
200
297
  ],
201
298
  title: "Check",
202
299
  type: "object"
203
300
  },
204
- CheckScorePolicy: {
205
- description: "Controls how a check reacts to linked observables.",
206
- enum: [
207
- "auto",
208
- "manual"
209
- ],
210
- title: "CheckScorePolicy",
211
- type: "string"
212
- },
213
301
  Container: {
214
302
  additionalProperties: false,
215
303
  description: "Groups checks and sub-containers for hierarchical organization.\n\nContainers allow structuring the investigation into logical sections\nwith aggregated scores and levels.",
@@ -419,14 +507,19 @@ var cyvest_schema_default = {
419
507
  title: "Key",
420
508
  type: "string"
421
509
  },
422
- generated_by_checks: {
423
- description: "Checks that generated this observable.",
510
+ check_links: {
511
+ description: "Checks that currently link to this observable (navigation-only).",
424
512
  items: {
425
513
  type: "string"
426
514
  },
427
515
  readOnly: true,
428
- title: "Generated By Checks",
516
+ title: "Check Links",
429
517
  type: "array"
518
+ },
519
+ score_display: {
520
+ readOnly: true,
521
+ title: "Score Display",
522
+ type: "string"
430
523
  }
431
524
  },
432
525
  required: [
@@ -441,11 +534,40 @@ var cyvest_schema_default = {
441
534
  "threat_intels",
442
535
  "relationships",
443
536
  "key",
444
- "generated_by_checks"
537
+ "check_links",
538
+ "score_display"
445
539
  ],
446
540
  title: "Observable",
447
541
  type: "object"
448
542
  },
543
+ ObservableLink: {
544
+ additionalProperties: false,
545
+ description: "Edge metadata for a Check\u2194Observable association.",
546
+ properties: {
547
+ observable_key: {
548
+ title: "Observable Key",
549
+ type: "string"
550
+ },
551
+ propagation_mode: {
552
+ $ref: "#/$defs/PropagationMode",
553
+ default: "LOCAL_ONLY"
554
+ }
555
+ },
556
+ required: [
557
+ "observable_key"
558
+ ],
559
+ title: "ObservableLink",
560
+ type: "object"
561
+ },
562
+ PropagationMode: {
563
+ description: "Controls how a Check\u2194Observable link propagates across merged investigations.",
564
+ enum: [
565
+ "LOCAL_ONLY",
566
+ "GLOBAL"
567
+ ],
568
+ title: "PropagationMode",
569
+ type: "string"
570
+ },
449
571
  Relationship: {
450
572
  description: "Represents a relationship between observables.",
451
573
  properties: {
@@ -665,6 +787,11 @@ var cyvest_schema_default = {
665
787
  key: {
666
788
  title: "Key",
667
789
  type: "string"
790
+ },
791
+ score_display: {
792
+ readOnly: true,
793
+ title: "Score Display",
794
+ type: "string"
668
795
  }
669
796
  },
670
797
  required: [
@@ -675,7 +802,8 @@ var cyvest_schema_default = {
675
802
  "score",
676
803
  "level",
677
804
  "taxonomies",
678
- "key"
805
+ "key",
806
+ "score_display"
679
807
  ],
680
808
  title: "ThreatIntel",
681
809
  type: "object"
@@ -686,6 +814,24 @@ var cyvest_schema_default = {
686
814
  additionalProperties: false,
687
815
  description: "Schema for a complete serialized investigation.\n\nThis model describes the output of `serialize_investigation()` from\n`cyvest.io_serialization`. It is the top-level schema for exported investigations.\n\nEntity types reference the runtime models directly. When generating schemas with\n`mode='serialization'`, Pydantic respects field_serializer decorators and produces\nschemas matching the actual model_dump() output.",
688
816
  properties: {
817
+ investigation_id: {
818
+ description: "Stable investigation identity (ULID).",
819
+ title: "Investigation Id",
820
+ type: "string"
821
+ },
822
+ investigation_name: {
823
+ anyOf: [
824
+ {
825
+ type: "string"
826
+ },
827
+ {
828
+ type: "null"
829
+ }
830
+ ],
831
+ default: null,
832
+ description: "Optional human-readable investigation name.",
833
+ title: "Investigation Name"
834
+ },
689
835
  started_at: {
690
836
  description: "Investigation start time (UTC).",
691
837
  format: "date-time",
@@ -714,6 +860,14 @@ var cyvest_schema_default = {
714
860
  title: "Whitelists",
715
861
  type: "array"
716
862
  },
863
+ event_log: {
864
+ description: "Append-only investigation audit log.",
865
+ items: {
866
+ $ref: "#/$defs/AuditEvent"
867
+ },
868
+ title: "Event Log",
869
+ type: "array"
870
+ },
717
871
  observables: {
718
872
  additionalProperties: {
719
873
  $ref: "#/$defs/Observable"
@@ -779,9 +933,16 @@ var cyvest_schema_default = {
779
933
  data_extraction: {
780
934
  $ref: "#/$defs/DataExtractionSchema",
781
935
  description: "Data extraction metadata."
936
+ },
937
+ score_display: {
938
+ description: "Global investigation score formatted as fixed-point x.xx.",
939
+ readOnly: true,
940
+ title: "Score Display",
941
+ type: "string"
782
942
  }
783
943
  },
784
944
  required: [
945
+ "investigation_id",
785
946
  "started_at",
786
947
  "score",
787
948
  "level",
@@ -795,7 +956,8 @@ var cyvest_schema_default = {
795
956
  "containers",
796
957
  "stats",
797
958
  "stats_checks",
798
- "data_extraction"
959
+ "data_extraction",
960
+ "score_display"
799
961
  ],
800
962
  title: "Cyvest Investigation",
801
963
  type: "object"
@@ -1275,17 +1437,6 @@ function findChecksByCheckId(inv, checkId) {
1275
1437
  }
1276
1438
  return result;
1277
1439
  }
1278
- function findManuallyScored(inv) {
1279
- const result = [];
1280
- for (const checks of Object.values(inv.checks)) {
1281
- for (const check of checks) {
1282
- if (check.score_policy === "manual") {
1283
- result.push(check);
1284
- }
1285
- }
1286
- }
1287
- return result;
1288
- }
1289
1440
  function findThreatIntelBySource(inv, source) {
1290
1441
  const normalizedSource = source.trim().toLowerCase();
1291
1442
  return Object.values(inv.threat_intels).filter(
@@ -1328,13 +1479,32 @@ function findContainersAtLeast(inv, minLevel2) {
1328
1479
  }
1329
1480
  function getChecksForObservable(inv, observableKey) {
1330
1481
  const result = [];
1482
+ const seen = /* @__PURE__ */ new Set();
1483
+ const checkLookup = /* @__PURE__ */ new Map();
1331
1484
  for (const checks of Object.values(inv.checks)) {
1332
1485
  for (const check of checks) {
1333
- if (check.observables.includes(observableKey)) {
1486
+ checkLookup.set(check.key, check);
1487
+ }
1488
+ }
1489
+ const observable = inv.observables[observableKey];
1490
+ if (observable) {
1491
+ for (const checkKey of observable.check_links) {
1492
+ const check = checkLookup.get(checkKey);
1493
+ if (check && !seen.has(check.key)) {
1334
1494
  result.push(check);
1495
+ seen.add(check.key);
1335
1496
  }
1336
1497
  }
1337
1498
  }
1499
+ for (const check of checkLookup.values()) {
1500
+ if (seen.has(check.key)) {
1501
+ continue;
1502
+ }
1503
+ if (check.observable_links.some((link) => link.observable_key === observableKey)) {
1504
+ result.push(check);
1505
+ seen.add(check.key);
1506
+ }
1507
+ }
1338
1508
  return result;
1339
1509
  }
1340
1510
  function getThreatIntelsForObservable(inv, observableKey) {
@@ -1350,7 +1520,11 @@ function getObservablesForCheck(inv, checkKey) {
1350
1520
  for (const checks of Object.values(inv.checks)) {
1351
1521
  for (const check of checks) {
1352
1522
  if (check.key === checkKey) {
1353
- return check.observables.map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1523
+ const keys = /* @__PURE__ */ new Set();
1524
+ for (const link of check.observable_links) {
1525
+ keys.add(link.observable_key);
1526
+ }
1527
+ return Array.from(keys).map((obsKey) => inv.observables[obsKey]).filter((obs) => obs !== void 0);
1354
1528
  }
1355
1529
  }
1356
1530
  }
@@ -1723,7 +1897,6 @@ function getRelationshipsForObservable(inv, observableKey) {
1723
1897
  findExternalObservables,
1724
1898
  findInternalObservables,
1725
1899
  findLeafObservables,
1726
- findManuallyScored,
1727
1900
  findObservablesAtLeast,
1728
1901
  findObservablesByLevel,
1729
1902
  findObservablesByType,