calmlens 0.20.0 → 0.21.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.
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
- type asset_classification_status = "pending" | "processing" | "completed" | "failed"
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-upload-limit" | "child-failed" | "processing-error"
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,42 @@ module CalmLens
97
89
  ?"sha384" => String?,
98
90
  ?"sha512" => String?
99
91
  }
100
- # The picture served at the rendered resource; it remains after the content is removed.
101
- type asset_image = {
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_rendered_kind = "image" | "pdf" | "video" | "audio"
107
+ # The asset's one displayable file, as the CDN's `rendered` resource serves it: an image, a PDF, or
108
+ # browser-safe video or audio. `peaks` is an audio waveform's normalised peaks.
109
+ type asset_rendered = {
110
+ "kind" => asset_rendered_kind,
111
+ "format" => String,
112
+ "width" => Integer?,
113
+ "height" => Integer?,
114
+ ?"peaks" => Array[Float]
115
+ }
116
+ # The still image that stands for the asset, as the CDN's `preview` resource serves it; the
117
+ # `placeholder` resource is its ThumbHash as a small blurred PNG.
118
+ type asset_preview = {
102
119
  "width" => Integer?,
103
120
  "height" => Integer?,
104
121
  "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?
122
+ "averageColor" => String?
109
123
  }
110
124
  type safety_hold = { "placedAt" => Integer, "reason" => "suspected-illegal-content", ?"disposedAt" => Integer? }
111
125
  # `type: "string"` carries the text in `content`; `type: "document"` stores it under `id`.
112
126
  type extracted_text = { "type" => "string" | "document", ?"content" => String, ?"id" => String }
113
- # Descriptive metadata embedded in an uploaded image. `capturedAt` is ISO 8601, with a UTC offset
127
+ # Descriptive metadata embedded in an uploaded file. `capturedAt` is ISO 8601, with a UTC offset
114
128
  # only when the file records one. `digitalSourceType` is the IPTC code the file declares, such as
115
129
  # `digitalCapture`. `containsLocation` says whether the uploaded file embedded GPS coordinates;
116
130
  # `creator` and `location` are sensitive and recorded only when `storeSensitiveMetadata` is on.
@@ -129,48 +143,76 @@ module CalmLens
129
143
  }
130
144
 
131
145
  type asset_upload = { "status" => "uploading" | "completed", "updatedAt" => Integer?, "partsReceived" => Integer? }
146
+ # How many sections of long audio or video are analysed so far.
147
+ type classification_progress = { "completedSections" => Integer, "totalSections" => Integer }
132
148
  type asset_classification = {
133
149
  "status" => asset_classification_status,
134
150
  # `null` unless `status` is `failed`.
135
151
  "failureReason" => asset_classification_failure_reason?,
136
152
  "updatedAt" => Integer?,
137
153
  "completedAt" => Integer?,
154
+ # While long audio or video is analysed in sections and `status` is `processing`: how many of its
155
+ # sections are done. `nil` otherwise.
156
+ "progress" => classification_progress?,
157
+ # Whether the results came from one of the project's test inputs rather than analysing the
158
+ # content. Never use test results, such as age ranges, for real decisions.
159
+ "testInput" => bool,
138
160
  "moderation" => asset_moderation,
139
- ?"personDetection" => person_detection_result,
140
- ?"faceDetection" => face_detection_result,
141
- ?"linkDetection" => link_detection_result,
142
- # Preview. Where the asset's links lead; present when the project's policy acts on links.
143
- ?"linkSafety" => link_safety_result,
144
- ?"aiGeneratedDetection" => ai_generated_detection_result,
145
- # Where OCR found text, and personal information within it; redaction transforms blur these regions.
146
- ?"textRegions" => Array[text_region],
147
- ?"labels" => Array[classification_label]?
148
- }
161
+ # OCR's result for an image processed with OCR turned on; `nil` when OCR didn't run.
162
+ "ocr" => ocr_result?,
163
+ # Link detection's result for an image; `nil` when it didn't run.
164
+ "linkDetection" => link_detection_result?,
165
+ # Preview. Person and face detection's results; `nil` when they didn't run.
166
+ ?"personDetection" => person_detection_result?,
167
+ ?"faceDetection" => face_detection_result?,
168
+ # Preview. Where the asset's links lead when the project's policy acts on links; otherwise `nil`.
169
+ ?"linkSafety" => link_safety_result?,
170
+ ?"aiGeneratedDetection" => ai_generated_detection_result?
171
+ }
172
+ # Who made a review: a person (`user`, also when an assistant's key acts for one) or an API key
173
+ # (`api-key`), with the user's or API key's ID, `nil` only when it was not recorded.
174
+ type review_actor = { "type" => "user" | "api-key", "id" => String? }
149
175
  type asset_review = {
150
176
  "id" => String,
151
177
  "decision" => asset_moderation_decision,
152
178
  "note" => String?,
153
- ?"reviewerName" => String?,
154
- ?"reviewerEmail" => String?,
179
+ "decidedBy" => review_actor,
155
180
  "reviewedAt" => Integer,
156
- "appliedToAsset" => bool
157
- }
158
- type regional_decision = { "region" => String, "action" => String, "rule" => String, ?"category" => String }
159
- type test_regional_action = { "region" => String, "action" => String }
181
+ # Whether the decision was applied to the asset; `false` for a review queue decision recorded
182
+ # without changing the asset's status.
183
+ "applied" => bool
184
+ }
185
+ # A stricter delivery decision in one region the project serves: the status in force there, the
186
+ # mandatory rule that sets it and the category whose findings it acted on, when it acts on one.
187
+ type regional_decision = {
188
+ "region" => String,
189
+ "status" => "limited" | "age-restricted" | "blocked" | "purged",
190
+ "rule" => String,
191
+ ?"category" => String
192
+ }
193
+ # What decided the automated status: the `policy`'s categories, the asset's `children`, a
194
+ # `hash-list` match, a `mandatory-rule` or `link-safety`.
195
+ type moderation_source = "policy" | "children" | "hash-list" | "mandatory-rule" | "link-safety"
196
+ # Every field but `status`, `manualReviews`, `flaggedCategories`, `regions` and `timeline` is `nil`
197
+ # until moderation decides.
160
198
  type asset_moderation = {
161
- ?"testCategoryActions" => Hash[String, String],
162
- ?"testRegionalActions" => Array[test_regional_action],
163
199
  "manualReviews" => Array[asset_review],
164
200
  "status" => asset_moderation_status,
165
- ?"automatedAction" => flagged_content_action,
166
- ?"source" => String, ?"rule" => String,
201
+ # The policy's original decision; a reviewer's decision can change `status` without changing it.
202
+ "automatedStatus" => asset_moderation_decision?,
203
+ "source" => moderation_source?,
204
+ # The mandatory rule that decided, when `source` is `mandatory-rule`; otherwise `nil`.
205
+ "rule" => String?,
167
206
  "flaggedCategories" => Array[String], "regions" => Array[regional_decision],
168
- ?"explanationComplete" => bool,
169
- ?"categories" => Hash[String, category_policy_score],
170
- # Preview. What the policy's link-safety section made of the asset's links; absent when the
207
+ "explanationComplete" => bool?,
208
+ "categories" => Hash[String, category_policy_score]?,
209
+ # Preview. What the policy's link-safety section made of the asset's links; `nil` when the
171
210
  # policy doesn't act on links.
172
- ?"linkSafety" => link_safety_decision,
173
- ?"raw" => moderation_raw
211
+ ?"linkSafety" => link_safety_decision?,
212
+ # An audio or video asset's findings timeline: how many segments `assets.list_timeline` lists.
213
+ # `null` for other assets and media without findings.
214
+ "timeline" => moderation_timeline?,
215
+ "raw" => moderation_raw?
174
216
  }
175
217
  # ASSET_CONTENT_SCHEMA. `format` is the MIME type.
176
218
  type asset_content = {
@@ -182,11 +224,25 @@ module CalmLens
182
224
  "extension" => String?,
183
225
  "sizeInBytes" => Integer?,
184
226
  "checksums" => checksums?,
185
- "image" => asset_image?,
227
+ # The file's own size, length and page count, where they apply; `null` when unknown.
228
+ "width" => Integer?,
229
+ "height" => Integer?,
230
+ "durationSeconds" => Float?,
231
+ "pageCount" => Integer?,
232
+ "perceptualHash" => String?,
233
+ # How much detail `perceptualHash` captured, from 0 to 100; hashes below 50 match unrelated pictures.
234
+ "perceptualHashQuality" => Integer?,
235
+ # Metadata embedded in the uploaded file; `null` when it declares none, once the content is
236
+ # removed and while the asset is held.
237
+ "metadata" => file_metadata?,
186
238
  "extractedText" => extracted_text?,
187
- # Metadata embedded in an uploaded image; `null` when it declares none, for other asset types,
188
- # once the content is removed and while the asset is held.
189
- "fileMetadata" => file_metadata?
239
+ # `null` until processing makes it, for text, spreadsheets and other files, once the content is
240
+ # removed and while the asset is held.
241
+ "rendered" => asset_rendered?,
242
+ # Preview. The adaptive stream once streaming has prepared one for audio or video; `nil` for
243
+ # other assets, until then, once the content is removed and while the asset is held.
244
+ "hls" => asset_hls?,
245
+ "preview" => asset_preview?
190
246
  }
191
247
 
192
248
  type asset = {
@@ -202,13 +258,14 @@ module CalmLens
202
258
  ?"externalId" => String?,
203
259
  ?"externalUrl" => String?,
204
260
  "type" => asset_type,
205
- ?"metadata" => Array[metadata_item]?,
261
+ # Empty when the asset has none.
262
+ "metadata" => Array[metadata_item],
206
263
  ?"authorId" => String?,
207
264
  # The earlier posts CalmLens used; null once the content is removed.
208
265
  ?"context" => moderation_context?,
209
- ?"tags" => Array[String]?,
210
- ?"processingOptions" => processing_options?,
211
- ?"visibility" => asset_visibility?,
266
+ # Empty when the asset has none.
267
+ "tags" => Array[String],
268
+ "visibility" => asset_visibility,
212
269
  "upload" => asset_upload,
213
270
  "classification" => asset_classification,
214
271
  "content" => asset_content
@@ -234,14 +291,12 @@ module CalmLens
234
291
 
235
292
  # `status: "evaluated"` or `"partial"` carries `likelihood` and `score`; `"not-evaluated"`
236
293
  # carries `reason`.
237
- type policy_condition_result = { "status" => "evaluated" | "not-evaluated", ?"score" => number, ?"reason" => not_evaluated_reason }
238
294
  type category_report = {
239
295
  "status" => "evaluated" | "partial" | "not-evaluated",
240
296
  ?"likelihood" => likelihood,
241
297
  ?"score" => number,
242
298
  ?"reason" => not_evaluated_reason,
243
- ?"qualifiers" => qualifier_results,
244
- ?"policyConditions" => Hash[String, policy_condition_result]
299
+ ?"qualifiers" => qualifier_results
245
300
  }
246
301
  type classification_categories = {
247
302
  "sexual" => category_report,
@@ -253,44 +308,27 @@ module CalmLens
253
308
  "personal-information" => category_report,
254
309
  "profanity" => category_report
255
310
  }
256
- type classification_label = {
257
- "description" => String,
258
- "score" => number,
259
- ?"topicalityScore" => number?,
260
- "likelihood" => likelihood,
261
- ?"knowledgeBaseId" => String?
262
- }
263
311
  type media_segment = {
264
312
  "source" => "frame" | "speech" | "frame-text" | "clip",
265
313
  "startSeconds" => number,
266
314
  "endSeconds" => number,
267
315
  "categories" => classification_categories
268
316
  }
269
- type media_report = {
270
- "durationSeconds" => number,
271
- ?"frameIntervalSeconds" => number,
272
- "sampledFrames" => Integer,
273
- "audioTranscribed" => bool,
274
- "segments" => Array[media_segment]
275
- }
276
317
 
277
318
  # Position and size as fractions of the image width and height, from 0 to 1.
278
319
  type bounding_box = { "left" => number, "top" => number, "width" => number, "height" => number }
279
320
  type age_range = { "low" => Integer, "high" => Integer }
280
321
  type detected_person = { "box" => bounding_box, "confidence" => number }
281
322
  type detected_face = { "box" => bounding_box, "confidence" => number, ?"ageRange" => age_range }
282
- type processing_feature_stage = "beta" | "ga"
283
323
  # `status: "evaluated"` carries `people`; `"not-evaluated"` carries `reason`.
284
324
  type person_detection_result = {
285
325
  "status" => "evaluated" | "not-evaluated",
286
- "stage" => processing_feature_stage,
287
326
  ?"people" => Array[detected_person],
288
327
  ?"reason" => not_evaluated_reason
289
328
  }
290
329
  # `status: "evaluated"` carries `faces`; `"not-evaluated"` carries `reason`.
291
330
  type face_detection_result = {
292
331
  "status" => "evaluated" | "not-evaluated",
293
- "stage" => processing_feature_stage,
294
332
  ?"faces" => Array[detected_face],
295
333
  ?"reason" => not_evaluated_reason
296
334
  }
@@ -300,7 +338,6 @@ module CalmLens
300
338
  # `status: "evaluated"` carries `qrCodes` and `links`; `"not-evaluated"` carries `reason`.
301
339
  type link_detection_result = {
302
340
  "status" => "evaluated" | "not-evaluated",
303
- "stage" => processing_feature_stage,
304
341
  ?"qrCodes" => Array[detected_qr_code],
305
342
  ?"links" => Array[detected_link],
306
343
  ?"reason" => not_evaluated_reason
@@ -338,7 +375,6 @@ module CalmLens
338
375
  # Preview. `status: "evaluated"` carries `links`; `"not-evaluated"` carries `reason`.
339
376
  type link_safety_result = {
340
377
  "status" => "evaluated" | "not-evaluated",
341
- "stage" => processing_feature_stage,
342
378
  ?"links" => Array[checked_link],
343
379
  ?"reason" => not_evaluated_reason
344
380
  }
@@ -355,66 +391,71 @@ module CalmLens
355
391
  },
356
392
  ?"offPlatformLinks" => { "action" => "limit" | "age-restrict" | "block", "allowedDomains" => Array[String] }
357
393
  }
358
- # Preview. The strongest action the asset's links take, the indexes into
359
- # `classification.linkSafety.links` of the links that take it, and the settings in force.
394
+ # Preview. The strongest action the asset's links take, the checked links that take it, and the
395
+ # settings in force.
360
396
  type link_safety_decision = {
361
397
  "action" => link_safety_action,
362
- "links" => Array[Integer],
398
+ "links" => Array[checked_link],
363
399
  "settings" => link_safety_settings
364
400
  }
365
401
  type provenance_signal = { "kind" => "c2pa" | "iptc-digital-source-type" | "generator-metadata", "value" => String }
366
402
  # `status: "evaluated"` carries `provenance` and `signals`; `"not-evaluated"` carries `reason`.
367
403
  type ai_generated_detection_result = {
368
404
  "status" => "evaluated" | "not-evaluated",
369
- "stage" => processing_feature_stage,
370
405
  ?"provenance" => "ai-generated" | "ai-edited" | "unknown",
371
406
  ?"signals" => Array[provenance_signal],
372
407
  ?"reason" => not_evaluated_reason
373
408
  }
374
409
  # Where OCR found text in an image, and whether it is personal information.
375
410
  type text_region = { "box" => bounding_box, "personalInformation" => bool }
376
- # Results of the features requested in `processingOptions.features`. OCR stores extracted text on the image
377
- # asset instead of a result here.
378
- type processing_feature_results = {
379
- ?"personDetection" => person_detection_result,
380
- ?"faceDetection" => face_detection_result,
381
- ?"linkDetection" => link_detection_result,
382
- ?"linkSafety" => link_safety_result,
383
- ?"aiGeneratedDetection" => ai_generated_detection_result
411
+ # `status: "evaluated"` carries `textRegions`, where OCR found text (redaction transforms blur
412
+ # these regions); `"not-evaluated"` carries `reason`. The text itself is `content.extractedText`.
413
+ type ocr_result = {
414
+ "status" => "evaluated" | "not-evaluated",
415
+ ?"textRegions" => Array[text_region],
416
+ ?"reason" => not_evaluated_reason
384
417
  }
385
418
 
386
419
  # How strongly each assessed category meets the policy and what the policy does with it.
387
420
  type policy_rule_snapshot = {
388
421
  "when" => Array[String], "action" => flagged_content_action,
389
- ?"name" => String, ?"match" => "all", ?"unless" => Array[String]
422
+ ?"name" => String, ?"unless" => Array[String]
390
423
  }
391
- type category_policy_source = { "kind" => String, ?"index" => Integer, ?"indexes" => Array[Integer] }
424
+ # What decided a category's action: its `default` action, a policy score `below-threshold`, or the
425
+ # `allowance` or `restriction` rules listed by `indexes` (at least one, the decisive rule first).
426
+ type category_policy_source = { "kind" => "default" | "below-threshold" } |
427
+ { "kind" => "allowance" | "restriction", "indexes" => Array[Integer] }
392
428
  type category_policy_settings_snapshot = {
393
- "categoryAction" => flagged_content_action,
429
+ "action" => flagged_content_action,
394
430
  "allowances" => Array[policy_rule_snapshot], "restrictions" => Array[policy_rule_snapshot]
395
431
  }
396
432
  type category_policy_score = {
397
433
  "score" => number, "action" => flagged_content_action,
398
434
  ?"source" => category_policy_source, ?"settings" => category_policy_settings_snapshot
399
435
  }
436
+ type moderation_timeline = { "segmentCount" => Integer }
400
437
  type moderation_raw = {
401
438
  "categories" => classification_categories,
402
- ?"timeline" => media_report,
403
- ?"hashMatches" => Array[hash_match]
439
+ # Empty when the image matched no hash list entry.
440
+ "hashMatches" => Array[hash_match]
404
441
  }
405
442
 
406
443
  # ---- Pages and search (Page.ts, AssetSearch.ts) --------------------------------------------
407
444
 
408
- type order_direction = "asc" | "desc"
409
- type order_input = { field: String, direction: order_direction }
410
- type order = { "field" => String, "direction" => order_direction }
445
+ # A list's sort: comma-separated fields, each ascending unless prefixed with `-`, such as
446
+ # `-createdAt,id`.
447
+ type sort = String
411
448
 
412
449
  type asset_page = {
413
450
  "items" => Array[asset],
414
451
  "hasMore" => bool,
415
- "nextCursor" => String?,
416
- "pageSize" => Integer,
417
- "ordering" => Array[order]
452
+ "nextCursor" => String?
453
+ }
454
+ # One page of an audio or video asset's findings timeline, in time order.
455
+ type asset_timeline_page = {
456
+ "items" => Array[media_segment],
457
+ "hasMore" => bool,
458
+ "nextCursor" => String?
418
459
  }
419
460
 
420
461
  type asset_search_mode = "keyword" | "semantic" | "hybrid"
@@ -428,8 +469,32 @@ module CalmLens
428
469
  }
429
470
 
430
471
  type asset_batch_operation = "delete" | "remove-content"
431
- type batch_assets_response = { "queued" => bool }
432
- type signed_url = { "url" => String, "expiresAt" => Integer }
472
+ # `batchId` is named by the `batch-id` fact of the events the batch causes.
473
+ type batch_assets_response = { "batchId" => String, "status" => "queued", "assetCount" => Integer }
474
+ # A signed asset URL, with any resource, selector and viewer claims appended, and when it expires
475
+ # (milliseconds since the Unix epoch).
476
+ type signed_asset_url = { "url" => String, "expiresAt" => Integer }
477
+ # Whether the viewer an asset URL's claims describe can see the content now.
478
+ type asset_availability = "available" | "age-restricted" | "unavailable"
479
+ # ASSET_INFO_SCHEMA: what the CDN's `info` resource returns, an allowlist of the asset's public
480
+ # fields plus the viewer's `availability`.
481
+ type asset_info = {
482
+ "id" => String,
483
+ "projectId" => String,
484
+ "type" => asset_type,
485
+ "externalUrl" => String?,
486
+ "content" => {
487
+ "format" => String?,
488
+ "width" => Integer?,
489
+ "height" => Integer?,
490
+ "durationSeconds" => Float?,
491
+ "pageCount" => Integer?,
492
+ "rendered" => asset_rendered?,
493
+ "preview" => asset_preview?,
494
+ "hls" => asset_hls?
495
+ },
496
+ "availability" => asset_availability
497
+ }
433
498
 
434
499
  # ---- Transforms and lenses (AssetTransform.ts, Lens.ts) -------------------------------------
435
500
 
@@ -544,20 +609,18 @@ module CalmLens
544
609
  type transform_input = String | image_transform_options_input
545
610
 
546
611
  type lens_type = "image" | "video" | "audio" | "document" | "website"
547
- # ENSURE_LENS_BODY_SCHEMA. Changing a saved lens needs a greater `version` (default 1).
612
+ # ENSURE_LENS_BODY_SCHEMA: a lens definition, which the CDN serves once it is saved.
548
613
  type lens_definition = {
549
614
  identifier: String,
550
615
  name: String,
551
616
  type: lens_type,
552
617
  active: bool,
553
618
  ?description: String?,
554
- ?version: Integer,
555
619
  ?transform: image_transform_options_input?
556
620
  }
557
621
  type lens = {
558
622
  "id" => String,
559
623
  ?"projectId" => String?,
560
- "version" => Integer,
561
624
  "identifier" => String,
562
625
  "name" => String,
563
626
  ?"description" => String?,
@@ -567,6 +630,11 @@ module CalmLens
567
630
  "createdAt" => Integer,
568
631
  ?"updatedAt" => Integer
569
632
  }
633
+ type lens_page = {
634
+ "items" => Array[lens],
635
+ "hasMore" => bool,
636
+ "nextCursor" => String?
637
+ }
570
638
 
571
639
  # ---- Folders (Folder.ts) --------------------------------------------------------------------
572
640
 
@@ -597,8 +665,8 @@ module CalmLens
597
665
  # picture); `action` is `block` when the match was close enough for a block list to block.
598
666
  type hash_match = {
599
667
  "source" => "hash-list",
600
- "listId" => String,
601
- "entryId" => String,
668
+ "hashListId" => String,
669
+ "hashListEntryId" => String,
602
670
  "distance" => Integer,
603
671
  "action" => hash_list_action
604
672
  }
@@ -610,73 +678,85 @@ module CalmLens
610
678
  "hash" => String,
611
679
  "quality" => number?,
612
680
  ?"label" => String?,
613
- ?"sourceAssetId" => String?,
681
+ # The asset the hash was taken from, when the entry was added from an asset.
682
+ ?"assetId" => String?,
614
683
  "createdAt" => Integer
615
684
  }
616
685
 
617
686
  type hash_list_entry_page = {
618
687
  "items" => Array[hash_list_entry],
619
688
  "hasMore" => bool,
620
- "nextCursor" => String?,
621
- "pageSize" => Integer,
622
- "ordering" => Array[order]
689
+ "nextCursor" => String?
623
690
  }
624
691
 
625
692
  # ---- Policies (Policy.ts) ---------------------------------------------------------------------
626
693
 
627
694
  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 (default
629
- # `block`), allowances that let covered content through or act on it more softly, and
630
- # restrictions, which outweigh allowances.
695
+ # What a policy does with one category: `action` when its policy score reaches 0.5, allowances
696
+ # that let covered content through or act on it more softly, and restrictions, which outweigh
697
+ # allowances.
631
698
  type category_policy_settings = {
632
- ?"action" => flagged_content_action,
633
- ?"allowances" => Array[policy_rule_snapshot],
634
- ?"restrictions" => Array[policy_rule_snapshot]
699
+ "action" => flagged_content_action,
700
+ "allowances" => Array[policy_rule_snapshot],
701
+ "restrictions" => Array[policy_rule_snapshot]
635
702
  }
636
- # Settings by category (`sexual`, `violence`, ...), and optionally link safety.
703
+ # Settings for every category, and optionally link safety.
637
704
  type policy_settings = {
638
- "categorySettings" => Hash[String, category_policy_settings],
705
+ "categorySettings" => {
706
+ "sexual" => category_policy_settings,
707
+ "violence" => category_policy_settings,
708
+ "self-harm" => category_policy_settings,
709
+ "harassment" => category_policy_settings,
710
+ "hate" => category_policy_settings,
711
+ "criminal-activity" => category_policy_settings,
712
+ "personal-information" => category_policy_settings,
713
+ "profanity" => category_policy_settings
714
+ },
639
715
  ?"linkSafety" => link_safety_settings
640
716
  }
717
+ # How a policy relates to its preset: `live` follows the latest release (the organisation's own
718
+ # preset policy with automatic updates on), `pinned` is the organisation's own preset policy held
719
+ # at one release, and `copy` is a policy made from a preset.
720
+ type policy_preset_mode = "live" | "pinned" | "copy"
641
721
  # Where a policy started from a built-in preset. `version` is the release it is pinned to,
642
- # `latestVersion` the newest; `own` is whether this is the organisation's own policy for the preset
643
- # rather than a copy made from it. An organisation has at most one per preset, and only it can
644
- # follow automatic updates.
722
+ # `latestVersion` the newest.
645
723
  type policy_preset_origin = {
646
724
  "id" => policy_preset_id,
647
725
  "version" => Integer,
648
726
  "latestVersion" => Integer,
649
- "own" => bool
727
+ "mode" => policy_preset_mode
650
728
  }
651
- # A moderation policy. Policies belong to the project's organisation and its projects share them.
652
- # Send `revision` with each change; a policy changed since is refused with `policy/revision-conflict`.
729
+ # A moderation policy. Policies belong to the organisation and its projects share them. Send
730
+ # `revision` with each change; a policy changed since is refused with `policy/revision-conflict`.
653
731
  type policy = {
654
732
  "id" => String,
655
733
  "name" => String,
656
734
  "description" => String,
657
735
  "settings" => policy_settings,
658
736
  "revision" => Integer,
659
- "automaticUpdates" => bool,
660
737
  "preset" => policy_preset_origin?,
661
738
  "projectIds" => Array[String],
662
739
  "createdAt" => Integer,
663
740
  "updatedAt" => Integer
664
741
  }
665
- # Every policy of the project's organisation, oldest first, and the one the project moderates with.
666
- type policy_list = { "policies" => Array[policy], "projectPolicyId" => String }
742
+ # A page of the organisation's policies, oldest first unless `sort` says otherwise.
743
+ type policy_page = { "items" => Array[policy], "hasMore" => bool, "nextCursor" => String? }
667
744
 
668
745
  # ---- Events and webhooks (Event.ts, EventCatalog.ts, WebhookPayload.ts) ----------------------
669
746
 
670
747
  # EVENT_TYPES in EventCatalog.ts. Ignore types your code does not handle. Webhook, Slack and email
671
748
  # 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.deleted" | "asset.content-removed" | "asset.retried" |
674
- "asset.review-requested" | "asset.hash-matched" | "usage.limit-reached" | "usage.spend-limit-reached" |
749
+ type event_type = "asset.uploaded" | "asset.classified" | "asset.region-restricted" | "asset.allowed" | "asset.limited" |
750
+ "asset.age-restricted" | "asset.blocked" | "asset.purged" | "asset.failed" | "asset.progress-updated" |
751
+ "asset.deleted" | "asset.content-removed" | "asset.retried" | "asset.rerun-requested" | "asset.review-requested" |
752
+ "asset.hash-matched" | "asset.link-flagged" | "usage.free-uploads-exhausted" | "usage.uploads-paused" |
675
753
  "upload-preset.daily-limit-reached" | "project.member-joined" | "project.member-removed" |
676
- "project.member-role-changed" | "project.invitation-sent" | "api-key.created" |
677
- "api-key.revoked" | "connector.failing" | "appeal.submitted" | "appeal.resolved"
754
+ "project.member-left" | "project.member-role-changed" | "project.invitation-sent" |
755
+ "project.transferred" | "api-key.created" | "api-key.revoked" | "api-key.deleted" |
756
+ "connector.disabled" | "appeal.submitted" | "appeal.resolved"
678
757
  type event_severity = "low" | "high"
679
- # A registered fact's value: text, an enum value, a count, a list of enum values, or null.
758
+ # A registered fact's value: text, an enum value, a count or a time in milliseconds (such as
759
+ # `resumes-at`), a list of enum values (such as `flagged-categories`), or null.
680
760
  # Test sends carry `{ "key" => "test", "value" => true }`.
681
761
  type event_fact_value = String | Integer | bool | Array[String] | nil
682
762
  # A registered fact. `key` is a kebab-case key registered for the event's type, such as
@@ -690,18 +770,31 @@ module CalmLens
690
770
  ?"uploadPresetId" => String?,
691
771
  ?"externalId" => String?,
692
772
  "upload" => { "status" => "uploading" | "completed" },
693
- "classification" => { "status" => asset_classification_status, "moderation" => { "status" => asset_moderation_status } },
773
+ # `testInput`: whether the results came from one of the project's test inputs rather than
774
+ # analysing the content. Never use test results, such as age ranges, for real decisions.
775
+ "classification" => { "status" => asset_classification_status, "testInput" => bool,
776
+ "moderation" => { "status" => asset_moderation_status } },
694
777
  "content" => { "status" => asset_content_status }
695
778
  }
779
+ # Who caused an event: a `user` (a person in the portal, or an assistant acting for one), an
780
+ # `api-key`, `automated` moderation or CalmLens itself (`system`). `id` is the user's or API key's
781
+ # ID, nil for `automated` and `system` and when it was not recorded.
782
+ type actor_type = "user" | "api-key" | "automated" | "system"
783
+ type actor = { "type" => actor_type, "id" => String? }
784
+ type actor_input = { type: actor_type, id: String? }
785
+
696
786
  # An `events.list` item, and the body of its webhook delivery.
697
787
  type event = {
698
788
  "id" => String,
699
789
  "projectId" => String,
790
+ "actor" => actor,
700
791
  "type" => event_type,
701
792
  "severity" => event_severity,
702
793
  "title" => String,
703
794
  "description" => String?,
704
795
  "assetId" => String?,
796
+ # Increases with each event about the same asset; nil for events not about an asset.
797
+ "assetSequence" => Integer?,
705
798
  "asset" => event_asset?,
706
799
  "facts" => Array[event_fact],
707
800
  "createdAt" => Integer
@@ -726,23 +819,31 @@ module CalmLens
726
819
  type asset_search_options = {
727
820
  query: String,
728
821
  ?mode: asset_search_mode,
729
- ?limit: Integer,
822
+ # How many results, 1 to 20 (default 10).
823
+ ?page_size: Integer,
730
824
  ?request_options: request_options
731
825
  }
732
826
  type list_assets_options = {
733
827
  ?cursor: String,
734
828
  ?page_size: Integer,
735
- ?ordering: Array[order_input],
736
- # An RSQL filter such as `classification.moderation.status==allowed`.
829
+ # `createdAt` and `id`; `-createdAt` by default.
830
+ ?sort: sort,
831
+ # An RSQL filter such as `classification.moderation.status==allowed`; `folderId==fldr_…` lists
832
+ # one folder's assets.
737
833
  ?filter: String?,
738
- ?folder_id: String?,
739
834
  ?request_options: request_options
740
835
  }
741
836
  type list_asset_children_options = {
742
837
  asset_id: String,
743
838
  ?cursor: String,
744
839
  ?page_size: Integer,
745
- ?ordering: Array[order_input],
840
+ ?sort: sort,
841
+ ?request_options: request_options
842
+ }
843
+ type list_asset_timeline_options = {
844
+ asset_id: String,
845
+ ?cursor: String,
846
+ ?page_size: Integer,
746
847
  ?request_options: request_options
747
848
  }
748
849
  type update_asset_options = {
@@ -767,15 +868,21 @@ module CalmLens
767
868
  ?confirm_purge: bool,
768
869
  ?request_options: request_options
769
870
  }
770
- type create_signed_url_options = {
771
- ?viewer_claims: viewer_claims,
772
- asset_id: String,
773
- # Defaults to `rendered` on the server; `original` takes no lens or transform.
774
- ?resource: "original" | "rendered",
775
- ?expires_in_seconds: Integer,
776
- # Transform options replace the lens's options of the same name.
871
+ # The resources beneath an asset URL ({CalmLens::CDN::RESOURCES}).
872
+ type cdn_resource = "original" | "rendered" | "preview" | "hls" | "embed" | "placeholder" | "info"
873
+ type sign_asset_url_options = {
874
+ # Exactly one of `asset_id` and `external_id`.
875
+ ?asset_id: String,
876
+ ?external_id: String,
877
+ ?project_id: String,
878
+ # Whole seconds from 1 to 86400; 900 by default.
879
+ ?expires_in: Integer,
880
+ # Whether the URL also serves `original`; false by default.
881
+ ?original: bool,
882
+ ?resource: cdn_resource,
777
883
  ?lens: String,
778
884
  ?transform: transform_input,
885
+ ?viewer_claims: viewer_claims,
779
886
  ?request_options: request_options
780
887
  }
781
888
 
@@ -802,6 +909,8 @@ module CalmLens
802
909
  ?description: String?,
803
910
  ?visibility: asset_visibility?,
804
911
  ?metadata: Array[metadata_item_input]?,
912
+ # Tags for the asset, such as `['catalogue', 'backpacks']`.
913
+ ?tags: Array[String]?,
805
914
  ?author_id: String,
806
915
  ?context: moderation_context_input,
807
916
  ?external_id: String?,
@@ -818,6 +927,8 @@ module CalmLens
818
927
  ?description: String?,
819
928
  ?visibility: asset_visibility?,
820
929
  ?metadata: Array[metadata_item_input]?,
930
+ # Tags for the asset, such as `['catalogue', 'backpacks']`.
931
+ ?tags: Array[String]?,
821
932
  ?author_id: String,
822
933
  ?context: moderation_context_input,
823
934
  ?external_id: String?,
@@ -833,6 +944,8 @@ module CalmLens
833
944
  ?description: String?,
834
945
  ?visibility: asset_visibility?,
835
946
  ?metadata: Array[metadata_item_input]?,
947
+ # Tags for the asset, such as `['catalogue', 'backpacks']`.
948
+ ?tags: Array[String]?,
836
949
  ?author_id: String,
837
950
  ?context: moderation_context_input,
838
951
  ?external_id: String?,
@@ -842,7 +955,8 @@ module CalmLens
842
955
  ?processing_options: processing_options_input?,
843
956
  ?request_options: request_options
844
957
  }
845
- type upload_part_options = { asset_id: String, part: upload_part, ?queue: bool, ?request_options: request_options }
958
+ # `wait` overrides whether the final part waits for the decision, chosen when the upload started.
959
+ type upload_part_options = { asset_id: String, part: upload_part, ?wait: bool, ?request_options: request_options }
846
960
 
847
961
  # Options of {Text#classify}: the text, with the shared asset fields. `name` defaults to `text`.
848
962
  type moderate_text_options = {
@@ -851,6 +965,7 @@ module CalmLens
851
965
  ?description: String?,
852
966
  ?visibility: asset_visibility?,
853
967
  ?metadata: Array[metadata_item_input]?,
968
+ ?tags: Array[String]?,
854
969
  ?author_id: String,
855
970
  ?context: moderation_context_input,
856
971
  ?external_id: String?,
@@ -865,19 +980,19 @@ module CalmLens
865
980
  type sign_upload_token_options = {
866
981
  upload_preset_id: String,
867
982
  ?external_id: String,
868
- ?expires_in_seconds: Integer,
983
+ # Seconds the token can start an upload, 1 to 3600; 600 by default.
984
+ ?expires_in: Integer,
869
985
  ?request_options: request_options
870
986
  }
871
987
  type signed_upload_token = { "token" => String, "expiresAt" => Integer }
872
988
 
873
- type folder_order_input = { field: "name" | "createdAt", direction: order_direction }
874
989
  type list_folders_options = {
875
990
  ?parent_id: String,
876
991
  ?cursor: String,
877
992
  # 1 to 100, default 50.
878
993
  ?page_size: Integer,
879
- # At most one entry; the default is `name` ascending.
880
- ?ordering: Array[folder_order_input],
994
+ # `name` (the default) or `createdAt`, descending when prefixed with `-`.
995
+ ?sort: sort,
881
996
  ?search: String,
882
997
  ?request_options: request_options
883
998
  }
@@ -885,39 +1000,36 @@ module CalmLens
885
1000
  "items" => Array[folder],
886
1001
  "ancestors" => Array[folder],
887
1002
  "hasMore" => bool,
888
- "nextCursor" => String?,
889
- "pageSize" => Integer,
890
- "ordering" => Array[order]
1003
+ "nextCursor" => String?
891
1004
  }
892
1005
  type folder_id_options = { folder_id: String, ?request_options: request_options }
893
1006
  type create_folder_options = { name: String, ?parent_id: String?, ?request_options: request_options }
894
1007
  type update_folder_options = { folder_id: String, ?name: String, ?request_options: request_options }
895
1008
  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 }
1009
+ # 1 to 100 lists per page, default 50; `sort` is `createdAt` and `id`, `-createdAt` by default.
1010
+ type list_hash_lists_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
898
1011
  type hash_list_page = {
899
1012
  "items" => Array[hash_list],
900
1013
  "hasMore" => bool,
901
- "nextCursor" => String?,
902
- "pageSize" => Integer,
903
- "ordering" => Array[order]
1014
+ "nextCursor" => String?
904
1015
  }
905
1016
  type hash_list_id_options = { hash_list_id: String, ?request_options: request_options }
906
1017
  type create_hash_list_options = { name: String, action: hash_list_action, ?description: String?, ?request_options: request_options }
907
1018
  type update_hash_list_options = { hash_list_id: String, ?name: String, ?description: String?, ?action: hash_list_action,
908
1019
  ?request_options: request_options }
909
- type list_hash_list_entries_options = { hash_list_id: String, ?cursor: String, ?page_size: Integer,
1020
+ type list_hash_list_entries_options = { hash_list_id: String, ?cursor: String, ?page_size: Integer, ?sort: sort,
910
1021
  ?request_options: request_options }
911
1022
  type add_hash_list_entry_options = { hash_list_id: String, ?hash: String, ?quality: number, ?asset_id: String, ?label: String,
912
1023
  ?request_options: request_options }
913
1024
  type hash_list_entry_id_options = { entry_id: String, ?request_options: request_options }
914
1025
 
915
1026
  # 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, ?match: "all", ?unless: Array[String] }
1027
+ type policy_rule_input = { when: Array[String], action: flagged_content_action, ?name: String, ?unless: Array[String] }
1028
+ # Every category needs its `action`, `allowances` and `restrictions`.
917
1029
  type category_policy_settings_input = {
918
- ?action: flagged_content_action,
919
- ?allowances: Array[policy_rule_input],
920
- ?restrictions: Array[policy_rule_input]
1030
+ action: flagged_content_action,
1031
+ allowances: Array[policy_rule_input],
1032
+ restrictions: Array[policy_rule_input]
921
1033
  }
922
1034
  type link_safety_settings_input = {
923
1035
  verdict_actions: Hash[String | Symbol, link_safety_action],
@@ -927,7 +1039,9 @@ module CalmLens
927
1039
  category_settings: Hash[String | Symbol, category_policy_settings_input],
928
1040
  ?link_safety: link_safety_settings_input
929
1041
  }
930
- type list_policies_options = { ?request_options: request_options }
1042
+ # `sort` is `createdAt` and `id`, `createdAt` (oldest first) by default.
1043
+ type list_policies_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
1044
+ type request_only_options = { ?request_options: request_options }
931
1045
  type policy_id_options = { policy_id: String, ?request_options: request_options }
932
1046
  # Send `settings` (defining every category) with a `name`, or `preset_id` to copy the latest
933
1047
  # release of a built-in preset, named after it unless you give a `name`.
@@ -935,16 +1049,18 @@ module CalmLens
935
1049
  ?preset_id: policy_preset_id, ?request_options: request_options }
936
1050
  type update_policy_options = { policy_id: String, revision: Integer, ?name: String, ?description: String,
937
1051
  ?settings: policy_settings_input, ?request_options: request_options }
938
- # `reset` restores the pinned preset version (send `preset.version`); `update` moves an unchanged
939
- # copy to the latest release (send `preset.latestVersion`).
940
- type apply_policy_preset_options = { policy_id: String, operation: "reset" | "update", revision: Integer,
941
- preset_version: Integer, ?request_options: request_options }
1052
+ # `reset` restores the pinned release (send `preset.version`); `upgrade` moves an unchanged
1053
+ # `pinned` or `copy` policy to the latest release (send `preset.latestVersion`).
1054
+ type restore_policy_options = { policy_id: String, revision: Integer, preset_version: Integer,
1055
+ ?request_options: request_options }
942
1056
  type set_policy_automatic_updates_options = { policy_id: String, enabled: bool, revision: Integer,
943
1057
  preset_version: Integer, ?request_options: request_options }
944
1058
  type assign_policy_options = { policy_id: String, ?request_options: request_options }
945
1059
 
946
- # `page_size` is 1 to 100, default 50.
947
- type list_events_options = { ?cursor: String, ?page_size: Integer, ?request_options: request_options }
1060
+ # `page_size` is 1 to 100, default 50. `types` and `asset_id` narrow the feed; a cursor belongs to
1061
+ # the filters it was issued with.
1062
+ type list_events_options = { ?cursor: String, ?page_size: Integer, ?types: Array[event_type], ?asset_id: String,
1063
+ ?request_options: request_options }
948
1064
 
949
1065
  type ensure_lenses_options = { lenses: Array[lens_definition], ?request_options: request_options }
950
1066
  type ensure_lens_options = {
@@ -953,28 +1069,49 @@ module CalmLens
953
1069
  type: lens_type,
954
1070
  active: bool,
955
1071
  ?description: String?,
956
- ?version: Integer,
1072
+ ?transform: image_transform_options_input?,
1073
+ ?request_options: request_options
1074
+ }
1075
+ # `sort` is `createdAt` and `id`, `-createdAt` (newest first) by default.
1076
+ type list_lenses_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
1077
+ type lens_id_options = { lens_id: String, ?request_options: request_options }
1078
+ # The identifier must be new to the project.
1079
+ type create_lens_options = ensure_lens_options
1080
+ type update_lens_options = {
1081
+ lens_id: String,
1082
+ ?name: String,
1083
+ ?description: String?,
1084
+ ?type: lens_type,
1085
+ ?active: bool,
957
1086
  ?transform: image_transform_options_input?,
958
1087
  ?request_options: request_options
959
1088
  }
960
1089
 
961
1090
  type asset_url_options = {
962
- ?viewer_claims: viewer_claims,
963
- # The asset ID or external ID.
964
- asset_identifier: String,
965
- # `rendered` is the default. `original` takes no lens or transform; `placeholder` is a small blurred PNG
966
- # that takes no lens or transform.
967
- ?resource: "original" | "rendered" | "placeholder",
968
- # Transform options replace the lens's options of the same name.
1091
+ # Exactly one of `asset_id` and `external_id`.
1092
+ ?asset_id: String,
1093
+ ?external_id: String,
1094
+ # The client's project by default.
1095
+ ?project_id: String,
1096
+ # Without one, the URL is the asset URL itself. `original`, `hls` (the HLS master playlist),
1097
+ # `embed` (the page that shows the asset), `placeholder` (a small blurred PNG) and `info` take no
1098
+ # lens or transform; `preview` takes them, and `rendered` does when it is an image.
1099
+ ?resource: cdn_resource,
1100
+ # Transform options replace the lens's options of the same name; both need a resource.
969
1101
  ?lens: String,
970
1102
  ?transform: transform_input,
971
- # Appends `?ageConfirmed=true`, so a public `age-restricted` asset is served from this URL. Set it
972
- # only where your app has already decided the viewer may see age-restricted content.
1103
+ # Unsigned viewer assertions, sent as the `viewerClaims` query without the defaults. Set
1104
+ # `age_confirmed` only where your app has already decided the viewer may see age-restricted content.
1105
+ ?viewer_claims: viewer_claims,
1106
+ ?request_options: request_options
973
1107
  }
974
1108
  type serve_options = {
1109
+ ?asset_id: String,
1110
+ ?external_id: String,
1111
+ ?project_id: String,
975
1112
  ?viewer_claims: viewer_claims,
976
- asset_identifier: String,
977
- ?resource: "original" | "rendered" | "placeholder",
1113
+ # `rendered` by default.
1114
+ ?resource: cdn_resource,
978
1115
  ?lens: String,
979
1116
  ?transform: transform_input,
980
1117
  ?init: { ?method: "GET" | "HEAD", ?headers: Hash[String, String] },
@@ -986,6 +1123,8 @@ module CalmLens
986
1123
  type: event_type,
987
1124
  ?id: String,
988
1125
  ?project_id: String,
1126
+ # The mock API key (`{ 'type' => 'api-key', 'id' => nil }`) when omitted.
1127
+ ?actor: actor_input,
989
1128
  ?severity: event_severity,
990
1129
  ?title: String,
991
1130
  ?description: String?,