calmlens 0.20.0 → 0.22.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.
- checksums.yaml +4 -4
- data/README.md +4 -1
- data/lib/calmlens/assets.rb +149 -110
- data/lib/calmlens/cdn.rb +197 -41
- data/lib/calmlens/error_codes.rb +100 -84
- data/lib/calmlens/errors.rb +11 -2
- data/lib/calmlens/events.rb +50 -1
- data/lib/calmlens/folders.rb +14 -9
- data/lib/calmlens/hash_lists.rb +29 -9
- data/lib/calmlens/internal.rb +9 -19
- data/lib/calmlens/lenses.rb +79 -6
- data/lib/calmlens/option_keys.rb +56 -26
- data/lib/calmlens/policies.rb +50 -18
- data/lib/calmlens/project_configuration.rb +113 -0
- data/lib/calmlens/resource.rb +24 -6
- data/lib/calmlens/server_client.rb +17 -6
- data/lib/calmlens/session.rb +29 -12
- data/lib/calmlens/testing/asset_filters.rb +39 -0
- data/lib/calmlens/testing/classification.rb +8 -2
- data/lib/calmlens/testing/fake_api.rb +950 -397
- data/lib/calmlens/testing/mock_decision.rb +6 -4
- data/lib/calmlens/testing/rsql.rb +245 -0
- data/lib/calmlens/testing/test_input_detections.rb +61 -0
- data/lib/calmlens/testing/test_input_scenario.rb +6 -2
- data/lib/calmlens/testing/test_inputs.rb +30 -10
- data/lib/calmlens/testing.rb +56 -15
- data/lib/calmlens/transform_rules.rb +1 -1
- data/lib/calmlens/upload_body.rb +85 -2
- data/lib/calmlens/upload_mime_types.rb +9 -1
- data/lib/calmlens/upload_tokens.rb +3 -3
- data/lib/calmlens/version.rb +1 -1
- data/lib/calmlens/webhooks.rb +58 -13
- data/lib/calmlens.rb +1 -0
- data/sig/calmlens.rbs +112 -13
- data/sig/error_codes.rbs +28 -20
- data/sig/qualifiers.rbs +2 -0
- data/sig/types.rbs +488 -190
- metadata +6 -2
data/sig/types.rbs
CHANGED
|
@@ -27,8 +27,10 @@ module CalmLens
|
|
|
27
27
|
|
|
28
28
|
# ---- Assets (Asset.ts) ----------------------------------------------------------------------
|
|
29
29
|
|
|
30
|
-
# Where the asset is in the pipeline
|
|
31
|
-
|
|
30
|
+
# Where the asset is in the pipeline: `queued` while it waits for its content (a multipart upload
|
|
31
|
+
# still receiving parts) or its turn, `processing`, then `completed` or `failed`. The asset is
|
|
32
|
+
# settled once it is `completed` or `failed`.
|
|
33
|
+
type asset_classification_status = "queued" | "processing" | "completed" | "failed"
|
|
32
34
|
# A moderation decision, which also decides delivery: served to anyone with access (`allowed`),
|
|
33
35
|
# served like `allowed` but marked so your app reduces its reach (`limited`), only through signed
|
|
34
36
|
# URLs or API keys (`age-restricted`), not served (`blocked`), or not served with the stored
|
|
@@ -41,7 +43,7 @@ module CalmLens
|
|
|
41
43
|
type asset_content_status = "temporary" | "stored" | "removed"
|
|
42
44
|
type asset_content_removal_reason = "policy" | "retention" | "requested" | "parent-removed" | "disposed"
|
|
43
45
|
# Why processing failed, while the classification status is `failed`.
|
|
44
|
-
type asset_classification_failure_reason = "file-too-large" | "duration-limit" | "resolution-limit" | "unsupported-format" | "undecodable-content" | "multiple-tracks" | "type-mismatch" | "free-
|
|
46
|
+
type asset_classification_failure_reason = "file-too-large" | "duration-limit" | "resolution-limit" | "unsupported-format" | "undecodable-content" | "multiple-tracks" | "type-mismatch" | "free-uploads-exhausted" | "media-limit" | "uploads-paused" | "too-many-items" | "processing-error"
|
|
45
47
|
type asset_type = "image" | "video" | "audio" | "plaintext-document" | "multimedia-document" | "website" | "file"
|
|
46
48
|
type asset_visibility = "public" | "private"
|
|
47
49
|
# FLAGGED_CONTENT_ACTION_SCHEMA in PolicyRule.ts.
|
|
@@ -66,7 +68,11 @@ module CalmLens
|
|
|
66
68
|
?ocr: { enabled: bool }?,
|
|
67
69
|
?person_detection: { enabled: bool }?,
|
|
68
70
|
?face_detection: { enabled: bool, ?age_estimation: bool }?,
|
|
69
|
-
?link_detection: { enabled: bool }
|
|
71
|
+
?link_detection: { enabled: bool }?,
|
|
72
|
+
# Preview. Prepares an adaptive stream (HLS) of audio or video, served at the `hls` resource and
|
|
73
|
+
# played by the `embed` resource; needs `keep_content_after_processing`. Left out, the project's
|
|
74
|
+
# streaming setting decides.
|
|
75
|
+
?streaming: { enabled: bool }?
|
|
70
76
|
}
|
|
71
77
|
type processing_options_input = {
|
|
72
78
|
?keep_content_after_processing: bool?,
|
|
@@ -76,20 +82,6 @@ module CalmLens
|
|
|
76
82
|
?features: processing_features_input?
|
|
77
83
|
}
|
|
78
84
|
|
|
79
|
-
type processing_features = {
|
|
80
|
-
?"ocr" => { "enabled" => bool }?,
|
|
81
|
-
?"personDetection" => { "enabled" => bool }?,
|
|
82
|
-
?"faceDetection" => { "enabled" => bool, ?"ageEstimation" => bool }?,
|
|
83
|
-
?"linkDetection" => { "enabled" => bool }?,
|
|
84
|
-
?"aiGeneratedDetection" => { "enabled" => bool }?
|
|
85
|
-
}
|
|
86
|
-
# The processing options an asset was uploaded with.
|
|
87
|
-
type processing_options = {
|
|
88
|
-
?"keepContentAfterProcessing" => bool?,
|
|
89
|
-
?"storeSensitiveMetadata" => bool?,
|
|
90
|
-
?"features" => processing_features?
|
|
91
|
-
}
|
|
92
|
-
|
|
93
85
|
type checksums = {
|
|
94
86
|
?"md5" => String?,
|
|
95
87
|
?"sha1" => String?,
|
|
@@ -97,20 +89,43 @@ module CalmLens
|
|
|
97
89
|
?"sha384" => String?,
|
|
98
90
|
?"sha512" => String?
|
|
99
91
|
}
|
|
100
|
-
#
|
|
101
|
-
|
|
92
|
+
# One rendition of an adaptive stream: `video` for a picture size (video renditions carry no sound;
|
|
93
|
+
# they play with the `audio` rendition), or `audio`. `bandwidth` is the peak bit rate in bits per
|
|
94
|
+
# second, counting the audio a video rendition plays with; `codecs` are RFC 6381 names.
|
|
95
|
+
type asset_hls_rendition = {
|
|
96
|
+
"kind" => "video" | "audio",
|
|
97
|
+
"width" => Integer?,
|
|
98
|
+
"height" => Integer?,
|
|
99
|
+
"bandwidth" => Integer,
|
|
100
|
+
"codecs" => String
|
|
101
|
+
}
|
|
102
|
+
# Preview. The adaptive stream of audio or video: HLS with fragmented MP4 (CMAF) segments, served
|
|
103
|
+
# at the CDN's `hls` resource (`hls/index.m3u8`) and played by its `embed` resource. Renditions list
|
|
104
|
+
# video from the largest down, then audio.
|
|
105
|
+
type asset_hls = { "renditions" => Array[asset_hls_rendition] }
|
|
106
|
+
type asset_hls_status = { "status" => String, "reason" => String? }
|
|
107
|
+
type asset_rendered_kind = "image" | "pdf" | "video" | "audio"
|
|
108
|
+
# The asset's one displayable file, as the CDN's `rendered` resource serves it: an image, a PDF, or
|
|
109
|
+
# browser-safe video or audio. `peaks` is an audio waveform's normalised peaks.
|
|
110
|
+
type asset_rendered = {
|
|
111
|
+
"kind" => asset_rendered_kind,
|
|
112
|
+
"format" => String,
|
|
113
|
+
"width" => Integer?,
|
|
114
|
+
"height" => Integer?,
|
|
115
|
+
?"peaks" => Array[Float]
|
|
116
|
+
}
|
|
117
|
+
# The still image that stands for the asset, as the CDN's `preview` resource serves it; the
|
|
118
|
+
# `placeholder` resource is its ThumbHash as a small blurred PNG.
|
|
119
|
+
type asset_preview = {
|
|
102
120
|
"width" => Integer?,
|
|
103
121
|
"height" => Integer?,
|
|
104
122
|
"thumbhash" => String?,
|
|
105
|
-
"averageColor" => String
|
|
106
|
-
"perceptualHash" => String?,
|
|
107
|
-
# How much detail `perceptualHash` captured, from 0 to 100; hashes below 50 match unrelated pictures.
|
|
108
|
-
"perceptualHashQuality" => Integer?
|
|
123
|
+
"averageColor" => String?
|
|
109
124
|
}
|
|
110
125
|
type safety_hold = { "placedAt" => Integer, "reason" => "suspected-illegal-content", ?"disposedAt" => Integer? }
|
|
111
126
|
# `type: "string"` carries the text in `content`; `type: "document"` stores it under `id`.
|
|
112
127
|
type extracted_text = { "type" => "string" | "document", ?"content" => String, ?"id" => String }
|
|
113
|
-
# Descriptive metadata embedded in an uploaded
|
|
128
|
+
# Descriptive metadata embedded in an uploaded file. `capturedAt` is ISO 8601, with a UTC offset
|
|
114
129
|
# only when the file records one. `digitalSourceType` is the IPTC code the file declares, such as
|
|
115
130
|
# `digitalCapture`. `containsLocation` says whether the uploaded file embedded GPS coordinates;
|
|
116
131
|
# `creator` and `location` are sensitive and recorded only when `storeSensitiveMetadata` is on.
|
|
@@ -129,48 +144,95 @@ module CalmLens
|
|
|
129
144
|
}
|
|
130
145
|
|
|
131
146
|
type asset_upload = { "status" => "uploading" | "completed", "updatedAt" => Integer?, "partsReceived" => Integer? }
|
|
147
|
+
# How many sections of long audio or video are analysed so far.
|
|
148
|
+
type classification_progress = { "completedSections" => Integer, "totalSections" => Integer }
|
|
132
149
|
type asset_classification = {
|
|
133
150
|
"status" => asset_classification_status,
|
|
134
151
|
# `null` unless `status` is `failed`.
|
|
135
152
|
"failureReason" => asset_classification_failure_reason?,
|
|
136
153
|
"updatedAt" => Integer?,
|
|
137
154
|
"completedAt" => Integer?,
|
|
155
|
+
# While long audio or video is analysed in sections and `status` is `processing`: how many of its
|
|
156
|
+
# sections are done. `nil` otherwise.
|
|
157
|
+
"progress" => classification_progress?,
|
|
158
|
+
# Whether the results came from one of the project's test inputs rather than analysing the
|
|
159
|
+
# content. Never use test results, such as age ranges, for real decisions.
|
|
160
|
+
"testInput" => bool,
|
|
138
161
|
"moderation" => asset_moderation,
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
?"
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
?"
|
|
148
|
-
|
|
162
|
+
# OCR's result for an image processed with OCR turned on; `nil` when OCR didn't run.
|
|
163
|
+
"ocr" => ocr_result?,
|
|
164
|
+
# Link detection's result for an image; `nil` when it didn't run.
|
|
165
|
+
"linkDetection" => link_detection_result?,
|
|
166
|
+
# Preview. Person and face detection's results; `nil` when they didn't run.
|
|
167
|
+
?"personDetection" => person_detection_result?,
|
|
168
|
+
?"faceDetection" => face_detection_result?,
|
|
169
|
+
# Preview. Where the asset's links lead when the project's policy acts on links; otherwise `nil`.
|
|
170
|
+
?"linkSafety" => link_safety_result?,
|
|
171
|
+
?"aiGeneratedDetection" => ai_generated_detection_result?
|
|
172
|
+
}
|
|
173
|
+
# Who made a review: a person (`user`, also when an assistant's key acts for one) or an API key
|
|
174
|
+
# (`api-key`), with the user's or API key's ID, `nil` only when it was not recorded.
|
|
175
|
+
type review_actor = { "type" => "user" | "api-key", "id" => String? }
|
|
149
176
|
type asset_review = {
|
|
150
177
|
"id" => String,
|
|
151
178
|
"decision" => asset_moderation_decision,
|
|
152
179
|
"note" => String?,
|
|
153
|
-
|
|
154
|
-
?"reviewerEmail" => String?,
|
|
180
|
+
"decidedBy" => review_actor,
|
|
155
181
|
"reviewedAt" => Integer,
|
|
156
|
-
|
|
182
|
+
# Whether the decision was applied to the asset; `false` for a review queue decision recorded
|
|
183
|
+
# without changing the asset's status.
|
|
184
|
+
"applied" => bool
|
|
185
|
+
}
|
|
186
|
+
# A stricter delivery decision in one region the project serves: the status in force there, the
|
|
187
|
+
# mandatory rule that sets it and the category whose findings it acted on, when it acts on one.
|
|
188
|
+
type regional_decision = {
|
|
189
|
+
"region" => String,
|
|
190
|
+
"status" => "limited" | "age-restricted" | "blocked" | "purged",
|
|
191
|
+
"rule" => String,
|
|
192
|
+
?"category" => String
|
|
193
|
+
}
|
|
194
|
+
# What decided the automated status: the `policy`'s categories, the asset's `children`, a
|
|
195
|
+
# `hash-list` match, a `mandatory-rule` or `link-safety`.
|
|
196
|
+
type moderation_source = "policy" | "children" | "hash-list" | "mandatory-rule" | "link-safety"
|
|
197
|
+
# The policy that made a decision: its ID, its revision then and, for a policy from a preset, the
|
|
198
|
+
# preset release it used.
|
|
199
|
+
type decision_policy = {
|
|
200
|
+
"id" => String,
|
|
201
|
+
"revision" => Integer,
|
|
202
|
+
"preset" => { "id" => String, "version" => Integer }?
|
|
203
|
+
}
|
|
204
|
+
# A review the human review queue is waiting for: when the asset joined it (Unix milliseconds),
|
|
205
|
+
# why, and the categories that made the decision uncertain.
|
|
206
|
+
type asset_pending_review = {
|
|
207
|
+
"requestedAt" => Integer,
|
|
208
|
+
"reason" => "sampled" | "uncertain",
|
|
209
|
+
"uncertainCategories" => Array[String]
|
|
157
210
|
}
|
|
158
|
-
|
|
159
|
-
|
|
211
|
+
# Every field but `status`, `manualReviews`, `flaggedCategories`, `regions` and `timeline` is `nil`
|
|
212
|
+
# until moderation decides; `pendingReview` is `nil` when no review is waiting.
|
|
160
213
|
type asset_moderation = {
|
|
161
|
-
?"testCategoryActions" => Hash[String, String],
|
|
162
|
-
?"testRegionalActions" => Array[test_regional_action],
|
|
163
214
|
"manualReviews" => Array[asset_review],
|
|
164
215
|
"status" => asset_moderation_status,
|
|
165
|
-
|
|
166
|
-
|
|
216
|
+
# The policy's original decision; a reviewer's decision can change `status` without changing it.
|
|
217
|
+
"automatedStatus" => asset_moderation_decision?,
|
|
218
|
+
# The policy that made the automated decision, as it was then.
|
|
219
|
+
"policy" => decision_policy?,
|
|
220
|
+
# The review the human review queue is waiting for, set with the automated decision that
|
|
221
|
+
# joined the queue; `nil` when no review is waiting.
|
|
222
|
+
"pendingReview" => asset_pending_review?,
|
|
223
|
+
"source" => moderation_source?,
|
|
224
|
+
# The mandatory rule that decided, when `source` is `mandatory-rule`; otherwise `nil`.
|
|
225
|
+
"rule" => String?,
|
|
167
226
|
"flaggedCategories" => Array[String], "regions" => Array[regional_decision],
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
# Preview. What the policy's link-safety section made of the asset's links;
|
|
227
|
+
"explanationComplete" => bool?,
|
|
228
|
+
"categories" => Hash[String, category_policy_score]?,
|
|
229
|
+
# Preview. What the policy's link-safety section made of the asset's links; `nil` when the
|
|
171
230
|
# policy doesn't act on links.
|
|
172
|
-
?"linkSafety" => link_safety_decision
|
|
173
|
-
|
|
231
|
+
?"linkSafety" => link_safety_decision?,
|
|
232
|
+
# An audio or video asset's findings timeline: how many segments `assets.list_timeline` lists.
|
|
233
|
+
# `null` for other assets and media without findings.
|
|
234
|
+
"timeline" => moderation_timeline?,
|
|
235
|
+
"raw" => moderation_raw?
|
|
174
236
|
}
|
|
175
237
|
# ASSET_CONTENT_SCHEMA. `format` is the MIME type.
|
|
176
238
|
type asset_content = {
|
|
@@ -182,17 +244,34 @@ module CalmLens
|
|
|
182
244
|
"extension" => String?,
|
|
183
245
|
"sizeInBytes" => Integer?,
|
|
184
246
|
"checksums" => checksums?,
|
|
185
|
-
|
|
247
|
+
# The file's own size, length and page count, where they apply; `null` when unknown.
|
|
248
|
+
"width" => Integer?,
|
|
249
|
+
"height" => Integer?,
|
|
250
|
+
"durationSeconds" => Float?,
|
|
251
|
+
"pageCount" => Integer?,
|
|
252
|
+
"perceptualHash" => String?,
|
|
253
|
+
# How much detail `perceptualHash` captured, from 0 to 100; hashes below 50 match unrelated pictures.
|
|
254
|
+
"perceptualHashQuality" => Integer?,
|
|
255
|
+
# Metadata embedded in the uploaded file; `null` when it declares none, once the content is
|
|
256
|
+
# removed and while the asset is held.
|
|
257
|
+
"metadata" => file_metadata?,
|
|
186
258
|
"extractedText" => extracted_text?,
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
"
|
|
259
|
+
# `null` until processing makes it, for text, spreadsheets and other files, once the content is
|
|
260
|
+
# removed and while the asset is held.
|
|
261
|
+
"rendered" => asset_rendered?,
|
|
262
|
+
# Preview. The adaptive stream once streaming has prepared one for audio or video; `nil` for
|
|
263
|
+
# other assets, until then, once the content is removed and while the asset is held.
|
|
264
|
+
"hls" => asset_hls?,
|
|
265
|
+
"hlsStatus" => asset_hls_status?,
|
|
266
|
+
"preview" => asset_preview?
|
|
190
267
|
}
|
|
191
268
|
|
|
192
269
|
type asset = {
|
|
193
270
|
"id" => String,
|
|
194
271
|
"projectId" => String,
|
|
195
272
|
?"parentId" => String?,
|
|
273
|
+
# The pages of the parent document a child shows, from 1; empty when unknown or not a child.
|
|
274
|
+
?"parentPages" => Array[Integer],
|
|
196
275
|
?"folderId" => String?,
|
|
197
276
|
?"uploadPresetId" => String?,
|
|
198
277
|
"createdAt" => Integer,
|
|
@@ -202,13 +281,14 @@ module CalmLens
|
|
|
202
281
|
?"externalId" => String?,
|
|
203
282
|
?"externalUrl" => String?,
|
|
204
283
|
"type" => asset_type,
|
|
205
|
-
|
|
284
|
+
# Empty when the asset has none.
|
|
285
|
+
"metadata" => Array[metadata_item],
|
|
206
286
|
?"authorId" => String?,
|
|
207
287
|
# The earlier posts CalmLens used; null once the content is removed.
|
|
208
288
|
?"context" => moderation_context?,
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
289
|
+
# Empty when the asset has none.
|
|
290
|
+
"tags" => Array[String],
|
|
291
|
+
"visibility" => asset_visibility,
|
|
212
292
|
"upload" => asset_upload,
|
|
213
293
|
"classification" => asset_classification,
|
|
214
294
|
"content" => asset_content
|
|
@@ -219,6 +299,9 @@ module CalmLens
|
|
|
219
299
|
type likelihood = "very-unlikely" | "unlikely" | "possible" | "likely" | "very-likely"
|
|
220
300
|
# not-supported: this processing path cannot assess the signal; unavailable: assessment failed.
|
|
221
301
|
type not_evaluated_reason = "not-supported" | "unavailable"
|
|
302
|
+
# A processing feature's reason, which adds in-children: a document's or website's images are each
|
|
303
|
+
# a child asset with its own result (`assets.list_children`).
|
|
304
|
+
type feature_not_evaluated_reason = not_evaluated_reason | "in-children"
|
|
222
305
|
type classification_category = "sexual" | "violence" | "self-harm" | "harassment" | "hate" | "criminal-activity"
|
|
223
306
|
|
|
224
307
|
# `status: "evaluated"` carries `someScore`, `likelihood` and optionally `allScore`;
|
|
@@ -234,14 +317,12 @@ module CalmLens
|
|
|
234
317
|
|
|
235
318
|
# `status: "evaluated"` or `"partial"` carries `likelihood` and `score`; `"not-evaluated"`
|
|
236
319
|
# carries `reason`.
|
|
237
|
-
type policy_condition_result = { "status" => "evaluated" | "not-evaluated", ?"score" => number, ?"reason" => not_evaluated_reason }
|
|
238
320
|
type category_report = {
|
|
239
321
|
"status" => "evaluated" | "partial" | "not-evaluated",
|
|
240
322
|
?"likelihood" => likelihood,
|
|
241
323
|
?"score" => number,
|
|
242
324
|
?"reason" => not_evaluated_reason,
|
|
243
|
-
?"qualifiers" => qualifier_results
|
|
244
|
-
?"policyConditions" => Hash[String, policy_condition_result]
|
|
325
|
+
?"qualifiers" => qualifier_results
|
|
245
326
|
}
|
|
246
327
|
type classification_categories = {
|
|
247
328
|
"sexual" => category_report,
|
|
@@ -253,46 +334,29 @@ module CalmLens
|
|
|
253
334
|
"personal-information" => category_report,
|
|
254
335
|
"profanity" => category_report
|
|
255
336
|
}
|
|
256
|
-
type classification_label = {
|
|
257
|
-
"description" => String,
|
|
258
|
-
"score" => number,
|
|
259
|
-
?"topicalityScore" => number?,
|
|
260
|
-
"likelihood" => likelihood,
|
|
261
|
-
?"knowledgeBaseId" => String?
|
|
262
|
-
}
|
|
263
337
|
type media_segment = {
|
|
264
338
|
"source" => "frame" | "speech" | "frame-text" | "clip",
|
|
265
339
|
"startSeconds" => number,
|
|
266
340
|
"endSeconds" => number,
|
|
267
341
|
"categories" => classification_categories
|
|
268
342
|
}
|
|
269
|
-
type media_report = {
|
|
270
|
-
"durationSeconds" => number,
|
|
271
|
-
?"frameIntervalSeconds" => number,
|
|
272
|
-
"sampledFrames" => Integer,
|
|
273
|
-
"audioTranscribed" => bool,
|
|
274
|
-
"segments" => Array[media_segment]
|
|
275
|
-
}
|
|
276
343
|
|
|
277
344
|
# Position and size as fractions of the image width and height, from 0 to 1.
|
|
278
345
|
type bounding_box = { "left" => number, "top" => number, "width" => number, "height" => number }
|
|
279
346
|
type age_range = { "low" => Integer, "high" => Integer }
|
|
280
347
|
type detected_person = { "box" => bounding_box, "confidence" => number }
|
|
281
348
|
type detected_face = { "box" => bounding_box, "confidence" => number, ?"ageRange" => age_range }
|
|
282
|
-
type processing_feature_stage = "beta" | "ga"
|
|
283
349
|
# `status: "evaluated"` carries `people`; `"not-evaluated"` carries `reason`.
|
|
284
350
|
type person_detection_result = {
|
|
285
351
|
"status" => "evaluated" | "not-evaluated",
|
|
286
|
-
"stage" => processing_feature_stage,
|
|
287
352
|
?"people" => Array[detected_person],
|
|
288
|
-
?"reason" =>
|
|
353
|
+
?"reason" => feature_not_evaluated_reason
|
|
289
354
|
}
|
|
290
355
|
# `status: "evaluated"` carries `faces`; `"not-evaluated"` carries `reason`.
|
|
291
356
|
type face_detection_result = {
|
|
292
357
|
"status" => "evaluated" | "not-evaluated",
|
|
293
|
-
"stage" => processing_feature_stage,
|
|
294
358
|
?"faces" => Array[detected_face],
|
|
295
|
-
?"reason" =>
|
|
359
|
+
?"reason" => feature_not_evaluated_reason
|
|
296
360
|
}
|
|
297
361
|
type detected_qr_code = { "value" => String, "box" => bounding_box }
|
|
298
362
|
# A web link found in a QR code or in the text OCR extracted.
|
|
@@ -300,10 +364,9 @@ module CalmLens
|
|
|
300
364
|
# `status: "evaluated"` carries `qrCodes` and `links`; `"not-evaluated"` carries `reason`.
|
|
301
365
|
type link_detection_result = {
|
|
302
366
|
"status" => "evaluated" | "not-evaluated",
|
|
303
|
-
"stage" => processing_feature_stage,
|
|
304
367
|
?"qrCodes" => Array[detected_qr_code],
|
|
305
368
|
?"links" => Array[detected_link],
|
|
306
|
-
?"reason" =>
|
|
369
|
+
?"reason" => feature_not_evaluated_reason
|
|
307
370
|
}
|
|
308
371
|
# Link safety (preview, LinkSafety.ts).
|
|
309
372
|
# What a link's destination is: `safe` when every reputation check passed, `adult` or `gambling`
|
|
@@ -338,7 +401,6 @@ module CalmLens
|
|
|
338
401
|
# Preview. `status: "evaluated"` carries `links`; `"not-evaluated"` carries `reason`.
|
|
339
402
|
type link_safety_result = {
|
|
340
403
|
"status" => "evaluated" | "not-evaluated",
|
|
341
|
-
"stage" => processing_feature_stage,
|
|
342
404
|
?"links" => Array[checked_link],
|
|
343
405
|
?"reason" => not_evaluated_reason
|
|
344
406
|
}
|
|
@@ -355,66 +417,71 @@ module CalmLens
|
|
|
355
417
|
},
|
|
356
418
|
?"offPlatformLinks" => { "action" => "limit" | "age-restrict" | "block", "allowedDomains" => Array[String] }
|
|
357
419
|
}
|
|
358
|
-
# Preview. The strongest action the asset's links take, the
|
|
359
|
-
#
|
|
420
|
+
# Preview. The strongest action the asset's links take, the checked links that take it, and the
|
|
421
|
+
# settings in force.
|
|
360
422
|
type link_safety_decision = {
|
|
361
423
|
"action" => link_safety_action,
|
|
362
|
-
"links" => Array[
|
|
424
|
+
"links" => Array[checked_link],
|
|
363
425
|
"settings" => link_safety_settings
|
|
364
426
|
}
|
|
365
427
|
type provenance_signal = { "kind" => "c2pa" | "iptc-digital-source-type" | "generator-metadata", "value" => String }
|
|
366
428
|
# `status: "evaluated"` carries `provenance` and `signals`; `"not-evaluated"` carries `reason`.
|
|
367
429
|
type ai_generated_detection_result = {
|
|
368
430
|
"status" => "evaluated" | "not-evaluated",
|
|
369
|
-
"stage" => processing_feature_stage,
|
|
370
431
|
?"provenance" => "ai-generated" | "ai-edited" | "unknown",
|
|
371
432
|
?"signals" => Array[provenance_signal],
|
|
372
|
-
?"reason" =>
|
|
433
|
+
?"reason" => feature_not_evaluated_reason
|
|
373
434
|
}
|
|
374
435
|
# Where OCR found text in an image, and whether it is personal information.
|
|
375
436
|
type text_region = { "box" => bounding_box, "personalInformation" => bool }
|
|
376
|
-
#
|
|
377
|
-
#
|
|
378
|
-
type
|
|
379
|
-
|
|
380
|
-
?"
|
|
381
|
-
?"
|
|
382
|
-
?"linkSafety" => link_safety_result,
|
|
383
|
-
?"aiGeneratedDetection" => ai_generated_detection_result
|
|
437
|
+
# `status: "evaluated"` carries `textRegions`, where OCR found text (redaction transforms blur
|
|
438
|
+
# these regions); `"not-evaluated"` carries `reason`. The text itself is `content.extractedText`.
|
|
439
|
+
type ocr_result = {
|
|
440
|
+
"status" => "evaluated" | "not-evaluated",
|
|
441
|
+
?"textRegions" => Array[text_region],
|
|
442
|
+
?"reason" => feature_not_evaluated_reason
|
|
384
443
|
}
|
|
385
444
|
|
|
386
445
|
# How strongly each assessed category meets the policy and what the policy does with it.
|
|
387
446
|
type policy_rule_snapshot = {
|
|
388
447
|
"when" => Array[String], "action" => flagged_content_action,
|
|
389
|
-
?"name" => String, ?"
|
|
448
|
+
?"name" => String, ?"unless" => Array[String]
|
|
390
449
|
}
|
|
391
|
-
|
|
450
|
+
# What decided a category's action: its `default` action, a policy score `below-threshold`, or the
|
|
451
|
+
# `allowance` or `restriction` rules listed by `indexes` (at least one, the decisive rule first).
|
|
452
|
+
type category_policy_source = { "kind" => "default" | "below-threshold" } |
|
|
453
|
+
{ "kind" => "allowance" | "restriction", "indexes" => Array[Integer], "conditionScore" => Float }
|
|
392
454
|
type category_policy_settings_snapshot = {
|
|
393
|
-
"
|
|
455
|
+
"action" => flagged_content_action,
|
|
394
456
|
"allowances" => Array[policy_rule_snapshot], "restrictions" => Array[policy_rule_snapshot]
|
|
395
457
|
}
|
|
396
458
|
type category_policy_score = {
|
|
397
459
|
"score" => number, "action" => flagged_content_action,
|
|
398
460
|
?"source" => category_policy_source, ?"settings" => category_policy_settings_snapshot
|
|
399
461
|
}
|
|
462
|
+
type moderation_timeline = { "segmentCount" => Integer }
|
|
400
463
|
type moderation_raw = {
|
|
401
464
|
"categories" => classification_categories,
|
|
402
|
-
|
|
403
|
-
|
|
465
|
+
# Empty when the image matched no hash list entry.
|
|
466
|
+
"hashMatches" => Array[hash_match]
|
|
404
467
|
}
|
|
405
468
|
|
|
406
469
|
# ---- Pages and search (Page.ts, AssetSearch.ts) --------------------------------------------
|
|
407
470
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
type
|
|
471
|
+
# A list's sort: comma-separated fields, each ascending unless prefixed with `-`, such as
|
|
472
|
+
# `-createdAt,id`.
|
|
473
|
+
type sort = String
|
|
411
474
|
|
|
412
475
|
type asset_page = {
|
|
413
476
|
"items" => Array[asset],
|
|
414
477
|
"hasMore" => bool,
|
|
415
|
-
"nextCursor" => String
|
|
416
|
-
|
|
417
|
-
|
|
478
|
+
"nextCursor" => String?
|
|
479
|
+
}
|
|
480
|
+
# One page of an audio or video asset's findings timeline, in time order.
|
|
481
|
+
type asset_timeline_page = {
|
|
482
|
+
"items" => Array[media_segment],
|
|
483
|
+
"hasMore" => bool,
|
|
484
|
+
"nextCursor" => String?
|
|
418
485
|
}
|
|
419
486
|
|
|
420
487
|
type asset_search_mode = "keyword" | "semantic" | "hybrid"
|
|
@@ -428,8 +495,32 @@ module CalmLens
|
|
|
428
495
|
}
|
|
429
496
|
|
|
430
497
|
type asset_batch_operation = "delete" | "remove-content"
|
|
431
|
-
|
|
432
|
-
type
|
|
498
|
+
# `batchId` is named by the `batch-id` fact of the events the batch causes.
|
|
499
|
+
type batch_assets_response = { "batchId" => String, "status" => "queued", "assetCount" => Integer }
|
|
500
|
+
# A signed asset URL, with any resource, selector and viewer claims appended, and when it expires
|
|
501
|
+
# (milliseconds since the Unix epoch).
|
|
502
|
+
type signed_asset_url = { "url" => String, "expiresAt" => Integer }
|
|
503
|
+
# Whether the viewer an asset URL's claims describe can see the content now.
|
|
504
|
+
type asset_availability = "available" | "age-restricted" | "unavailable"
|
|
505
|
+
# ASSET_INFO_SCHEMA: what the CDN's `info` resource returns, an allowlist of the asset's public
|
|
506
|
+
# fields plus the viewer's `availability`.
|
|
507
|
+
type asset_info = {
|
|
508
|
+
"id" => String,
|
|
509
|
+
"projectId" => String,
|
|
510
|
+
"type" => asset_type,
|
|
511
|
+
"externalUrl" => String?,
|
|
512
|
+
"content" => {
|
|
513
|
+
"format" => String?,
|
|
514
|
+
"width" => Integer?,
|
|
515
|
+
"height" => Integer?,
|
|
516
|
+
"durationSeconds" => Float?,
|
|
517
|
+
"pageCount" => Integer?,
|
|
518
|
+
"rendered" => asset_rendered?,
|
|
519
|
+
"preview" => asset_preview?,
|
|
520
|
+
"hls" => asset_hls?
|
|
521
|
+
},
|
|
522
|
+
"availability" => asset_availability
|
|
523
|
+
}
|
|
433
524
|
|
|
434
525
|
# ---- Transforms and lenses (AssetTransform.ts, Lens.ts) -------------------------------------
|
|
435
526
|
|
|
@@ -544,20 +635,18 @@ module CalmLens
|
|
|
544
635
|
type transform_input = String | image_transform_options_input
|
|
545
636
|
|
|
546
637
|
type lens_type = "image" | "video" | "audio" | "document" | "website"
|
|
547
|
-
# ENSURE_LENS_BODY_SCHEMA
|
|
638
|
+
# ENSURE_LENS_BODY_SCHEMA: a lens definition, which the CDN serves once it is saved.
|
|
548
639
|
type lens_definition = {
|
|
549
640
|
identifier: String,
|
|
550
641
|
name: String,
|
|
551
642
|
type: lens_type,
|
|
552
643
|
active: bool,
|
|
553
644
|
?description: String?,
|
|
554
|
-
?version: Integer,
|
|
555
645
|
?transform: image_transform_options_input?
|
|
556
646
|
}
|
|
557
647
|
type lens = {
|
|
558
648
|
"id" => String,
|
|
559
649
|
?"projectId" => String?,
|
|
560
|
-
"version" => Integer,
|
|
561
650
|
"identifier" => String,
|
|
562
651
|
"name" => String,
|
|
563
652
|
?"description" => String?,
|
|
@@ -567,6 +656,86 @@ module CalmLens
|
|
|
567
656
|
"createdAt" => Integer,
|
|
568
657
|
?"updatedAt" => Integer
|
|
569
658
|
}
|
|
659
|
+
type lens_page = {
|
|
660
|
+
"items" => Array[lens],
|
|
661
|
+
"hasMore" => bool,
|
|
662
|
+
"nextCursor" => String?
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
# ---- Configuration as data (UploadPreset.ts, ProjectConfiguration.ts) --------------------------
|
|
666
|
+
|
|
667
|
+
type upload_preset_access = "token" | "anyone"
|
|
668
|
+
# An upload preset's processing options, as the API returns them.
|
|
669
|
+
type upload_preset_processing_options = {
|
|
670
|
+
?"keepContentAfterProcessing" => bool?,
|
|
671
|
+
?"storeSensitiveMetadata" => bool?,
|
|
672
|
+
?"features" => {
|
|
673
|
+
?"ocr" => { "enabled" => bool }?,
|
|
674
|
+
?"personDetection" => { "enabled" => bool }?,
|
|
675
|
+
?"faceDetection" => { "enabled" => bool, ?"ageEstimation" => bool? }?,
|
|
676
|
+
?"linkDetection" => { "enabled" => bool }?,
|
|
677
|
+
?"streaming" => { "enabled" => bool }?
|
|
678
|
+
}?
|
|
679
|
+
}
|
|
680
|
+
# The rules for uploads made from browsers and apps. `key` is unique in its project; `revision`
|
|
681
|
+
# counts changes, starting at 1. Send it back with a change.
|
|
682
|
+
type upload_preset = {
|
|
683
|
+
"id" => String,
|
|
684
|
+
"projectId" => String,
|
|
685
|
+
?"createdByUserId" => String?,
|
|
686
|
+
"key" => String,
|
|
687
|
+
"revision" => Integer,
|
|
688
|
+
"name" => String,
|
|
689
|
+
"access" => upload_preset_access,
|
|
690
|
+
"enabled" => bool,
|
|
691
|
+
?"allowedContentTypes" => Array[String]?,
|
|
692
|
+
?"maxSizeInBytes" => Integer?,
|
|
693
|
+
?"folderId" => String?,
|
|
694
|
+
?"policyId" => String?,
|
|
695
|
+
"visibility" => asset_visibility,
|
|
696
|
+
?"processingOptions" => upload_preset_processing_options?,
|
|
697
|
+
"revealDecision" => bool,
|
|
698
|
+
?"dailyUploadLimit" => Integer?,
|
|
699
|
+
?"allowedOrigins" => Array[String]?,
|
|
700
|
+
"createdAt" => Integer,
|
|
701
|
+
"updatedAt" => Integer
|
|
702
|
+
}
|
|
703
|
+
type upload_preset_page = { "items" => Array[upload_preset], "hasMore" => bool, "nextCursor" => String? }
|
|
704
|
+
type ensure_upload_presets_response = { "uploadPresets" => Array[upload_preset] }
|
|
705
|
+
|
|
706
|
+
type remote_url_rule = { "mode" => "allow" | "deny", "domains" => Array[String] }
|
|
707
|
+
type human_review_settings = {
|
|
708
|
+
"allowedSamplePercent" => number,
|
|
709
|
+
"restrictedSamplePercent" => number,
|
|
710
|
+
"uncertaintyMarginPercent" => number,
|
|
711
|
+
"reviewMissingEvidence" => bool
|
|
712
|
+
}
|
|
713
|
+
type public_project_settings = {
|
|
714
|
+
"optOutJurisdictions" => Array[String],
|
|
715
|
+
"blockUnmoderatedAssets" => bool,
|
|
716
|
+
"storeSensitiveMetadata" => bool,
|
|
717
|
+
"streamingEnabled" => bool,
|
|
718
|
+
"aiMediaSearchEnabled" => bool,
|
|
719
|
+
"remoteUrlRule" => remote_url_rule?,
|
|
720
|
+
"websiteSubmissionsPerMinute" => Integer?,
|
|
721
|
+
"humanReview" => human_review_settings
|
|
722
|
+
}
|
|
723
|
+
# The project's settings, with defaults filled in. `revision` counts changes to the settings and
|
|
724
|
+
# metadata fields, starting at 1. Send it back with a change.
|
|
725
|
+
type project_settings_resource = { "projectId" => String, "revision" => Integer, "settings" => public_project_settings }
|
|
726
|
+
|
|
727
|
+
type metadata_field_type = "string" | "number" | "boolean" | "date" | "url"
|
|
728
|
+
type metadata_field_icon = "tag" | "hash" | "user" | "folder" | "layers" | "photo" | "link"
|
|
729
|
+
# A metadata field the portal shows and filters by. `color` is `#rrggbb`.
|
|
730
|
+
type metadata_field = {
|
|
731
|
+
"id" => String,
|
|
732
|
+
"title" => String,
|
|
733
|
+
?"description" => String,
|
|
734
|
+
"type" => metadata_field_type,
|
|
735
|
+
"icon" => metadata_field_icon,
|
|
736
|
+
"color" => String
|
|
737
|
+
}
|
|
738
|
+
type metadata_fields_resource = { "projectId" => String, "revision" => Integer, "fields" => Array[metadata_field] }
|
|
570
739
|
|
|
571
740
|
# ---- Folders (Folder.ts) --------------------------------------------------------------------
|
|
572
741
|
|
|
@@ -597,8 +766,8 @@ module CalmLens
|
|
|
597
766
|
# picture); `action` is `block` when the match was close enough for a block list to block.
|
|
598
767
|
type hash_match = {
|
|
599
768
|
"source" => "hash-list",
|
|
600
|
-
"
|
|
601
|
-
"
|
|
769
|
+
"hashListId" => String,
|
|
770
|
+
"hashListEntryId" => String,
|
|
602
771
|
"distance" => Integer,
|
|
603
772
|
"action" => hash_list_action
|
|
604
773
|
}
|
|
@@ -610,73 +779,85 @@ module CalmLens
|
|
|
610
779
|
"hash" => String,
|
|
611
780
|
"quality" => number?,
|
|
612
781
|
?"label" => String?,
|
|
613
|
-
|
|
782
|
+
# The asset the hash was taken from, when the entry was added from an asset.
|
|
783
|
+
?"assetId" => String?,
|
|
614
784
|
"createdAt" => Integer
|
|
615
785
|
}
|
|
616
786
|
|
|
617
787
|
type hash_list_entry_page = {
|
|
618
788
|
"items" => Array[hash_list_entry],
|
|
619
789
|
"hasMore" => bool,
|
|
620
|
-
"nextCursor" => String
|
|
621
|
-
"pageSize" => Integer,
|
|
622
|
-
"ordering" => Array[order]
|
|
790
|
+
"nextCursor" => String?
|
|
623
791
|
}
|
|
624
792
|
|
|
625
793
|
# ---- Policies (Policy.ts) ---------------------------------------------------------------------
|
|
626
794
|
|
|
627
795
|
type policy_preset_id = "general-community" | "children-platform" | "education-support" | "wholesome-community"
|
|
628
|
-
# What a policy does with one category: `action` when its policy score reaches 0.5
|
|
629
|
-
#
|
|
630
|
-
#
|
|
796
|
+
# What a policy does with one category: `action` when its policy score reaches 0.5, allowances
|
|
797
|
+
# that let covered content through or act on it more softly, and restrictions, which outweigh
|
|
798
|
+
# allowances.
|
|
631
799
|
type category_policy_settings = {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
800
|
+
"action" => flagged_content_action,
|
|
801
|
+
"allowances" => Array[policy_rule_snapshot],
|
|
802
|
+
"restrictions" => Array[policy_rule_snapshot]
|
|
635
803
|
}
|
|
636
|
-
# Settings
|
|
804
|
+
# Settings for every category, and optionally link safety.
|
|
637
805
|
type policy_settings = {
|
|
638
|
-
"categorySettings" =>
|
|
806
|
+
"categorySettings" => {
|
|
807
|
+
"sexual" => category_policy_settings,
|
|
808
|
+
"violence" => category_policy_settings,
|
|
809
|
+
"self-harm" => category_policy_settings,
|
|
810
|
+
"harassment" => category_policy_settings,
|
|
811
|
+
"hate" => category_policy_settings,
|
|
812
|
+
"criminal-activity" => category_policy_settings,
|
|
813
|
+
"personal-information" => category_policy_settings,
|
|
814
|
+
"profanity" => category_policy_settings
|
|
815
|
+
},
|
|
639
816
|
?"linkSafety" => link_safety_settings
|
|
640
817
|
}
|
|
818
|
+
# How a policy relates to its preset: `live` follows the latest release (the organisation's own
|
|
819
|
+
# preset policy with automatic updates on), `pinned` is the organisation's own preset policy held
|
|
820
|
+
# at one release, and `copy` is a policy made from a preset.
|
|
821
|
+
type policy_preset_mode = "live" | "pinned" | "copy"
|
|
641
822
|
# Where a policy started from a built-in preset. `version` is the release it is pinned to,
|
|
642
|
-
# `latestVersion` the newest
|
|
643
|
-
# rather than a copy made from it. An organisation has at most one per preset, and only it can
|
|
644
|
-
# follow automatic updates.
|
|
823
|
+
# `latestVersion` the newest.
|
|
645
824
|
type policy_preset_origin = {
|
|
646
825
|
"id" => policy_preset_id,
|
|
647
826
|
"version" => Integer,
|
|
648
827
|
"latestVersion" => Integer,
|
|
649
|
-
"
|
|
828
|
+
"mode" => policy_preset_mode
|
|
650
829
|
}
|
|
651
|
-
# A moderation policy. Policies belong to the
|
|
652
|
-
#
|
|
830
|
+
# A moderation policy. Policies belong to the organisation and its projects share them. Send
|
|
831
|
+
# `revision` with each change; a policy changed since is refused with `policy/revision-conflict`.
|
|
653
832
|
type policy = {
|
|
654
833
|
"id" => String,
|
|
655
834
|
"name" => String,
|
|
656
835
|
"description" => String,
|
|
657
836
|
"settings" => policy_settings,
|
|
658
837
|
"revision" => Integer,
|
|
659
|
-
"automaticUpdates" => bool,
|
|
660
838
|
"preset" => policy_preset_origin?,
|
|
661
839
|
"projectIds" => Array[String],
|
|
662
840
|
"createdAt" => Integer,
|
|
663
841
|
"updatedAt" => Integer
|
|
664
842
|
}
|
|
665
|
-
#
|
|
666
|
-
type
|
|
843
|
+
# A page of the organisation's policies, oldest first unless `sort` says otherwise.
|
|
844
|
+
type policy_page = { "items" => Array[policy], "hasMore" => bool, "nextCursor" => String? }
|
|
667
845
|
|
|
668
846
|
# ---- Events and webhooks (Event.ts, EventCatalog.ts, WebhookPayload.ts) ----------------------
|
|
669
847
|
|
|
670
848
|
# EVENT_TYPES in EventCatalog.ts. Ignore types your code does not handle. Webhook, Slack and email
|
|
671
849
|
# deliveries and the public events feed leave out facts that hold personal or account data.
|
|
672
|
-
type event_type = "asset.uploaded" | "asset.classified" | "asset.allowed" | "asset.limited" |
|
|
673
|
-
"asset.age-restricted" | "asset.blocked" | "asset.purged" | "asset.failed" | "asset.
|
|
674
|
-
"asset.
|
|
850
|
+
type event_type = "asset.uploaded" | "asset.classified" | "asset.region-restricted" | "asset.allowed" | "asset.limited" |
|
|
851
|
+
"asset.age-restricted" | "asset.blocked" | "asset.purged" | "asset.failed" | "asset.progress-updated" |
|
|
852
|
+
"asset.deleted" | "asset.content-removed" | "asset.retried" | "asset.rerun-requested" | "asset.review-requested" |
|
|
853
|
+
"asset.hash-matched" | "asset.link-flagged" | "usage.free-uploads-exhausted" | "usage.uploads-paused" |
|
|
675
854
|
"upload-preset.daily-limit-reached" | "project.member-joined" | "project.member-removed" |
|
|
676
|
-
"project.member-
|
|
677
|
-
"
|
|
855
|
+
"project.member-left" | "project.member-role-changed" | "project.invitation-sent" |
|
|
856
|
+
"project.transferred" | "api-key.created" | "api-key.revoked" | "api-key.deleted" |
|
|
857
|
+
"connector.disabled" | "appeal.submitted" | "appeal.resolved"
|
|
678
858
|
type event_severity = "low" | "high"
|
|
679
|
-
# A registered fact's value: text, an enum value, a count
|
|
859
|
+
# A registered fact's value: text, an enum value, a count or a time in milliseconds (such as
|
|
860
|
+
# `resumes-at`), a list of enum values (such as `flagged-categories`), or null.
|
|
680
861
|
# Test sends carry `{ "key" => "test", "value" => true }`.
|
|
681
862
|
type event_fact_value = String | Integer | bool | Array[String] | nil
|
|
682
863
|
# A registered fact. `key` is a kebab-case key registered for the event's type, such as
|
|
@@ -690,18 +871,31 @@ module CalmLens
|
|
|
690
871
|
?"uploadPresetId" => String?,
|
|
691
872
|
?"externalId" => String?,
|
|
692
873
|
"upload" => { "status" => "uploading" | "completed" },
|
|
693
|
-
|
|
874
|
+
# `testInput`: whether the results came from one of the project's test inputs rather than
|
|
875
|
+
# analysing the content. Never use test results, such as age ranges, for real decisions.
|
|
876
|
+
"classification" => { "status" => asset_classification_status, "testInput" => bool,
|
|
877
|
+
"moderation" => { "status" => asset_moderation_status } },
|
|
694
878
|
"content" => { "status" => asset_content_status }
|
|
695
879
|
}
|
|
880
|
+
# Who caused an event: a `user` (a person in the portal, or an assistant acting for one), an
|
|
881
|
+
# `api-key`, `automated` moderation or CalmLens itself (`system`). `id` is the user's or API key's
|
|
882
|
+
# ID, nil for `automated` and `system` and when it was not recorded.
|
|
883
|
+
type actor_type = "user" | "api-key" | "automated" | "system"
|
|
884
|
+
type actor = { "type" => actor_type, "id" => String? }
|
|
885
|
+
type actor_input = { type: actor_type, id: String? }
|
|
886
|
+
|
|
696
887
|
# An `events.list` item, and the body of its webhook delivery.
|
|
697
888
|
type event = {
|
|
698
889
|
"id" => String,
|
|
699
890
|
"projectId" => String,
|
|
891
|
+
"actor" => actor,
|
|
700
892
|
"type" => event_type,
|
|
701
893
|
"severity" => event_severity,
|
|
702
894
|
"title" => String,
|
|
703
895
|
"description" => String?,
|
|
704
896
|
"assetId" => String?,
|
|
897
|
+
# Increases with each event about the same asset; nil for events not about an asset.
|
|
898
|
+
"assetSequence" => Integer?,
|
|
705
899
|
"asset" => event_asset?,
|
|
706
900
|
"facts" => Array[event_fact],
|
|
707
901
|
"createdAt" => Integer
|
|
@@ -726,23 +920,31 @@ module CalmLens
|
|
|
726
920
|
type asset_search_options = {
|
|
727
921
|
query: String,
|
|
728
922
|
?mode: asset_search_mode,
|
|
729
|
-
|
|
923
|
+
# How many results, 1 to 20 (default 10).
|
|
924
|
+
?page_size: Integer,
|
|
730
925
|
?request_options: request_options
|
|
731
926
|
}
|
|
732
927
|
type list_assets_options = {
|
|
733
928
|
?cursor: String,
|
|
734
929
|
?page_size: Integer,
|
|
735
|
-
|
|
736
|
-
|
|
930
|
+
# `createdAt` and `id`; `-createdAt` by default.
|
|
931
|
+
?sort: sort,
|
|
932
|
+
# An RSQL filter such as `classification.moderation.status==allowed`; `folderId==fldr_…` lists
|
|
933
|
+
# one folder's assets.
|
|
737
934
|
?filter: String?,
|
|
738
|
-
?folder_id: String?,
|
|
739
935
|
?request_options: request_options
|
|
740
936
|
}
|
|
741
937
|
type list_asset_children_options = {
|
|
742
938
|
asset_id: String,
|
|
743
939
|
?cursor: String,
|
|
744
940
|
?page_size: Integer,
|
|
745
|
-
?
|
|
941
|
+
?sort: sort,
|
|
942
|
+
?request_options: request_options
|
|
943
|
+
}
|
|
944
|
+
type list_asset_timeline_options = {
|
|
945
|
+
asset_id: String,
|
|
946
|
+
?cursor: String,
|
|
947
|
+
?page_size: Integer,
|
|
746
948
|
?request_options: request_options
|
|
747
949
|
}
|
|
748
950
|
type update_asset_options = {
|
|
@@ -767,15 +969,21 @@ module CalmLens
|
|
|
767
969
|
?confirm_purge: bool,
|
|
768
970
|
?request_options: request_options
|
|
769
971
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
#
|
|
774
|
-
?
|
|
775
|
-
?
|
|
776
|
-
|
|
972
|
+
# The resources beneath an asset URL ({CalmLens::CDN::RESOURCES}).
|
|
973
|
+
type cdn_resource = "original" | "rendered" | "preview" | "hls" | "embed" | "placeholder" | "info"
|
|
974
|
+
type sign_asset_url_options = {
|
|
975
|
+
# Exactly one of `asset_id` and `external_id`.
|
|
976
|
+
?asset_id: String,
|
|
977
|
+
?external_id: String,
|
|
978
|
+
?project_id: String,
|
|
979
|
+
# Whole seconds from 1 to 86400; 900 by default.
|
|
980
|
+
?expires_in: Integer,
|
|
981
|
+
# Whether the URL also serves `original`; false by default.
|
|
982
|
+
?original: bool,
|
|
983
|
+
?resource: cdn_resource,
|
|
777
984
|
?lens: String,
|
|
778
985
|
?transform: transform_input,
|
|
986
|
+
?viewer_claims: viewer_claims,
|
|
779
987
|
?request_options: request_options
|
|
780
988
|
}
|
|
781
989
|
|
|
@@ -802,6 +1010,8 @@ module CalmLens
|
|
|
802
1010
|
?description: String?,
|
|
803
1011
|
?visibility: asset_visibility?,
|
|
804
1012
|
?metadata: Array[metadata_item_input]?,
|
|
1013
|
+
# Tags for the asset, such as `['catalogue', 'backpacks']`.
|
|
1014
|
+
?tags: Array[String]?,
|
|
805
1015
|
?author_id: String,
|
|
806
1016
|
?context: moderation_context_input,
|
|
807
1017
|
?external_id: String?,
|
|
@@ -818,6 +1028,8 @@ module CalmLens
|
|
|
818
1028
|
?description: String?,
|
|
819
1029
|
?visibility: asset_visibility?,
|
|
820
1030
|
?metadata: Array[metadata_item_input]?,
|
|
1031
|
+
# Tags for the asset, such as `['catalogue', 'backpacks']`.
|
|
1032
|
+
?tags: Array[String]?,
|
|
821
1033
|
?author_id: String,
|
|
822
1034
|
?context: moderation_context_input,
|
|
823
1035
|
?external_id: String?,
|
|
@@ -833,6 +1045,8 @@ module CalmLens
|
|
|
833
1045
|
?description: String?,
|
|
834
1046
|
?visibility: asset_visibility?,
|
|
835
1047
|
?metadata: Array[metadata_item_input]?,
|
|
1048
|
+
# Tags for the asset, such as `['catalogue', 'backpacks']`.
|
|
1049
|
+
?tags: Array[String]?,
|
|
836
1050
|
?author_id: String,
|
|
837
1051
|
?context: moderation_context_input,
|
|
838
1052
|
?external_id: String?,
|
|
@@ -842,7 +1056,8 @@ module CalmLens
|
|
|
842
1056
|
?processing_options: processing_options_input?,
|
|
843
1057
|
?request_options: request_options
|
|
844
1058
|
}
|
|
845
|
-
|
|
1059
|
+
# `wait` overrides whether the final part waits for the decision, chosen when the upload started.
|
|
1060
|
+
type upload_part_options = { asset_id: String, part: upload_part, ?wait: bool, ?request_options: request_options }
|
|
846
1061
|
|
|
847
1062
|
# Options of {Text#classify}: the text, with the shared asset fields. `name` defaults to `text`.
|
|
848
1063
|
type moderate_text_options = {
|
|
@@ -851,6 +1066,7 @@ module CalmLens
|
|
|
851
1066
|
?description: String?,
|
|
852
1067
|
?visibility: asset_visibility?,
|
|
853
1068
|
?metadata: Array[metadata_item_input]?,
|
|
1069
|
+
?tags: Array[String]?,
|
|
854
1070
|
?author_id: String,
|
|
855
1071
|
?context: moderation_context_input,
|
|
856
1072
|
?external_id: String?,
|
|
@@ -865,19 +1081,19 @@ module CalmLens
|
|
|
865
1081
|
type sign_upload_token_options = {
|
|
866
1082
|
upload_preset_id: String,
|
|
867
1083
|
?external_id: String,
|
|
868
|
-
|
|
1084
|
+
# Seconds the token can start an upload, 1 to 3600; 600 by default.
|
|
1085
|
+
?expires_in: Integer,
|
|
869
1086
|
?request_options: request_options
|
|
870
1087
|
}
|
|
871
1088
|
type signed_upload_token = { "token" => String, "expiresAt" => Integer }
|
|
872
1089
|
|
|
873
|
-
type folder_order_input = { field: "name" | "createdAt", direction: order_direction }
|
|
874
1090
|
type list_folders_options = {
|
|
875
1091
|
?parent_id: String,
|
|
876
1092
|
?cursor: String,
|
|
877
1093
|
# 1 to 100, default 50.
|
|
878
1094
|
?page_size: Integer,
|
|
879
|
-
#
|
|
880
|
-
?
|
|
1095
|
+
# `name` (the default) or `createdAt`, descending when prefixed with `-`.
|
|
1096
|
+
?sort: sort,
|
|
881
1097
|
?search: String,
|
|
882
1098
|
?request_options: request_options
|
|
883
1099
|
}
|
|
@@ -885,39 +1101,36 @@ module CalmLens
|
|
|
885
1101
|
"items" => Array[folder],
|
|
886
1102
|
"ancestors" => Array[folder],
|
|
887
1103
|
"hasMore" => bool,
|
|
888
|
-
"nextCursor" => String
|
|
889
|
-
"pageSize" => Integer,
|
|
890
|
-
"ordering" => Array[order]
|
|
1104
|
+
"nextCursor" => String?
|
|
891
1105
|
}
|
|
892
1106
|
type folder_id_options = { folder_id: String, ?request_options: request_options }
|
|
893
1107
|
type create_folder_options = { name: String, ?parent_id: String?, ?request_options: request_options }
|
|
894
1108
|
type update_folder_options = { folder_id: String, ?name: String, ?request_options: request_options }
|
|
895
1109
|
type move_folder_options = { folder_id: String, parent_id: String?, ?request_options: request_options }
|
|
896
|
-
# 1 to 100 lists per page, default 50.
|
|
897
|
-
type list_hash_lists_options = { ?cursor: String, ?page_size: Integer, ?request_options: request_options }
|
|
1110
|
+
# 1 to 100 lists per page, default 50; `sort` is `createdAt` and `id`, `-createdAt` by default.
|
|
1111
|
+
type list_hash_lists_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
|
|
898
1112
|
type hash_list_page = {
|
|
899
1113
|
"items" => Array[hash_list],
|
|
900
1114
|
"hasMore" => bool,
|
|
901
|
-
"nextCursor" => String
|
|
902
|
-
"pageSize" => Integer,
|
|
903
|
-
"ordering" => Array[order]
|
|
1115
|
+
"nextCursor" => String?
|
|
904
1116
|
}
|
|
905
1117
|
type hash_list_id_options = { hash_list_id: String, ?request_options: request_options }
|
|
906
1118
|
type create_hash_list_options = { name: String, action: hash_list_action, ?description: String?, ?request_options: request_options }
|
|
907
1119
|
type update_hash_list_options = { hash_list_id: String, ?name: String, ?description: String?, ?action: hash_list_action,
|
|
908
1120
|
?request_options: request_options }
|
|
909
|
-
type list_hash_list_entries_options = { hash_list_id: String, ?cursor: String, ?page_size: Integer,
|
|
1121
|
+
type list_hash_list_entries_options = { hash_list_id: String, ?cursor: String, ?page_size: Integer, ?sort: sort,
|
|
910
1122
|
?request_options: request_options }
|
|
911
1123
|
type add_hash_list_entry_options = { hash_list_id: String, ?hash: String, ?quality: number, ?asset_id: String, ?label: String,
|
|
912
1124
|
?request_options: request_options }
|
|
913
1125
|
type hash_list_entry_id_options = { entry_id: String, ?request_options: request_options }
|
|
914
1126
|
|
|
915
1127
|
# Policy settings as options: snake_case Symbol keys, or a policy's `settings` as the API returned it.
|
|
916
|
-
type policy_rule_input = { when: Array[String], action: flagged_content_action, ?name: String, ?
|
|
1128
|
+
type policy_rule_input = { when: Array[String], action: flagged_content_action, ?name: String, ?unless: Array[String] }
|
|
1129
|
+
# Every category needs its `action`, `allowances` and `restrictions`.
|
|
917
1130
|
type category_policy_settings_input = {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1131
|
+
action: flagged_content_action,
|
|
1132
|
+
allowances: Array[policy_rule_input],
|
|
1133
|
+
restrictions: Array[policy_rule_input]
|
|
921
1134
|
}
|
|
922
1135
|
type link_safety_settings_input = {
|
|
923
1136
|
verdict_actions: Hash[String | Symbol, link_safety_action],
|
|
@@ -927,7 +1140,9 @@ module CalmLens
|
|
|
927
1140
|
category_settings: Hash[String | Symbol, category_policy_settings_input],
|
|
928
1141
|
?link_safety: link_safety_settings_input
|
|
929
1142
|
}
|
|
930
|
-
|
|
1143
|
+
# `sort` is `createdAt` and `id`, `createdAt` (oldest first) by default.
|
|
1144
|
+
type list_policies_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
|
|
1145
|
+
type request_only_options = { ?request_options: request_options }
|
|
931
1146
|
type policy_id_options = { policy_id: String, ?request_options: request_options }
|
|
932
1147
|
# Send `settings` (defining every category) with a `name`, or `preset_id` to copy the latest
|
|
933
1148
|
# release of a built-in preset, named after it unless you give a `name`.
|
|
@@ -935,16 +1150,18 @@ module CalmLens
|
|
|
935
1150
|
?preset_id: policy_preset_id, ?request_options: request_options }
|
|
936
1151
|
type update_policy_options = { policy_id: String, revision: Integer, ?name: String, ?description: String,
|
|
937
1152
|
?settings: policy_settings_input, ?request_options: request_options }
|
|
938
|
-
# `reset` restores the pinned
|
|
939
|
-
# copy to the latest release (send `preset.latestVersion`).
|
|
940
|
-
type
|
|
941
|
-
|
|
1153
|
+
# `reset` restores the pinned release (send `preset.version`); `upgrade` moves an unchanged
|
|
1154
|
+
# `pinned` or `copy` policy to the latest release (send `preset.latestVersion`).
|
|
1155
|
+
type restore_policy_options = { policy_id: String, revision: Integer, preset_version: Integer,
|
|
1156
|
+
?request_options: request_options }
|
|
942
1157
|
type set_policy_automatic_updates_options = { policy_id: String, enabled: bool, revision: Integer,
|
|
943
1158
|
preset_version: Integer, ?request_options: request_options }
|
|
944
1159
|
type assign_policy_options = { policy_id: String, ?request_options: request_options }
|
|
945
1160
|
|
|
946
|
-
# `page_size` is 1 to 100, default 50.
|
|
947
|
-
|
|
1161
|
+
# `page_size` is 1 to 100, default 50. `types` and `asset_id` narrow the feed; a cursor belongs to
|
|
1162
|
+
# the filters it was issued with.
|
|
1163
|
+
type list_events_options = { ?cursor: String, ?page_size: Integer, ?types: Array[event_type], ?asset_id: String,
|
|
1164
|
+
?request_options: request_options }
|
|
948
1165
|
|
|
949
1166
|
type ensure_lenses_options = { lenses: Array[lens_definition], ?request_options: request_options }
|
|
950
1167
|
type ensure_lens_options = {
|
|
@@ -953,28 +1170,107 @@ module CalmLens
|
|
|
953
1170
|
type: lens_type,
|
|
954
1171
|
active: bool,
|
|
955
1172
|
?description: String?,
|
|
956
|
-
?
|
|
1173
|
+
?transform: image_transform_options_input?,
|
|
1174
|
+
?request_options: request_options
|
|
1175
|
+
}
|
|
1176
|
+
# `sort` is `createdAt` and `id`, `-createdAt` (newest first) by default.
|
|
1177
|
+
type list_lenses_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
|
|
1178
|
+
type lens_id_options = { lens_id: String, ?request_options: request_options }
|
|
1179
|
+
# The identifier must be new to the project.
|
|
1180
|
+
type create_lens_options = ensure_lens_options
|
|
1181
|
+
type update_lens_options = {
|
|
1182
|
+
lens_id: String,
|
|
1183
|
+
?name: String,
|
|
1184
|
+
?description: String?,
|
|
1185
|
+
?type: lens_type,
|
|
1186
|
+
?active: bool,
|
|
957
1187
|
?transform: image_transform_options_input?,
|
|
958
1188
|
?request_options: request_options
|
|
959
1189
|
}
|
|
960
1190
|
|
|
1191
|
+
# `sort` is `createdAt` and `id`, `createdAt` (oldest first) by default.
|
|
1192
|
+
type list_upload_presets_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
|
|
1193
|
+
# One preset's whole definition, by `key`; fields left out take their defaults. Send the `revision`
|
|
1194
|
+
# you read (0 for a preset that must not exist yet) to refuse a change made since.
|
|
1195
|
+
type upload_preset_definition = {
|
|
1196
|
+
key: String,
|
|
1197
|
+
name: String,
|
|
1198
|
+
?revision: Integer,
|
|
1199
|
+
?access: upload_preset_access,
|
|
1200
|
+
?enabled: bool,
|
|
1201
|
+
?allowed_content_types: Array[String]?,
|
|
1202
|
+
?max_size_in_bytes: Integer?,
|
|
1203
|
+
?folder_id: String?,
|
|
1204
|
+
?policy_id: String?,
|
|
1205
|
+
?visibility: asset_visibility,
|
|
1206
|
+
?processing_options: processing_options_input?,
|
|
1207
|
+
?reveal_decision: bool,
|
|
1208
|
+
?daily_upload_limit: Integer?,
|
|
1209
|
+
?allowed_origins: Array[String]?
|
|
1210
|
+
}
|
|
1211
|
+
type ensure_upload_presets_options = { upload_presets: Array[upload_preset_definition], ?request_options: request_options }
|
|
1212
|
+
type upload_preset_id_options = { upload_preset_id: String, ?request_options: request_options }
|
|
1213
|
+
# The complete settings: those left out return to their defaults.
|
|
1214
|
+
type project_settings_input = {
|
|
1215
|
+
?opt_out_jurisdictions: Array[String],
|
|
1216
|
+
?block_unmoderated_assets: bool,
|
|
1217
|
+
?store_sensitive_metadata: bool,
|
|
1218
|
+
?streaming_enabled: bool,
|
|
1219
|
+
?ai_media_search_enabled: bool,
|
|
1220
|
+
?remote_url_rule: { mode: "allow" | "deny", domains: Array[String] }?,
|
|
1221
|
+
?website_submissions_per_minute: Integer?,
|
|
1222
|
+
?human_review: {
|
|
1223
|
+
?allowed_sample_percent: number,
|
|
1224
|
+
?restricted_sample_percent: number,
|
|
1225
|
+
?uncertainty_margin_percent: number,
|
|
1226
|
+
?review_missing_evidence: bool
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
# Send the `revision` you read to refuse settings changed since. `search_indexing_budget_units` is
|
|
1230
|
+
# needed when turning on `ai_media_search_enabled`.
|
|
1231
|
+
type update_project_settings_options = {
|
|
1232
|
+
?revision: Integer,
|
|
1233
|
+
settings: project_settings_input,
|
|
1234
|
+
?search_indexing_budget_units: number,
|
|
1235
|
+
?request_options: request_options
|
|
1236
|
+
}
|
|
1237
|
+
type metadata_field_input = {
|
|
1238
|
+
id: String,
|
|
1239
|
+
title: String,
|
|
1240
|
+
?description: String,
|
|
1241
|
+
type: metadata_field_type,
|
|
1242
|
+
icon: metadata_field_icon,
|
|
1243
|
+
color: String
|
|
1244
|
+
}
|
|
1245
|
+
# Fields to create or replace by ID; other fields are kept.
|
|
1246
|
+
type ensure_metadata_fields_options = { ?revision: Integer, fields: Array[metadata_field_input], ?request_options: request_options }
|
|
1247
|
+
type delete_metadata_field_options = { field_id: String, ?revision: Integer, ?request_options: request_options }
|
|
1248
|
+
|
|
961
1249
|
type asset_url_options = {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
#
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
#
|
|
1250
|
+
# Exactly one of `asset_id` and `external_id`.
|
|
1251
|
+
?asset_id: String,
|
|
1252
|
+
?external_id: String,
|
|
1253
|
+
# The client's project by default.
|
|
1254
|
+
?project_id: String,
|
|
1255
|
+
# Without one, the URL is the asset URL itself. `original`, `hls` (the HLS master playlist),
|
|
1256
|
+
# `embed` (the page that shows the asset), `placeholder` (a small blurred PNG) and `info` take no
|
|
1257
|
+
# lens or transform; `preview` takes them, and `rendered` does when it is an image.
|
|
1258
|
+
?resource: cdn_resource,
|
|
1259
|
+
# Transform options replace the lens's options of the same name; both need a resource.
|
|
969
1260
|
?lens: String,
|
|
970
1261
|
?transform: transform_input,
|
|
971
|
-
#
|
|
972
|
-
# only where your app has already decided the viewer may see age-restricted content.
|
|
1262
|
+
# Unsigned viewer assertions, sent as the `viewerClaims` query without the defaults. Set
|
|
1263
|
+
# `age_confirmed` only where your app has already decided the viewer may see age-restricted content.
|
|
1264
|
+
?viewer_claims: viewer_claims,
|
|
1265
|
+
?request_options: request_options
|
|
973
1266
|
}
|
|
974
1267
|
type serve_options = {
|
|
1268
|
+
?asset_id: String,
|
|
1269
|
+
?external_id: String,
|
|
1270
|
+
?project_id: String,
|
|
975
1271
|
?viewer_claims: viewer_claims,
|
|
976
|
-
|
|
977
|
-
?resource:
|
|
1272
|
+
# `rendered` by default.
|
|
1273
|
+
?resource: cdn_resource,
|
|
978
1274
|
?lens: String,
|
|
979
1275
|
?transform: transform_input,
|
|
980
1276
|
?init: { ?method: "GET" | "HEAD", ?headers: Hash[String, String] },
|
|
@@ -986,6 +1282,8 @@ module CalmLens
|
|
|
986
1282
|
type: event_type,
|
|
987
1283
|
?id: String,
|
|
988
1284
|
?project_id: String,
|
|
1285
|
+
# The mock API key (`{ 'type' => 'api-key', 'id' => nil }`) when omitted.
|
|
1286
|
+
?actor: actor_input,
|
|
989
1287
|
?severity: event_severity,
|
|
990
1288
|
?title: String,
|
|
991
1289
|
?description: String?,
|