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.
@@ -15,25 +15,34 @@ module CalmLens
15
15
  WEBHOOK_SIGNATURE_TOLERANCE_SECONDS = 300
16
16
 
17
17
  # A verified webhook delivery. The body has the shape of an {Events#list} item:
18
- # `{id, projectId, type, severity, title, description, assetId, asset, facts, createdAt}`.
18
+ # `{id, projectId, actor, type, severity, title, description, assetId, assetSequence, asset, facts, createdAt}`.
19
19
  # Fields CalmLens adds later are kept in {#payload}, as are unknown asset and fact fields.
20
20
  #
21
21
  # @!attribute id [String] the event ID.
22
22
  # @!attribute project_id [String]
23
+ # @!attribute actor [Hash, nil] who caused the event: `{'type', 'id'}`, with `type` `user`, `api-key`,
24
+ # `automated` or `system`, and `id` the user's or API key's ID, or nil when it was not recorded.
23
25
  # @!attribute type [String] such as `asset.allowed`. New types may appear: ignore unknown ones.
24
26
  # @!attribute severity [String, nil] `low` or `high`.
25
27
  # @!attribute title [String, nil]
26
28
  # @!attribute description [String, nil]
27
29
  # @!attribute asset_id [String, nil]
30
+ # @!attribute asset_sequence [Integer, nil] increases with each event about the same asset; nil for
31
+ # events not about an asset. Deliveries can arrive out of order: see {#newer_than?}.
28
32
  # @!attribute asset [Hash, nil] the asset's status when the event was created.
29
33
  # @!attribute facts [Array<Hash>] `{'key', 'value', 'url'?}` entries registered for the event type.
30
34
  # @!attribute created_at [Integer] milliseconds since the epoch.
31
35
  # @!attribute payload [Hash{String => Object}] the delivery body as received, with every field.
32
- WebhookEvent = Struct.new(:id, :project_id, :type, :severity, :title, :description, :asset_id, :asset, :facts,
33
- :created_at, :payload, keyword_init: true) do
36
+ WebhookEvent = Struct.new(:id, :project_id, :actor, :type, :severity, :title, :description, :asset_id, :asset_sequence, :asset,
37
+ :facts, :created_at, :payload, keyword_init: true) do
34
38
  # @return [Boolean] true for a test send from the portal or CLI.
35
39
  def test? = Webhooks.test_event?(self)
36
40
 
41
+ # @param last_sequence [Integer, nil] the highest `assetSequence` applied for this event's asset
42
+ # @return [Boolean] whether to apply this event after it.
43
+ # @see Webhooks.newer_asset_event?
44
+ def newer_than?(last_sequence) = Webhooks.newer_asset_event?(self, last_sequence)
45
+
37
46
  # @return [Hash{String => Object}] the delivery body as received, with every field.
38
47
  def to_payload = payload
39
48
  end
@@ -79,16 +88,34 @@ module CalmLens
79
88
  facts.is_a?(Array) && facts.any? { |fact| fact.is_a?(Hash) && fact['key'] == 'test' && fact['value'] == true }
80
89
  end
81
90
 
91
+ # Whether to apply `event` after `last_sequence`, the highest `assetSequence` you have applied
92
+ # for its asset (nil when none). Deliveries can arrive out of order: an event about an asset is
93
+ # newer only with a higher `assetSequence`, so a retried or repeated delivery of an earlier one
94
+ # returns false. Events that aren't about an asset have no sequence and are always new. Store
95
+ # the highest `assetSequence` applied per `assetId` and ignore lower ones.
96
+ # @param event [WebhookEvent, Hash] a parsed delivery, or a delivery body with string keys
97
+ # @param last_sequence [Integer, nil]
98
+ # @return [Boolean]
99
+ def newer_asset_event?(event, last_sequence)
100
+ sequence = event.is_a?(Hash) ? event['assetSequence'] : event.asset_sequence
101
+ sequence.nil? || last_sequence.nil? || sequence > last_sequence
102
+ end
103
+
82
104
  # Converts an event from {Events#list} to the JSON body of its webhook delivery, which has the
83
- # same fields: `description`, `assetId` and `asset` are nil when absent.
105
+ # same fields: `description`, `assetId`, `assetSequence` and `asset` are nil when absent, and
106
+ # `actor` is left out when the event has none.
84
107
  # @param event [Hash] an event with string keys, as {Events#list} returns it
85
- # @return [Hash] `{ 'id', 'projectId', 'type', 'severity', 'title', 'description', 'assetId', 'asset', 'facts', 'createdAt' }`
108
+ # @return [Hash] `{ 'id', 'projectId', 'actor', 'type', 'severity', 'title', 'description', 'assetId',
109
+ # 'assetSequence', 'asset', 'facts', 'createdAt' }`
86
110
  def to_payload(event)
87
111
  raise Internal.invalid('event must be a Hash') unless event.is_a?(Hash)
88
112
 
89
- { 'id' => event['id'], 'projectId' => event['projectId'], 'type' => event['type'], 'severity' => event['severity'],
90
- 'title' => event['title'], 'description' => event['description'], 'assetId' => event['assetId'],
91
- 'asset' => event['asset'], 'facts' => event['facts'], 'createdAt' => event['createdAt'] }
113
+ payload = { 'id' => event['id'], 'projectId' => event['projectId'] }
114
+ payload['actor'] = event['actor'] if event.key?('actor')
115
+ payload.merge('type' => event['type'], 'severity' => event['severity'], 'title' => event['title'],
116
+ 'description' => event['description'], 'assetId' => event['assetId'],
117
+ 'assetSequence' => event['assetSequence'], 'asset' => event['asset'], 'facts' => event['facts'],
118
+ 'createdAt' => event['createdAt'])
92
119
  end
93
120
 
94
121
  # Checks a delivery's signature and freshness in constant time. Pass the `signature` and
@@ -149,9 +176,10 @@ module CalmLens
149
176
  body = JSON.parse(payload.dup.force_encoding(Encoding::UTF_8))
150
177
  raise WebhookVerificationError.new(SdkErrorCodes::INVALID_WEBHOOK_PAYLOAD, 'Webhook body is not a CalmLens event') unless event?(body)
151
178
 
152
- WebhookEvent.new(id: body['id'], project_id: body['projectId'], type: body['type'], severity: body['severity'],
179
+ WebhookEvent.new(id: body['id'], project_id: body['projectId'], actor: body['actor'], type: body['type'], severity: body['severity'],
153
180
  title: body['title'], description: body['description'], asset_id: body['assetId'],
154
- asset: body['asset'], facts: body.fetch('facts', []), created_at: body['createdAt'], payload: body)
181
+ asset_sequence: body['assetSequence'], asset: body['asset'], facts: body.fetch('facts', []),
182
+ created_at: body['createdAt'], payload: body)
155
183
  rescue JSON::ParserError, EncodingError => e
156
184
  raise WebhookVerificationError.new(SdkErrorCodes::INVALID_WEBHOOK_PAYLOAD, 'Webhook body is not JSON'), cause: e
157
185
  end
@@ -163,9 +191,17 @@ module CalmLens
163
191
  body['projectId'].is_a?(String) && body['createdAt'].is_a?(Numeric)
164
192
 
165
193
  optional = ->(key, *types) { !body.key?(key) || types.any? { |type| type.nil? ? body[key].nil? : body[key].is_a?(type) } }
166
- asset = body['asset']
167
194
  optional.call('severity', String) && optional.call('title', String) && optional.call('description', String, nil) &&
168
- optional.call('assetId', String, nil) && (asset.nil? || (asset.is_a?(Hash) && asset['id'].is_a?(String))) &&
195
+ optional.call('assetId', String, nil) && optional.call('assetSequence', Numeric, nil) && nested?(body)
196
+ end
197
+
198
+ # The nested fields, when present: `actor` is `{type, id}` with a String type and a String or null
199
+ # ID, `asset` has a String `id` and `facts` lists `{key, value, url?}` entries.
200
+ def nested?(body)
201
+ actor = body.fetch('actor', { 'type' => '' })
202
+ asset = body['asset']
203
+ actor.is_a?(Hash) && actor['type'].is_a?(String) && (actor['id'].nil? || actor['id'].is_a?(String)) &&
204
+ (asset.nil? || (asset.is_a?(Hash) && asset['id'].is_a?(String))) &&
169
205
  (!body.key?('facts') || (body['facts'].is_a?(Array) && body['facts'].all? { |fact| fact?(fact) }))
170
206
  end
171
207
 
@@ -191,7 +227,7 @@ module CalmLens
191
227
  raise Internal.invalid("Webhook payload must be the raw body String, not a #{payload.class}. " \
192
228
  'Read request.raw_post (Rails) or request.body.read (Rack, Sinatra) before parsing.')
193
229
  end
194
- private_class_method :decode_event, :event?, :fact?, :header, :raw_body
230
+ private_class_method :decode_event, :event?, :nested?, :fact?, :header, :raw_body
195
231
  end
196
232
 
197
233
  # @see Webhooks.signature_header
@@ -214,4 +250,13 @@ module CalmLens
214
250
 
215
251
  # @see Webhooks.test_event?
216
252
  def self.test_webhook_event?(...) = Webhooks.test_event?(...)
253
+
254
+ # @see Webhooks.newer_asset_event?
255
+ def self.newer_asset_event?(...) = Webhooks.newer_asset_event?(...)
256
+
257
+ # @see EventFacts.value
258
+ def self.get_event_fact(...) = EventFacts.value(...)
259
+
260
+ # @see EventFacts.values
261
+ def self.get_event_facts(...) = EventFacts.values(...)
217
262
  end
data/sig/calmlens.rbs CHANGED
@@ -121,6 +121,7 @@ module CalmLens
121
121
  attr_reader upload_tokens: UploadTokens
122
122
  attr_reader events: Events
123
123
  attr_reader cdn: CDN
124
+ attr_reader lenses: Lenses
124
125
  attr_reader project_id: String
125
126
  attr_reader base_url: String
126
127
  attr_reader cdn_base_url: String
@@ -148,16 +149,12 @@ module CalmLens
148
149
  end
149
150
 
150
151
  class Assets < Resource
151
- # The moderation status before a decision.
152
- PENDING_MODERATION_STATUS: String
153
- # Processing statuses after which no decision arrives without a retry.
154
- FINISHED_PROCESSING_STATUSES: Array[String]
152
+ # The classification statuses of a settled asset; wait_for_decision returns at the first.
153
+ SETTLED_STATUSES: Array[String]
155
154
  DECISION_POLL_FIRST_DELAY: Float
156
155
  DECISION_POLL_FACTOR: Float
157
156
  DECISION_POLL_MAX_DELAY: Float
158
157
  DEFAULT_DECISION_TIMEOUT: Integer
159
- DEFAULT_SIGNED_URL_SECONDS: Integer
160
- MAX_SIGNED_URL_SECONDS: Integer
161
158
  BATCH_OPERATIONS: Array[asset_batch_operation]
162
159
  MAX_BATCH_ASSETS: Integer
163
160
 
@@ -168,24 +165,30 @@ module CalmLens
168
165
  def list_children: (list_asset_children_options options) -> asset_page
169
166
  def each_child: (list_asset_children_options options) { (asset) -> void } -> nil
170
167
  | (list_asset_children_options options) -> Enumerator[asset, nil]
168
+ def list_timeline: (list_asset_timeline_options options) -> asset_timeline_page
169
+ def each_timeline_segment: (list_asset_timeline_options options) { (media_segment) -> void } -> nil
170
+ | (list_asset_timeline_options options) -> Enumerator[media_segment, nil]
171
171
  def retrieve: (asset_id_options options) -> asset
172
172
  def wait_for_decision: (wait_for_decision_options options) -> asset
173
173
  def update: (update_asset_options options) -> asset
174
174
  def retry: (asset_id_options options) -> asset
175
175
  def decide: (decide_asset_options options) -> asset
176
176
  def explain: (explain_asset_options options) -> asset
177
- def delete_content: (asset_id_options options) -> asset
177
+ def remove_content: (asset_id_options options) -> asset
178
178
  def delete: (asset_id_options options) -> nil
179
179
  def batch: (batch_assets_options options) -> batch_assets_response
180
180
  def move: (move_asset_options options) -> asset
181
- def create_signed_url: (create_signed_url_options options) -> signed_url
182
181
  def create: (upload_options options) -> asset
183
182
  def classify: (upload_options options) -> asset
184
183
  def upload_part: (upload_part_options options) -> asset
184
+ # Waits between decision checks; a mock client's waits take no real time.
185
+ private def sleep: (Numeric seconds) -> void
185
186
  end
186
187
 
187
188
  class Folders < Resource
188
189
  def list: (?list_folders_options options) -> folder_page
190
+ def each: (?list_folders_options options) { (folder) -> void } -> nil
191
+ | (?list_folders_options options) -> Enumerator[folder, nil]
189
192
  def create: (create_folder_options options) -> folder
190
193
  def retrieve: (folder_id_options options) -> folder
191
194
  def update: (update_folder_options options) -> folder
@@ -195,26 +198,45 @@ module CalmLens
195
198
 
196
199
  class HashLists < Resource
197
200
  def list: (?list_hash_lists_options options) -> hash_list_page
201
+ def each: (?list_hash_lists_options options) { (hash_list) -> void } -> nil
202
+ | (?list_hash_lists_options options) -> Enumerator[hash_list, nil]
198
203
  def retrieve: (hash_list_id_options options) -> hash_list
199
204
  def create: (create_hash_list_options options) -> hash_list
200
205
  def update: (update_hash_list_options options) -> hash_list
201
206
  def delete: (hash_list_id_options options) -> nil
202
207
  def list_entries: (list_hash_list_entries_options options) -> hash_list_entry_page
208
+ def each_entry: (list_hash_list_entries_options options) { (hash_list_entry) -> void } -> nil
209
+ | (list_hash_list_entries_options options) -> Enumerator[hash_list_entry, nil]
203
210
  def add_entry: (add_hash_list_entry_options options) -> hash_list_entry
204
211
  def remove_entry: (hash_list_entry_id_options options) -> nil
205
212
  end
206
213
 
207
214
  class Policies < Resource
208
- def list: (?list_policies_options options) -> policy_list
215
+ def list: (?list_policies_options options) -> policy_page
216
+ def each: (?list_policies_options options) { (policy) -> void } -> nil
217
+ | (?list_policies_options options) -> Enumerator[policy, nil]
209
218
  def retrieve: (policy_id_options options) -> policy
219
+ # The policy the project moderates with.
220
+ def retrieve_assigned: (?request_only_options options) -> policy
210
221
  def create: (create_policy_options options) -> policy
211
222
  def update: (update_policy_options options) -> policy
212
- def apply_preset: (apply_policy_preset_options options) -> policy
223
+ def reset: (restore_policy_options options) -> policy
224
+ def upgrade: (restore_policy_options options) -> policy
213
225
  def set_automatic_updates: (set_policy_automatic_updates_options options) -> policy
214
226
  def delete: (policy_id_options options) -> nil
215
227
  def assign: (assign_policy_options options) -> policy
216
228
  end
217
229
 
230
+ class Lenses < Resource
231
+ def list: (?list_lenses_options options) -> lens_page
232
+ def each: (?list_lenses_options options) { (lens) -> void } -> nil
233
+ | (?list_lenses_options options) -> Enumerator[lens, nil]
234
+ def create: (create_lens_options options) -> lens
235
+ def retrieve: (lens_id_options options) -> lens
236
+ def update: (update_lens_options options) -> lens
237
+ def delete: (lens_id_options options) -> nil
238
+ end
239
+
218
240
  class UploadTokens < Resource
219
241
  TOKEN_PREFIX: String
220
242
  SIGNING_CONTEXT: String
@@ -238,7 +260,19 @@ module CalmLens
238
260
  end
239
261
 
240
262
  class CDN < Resource
263
+ # Every CDN resource beneath an asset URL.
264
+ RESOURCES: Array[cdn_resource]
265
+ # A signed asset URL's lifetime in seconds when `expires_in` is omitted.
266
+ DEFAULT_SIGNED_URL_EXPIRES_IN: Integer
267
+ # The longest signed asset URL lifetime, in seconds.
268
+ MAX_SIGNED_URL_EXPIRES_IN: Integer
269
+ # The start of the asset segment that names an asset by its external ID.
270
+ EXTERNAL_ID_PREFIX: String
271
+ # The ISO 3166-1 alpha-2 countries a viewer's `region` can be.
272
+ VIEWER_COUNTRIES: Array[String]
241
273
  def get_asset_url: (asset_url_options options) -> String
274
+ def sign_asset_url: (sign_asset_url_options options) -> signed_asset_url
275
+ def get_asset_info: (String url, ?viewer_claims: viewer_claims?) -> asset_info
242
276
  def serve: (serve_options options) -> Response
243
277
  | [T] (serve_options options) { (Response) -> T } -> T
244
278
  end
@@ -247,12 +281,16 @@ module CalmLens
247
281
  class WebhookEvent < Struct[untyped]
248
282
  attr_accessor id: String
249
283
  attr_accessor project_id: String
284
+ # nil for a delivery without one.
285
+ attr_accessor actor: actor?
250
286
  # New types may appear: ignore unknown ones.
251
287
  attr_accessor type: event_type | String
252
288
  attr_accessor severity: event_severity?
253
289
  attr_accessor title: String?
254
290
  attr_accessor description: String?
255
291
  attr_accessor asset_id: String?
292
+ # Increases with each event about the same asset; nil for events not about an asset.
293
+ attr_accessor asset_sequence: Integer?
256
294
  attr_accessor asset: event_asset?
257
295
  attr_accessor facts: Array[event_fact]
258
296
  # Milliseconds since the Unix epoch.
@@ -260,9 +298,10 @@ module CalmLens
260
298
  # The delivery body as received, with every field.
261
299
  attr_accessor payload: Hash[String, json_value]
262
300
  def initialize: (?id: String, ?project_id: String, ?type: event_type | String, ?severity: event_severity?, ?title: String?,
263
- ?description: String?, ?asset_id: String?, ?asset: event_asset?, ?facts: Array[event_fact],
301
+ ?description: String?, ?asset_id: String?, ?asset_sequence: Integer?, ?asset: event_asset?, ?facts: Array[event_fact],
264
302
  ?created_at: Integer, ?payload: Hash[String, json_value]) -> void
265
303
  def test?: () -> bool
304
+ def newer_than?: (Integer? last_sequence) -> bool
266
305
  # The delivery body as received, with every field.
267
306
  def to_payload: () -> Hash[String, json_value]
268
307
  end
@@ -286,6 +325,16 @@ module CalmLens
286
325
  def self.parse_event: (payload: String, secret: String, ?signature: String?, ?timestamp: String?, ?headers: webhook_headers?,
287
326
  ?tolerance_seconds: Integer, ?now: number) -> WebhookEvent
288
327
  def self.test_event?: (WebhookEvent | Hash[String, untyped] event) -> bool
328
+ def self.newer_asset_event?: (WebhookEvent | Hash[String, untyped] event, Integer? last_sequence) -> bool
329
+ # The value of an event's fact by key (the first, when the event repeats it), or nil without one.
330
+ def self.get_event_fact: (WebhookEvent | Hash[String, untyped] event, String key) -> event_fact_value
331
+ # An event's facts as values by key; a repeated key keeps its first value.
332
+ def self.get_event_facts: (WebhookEvent | Hash[String, untyped] event) -> Hash[String, event_fact_value]
333
+ end
334
+
335
+ module EventFacts
336
+ def self.value: (WebhookEvent | Hash[String, untyped] event, String key) -> event_fact_value
337
+ def self.values: (WebhookEvent | Hash[String, untyped] event) -> Hash[String, event_fact_value]
289
338
  end
290
339
 
291
340
  def self.create_webhook_signature_header: (payload: String, timestamp: String | Integer, secret: String) -> String
@@ -298,6 +347,11 @@ module CalmLens
298
347
  def self.parse_webhook_event: (payload: String, secret: String, ?signature: String?, ?timestamp: String?,
299
348
  ?headers: webhook_headers?, ?tolerance_seconds: Integer, ?now: number) -> WebhookEvent
300
349
  def self.test_webhook_event?: (WebhookEvent | Hash[String, untyped] event) -> bool
350
+ def self.newer_asset_event?: (WebhookEvent | Hash[String, untyped] event, Integer? last_sequence) -> bool
351
+ # The value of an event's fact by key (the first, when the event repeats it), or nil without one.
352
+ def self.get_event_fact: (WebhookEvent | Hash[String, untyped] event, String key) -> event_fact_value
353
+ # An event's facts as values by key; a repeated key keeps its first value.
354
+ def self.get_event_facts: (WebhookEvent | Hash[String, untyped] event) -> Hash[String, event_fact_value]
301
355
 
302
356
  # require 'calmlens/testing'
303
357
  module Testing
@@ -366,6 +420,8 @@ module CalmLens
366
420
  def enqueue: (body: json_input, ?status: Integer, ?headers: Hash[String, String]) -> self
367
421
  def enqueue_raw: (body: String, ?status: Integer, ?headers: Hash[String, String]) -> self
368
422
  def enqueue_error: (Exception error) -> self
423
+ # Fetches a mock CDN URL with a GET and without the API key, as a browser would.
424
+ def fetch_cdn: (String url) -> Response
369
425
  def enqueue_event: (mock_event_input event) -> event
370
426
  # Applies a reviewer's decision and adds the matching `asset.<decision>` event.
371
427
  def decide: (String asset_id, asset_moderation_decision decision) -> asset
@@ -416,6 +472,12 @@ module CalmLens
416
472
  QUALIFIERS: Hash[String, Array[String]]
417
473
  # Qualifiers the input type sets, which a TestInputs scenario cannot list.
418
474
  INPUT_QUALIFIERS: Array[String]
475
+ # Test scenario detections: entries per list, the basis points of a full side, the oldest age
476
+ # and the age presets.
477
+ TEST_DETECTIONS_MAX: Integer
478
+ TEST_DETECTION_BOX_MAX: Integer
479
+ TEST_FACE_AGE_MAX: Integer
480
+ TEST_FACE_AGE_PRESETS: Array[String]
419
481
  end
420
482
 
421
483
  # Signed test inputs: text codes, test images and media phrases signed with a project's secret
@@ -426,9 +488,20 @@ module CalmLens
426
488
  type regional_action = { "region" => region, "action" => "limit" | "age-restrict" | "block" }
427
489
  # One qualifying instance; set an action on every instance or on none.
428
490
  type test_instance = { "category" => classification_category, ?"score" => number, ?"action" => action, "qualifiers" => Array[String] }
491
+ # `[left, top, width, height]`: Integers in basis points of the image, 0 to 10000, inside it.
492
+ type detection_box = [Integer, Integer, Integer, Integer]
493
+ # A person a test image reports, with an optional Integer confidence from 0 to 100.
494
+ type test_person = { "box" => detection_box, ?"confidence" => Integer }
495
+ # A face's age: a preset, or a range of Integers from 0 to 120 with `low` at most `high`.
496
+ type test_face_age = "adult" | "minor" | { "low" => Integer, "high" => Integer }
497
+ # A face a test image reports, with an optional confidence and age.
498
+ type test_face = { "box" => detection_box, ?"confidence" => Integer, ?"age" => test_face_age }
499
+ # The people and faces a test image reports: at most 32 of each, or `unavailable` to report the
500
+ # feature as not evaluated.
501
+ type test_detections = { ?"people" => Array[test_person] | "unavailable", ?"faces" => Array[test_face] | "unavailable" }
429
502
  # A scenario with String keys; Symbol and snake_case keys are accepted as a plain Hash.
430
503
  type scenario = { ?"regionalActions" => Array[regional_action], ?"unassessedCategories" => Array[classification_category],
431
- "instances" => Array[test_instance] }
504
+ "instances" => Array[test_instance], ?"detections" => test_detections }
432
505
  type signal = classification_category | "sexual.involving-minors" | "harassment.insult" | "sexual.adult"
433
506
  | "hate.regional-symbol" | "violence.graphic"
434
507
  type media_signal = classification_category | "violence.graphic"
@@ -447,7 +520,8 @@ module CalmLens
447
520
  REGIONS: Array[region]
448
521
  SIGNALS: Array[signal]
449
522
  MEDIA_SIGNALS: Array[media_signal]
450
- # clean, limited, adult_image, adult_text, regional_delivery, germany and mixed (deeply frozen).
523
+ # clean, limited, adult_image, adult_text, regional_delivery, germany, mixed, one_face, no_face,
524
+ # adult_face, minor_face and group (deeply frozen).
451
525
  PRESETS: Hash[Symbol, scenario]
452
526
 
453
527
  def self.for_signal: (signal signal, ?("text" | "image") kind) -> scenario
data/sig/error_codes.rbs CHANGED
@@ -9,6 +9,8 @@ module CalmLens
9
9
  REGIONAL_EVIDENCE_REQUIRED: String
10
10
  SIGNED_URL_EXPIRED: String
11
11
  SIGNED_URL_INVALID: String
12
+ SIGNED_URL_ORIGINAL_NOT_GRANTED: String
13
+ INVALID_REQUEST: String
12
14
  INVALID_TYPE: String
13
15
  TOO_SMALL: String
14
16
  TOO_BIG: String
@@ -17,7 +19,7 @@ module CalmLens
17
19
  UNKNOWN_FIELD: String
18
20
  UNSUPPORTED_CONTENT_TYPE: String
19
21
  INVALID_FILTER: String
20
- INVALID_ORDERING_FIELD: String
22
+ UNSUPPORTED_ORDERING_FIELD: String
21
23
  ROUTE_NOT_FOUND: String
22
24
  INTERNAL_ERROR: String
23
25
  UNAUTHENTICATED: String
@@ -26,24 +28,20 @@ module CalmLens
26
28
  SEARCH_UNAVAILABLE: String
27
29
  INVALID_TRANSFORM: String
28
30
  INVALID_TRANSFORM_OPTIONS: String
29
- REMOTE_URL_REDIRECT_LIMIT: String
30
- COPYRIGHT_CONTENT_HELD: String
31
- DOWNLOAD_PERMISSION_REQUIRED: String
31
+ REMOTE_URL_TOO_MANY_REDIRECTS: String
32
32
  INVALID_CURSOR: String
33
- MISSING_TOKEN: String
33
+ MISSING_API_KEY: String
34
34
  INVALID_API_KEY: String
35
35
  API_KEY_PROJECT_MISMATCH: String
36
36
  API_KEY_NOT_ACCEPTED: String
37
37
  PERMISSION_DENIED: String
38
- FILE_TOO_LARGE: String
39
- MULTIPART_IMAGE_TOO_LARGE: String
40
- IMAGE_EXCEEDED_MAX_DIMENSIONS: String
41
- IMAGE_INVALID_INPUT: String
42
- IMAGE_UNSUPPORTED_FORMAT: String
43
- IMAGE_INPUT_LIMIT: String
44
- UPLOAD_LIMIT_EXCEEDED: String
45
- SPEND_LIMIT_REACHED: String
46
- INVALID_UPLOAD_MIME_TYPE: String
38
+ UPLOAD_TOO_LARGE: String
39
+ DOCUMENT_TOO_MANY_ITEMS: String
40
+ INVALID_IMAGE: String
41
+ IMAGE_TOO_LARGE: String
42
+ FREE_UPLOADS_EXHAUSTED: String
43
+ UPLOADS_PAUSED: String
44
+ UNSUPPORTED_UPLOAD_TYPE: String
47
45
  INVALID_UPLOAD_PAYLOAD: String
48
46
  USE_UPLOAD_PART: String
49
47
  UPLOAD_NOT_OPEN: String
@@ -53,12 +51,14 @@ module CalmLens
53
51
  INVALID_IDEMPOTENCY_KEY: String
54
52
  IDEMPOTENCY_KEY_REUSED: String
55
53
  IDEMPOTENT_REQUEST_IN_PROGRESS: String
54
+ NO_RENDERED_VERSION: String
56
55
  ASSET_NOT_FOUND: String
57
56
  PROJECT_NOT_FOUND: String
57
+ ASSET_CHILD_NOT_DELETABLE: String
58
58
  ASSET_REVIEW_CHANGED: String
59
59
  ASSET_REVIEW_NOTE_REQUIRED: String
60
60
  ASSET_UPDATE_FAILED: String
61
- ASSET_SAFETY_HELD: String
61
+ ASSET_HELD: String
62
62
  ASSET_PROCESSING: String
63
63
  ASSET_DECISION_NOT_ALLOWED: String
64
64
  ASSET_DECISION_UNCHANGED: String
@@ -74,7 +74,8 @@ module CalmLens
74
74
  DUPLICATE_FOLDER_NAME: String
75
75
  FOLDER_NOT_EMPTY: String
76
76
  FOLDER_PARENT_CYCLE: String
77
- LENS_VERSION_CONFLICT: String
77
+ LENS_NOT_FOUND: String
78
+ LENS_IDENTIFIER_TAKEN: String
78
79
  LENS_IDENTIFIER_RESERVED: String
79
80
  HASH_LIST_NOT_FOUND: String
80
81
  HASH_LIST_ENTRY_NOT_FOUND: String
@@ -94,9 +95,7 @@ module CalmLens
94
95
  UPLOAD_PRESET_DISABLED: String
95
96
  UPLOAD_PRESET_TOKEN_REQUIRED: String
96
97
  REMOTE_URL_NOT_ALLOWED: String
97
- WEBSITE_RATE_LIMIT_EXCEEDED: String
98
- UPLOAD_PRESET_CONTENT_TYPE_NOT_ALLOWED: String
99
- UPLOAD_PRESET_TOO_LARGE: String
98
+ WEBSITE_RATE_LIMIT_REACHED: String
100
99
  UPLOAD_PRESET_DAILY_LIMIT_REACHED: String
101
100
  UPLOAD_PRESET_ORIGIN_NOT_ALLOWED: String
102
101
  UPLOAD_PRESET_FIELD_NOT_ALLOWED: String
@@ -112,7 +111,6 @@ module CalmLens
112
111
  APPEAL_ALREADY_REVIEWED: String
113
112
  APPEAL_DECISION_CHANGED: String
114
113
  APPEAL_INVALID_ACTION: String
115
- APPEAL_SAFETY_HELD: String
116
114
  APPEAL_CONTENT_UNAVAILABLE: String
117
115
  STATUSES: Hash[String, Integer]
118
116
  end
data/sig/qualifiers.rbs CHANGED
@@ -42,6 +42,8 @@ module CalmLens
42
42
  ?"sexual-non-consensual" => qualifier_result,
43
43
  ?"sexual-intimate-image-abuse" => qualifier_result,
44
44
  ?"sexual-extreme" => qualifier_result,
45
+ ?"sexual-strangulation" => qualifier_result,
46
+ ?"sexual-incest" => qualifier_result,
45
47
  ?"sexual-minors" => qualifier_result,
46
48
  ?"sexual-solicitation" => qualifier_result,
47
49
  ?"sexual-paid" => qualifier_result,