noresponse 3.0.1 → 3.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ced920c7288c6434e1fbd06de24541b1ac3bec7dccb43bcef7aa7ccad375377
4
- data.tar.gz: 67f9fc2cce7b114edd72d84031d91312c04414114fd61ce3f7db0c3e63c6714e
3
+ metadata.gz: 6272c4f6b966191e3e8d1879bb44b6eea0ff2787788deddda4c756eb41505f57
4
+ data.tar.gz: a0e14b7bffcc0e479bd3eff446a429f0a0219fa476a1b0d12eb20d94b489db04
5
5
  SHA512:
6
- metadata.gz: a7c8af727605dcef753fb10d0d3c46bf0a5fc8c90bb411d0117aceb023fb5807af788984dd5d77a09dc984a0979ee797ea75cdf6c301edc8d4aa4f74e3c83fdd
7
- data.tar.gz: 02faf461ec16e415a4c799557fff8ae5e9bdcd5f62a192dfa5682c0a37bdbe10c00176d71b7de6f360616442f00b055ce429be012dc70a24acf75b18bdc3fc96
6
+ metadata.gz: a5560fb17f62d0bb9818153ca09b167961a889e4632063104dc4b39187d129f9f70c61d3b2b8616bd2ee5f8fe3b53d7fab97b290dffa26b89bd4e192aacd100a
7
+ data.tar.gz: bc91446c598e079f66b8ac40e687bded47e02b320afd56c064c089e08b1713ceaeba1a861644a37ad124c11a9508395cf7161a5a153ef7fee5571b9ee035a7ef
@@ -0,0 +1,336 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "faraday"
5
+ require "faraday/multipart"
6
+ require "faraday/retry"
7
+ require "sorbet-runtime"
8
+
9
+ require_relative "sdk_hooks/hooks"
10
+ require_relative "utils/retries"
11
+
12
+ module NoResponse
13
+ extend T::Sig
14
+
15
+ class KeyUsage
16
+ extend T::Sig
17
+
18
+ sig { params(sdk_config: SDKConfiguration).void }
19
+ def initialize(sdk_config)
20
+ @sdk_configuration = sdk_config
21
+ end
22
+
23
+ sig { params(base_url: String, url_variables: T.nilable(T::Hash[Symbol, T.any(String, T::Enum)])).returns(String) }
24
+ def get_url(base_url:, url_variables: nil)
25
+ sd_base_url, sd_options = @sdk_configuration.get_server_details
26
+
27
+ if base_url.nil?
28
+ base_url = sd_base_url
29
+ end
30
+
31
+ if url_variables.nil?
32
+ url_variables = sd_options
33
+ end
34
+
35
+ return Utils.template_url(base_url, url_variables)
36
+ end
37
+
38
+ sig {
39
+ params(
40
+ body: Models::Shared::KeyUsageBatchRequest,
41
+ idempotency_key: T.nilable(::String),
42
+ retries: T.nilable(Utils::RetryConfig),
43
+ timeout_ms: T.nilable(Integer),
44
+ http_headers: T.nilable(T::Hash[T.any(String, Symbol), String])
45
+ )
46
+ .returns(Models::Operations::RecordKeyUsageResponse)
47
+ }
48
+ def record(body:, idempotency_key: nil, retries: nil, timeout_ms: nil, http_headers: nil)
49
+ # record - Report requests made with API keys your signup gate issued.
50
+ # Records requests made with API keys your signup gate issued to your accounts, one event per request: the key's SHA-256 (the issued_credential.sha256 the account's assessment carried), the client IP, the time and optionally the user agent, model and token counts. Most callers use the SDK's usage buffer, which batches events and sends them in the background. Sampling is allowed: sample_rate weights an event's request and token counts. Requires the assess scope. Idempotency-Key is optional in the SDK and handled as on POST /v1/assessments: a retry with the same key and body answers the same record with Idempotent-Replayed: true and counts nothing again; a different body answers 409. A batch holds 1 to 500 events and at most 256 KiB. No raw event is kept: usage is aggregated per key, and IPs, user agents and models are kept only as keyed digests, with the IP's country, for 24 hours. When one key is used from 20 or more IP addresses, or 3 or more countries, within 24 hours, every account whose assessment carried that key gets the shared_api_key reason for 30 days.
51
+ request = Models::Operations::RecordKeyUsageRequest.new(
52
+ body: body,
53
+ idempotency_key: idempotency_key
54
+ )
55
+ url, params = @sdk_configuration.get_server_details
56
+ base_url = Utils.template_url(url, params)
57
+ url = "#{base_url}/v1/key_usage/batches"
58
+ headers = Utils.get_headers(request)
59
+ headers = T.cast(headers, T::Hash[String, String])
60
+ req_content_type, data, form = Utils.serialize_request_body(request, false, false, :body, :json)
61
+ headers["content-type"] = req_content_type
62
+ raise StandardError, "request body is required" if data.nil? && form.nil?
63
+
64
+ if form && !form.empty?
65
+ body = Utils.encode_form(form)
66
+ elsif Utils.match_content_type(req_content_type, "application/x-www-form-urlencoded")
67
+ body = URI.encode_www_form(T.cast(data, T::Hash[Symbol, Object]))
68
+ else
69
+ body = data
70
+ end
71
+
72
+ headers["Accept"] = "application/json"
73
+ headers["user-agent"] = @sdk_configuration.user_agent
74
+ retries ||= @sdk_configuration.retry_config
75
+ retries ||= Utils::RetryConfig.new(
76
+ backoff: Utils::BackoffStrategy.new(
77
+ exponent: 2.0,
78
+ initial_interval: 500,
79
+ max_elapsed_time: 30_000,
80
+ max_interval: 8000
81
+ ),
82
+ retry_connection_errors: true,
83
+ strategy: "backoff"
84
+ )
85
+ retry_options = retries.to_faraday_retry_options(initial_time: Time.now)
86
+ retry_options[:retry_statuses] = [408, 429, 500, 501, 502, 503, 504, 505]
87
+
88
+ security = @sdk_configuration.security_source&.call
89
+
90
+ timeout = (timeout_ms.to_f / 1000) unless timeout_ms.nil?
91
+ timeout ||= @sdk_configuration.timeout
92
+
93
+ connection = @sdk_configuration.client.dup
94
+ connection.use(Utils::RetryMiddleware, retry_options)
95
+
96
+ hook_ctx = SDKHooks::HookContext.new(
97
+ config: @sdk_configuration,
98
+ base_url: base_url,
99
+ oauth2_scopes: nil,
100
+ operation_id: "recordKeyUsage",
101
+ security_source: @sdk_configuration.security_source
102
+ )
103
+
104
+ error = T.let(nil, T.nilable(StandardError))
105
+ http_response = T.let(nil, T.nilable(Faraday::Response))
106
+
107
+ begin
108
+ http_response = T.must(connection).post(url) do |req|
109
+ req.body = body
110
+ req.headers.merge!(headers)
111
+ req.options.timeout = timeout unless timeout.nil?
112
+ Utils.configure_request_security(req, security)
113
+ http_headers&.each do |key, value|
114
+ req.headers[key.to_s] = value
115
+ end
116
+
117
+ @sdk_configuration.hooks.before_request(
118
+ hook_ctx: SDKHooks::BeforeRequestHookContext.new(
119
+ hook_ctx: hook_ctx
120
+ ),
121
+ request: req
122
+ )
123
+ end
124
+
125
+ rescue StandardError => e
126
+ error = e
127
+ ensure
128
+ if http_response.nil? || Utils.error_status?(http_response.status)
129
+ http_response = @sdk_configuration.hooks.after_error(
130
+ error: error,
131
+ hook_ctx: SDKHooks::AfterErrorHookContext.new(
132
+ hook_ctx: hook_ctx
133
+ ),
134
+ response: http_response
135
+ )
136
+ else
137
+ http_response = @sdk_configuration.hooks.after_success(
138
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
139
+ hook_ctx: hook_ctx
140
+ ),
141
+ response: http_response
142
+ )
143
+ end
144
+
145
+ if http_response.nil?
146
+ raise error if !error.nil?
147
+ raise "no response"
148
+ end
149
+ end
150
+
151
+ content_type = http_response.headers.fetch("Content-Type", "application/octet-stream")
152
+ if Utils.match_status_code(http_response.status, ["202"])
153
+ if Utils.match_content_type(content_type, "application/json")
154
+ @sdk_configuration.hooks.after_success(
155
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
156
+ hook_ctx: hook_ctx
157
+ ),
158
+ response: http_response
159
+ )
160
+ response_data = http_response.env.response_body
161
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Shared::KeyUsageBatch)
162
+ result = obj
163
+ response = Models::Operations::RecordKeyUsageResponse.new(
164
+ result: result,
165
+ headers: http_response.headers
166
+ )
167
+
168
+ return response
169
+ else
170
+ raise(
171
+ ::NoResponse::Models::Errors::APIStatusError.new(
172
+ status_code: http_response.status,
173
+ body: http_response.env.response_body,
174
+ raw_response: http_response
175
+ ),
176
+ "Unknown content type received"
177
+ )
178
+ end
179
+ elsif Utils.match_status_code(http_response.status, ["400"])
180
+ if Utils.match_content_type(content_type, "application/problem+json")
181
+ @sdk_configuration.hooks.after_success(
182
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
183
+ hook_ctx: hook_ctx
184
+ ),
185
+ response: http_response
186
+ )
187
+ response_data = http_response.env.response_body
188
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::BadRequestError)
189
+ raise obj
190
+ else
191
+ raise(
192
+ ::NoResponse::Models::Errors::APIStatusError.new(
193
+ status_code: http_response.status,
194
+ body: http_response.env.response_body,
195
+ raw_response: http_response
196
+ ),
197
+ "Unknown content type received"
198
+ )
199
+ end
200
+ elsif Utils.match_status_code(http_response.status, ["401"])
201
+ if Utils.match_content_type(content_type, "application/problem+json")
202
+ @sdk_configuration.hooks.after_success(
203
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
204
+ hook_ctx: hook_ctx
205
+ ),
206
+ response: http_response
207
+ )
208
+ response_data = http_response.env.response_body
209
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::AuthenticationError)
210
+ raise obj
211
+ else
212
+ raise(
213
+ ::NoResponse::Models::Errors::APIStatusError.new(
214
+ status_code: http_response.status,
215
+ body: http_response.env.response_body,
216
+ raw_response: http_response
217
+ ),
218
+ "Unknown content type received"
219
+ )
220
+ end
221
+ elsif Utils.match_status_code(http_response.status, ["403"])
222
+ if Utils.match_content_type(content_type, "application/problem+json")
223
+ @sdk_configuration.hooks.after_success(
224
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
225
+ hook_ctx: hook_ctx
226
+ ),
227
+ response: http_response
228
+ )
229
+ response_data = http_response.env.response_body
230
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::PermissionDeniedError)
231
+ raise obj
232
+ else
233
+ raise(
234
+ ::NoResponse::Models::Errors::APIStatusError.new(
235
+ status_code: http_response.status,
236
+ body: http_response.env.response_body,
237
+ raw_response: http_response
238
+ ),
239
+ "Unknown content type received"
240
+ )
241
+ end
242
+ elsif Utils.match_status_code(http_response.status, ["404"])
243
+ if Utils.match_content_type(content_type, "application/problem+json")
244
+ @sdk_configuration.hooks.after_success(
245
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
246
+ hook_ctx: hook_ctx
247
+ ),
248
+ response: http_response
249
+ )
250
+ response_data = http_response.env.response_body
251
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::NotFoundError)
252
+ raise obj
253
+ else
254
+ raise(
255
+ ::NoResponse::Models::Errors::APIStatusError.new(
256
+ status_code: http_response.status,
257
+ body: http_response.env.response_body,
258
+ raw_response: http_response
259
+ ),
260
+ "Unknown content type received"
261
+ )
262
+ end
263
+ elsif Utils.match_status_code(http_response.status, ["409"])
264
+ if Utils.match_content_type(content_type, "application/problem+json")
265
+ @sdk_configuration.hooks.after_success(
266
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
267
+ hook_ctx: hook_ctx
268
+ ),
269
+ response: http_response
270
+ )
271
+ response_data = http_response.env.response_body
272
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::ConflictError)
273
+ raise obj
274
+ else
275
+ raise(
276
+ ::NoResponse::Models::Errors::APIStatusError.new(
277
+ status_code: http_response.status,
278
+ body: http_response.env.response_body,
279
+ raw_response: http_response
280
+ ),
281
+ "Unknown content type received"
282
+ )
283
+ end
284
+ elsif Utils.match_status_code(http_response.status, ["429"])
285
+ if Utils.match_content_type(content_type, "application/problem+json")
286
+ @sdk_configuration.hooks.after_success(
287
+ hook_ctx: SDKHooks::AfterSuccessHookContext.new(
288
+ hook_ctx: hook_ctx
289
+ ),
290
+ response: http_response
291
+ )
292
+ response_data = http_response.env.response_body
293
+ obj = Crystalline.unmarshal_json(JSON.parse(response_data), Models::Errors::RateLimitError)
294
+ raise obj
295
+ else
296
+ raise(
297
+ ::NoResponse::Models::Errors::APIStatusError.new(
298
+ status_code: http_response.status,
299
+ body: http_response.env.response_body,
300
+ raw_response: http_response
301
+ ),
302
+ "Unknown content type received"
303
+ )
304
+ end
305
+ elsif Utils.match_status_code(http_response.status, ["4XX"])
306
+ raise(
307
+ ::NoResponse::Models::Errors::APIStatusError.new(
308
+ status_code: http_response.status,
309
+ body: http_response.env.response_body,
310
+ raw_response: http_response
311
+ ),
312
+ "API error occurred"
313
+ )
314
+ elsif Utils.match_status_code(http_response.status, ["5XX"])
315
+ raise(
316
+ ::NoResponse::Models::Errors::APIStatusError.new(
317
+ status_code: http_response.status,
318
+ body: http_response.env.response_body,
319
+ raw_response: http_response
320
+ ),
321
+ "API error occurred"
322
+ )
323
+ else
324
+ raise(
325
+ ::NoResponse::Models::Errors::APIStatusError.new(
326
+ status_code: http_response.status,
327
+ body: http_response.env.response_body,
328
+ raw_response: http_response
329
+ ),
330
+ "Unknown status code received"
331
+ )
332
+
333
+ end
334
+ end
335
+ end
336
+ end
@@ -0,0 +1,36 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Operations
7
+
8
+ class RecordKeyUsageRequest
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ field :body, Models::Shared::KeyUsageBatchRequest, {'request': {'media_type': "application/json"}}
13
+ # Opaque client key, 16 to 128 characters of [A-Za-z0-9._:-] (a UUID or ULID fits). Scoped to the tenant principal and bound to the canonical body for 24 hours. Optional: the SDK generates a UUID when you omit it and sends the same key on every retry of the call.
14
+ field(
15
+ :idempotency_key,
16
+ Crystalline::Nilable.new(::String),
17
+ {'header': {'field_name': "Idempotency-Key", 'style': "simple", 'explode': false}}
18
+ )
19
+
20
+ sig { params(body: Models::Shared::KeyUsageBatchRequest, idempotency_key: T.nilable(::String)).void }
21
+ def initialize(body:, idempotency_key: nil)
22
+ @body = body
23
+ @idempotency_key = idempotency_key
24
+ end
25
+
26
+ sig { params(other: T.untyped).returns(T::Boolean) }
27
+ def ==(other)
28
+ return false unless other.is_a?(self.class)
29
+ return false unless @body == other.body
30
+ return false unless @idempotency_key == other.idempotency_key
31
+ true
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Operations::RecordKeyUsageRequest
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Operations::RecordKeyUsageRequest
9
+ def body
10
+ end
11
+
12
+ def body=(str_)
13
+ end
14
+
15
+ def idempotency_key
16
+ end
17
+
18
+ def idempotency_key=(str_)
19
+ end
20
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Operations
7
+
8
+ class RecordKeyUsageResponse
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ field :headers, Crystalline::Hash.new(Symbol, Crystalline::Array.new(::String))
13
+
14
+ field :result, Models::Shared::KeyUsageBatch, {}
15
+
16
+ sig { params(headers: T::Hash[Symbol, T::Array[::String]], result: Models::Shared::KeyUsageBatch).void }
17
+ def initialize(headers:, result:)
18
+ @headers = headers
19
+ @result = result
20
+ end
21
+
22
+ sig { params(other: T.untyped).returns(T::Boolean) }
23
+ def ==(other)
24
+ return false unless other.is_a?(self.class)
25
+ return false unless @headers == other.headers
26
+ return false unless @result == other.result
27
+ true
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,20 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Operations::RecordKeyUsageResponse
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Operations::RecordKeyUsageResponse
9
+ def headers
10
+ end
11
+
12
+ def headers=(str_)
13
+ end
14
+
15
+ def result
16
+ end
17
+
18
+ def result=(str_)
19
+ end
20
+ end
@@ -29,6 +29,8 @@ module NoResponse
29
29
  autoload :QueryAccountAssessmentsResponse, "no_response/models/operations/queryaccountassessments_response.rb"
30
30
  autoload :RecordAssessmentOutcomeRequest, "no_response/models/operations/recordassessmentoutcome_request.rb"
31
31
  autoload :RecordAssessmentOutcomeResponse, "no_response/models/operations/recordassessmentoutcome_response.rb"
32
+ autoload :RecordKeyUsageRequest, "no_response/models/operations/recordkeyusage_request.rb"
33
+ autoload :RecordKeyUsageResponse, "no_response/models/operations/recordkeyusage_response.rb"
32
34
  autoload :ReplayWebhookDeliveryRequest, "no_response/models/operations/replaywebhookdelivery_request.rb"
33
35
  autoload :ReplayWebhookDeliveryResponse, "no_response/models/operations/replaywebhookdelivery_response.rb"
34
36
  autoload :RotateApiKeyResponse, "no_response/models/operations/rotateapikey_response.rb"
@@ -4,7 +4,7 @@
4
4
  module NoResponse
5
5
  module Models
6
6
  module Shared
7
- # Body of the 200 answer to GET /v1/accounts/{account_id}: the one current risk of one of the calling tenant's accounts. It is the risk of the account's latest assessment that has a decision (status complete or partial), by created_at and then assessment_id, scored exactly as GET /v1/assessments/{assessment_id} scores that assessment. Its assessments are the account's history (GET /v1/accounts/{account_id}/assessments).
7
+ # Body of the 200 answer to GET /v1/accounts/{account_id}: the one current risk of one of the calling tenant's accounts. It is the risk of the account's latest assessment that has a decision (status complete or partial), by created_at and then assessment_id, scored exactly as GET /v1/assessments/{assessment_id} scores that assessment, plus the account's own reason shared_api_key when a key issued to the account was used from many IP addresses or countries (POST /v1/key_usage/batches). Its assessments are the account's history (GET /v1/accounts/{account_id}/assessments).
8
8
  class Account
9
9
  extend T::Sig
10
10
  include Crystalline::MetadataFields
@@ -59,7 +59,7 @@ module NoResponse
59
59
  ::String,
60
60
  {'format_json': {'letter_case': ::NoResponse::Utils.field_name("schema_version"), required: true}}
61
61
  )
62
- # Body of the 200 answer to GET /v1/accounts/{account_id}: the one current risk of one of the calling tenant's accounts. It is the risk of the account's latest assessment that has a decision (status complete or partial), by created_at and then assessment_id, scored exactly as GET /v1/assessments/{assessment_id} scores that assessment. Its assessments are the account's history (GET /v1/accounts/{account_id}/assessments).
62
+ # Body of the 200 answer to GET /v1/accounts/{account_id}: the one current risk of one of the calling tenant's accounts. It is the risk of the account's latest assessment that has a decision (status complete or partial), by created_at and then assessment_id, scored exactly as GET /v1/assessments/{assessment_id} scores that assessment, plus the account's own reason shared_api_key when a key issued to the account was used from many IP addresses or countries (POST /v1/key_usage/batches). Its assessments are the account's history (GET /v1/accounts/{account_id}/assessments).
63
63
  field(
64
64
  :account,
65
65
  Crystalline::Nilable.new(Models::Shared::Account),
@@ -0,0 +1,53 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Shared
7
+ # The 202 answer of POST /v1/key_usage/batches. A replay with the same Idempotency-Key and body answers the same record and counts nothing again.
8
+ class KeyUsageBatch
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ # Opaque, server-assigned id of the batch: 'kub_' and a 26-character Crockford base32 ULID.
13
+ field :id, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("id"), required: true}}
14
+ # When NoResponse first recorded the batch.
15
+ field(
16
+ :received_at,
17
+ ::String,
18
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("received_at"), required: true}}
19
+ )
20
+ # Events counted.
21
+ field(
22
+ :accepted,
23
+ ::Integer,
24
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("accepted"), required: true}}
25
+ )
26
+ # Events that added nothing: a private, reserved or unreadable ip, or an occurred_at more than 24 hours old or more than 5 minutes ahead.
27
+ field(
28
+ :ignored,
29
+ ::Integer,
30
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("ignored"), required: true}}
31
+ )
32
+
33
+ sig { params(id: ::String, received_at: ::String, accepted: ::Integer, ignored: ::Integer).void }
34
+ def initialize(id:, received_at:, accepted:, ignored:)
35
+ @id = id
36
+ @received_at = received_at
37
+ @accepted = accepted
38
+ @ignored = ignored
39
+ end
40
+
41
+ sig { params(other: T.untyped).returns(T::Boolean) }
42
+ def ==(other)
43
+ return false unless other.is_a?(self.class)
44
+ return false unless @id == other.id
45
+ return false unless @received_at == other.received_at
46
+ return false unless @accepted == other.accepted
47
+ return false unless @ignored == other.ignored
48
+ true
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Shared::KeyUsageBatch
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Shared::KeyUsageBatch
9
+ def id
10
+ end
11
+
12
+ def id=(str_)
13
+ end
14
+
15
+ def received_at
16
+ end
17
+
18
+ def received_at=(str_)
19
+ end
20
+
21
+ def accepted
22
+ end
23
+
24
+ def accepted=(str_)
25
+ end
26
+
27
+ def ignored
28
+ end
29
+
30
+ def ignored=(str_)
31
+ end
32
+ end
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Shared
7
+ # POST /v1/key_usage/batches body: facts about requests made with API keys your signup gate issued to your accounts, one event per request. Each event names the key by the SHA-256 that the assessment's issued_credential.sha256 carried, not the key itself. The SDKs buffer events and send them in the background. A batch holds 1 to 500 events and at most 256 KiB. Idempotency-Key is required and binds the body as on POST /v1/assessments, so a retried batch is counted once.
8
+ class KeyUsageBatchRequest
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ field(
13
+ :events,
14
+ Crystalline::Array.new(Models::Shared::KeyUsageEvent),
15
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("events"), required: true}}
16
+ )
17
+
18
+ sig { params(events: T::Array[Models::Shared::KeyUsageEvent]).void }
19
+ def initialize(events:)
20
+ @events = events
21
+ end
22
+
23
+ sig { params(other: T.untyped).returns(T::Boolean) }
24
+ def ==(other)
25
+ return false unless other.is_a?(self.class)
26
+ return false unless @events == other.events
27
+ true
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,14 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Shared::KeyUsageBatchRequest
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Shared::KeyUsageBatchRequest
9
+ def events
10
+ end
11
+
12
+ def events=(str_)
13
+ end
14
+ end
@@ -0,0 +1,106 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module NoResponse
5
+ module Models
6
+ module Shared
7
+ # One request made with an issued key. An event whose ip is not a public address, or whose occurred_at is more than 24 hours old or more than 5 minutes ahead, is counted in ignored and adds nothing.
8
+ class KeyUsageEvent
9
+ extend T::Sig
10
+ include Crystalline::MetadataFields
11
+
12
+ # SHA-256 of the issued key's UTF-8 bytes, as 64 lower-case hex characters: the value sent as issued_credential.sha256 when the account was assessed. Each SDK's issued-credential helper computes it.
13
+ field(
14
+ :key_sha256,
15
+ ::String,
16
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("key_sha256"), required: true}}
17
+ )
18
+ # The client IP address the request came from, IPv4 or IPv6, as your server saw it. Stored only as a keyed digest and its country.
19
+ field :ip, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("ip"), required: true}}
20
+ # When the request was made.
21
+ field(
22
+ :occurred_at,
23
+ ::String,
24
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("occurred_at"), required: true}}
25
+ )
26
+ # The request's User-Agent header, at most 512 characters. Stored only as a keyed digest.
27
+ field(
28
+ :user_agent,
29
+ Crystalline::Nilable.new(::String),
30
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("user_agent")}}
31
+ )
32
+ # The model or product the request used, such as gpt-4o-mini. Stored only as a keyed digest.
33
+ field(
34
+ :model,
35
+ Crystalline::Nilable.new(::String),
36
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("model")}}
37
+ )
38
+ # Input tokens the request consumed.
39
+ field(
40
+ :input_tokens,
41
+ Crystalline::Nilable.new(::Integer),
42
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("input_tokens")}}
43
+ )
44
+ # Output tokens the request produced.
45
+ field(
46
+ :output_tokens,
47
+ Crystalline::Nilable.new(::Integer),
48
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("output_tokens")}}
49
+ )
50
+ # The share of requests your sampler records, when it records only some: 0.1 means this event stands for 10 requests. Request and token totals are weighted by its inverse. Distinct IP and country counts see only the events sent.
51
+ field(
52
+ :sample_rate,
53
+ Crystalline::Nilable.new(::Float),
54
+ {'format_json': {'letter_case': ::NoResponse::Utils.field_name("sample_rate")}}
55
+ )
56
+
57
+ sig {
58
+ params(
59
+ key_sha256: ::String,
60
+ ip: ::String,
61
+ occurred_at: ::String,
62
+ user_agent: T.nilable(::String),
63
+ model: T.nilable(::String),
64
+ input_tokens: T.nilable(::Integer),
65
+ output_tokens: T.nilable(::Integer),
66
+ sample_rate: T.nilable(::Float)
67
+ )
68
+ .void
69
+ }
70
+ def initialize(
71
+ key_sha256:,
72
+ ip:,
73
+ occurred_at:,
74
+ user_agent: nil,
75
+ model: nil,
76
+ input_tokens: nil,
77
+ output_tokens: nil,
78
+ sample_rate: 1.0
79
+ )
80
+ @key_sha256 = key_sha256
81
+ @ip = ip
82
+ @occurred_at = occurred_at
83
+ @user_agent = user_agent
84
+ @model = model
85
+ @input_tokens = input_tokens
86
+ @output_tokens = output_tokens
87
+ @sample_rate = sample_rate
88
+ end
89
+
90
+ sig { params(other: T.untyped).returns(T::Boolean) }
91
+ def ==(other)
92
+ return false unless other.is_a?(self.class)
93
+ return false unless @key_sha256 == other.key_sha256
94
+ return false unless @ip == other.ip
95
+ return false unless @occurred_at == other.occurred_at
96
+ return false unless @user_agent == other.user_agent
97
+ return false unless @model == other.model
98
+ return false unless @input_tokens == other.input_tokens
99
+ return false unless @output_tokens == other.output_tokens
100
+ return false unless @sample_rate == other.sample_rate
101
+ true
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,56 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ class NoResponse::Models::Shared::KeyUsageEvent
5
+ extend ::Crystalline::MetadataFields::ClassMethods
6
+ end
7
+
8
+ class NoResponse::Models::Shared::KeyUsageEvent
9
+ def key_sha256
10
+ end
11
+
12
+ def key_sha256=(str_)
13
+ end
14
+
15
+ def ip
16
+ end
17
+
18
+ def ip=(str_)
19
+ end
20
+
21
+ def occurred_at
22
+ end
23
+
24
+ def occurred_at=(str_)
25
+ end
26
+
27
+ def user_agent
28
+ end
29
+
30
+ def user_agent=(str_)
31
+ end
32
+
33
+ def model
34
+ end
35
+
36
+ def model=(str_)
37
+ end
38
+
39
+ def input_tokens
40
+ end
41
+
42
+ def input_tokens=(str_)
43
+ end
44
+
45
+ def output_tokens
46
+ end
47
+
48
+ def output_tokens=(str_)
49
+ end
50
+
51
+ def sample_rate
52
+ end
53
+
54
+ def sample_rate=(str_)
55
+ end
56
+ end
@@ -44,6 +44,7 @@ module NoResponse
44
44
  CONTEXT_LINE_COUNTRY_MISMATCH = new("context_line_country_mismatch")
45
45
  PRIOR_ABUSE_LINK = new("prior_abuse_link")
46
46
  TEST_SCENARIO = new("test_scenario")
47
+ SHARED_API_KEY = new("shared_api_key")
47
48
  end
48
49
 
49
50
  open!
@@ -61,6 +61,9 @@ module NoResponse
61
61
  autoload :IpSummaryType, "no_response/models/shared/ipsummarytype.rb"
62
62
  autoload :KeyRotation, "no_response/models/shared/keyrotation.rb"
63
63
  autoload :KeyRotationRequest, "no_response/models/shared/keyrotationrequest.rb"
64
+ autoload :KeyUsageBatch, "no_response/models/shared/keyusagebatch.rb"
65
+ autoload :KeyUsageBatchRequest, "no_response/models/shared/keyusagebatchrequest.rb"
66
+ autoload :KeyUsageEvent, "no_response/models/shared/keyusageevent.rb"
64
67
  autoload :Lane, "no_response/models/shared/lane.rb"
65
68
  autoload :LineType, "no_response/models/shared/linetype.rb"
66
69
  autoload :NotFoundErrorCode, "no_response/models/shared/notfounderrorcode.rb"
@@ -15,7 +15,7 @@ module NoResponse
15
15
  class NoResponseClient
16
16
  extend T::Sig
17
17
 
18
- attr_accessor :assessments, :accounts, :keys, :integrations, :webhook_endpoints
18
+ attr_accessor :assessments, :accounts, :key_usage, :keys, :integrations, :webhook_endpoints
19
19
 
20
20
  # Instantiates the SDK, configuring it with the provided parameters.
21
21
  #
@@ -89,6 +89,7 @@ module NoResponse
89
89
  def init_sdks
90
90
  @assessments = Assessments.new(@sdk_configuration)
91
91
  @accounts = Accounts.new(@sdk_configuration)
92
+ @key_usage = KeyUsage.new(@sdk_configuration)
92
93
  @keys = Keys.new(@sdk_configuration)
93
94
  @integrations = Integrations.new(@sdk_configuration)
94
95
  @webhook_endpoints = WebhookEndpoints.new(@sdk_configuration)
@@ -95,9 +95,9 @@ module NoResponse
95
95
 
96
96
  @language = "ruby"
97
97
  @openapi_doc_version = "1"
98
- @sdk_version = "3.0.1"
98
+ @sdk_version = "3.0.3"
99
99
  @gen_version = "internal"
100
- @user_agent = "noresponse-sdk/ruby 3.0.1 internal 1 noresponse"
100
+ @user_agent = "noresponse-sdk/ruby 3.0.3 internal 1 noresponse"
101
101
  end
102
102
 
103
103
  sig { returns([String, T::Hash[Symbol, String]]) }
data/lib/noresponse.rb CHANGED
@@ -5,6 +5,7 @@ module NoResponse
5
5
  autoload :NoResponseClient, "no_response/noresponseclient"
6
6
  autoload :Assessments, "no_response/assessments"
7
7
  autoload :Accounts, "no_response/accounts"
8
+ autoload :KeyUsage, "no_response/keyusage"
8
9
  autoload :Keys, "no_response/keys"
9
10
  autoload :Integrations, "no_response/integrations"
10
11
  autoload :WebhookEndpoints, "no_response/webhookendpoints"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noresponse
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - NoResponse
@@ -258,6 +258,7 @@ files:
258
258
  - lib/no_response/integrations.rb
259
259
  - lib/no_response/issued_credential.rb
260
260
  - lib/no_response/keys.rb
261
+ - lib/no_response/keyusage.rb
261
262
  - lib/no_response/late_results.rb
262
263
  - lib/no_response/models/callbacks.rb
263
264
  - lib/no_response/models/errors.rb
@@ -326,6 +327,10 @@ files:
326
327
  - lib/no_response/models/operations/recordassessmentoutcome_request.rbi
327
328
  - lib/no_response/models/operations/recordassessmentoutcome_response.rb
328
329
  - lib/no_response/models/operations/recordassessmentoutcome_response.rbi
330
+ - lib/no_response/models/operations/recordkeyusage_request.rb
331
+ - lib/no_response/models/operations/recordkeyusage_request.rbi
332
+ - lib/no_response/models/operations/recordkeyusage_response.rb
333
+ - lib/no_response/models/operations/recordkeyusage_response.rbi
329
334
  - lib/no_response/models/operations/replaywebhookdelivery_request.rb
330
335
  - lib/no_response/models/operations/replaywebhookdelivery_request.rbi
331
336
  - lib/no_response/models/operations/replaywebhookdelivery_response.rb
@@ -467,6 +472,12 @@ files:
467
472
  - lib/no_response/models/shared/keyrotation.rbi
468
473
  - lib/no_response/models/shared/keyrotationrequest.rb
469
474
  - lib/no_response/models/shared/keyrotationrequest.rbi
475
+ - lib/no_response/models/shared/keyusagebatch.rb
476
+ - lib/no_response/models/shared/keyusagebatch.rbi
477
+ - lib/no_response/models/shared/keyusagebatchrequest.rb
478
+ - lib/no_response/models/shared/keyusagebatchrequest.rbi
479
+ - lib/no_response/models/shared/keyusageevent.rb
480
+ - lib/no_response/models/shared/keyusageevent.rbi
470
481
  - lib/no_response/models/shared/lane.rb
471
482
  - lib/no_response/models/shared/lane.rbi
472
483
  - lib/no_response/models/shared/linetype.rb