-
Notifications
You must be signed in to change notification settings - Fork 33
/
common.cljc
599 lines (547 loc) · 29.1 KB
/
common.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
(ns ctim.schemas.common
(:refer-clojure :exclude [ref uri?])
(:require [clj-momo.lib.clj-time.coerce :refer [to-long]]
[clojure.set :refer [map-invert]]
#?(:clj [clojure.spec.alpha :as cs]
:cljs [cljs.spec.alpha :as cs])
[clojure.zip :as z]
[ctim.domain.id :as id]
[ctim.generators.id :as gen-id]
#?(:clj [ctim.lib.generators :as gen])
[ctim.lib.predicates :as pred]
[ctim.schemas.vocabularies :as v]
#?(:clj [flanders.core :as f :refer [def-map-type
def-enum-type
def-eq]]
:cljs [flanders.core :as f :refer-macros [def-map-type
def-enum-type
def-eq]])
[flanders.navigation :as fn]
[flanders.predicates :as fp]
[clojure.string :as str]))
(def ctim-schema-version "1.0.16")
(def-eq CTIMSchemaVersion ctim-schema-version)
(cs/def ::ctim-schema-version
#(re-matches #"\w+.\w+\.\w+" %))
(def SchemaVersion
(f/str
:description (str "A semantic version matching the CTIM version against which "
"this object should be valid.")
:default ctim-schema-version
:gen (cs/gen #{ctim-schema-version})
:spec (cs/and string? ::ctim-schema-version)))
(def PosInt
(f/int :description "Zero, or a positive integer"
:spec (cs/and integer?
(cs/or :zero zero?
:positive pos?))
:gen #?(:clj gen/pos-int
:cljs nil)))
(def Reference
(f/str :description "A URI leading to an entity"
:spec (cs/and string?
(pred/max-len 2048)
(cs/or :long-id :ctim.domain.id/long-id
:transient-id :ctim.domain.id/transient-id))
:gen gen-id/gen-url-id))
(defn ref
"Make a custom Reference"
[& opts]
(apply (partial assoc Reference) opts))
(defn ref-for-type
[type]
(ref :spec (cs/and string?
(id/long-id-of-type? type))
:gen (gen-id/gen-url-id-of-type type)))
(defn id-generator
"Generate an ID. Takes the clojure.zip location of an ID in the
DDL tree and tries to navigate up the tree to find a type value.
If the type cannot be found, a random type is used."
[loc]
(if-let [type (some-> loc z/up fp/entry z/up fp/map (fn/find-entry-value :type))]
(gen-id/gen-url-id-of-type type)
gen-id/gen-url-id))
(def ID
(f/str :description
(str "IDs are URIs, for example "
"`https://www.domain.com/ctia/judgement/judgement-de305d54-75b4-431b-adb2-eb6b9e546014` "
"for a [Judgement](judgement.md). This _ID_ type compares to the "
"STIX _id_ field. The optional STIX _idref_ field is not used.")
:spec (cs/and string?
(pred/max-len 2048)
(cs/or :long-id :ctim.domain.id/long-id
:transient-id :ctim.domain.id/transient-id))
:loc-gen id-generator))
#?(:clj
(defn uri? [str]
(if (> (count str) 0)
(try
(some? (java.net.URI/create str))
(catch Exception e
false))
false)))
(def URI
(f/str :description "A URI"
:spec (cs/and string?
(pred/max-len 2048)
#?(:clj uri?))
:gen #?(:clj gen/uri
:cljs nil)))
(cs/def ::recent-time (cs/inst-in #inst "2010" #inst "2025"))
(cs/def ::relevant-time (cs/inst-in #inst "1970" #inst "2525-01-01T00:00:00.000-00:01"))
(def Time
(f/inst :description (str "Schema definition for all date or timestamp values. "
"Serialized as a string, the field should follow the "
"rules of the [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) "
"standard.")
:name "ISO8601 Timestamp"
:spec ::relevant-time
:gen (cs/gen ::recent-time)))
(def ShortString
(f/str :description "String with at most 1024 characters"
:name "ShortString"
:spec (cs/and string? (pred/max-len 1024))
:gen #?(:clj (gen/string-max-len 1024)
:cljs nil)))
(def MedString
(f/str :description "String with at most 2048 characters"
:name "MedString"
:spec (cs/and string? (pred/max-len 2048))
:gen #?(:clj (gen/string-max-len 2048)
:cljs nil)))
(def LongString
(f/str :description "String with at most 5000 characters"
:name "LongString"
:spec (cs/and string? (pred/max-len 5000))
:gen #?(:clj (gen/string-max-len 5000)
:cljs nil)))
(def Markdown
(assoc LongString
:name "Markdown"
:description "Markdown string with at most 5000 characters"))
(def OpenVocab
(f/str :description (str "SHOULD be all lowercase (where lowercase is defined by the "
"locality conventions) and SHOULD use hyphens instead of "
"spaces or underscores as word separators.")
:reference "[Open Vocabulary](https://docs.google.com/document/d/1dIrh1Lp3KAjEMm8o2VzAmuV0Peu-jt9aAh1IHrjAroM/pub#h.u4s6d165nk3c)"
:spec (cs/and string?
(pred/max-len 1024)
#(= % (str/lower-case %))
#(re-matches #"[0-9a-z_\-]+" %))
:gen #?(:clj gen/open-vocab-chars
:cljs nil)))
(defn open-vocab
"Defines an OpenVocab type with a suggested vocabulary"
[values]
(assoc OpenVocab
:open? true
:values values))
(def default-tlp "green")
(def-enum-type TLP
#{"red" "amber" "green" "white"}
:default default-tlp
:description (str "TLP stands for [Traffic Light Protocol]"
"(https://www.us-cert.gov/tlp), which indicates precisely "
"how this resource is intended to be shared, replicated, "
"copied, etc."))
(def-map-type ExternalReference
(concat
(f/required-entries
(f/entry :source_name MedString
:description (str "The source within which the external-reference is defined "
"(system, registry, organization, etc.)")))
(f/optional-entries
(f/entry :description Markdown)
(f/entry :url URI
:description "A URL reference to an external resource")
(f/entry :hashes f/any-string-seq
:description "Specifies a dictionary of hashes for the contents of the url.")
(f/entry :external_id f/any-str
:description "An identifier for the external reference content.")))
:description (str "External references are used to describe pointers to information "
"represented outside of CTIM. For example, a Malware object could "
"use an external reference to indicate an ID for that malware in an "
"external database or a report could use references to represent source "
"material.")
:reference "[External Reference](https://docs.google.com/document/d/1dIrh1Lp3KAjEMm8o2VzAmuV0Peu-jt9aAh1IHrjAroM/pub#h.72bcfr3t79jx)")
(def base-entity-entries
(concat
(f/required-entries
(f/entry :id ID
:description "Globally unique URI identifying this object.")
(f/entry :type f/any-str)
(f/entry :schema_version SchemaVersion
:description "CTIM schema version for this entity"))
(f/optional-entries
(f/entry :revision PosInt
:description "A monotonically increasing revision, incremented each time the object is changed.")
(f/entry :external_ids f/any-string-seq)
(f/entry :external_references [ExternalReference]
:description (str "Specifies a list of external references which "
"refers to non-CTIM information. This property "
"is used to provide one or more URLs, "
"descriptions, or IDs to records in other systems."))
(f/entry :timestamp Time
:description "The time this object was created at, or last modified.")
(f/entry :language ShortString
:description "The human language this object is specified in.")
(f/entry :tlp TLP
:description "Specification for how, and to whom, this object can be shared."))))
(def base-new-entity-entries
"Base for New Entities, optionalizes ID and type and schema_version"
(concat
base-entity-entries
(f/optional-entries
(f/entry :id ID)
(f/entry :type f/any-str
:description "A valid entity type identifer")
(f/entry :schema_version CTIMSchemaVersion
:description "CTIM schema version for this entity"))))
(def describable-entity-entries
"These fields for describable entities"
(f/optional-entries
(f/entry :title ShortString
:description "A short title for this object, used as primary display and reference value")
(f/entry :description Markdown
:description "A description of object, which may be detailed.")
(f/entry :short_description MedString
:description "A single line, short summary of the object.")))
(def sourced-object-entries
"An object that must have a source"
[(f/entry :source MedString
:required? true)
(f/entry :source_uri URI
:required? false)])
(def sourcable-object-entries
"An object that MAY have a source"
(apply f/optional-entries
sourced-object-entries))
(def specification-types
#{"Judgement"
"ThreatBrain"
"SIOC"
"Snort"
"OpenIOC"})
(def-enum-type SpecificationType
specification-types
:description (str "Types of Indicator we support Currently only Judgement "
"indicators,which contain a list of Judgements "
"associated with this indicator."))
(def scope-wrapper-entries
(f/optional-entries
(f/entry :scope v/Scope)))
(def-map-type Contributor
(f/optional-entries
(f/entry :role f/any-str
:description "role played by this contributor")
(f/entry :name f/any-str
:description "name of this contributor")
(f/entry :email f/any-str
:description "email of this contributor")
(f/entry :phone f/any-str
:description "telephone number of this contributor")
(f/entry :organization f/any-str
:description "organization name of this contributor")
(f/entry :date Time
:description (str "description (bounding) of the timing of this "
"contributor's involvement"))
(f/entry :contribution_location f/any-str
:description (str "information describing the location at which the "
"contributory activity occured")))
:description "Person who contributed cyber observation data"
:reference "[ContributorType](http://stixproject.github.io/data-model/1.2/cyboxCommon/ContributorType/)")
(def-map-type RelatedIdentity
(concat
(f/required-entries
(f/entry :identity URI ;; Should this be a Reference or a URI?
:description "The reference (URI) of the related Identity object"))
(f/optional-entries
(f/entry :confidence v/HighMedLow
:description (str "Specifies the level of confidence in the assertion "
"of the relationship between the two objects"))
(f/entry :information_source f/any-str
:description (str "Specifies the source of the information about "
"the relationship between the two components"))
(f/entry :relationship f/any-str)))
:description "Describes a related Identity"
:reference "[RelatedIdentityType](http://stixproject.github.io/data-model/1.2/stixCommon/RelatedIdentityType/)")
(def-map-type Identity
(f/required-entries
(f/entry :description Markdown)
(f/entry :related_identities [RelatedIdentity]
:description (str "Identifies other entity Identities related to "
"this Identity")))
:description "Describes a person or an organization"
:reference "[IdentityType](http://stixproject.github.io/data-model/1.2/stixCommon/IdentityType/)")
(def-map-type Activity
(f/required-entries
(f/entry :date_time Time
:description "Specifies the date and time at which the activity occured")
(f/entry :description Markdown
:description "A description of the activity"))
:description "What happend, when?"
:reference "[ActivityType](http://stixproject.github.io/data-model/1.2/stixCommon/ActivityType/)")
(def-map-type Observable
(f/required-entries
(f/entry :value f/any-str)
(f/entry :type v/ObservableTypeIdentifier))
:description (str "A simple, atomic value which has a consistent identity, "
"and is stable enough to be attributed an intent or nature. "
"This is the classic 'indicator' which might appear in a "
"data feed of bad IPs, or bad Domains. These do not exist "
"as objects within the CTIA storage model, so you never "
"create an observable."))
(def-map-type ValidTime
(f/optional-entries
(f/entry :start_time Time
:description (str "If not present, the valid time position of the "
"indicator does not have an upper bound"))
(f/entry :end_time Time
:description (str "If end_time is not present, then the valid time "
"position of the object does not have an upper bound.")))
:spec (fn [{:keys [start_time end_time]}]
(if (and start_time end_time)
(<= (to-long start_time) (to-long end_time))
true))
:gen #?(:clj gen/valid-time
:cljs nil)
:description "Period of time when a cyber observation is valid."
:reference "[ValidTimeType](http://stixproject.github.io/data-model/1.2/indicator/ValidTimeType/)")
(def-map-type ObservedTime
[(f/entry :start_time Time
:description (str "Time of the observation. If the observation was "
"made over a period of time, than this field "
"indicates the start of that period"))
(f/entry :end_time Time
:required? false
:description (str "If the observation was made over a period of "
"time, than this field indicates the end of that "
"period"))]
:spec (fn [{:keys [start_time end_time]}]
(if end_time
(<= (to-long start_time) (to-long end_time))
true))
:gen #?(:clj gen/observed-time
:cljs nil)
:description (str "Period of time when a cyber observation is valid. "
"`start_time` must come before `end_time` (if specified).")
:reference "[ValidTimeType](http://stixproject.github.io/data-model/1.2/indicator/ValidTimeType/)")
;;Allowed disposition values are:
(def disposition-map
"Map of disposition numeric values to disposition names, as humans might use them."
{1 "Clean"
2 "Malicious"
3 "Suspicious"
4 "Common"
5 "Unknown"})
(def dispositions
(-> disposition-map vals set))
(def disposition-map-inverted
(map-invert disposition-map))
(def-enum-type DispositionNumber
(keys disposition-map)
:description "Numeric verdict identifiers")
(def-enum-type DispositionName
(vals disposition-map)
:description "String verdict identifiers")
(def-map-type KillChainPhase
;; Stix 2.0
[(f/entry :kill_chain_name (open-vocab #{v/kill-chain-name})
:description "The name of the kill chain.")
(f/entry :phase_name (open-vocab v/kill-chain-phases)
:description "The name of the phase in the kill chain.")]
:spec (fn [{:keys [kill_chain_name phase_name]}]
(if (= kill_chain_name v/kill-chain-name)
(contains? v/kill-chain-phases phase_name)
true))
:description (str "The kill-chain-phase represents a phase in a kill chain, "
"which describes the various phases an attacker may "
"undertake in order to achieve their objectives.")
:reference "[Kill Chain Phase](https://docs.google.com/document/d/1dIrh1Lp3KAjEMm8o2VzAmuV0Peu-jt9aAh1IHrjAroM/pub#h.i4tjv75ce50h)")
;; ## Relations
(def observable-relations-map
{"Allocated" "Specifies that this object allocated the related object."
"Allocated_By" "Specifies that this object was allocated by the related object."
"Attached_To" "Specifies that this object was attached to the related object"
"Bound" "Specifies that this object bound the related object."
"Bound_By" "Specifies that this object was bound by the related object."
"Characterized_By" "Specifies that the related object describes the properties of this object. This is most applicable in cases where the related object is a non-Artifact Object and this object is an Artifact Object."
"Characterizes" "Specifies that this object describes the properties of the related object. This is most applicable in cases where the related object is an Artifact Object and this object is a non-Artifact Object."
"Child_Of" "Specifies that this object is a child of the related object."
"Closed" "Specifies that this object closed the related object."
"Closed_By" "Specifies that this object was closed by the related object."
"Compressed" "Specifies that this object compressed the related object."
"Compressed_By" "Specifies that this object was compressed by the related object."
"Compressed_From" "Specifies that this object was compressed from the related object."
"Compressed_Into" "Specifies that this object was compressed into the related object."
"Connected_From" "Specifies that this object was connected to from the related object."
"Connected_To" "Specifies that this object connected to the related object."
"Contained_Within" "Specifies that this object is contained within the related object."
"Contains" "Specifies that this object contains the related object."
"Copied" "Specifies that this object copied the related object."
"Copied_By" "Specifies that this object was copied by the related object."
"Copied_From" "Specifies that this object was copied from the related object."
"Copied_To" "Specifies that this object was copied to the related object."
"Created_By" "Specifies that this object was created by the related object."
"Decoded" "Specifies that this object decoded the related object."
"Decoded_By" "Specifies that this object was decoded by the related object."
"Decompressed" "Specifies that this object decompressed the related object."
"Decompressed_By" "Specifies that this object was decompressed by the related object."
"Decrypted" "Specifies that this object decrypted the related object."
"Decrypted_By" "Specifies that this object was decrypted by the related object."
"Deleted" "Specifies that this object deleted the related object."
"Deleted_By" "Specifies that this object was deleted by the related object."
"Deleted_From" "Specifies that this object was deleted from the related object."
"Downloaded" "Specifies that this object downloaded the related object."
"Downloaded_By" "Specifies that this object was downloaded by the related object."
"Downloaded_From" "Specifies that this object was downloaded from the related object."
"Downloaded_To" "Specifies that this object downloaded the related object."
"Dropped" "Specifies that this object dropped the related object."
"Dropped_By" "Specifies that this object was dropped by the related object."
"Encoded" "Specifies that this object encoded the related object."
"Encoded_By" "Specifies that this object was encoded by the related object."
"Encrypted" "Specifies that this object encrypted the related object."
"Encrypted_By" "Specifies that this object was encrypted by the related object."
"Encrypted_From" "Specifies that this object was encrypted from the related object."
"Encrypted_To" "Specifies that this object was encrypted to the related object."
"Extracted_From" "Specifies that this object was extracted from the related object."
"FQDN_Of" "Specifies that this object is an FQDN of the related object."
"Freed" "Specifies that this object freed the related object."
"Freed_By" "Specifies that this object was freed by the related object."
"Hooked" "Specifies that this object hooked the related object."
"Hooked_By" "Specifies that this object was hooked by the related object."
"Initialized_By" "Specifies that this object was initialized by the related object."
"Initialized_To" "Specifies that this object was initialized to the related object."
"Injected" "Specifies that this object injected the related object."
"Injected_As" "Specifies that this object injected as the related object."
"Injected_By" "Specifies that this object was injected by the related object."
"Injected_Into" "Specifies that this object injected into the related object."
"Installed" "Specifies that this object installed the related object."
"Installed_By" "Specifies that this object was installed by the related object."
"Joined" "Specifies that this object joined the related object."
"Joined_By" "Specifies that this object was joined by the related object."
"Killed" "Specifies that this object killed the related object."
"Killed_By" "Specifies that this object was killed by the related object."
"Listened_On" "Specifies that this object listened on the related object."
"Listened_On_By" "Specifies that this object was listened on by the related object."
"Loaded_From" "Specifies that this object was loaded from the related object."
"Loaded_Into" "Specifies that this object loaded into the related object."
"Locked" "Specifies that this object locked the related object."
"Locked_By" "Specifies that this object was locked by the related object."
"Mapped_By" "Specifies that this object was mapped by the related object."
"Mapped_Into" "Specifies that this object was mapped into the related object."
"Merged" "Specifies that this object merged the related object."
"Merged_By" "Specifies that this object was merged by the related object."
"Modified_Properties_Of" "Specifies that this object modified the properties of the related object."
"Monitored" "Specifies that this object monitored the related object."
"Monitored_By" "Specifies that this object was monitored by the related object."
"Moved" "Specifies that this object moved the related object."
"Moved_By" "Specifies that this object was moved by the related object."
"Moved_From" "Specifies that this object was moved from the related object."
"Moved_To" "Specifies that this object was moved to the related object."
"Opened" "Specifies that this object opened the related object."
"Opened_By" "Specifies that this object was opened by the related object."
"Packed" "Specifies that this object packed the related object."
"Packed_By" "Specifies that this object was packed by the related object."
"Packed_From" "Specifies that this object was packed from the related object."
"Packed_Into" "Specifies that this object was packed into the related object."
"Parent_Of" "Specifies that this object is a parent of the related object."
"Paused" "Specifies that this object paused the related object."
"Paused_By" "Specifies that this object was paused by the related object."
"Previously_Contained" "Specifies that this object previously contained the related object."
"Properties_Modified_By" "Specifies that the properties of this object were modified by the related object."
"Properties_Queried" "Specifies that the object queried properties of the related object."
"Properties_Queried_By" "Specifies that the properties of this object were queried by the related object."
"Read_From" "Specifies that this object was read from the related object."
"Read_From_By" "Specifies that this object was read from by the related object."
"Received" "Specifies that this object received the related object."
"Received_By" "Specifies that this object was received by the related object."
"Received_From" "Specifies that this object was received from the related object."
"Received_Via_Upload" "Specifies that this object received the related object via upload."
"Redirects_To" "Specifies that this object redirects to the related object."
"Refers_To" "Specifies that this object refers to the related object"
"Related_To" "Specifies that this object is related to the related object."
"Renamed" "Specifies that this object renamed the related object."
"Renamed_By" "Specifies that this object was renamed by the related object."
"Renamed_From" "Specifies that this object was renamed from the related object."
"Renamed_To" "Specifies that this object was renamed to the related object."
"Resolved_To" "Specifies that this object was resolved to the related object."
"Resumed" "Specifies that this object resumed the related object."
"Resumed_By" "Specifies that this object was resumed by the related object."
"Root_Domain_Of" "Specifies that this object is the root domain of the related object."
"Searched_For" "Specifies that this object searched for the related object."
"Searched_For_By" "Specifies that this object was searched for by the related object."
"Sent" "Specifies that this object sent the related object."
"Sent_By" "Specifies that this object was sent by the related object."
"Sent_To" "Specifies that this object was sent to the related object."
"Sent_Via_Upload" "Specifies that this object sent the related object via upload."
"Set_From" "Specifies that this object was set from the related object."
"Set_To" "Specifies that this object was set to the related object."
"Sub-domain_Of" "Specifies that this object is a sub-domain of the related object."
"Supra-domain_Of" "Specifies that this object is a supra-domain of the related object."
"Suspended" "Specifies that this object suspended the related object."
"Suspended_By" "Specifies that this object was suspended by the related object."
"Unhooked" "Specifies that this object unhooked the related object."
"Unhooked_By" "Specifies that this object was unhooked by the related object."
"Unlocked" "Specifies that this object unlocked the related object."
"Unlocked_By" "Specifies that this object was unlocked by the related object."
"Unpacked" "Specifies that this object unpacked the related object."
"Unpacked_By" "Specifies that this object was unpacked by the related object."
"Uploaded" "Specifies that this object uploaded the related object."
"Uploaded_By" "Specifies that this object was uploaded by the related object."
"Uploaded_From" "Specifies that this object was uploaded from the related object."
"Uploaded_To" "Specifies that this object was uploaded to the related object."
"Used" "Specifies that this object used the related object."
"Used_By" "Specifies that this object was used by the related object."
"Values_Enumerated" "Specifies that the object enumerated values of the related object."
"Values_Enumerated_By" "Specifies that the values of the object were enumerated by the related object."
"Written_To_By" "Specifies that this object was written to by the related object."
"Wrote_To" "Specifies that this object wrote to the related object."
"Created" "Specifies that this object created the related object."})
(def relation-types
(set (keys observable-relations-map)))
(def-enum-type ObservableRelationType
relation-types
:open? true
:gen (cs/gen relation-types))
(def-map-type ObservedRelation
[(f/entry :origin f/any-str)
(f/entry :origin_uri URI
:required? false)
(f/entry :relation ObservableRelationType)
(f/entry :relation_info (f/map
[(f/entry f/any-keyword f/any)])
:required? false)
(f/entry :source Observable)
(f/entry :related Observable)]
:description "A relation inside a Sighting.")
(def-map-type ObservableRelation
(concat
[(f/entry :id f/any-num)
(f/entry :timestamp Time)]
(:entries ObservedRelation)))
(def-map-type IdentitySpecification
(concat
(f/required-entries
(f/entry :type v/Sensor)
(f/entry :observables [Observable])
(f/entry :observed_time ObservedTime))
(f/optional-entries
(f/entry :os f/any-str)))
:description "Describes the target of the sighting and contains identifying observables for the target.")
;; ---- helper fns used by schemas ----
(defn determine-disposition-id
"Takes a judgement and determines the disposition.
Defaults to 'Unknown' disposition (in case none is provided).
Throws an bad-request! if the provided disposition and
disposition_name do not match."
[{:keys [disposition disposition_name] :as judgement}]
(cond
(every? nil? [disposition disposition_name]) (get disposition-map-inverted "Unknown")
(nil? disposition) (get disposition-map-inverted disposition_name)
(nil? disposition_name) disposition
(= disposition (get disposition-map-inverted disposition_name)) disposition
:else (throw
(ex-info "Mismatching :dispostion and dispositon_name for judgement"
{:type ::disposition-missing
:judgement judgement}))))