noresponse 5.1.1 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/no_response/accounts.rb +663 -71
- data/lib/no_response/late_results.rb +10 -8
- data/lib/no_response/models/operations/listaccounts_request.rb +52 -0
- data/lib/no_response/models/operations/listaccounts_request.rbi +26 -0
- data/lib/no_response/models/operations/listaccounts_response.rb +32 -0
- data/lib/no_response/models/operations/listaccounts_response.rbi +20 -0
- data/lib/no_response/models/operations/recordenforcement_request.rb +33 -0
- data/lib/no_response/models/operations/recordenforcement_request.rbi +20 -0
- data/lib/no_response/models/operations/recordenforcement_response.rb +32 -0
- data/lib/no_response/models/operations/recordenforcement_response.rbi +20 -0
- data/lib/no_response/models/operations.rb +4 -0
- data/lib/no_response/models/shared/accountdeleted.rb +49 -0
- data/lib/no_response/models/shared/accountdeleted.rbi +26 -0
- data/lib/no_response/models/shared/accountdeletedevent.rb +70 -0
- data/lib/no_response/models/shared/accountdeletedevent.rbi +38 -0
- data/lib/no_response/models/shared/accountlist.rb +40 -0
- data/lib/no_response/models/shared/accountlist.rbi +20 -0
- data/lib/no_response/models/shared/accountriskchanged.rb +44 -0
- data/lib/no_response/models/shared/accountriskchanged.rbi +20 -0
- data/lib/no_response/models/shared/accountriskchangedevent.rb +70 -0
- data/lib/no_response/models/shared/accountriskchangedevent.rbi +38 -0
- data/lib/no_response/models/shared/assessmentexpired.rb +82 -0
- data/lib/no_response/models/shared/assessmentexpired.rbi +38 -0
- data/lib/no_response/models/shared/assessmentupdateddata.rb +23 -0
- data/lib/no_response/models/shared/assessmentupdateddata.rbi +9 -0
- data/lib/no_response/models/shared/assessmentupdatedevent.rb +79 -0
- data/lib/no_response/models/shared/assessmentupdatedevent.rbi +38 -0
- data/lib/no_response/models/shared/conflicterrorcode.rb +1 -0
- data/lib/no_response/models/shared/endpointverification.rb +41 -0
- data/lib/no_response/models/shared/endpointverification.rbi +20 -0
- data/lib/no_response/models/shared/endpointverificationevent.rb +70 -0
- data/lib/no_response/models/shared/endpointverificationevent.rbi +38 -0
- data/lib/no_response/models/shared/enforcement.rb +156 -0
- data/lib/no_response/models/shared/enforcement.rbi +68 -0
- data/lib/no_response/models/shared/enforcementaction.rb +23 -0
- data/lib/no_response/models/shared/enforcementaction.rbi +9 -0
- data/lib/no_response/models/shared/enforcementprovider.rb +21 -0
- data/lib/no_response/models/shared/enforcementprovider.rbi +9 -0
- data/lib/no_response/models/shared/enforcementrequest.rb +122 -0
- data/lib/no_response/models/shared/enforcementrequest.rbi +50 -0
- data/lib/no_response/models/shared/enforcementstate.rb +22 -0
- data/lib/no_response/models/shared/enforcementstate.rbi +9 -0
- data/lib/no_response/models/shared/enforcementstatus.rb +19 -0
- data/lib/no_response/models/shared/enforcementstatus.rbi +9 -0
- data/lib/no_response/models/shared/environment.rb +16 -0
- data/lib/no_response/models/shared/environment.rbi +9 -0
- data/lib/no_response/models/shared/webhookendpointdisabled.rb +49 -0
- data/lib/no_response/models/shared/webhookendpointdisabled.rbi +26 -0
- data/lib/no_response/models/shared/webhookendpointdisabledevent.rb +70 -0
- data/lib/no_response/models/shared/webhookendpointdisabledevent.rbi +38 -0
- data/lib/no_response/models/shared/webhookevent.rb +23 -0
- data/lib/no_response/models/shared/webhookevent.rbi +9 -0
- data/lib/no_response/models/shared/webhookverificationresponse.rb +33 -0
- data/lib/no_response/models/shared/webhookverificationresponse.rbi +14 -0
- data/lib/no_response/models/shared/workspacedeleted.rb +55 -0
- data/lib/no_response/models/shared/workspacedeleted.rbi +26 -0
- data/lib/no_response/models/shared/workspacedeletedevent.rb +70 -0
- data/lib/no_response/models/shared/workspacedeletedevent.rbi +38 -0
- data/lib/no_response/models/shared.rb +23 -0
- data/lib/no_response/sdk_hooks/registration.rb +0 -1
- data/lib/no_response/sdkconfiguration.rb +2 -2
- data/lib/no_response/webhook_verification.rb +170 -0
- data/lib/noresponse.rb +2 -0
- metadata +56 -2
- data/lib/no_response/webhooks.rb +0 -264
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
# An assessment can be revised after the account creation was allowed: a slow source
|
|
7
7
|
# settles and the account's decision rises. NoResponse sends the new version as a
|
|
8
8
|
# signed assessment.updated webhook. LateResults.handle verifies that delivery
|
|
9
|
-
# with
|
|
9
|
+
# with WebhookVerification.construct_event, picks an action from your policy, and acts
|
|
10
10
|
# through the auth provider's admin API: revoke the user's sessions or ban the
|
|
11
11
|
# user.
|
|
12
12
|
#
|
|
@@ -20,7 +20,6 @@ require 'erb'
|
|
|
20
20
|
require 'json'
|
|
21
21
|
require 'net/http'
|
|
22
22
|
require 'uri'
|
|
23
|
-
require_relative 'webhooks'
|
|
24
23
|
|
|
25
24
|
module NoResponse
|
|
26
25
|
module LateResults
|
|
@@ -53,13 +52,14 @@ module NoResponse
|
|
|
53
52
|
end
|
|
54
53
|
end
|
|
55
54
|
|
|
56
|
-
# event is the verified
|
|
55
|
+
# event is the verified event from WebhookVerification.construct_event,
|
|
56
|
+
# such as a Models::Shared::AssessmentUpdatedEvent. action is the action that ran:
|
|
57
57
|
# NONE when the policy, the event or the user id called for nothing. It can
|
|
58
58
|
# be stronger than the policy's action when the provider had to fall back:
|
|
59
59
|
# the auth0 provider reports BAN when it blocked the user because the
|
|
60
60
|
# tenant's plan cannot end sessions. user_id is
|
|
61
61
|
# the provider user id acted on, set only when an action was taken. Answer
|
|
62
|
-
# an endpoint.verification with
|
|
62
|
+
# an endpoint.verification with { 'challenge' => event.data.challenge }.
|
|
63
63
|
Result = Struct.new(:event, :action, :user_id, keyword_init: true)
|
|
64
64
|
|
|
65
65
|
class << self
|
|
@@ -70,7 +70,8 @@ module NoResponse
|
|
|
70
70
|
# strings or symbols) to NONE, REVOKE_SESSIONS or BAN; a decision you
|
|
71
71
|
# leave out does nothing. An unknown action raises ArgumentError.
|
|
72
72
|
def action_for(event, policy = DEFAULT_POLICY)
|
|
73
|
-
|
|
73
|
+
# Only an assessment.updated event can be a test event.
|
|
74
|
+
return NONE if event.type == 'assessment.updated' && event.test == true
|
|
74
75
|
|
|
75
76
|
data = event.data
|
|
76
77
|
if event.type == 'account.risk_changed'
|
|
@@ -79,6 +80,7 @@ module NoResponse
|
|
|
79
80
|
decision = data.account.decisions_by_flow.login.to_s
|
|
80
81
|
return NONE if data.previous_decisions_by_flow&.login.to_s == decision
|
|
81
82
|
elsif event.type == 'assessment.updated'
|
|
83
|
+
return NONE if data.is_a?(Models::Shared::AssessmentExpired)
|
|
82
84
|
return NONE if data.status == Models::Shared::Status::PENDING || data.account.nil?
|
|
83
85
|
decision = data.account.risk.decision.to_s
|
|
84
86
|
else
|
|
@@ -101,8 +103,8 @@ module NoResponse
|
|
|
101
103
|
# Verify a webhook delivery and apply your policy to it.
|
|
102
104
|
#
|
|
103
105
|
# payload, headers and secrets, plus tolerance_seconds and now, are
|
|
104
|
-
# exactly what
|
|
105
|
-
# verification raises
|
|
106
|
+
# exactly what WebhookVerification.construct_event takes; a delivery that fails
|
|
107
|
+
# verification raises WebhookVerification::VerificationError before any provider
|
|
106
108
|
# call. Deduplicate on result.event.id and ignore versions older than one
|
|
107
109
|
# you have acted on.
|
|
108
110
|
#
|
|
@@ -111,7 +113,7 @@ module NoResponse
|
|
|
111
113
|
# account_id; it defaults to the account_id itself, as when you assess
|
|
112
114
|
# with the provider's user id. Return nil or "" to take no action.
|
|
113
115
|
def handle(payload, headers, secrets, provider, policy: DEFAULT_POLICY, user_id: nil, **verify)
|
|
114
|
-
event =
|
|
116
|
+
event = WebhookVerification.construct_event(payload, headers, secrets, **verify)
|
|
115
117
|
action = action_for(event, policy)
|
|
116
118
|
return Result.new(event: event, action: NONE) if action == NONE
|
|
117
119
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Operations
|
|
7
|
+
|
|
8
|
+
class ListAccountsRequest
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# next_cursor from an earlier page, unchanged. Absent, the list starts from the oldest change.
|
|
13
|
+
field(
|
|
14
|
+
:changed_since,
|
|
15
|
+
Crystalline::Nilable.new(::String),
|
|
16
|
+
{'query_param': {'field_name': "changed_since", 'style': "form", 'explode': true}}
|
|
17
|
+
)
|
|
18
|
+
# Most accounts per page.
|
|
19
|
+
field(
|
|
20
|
+
:limit,
|
|
21
|
+
Crystalline::Nilable.new(::Integer),
|
|
22
|
+
{'query_param': {'field_name': "limit", 'style': "form", 'explode': true}}
|
|
23
|
+
)
|
|
24
|
+
# true lists only accounts with a decision other than allow for some flow and no applied enforcement at their current risk_version.
|
|
25
|
+
field(
|
|
26
|
+
:unenforced,
|
|
27
|
+
Crystalline::Nilable.new(Crystalline::Boolean.new),
|
|
28
|
+
{'query_param': {'field_name': "unenforced", 'style': "form", 'explode': true}}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
sig {
|
|
32
|
+
params(changed_since: T.nilable(::String), limit: T.nilable(::Integer), unenforced: T.nilable(T::Boolean))
|
|
33
|
+
.void
|
|
34
|
+
}
|
|
35
|
+
def initialize(changed_since: nil, limit: 50, unenforced: false)
|
|
36
|
+
@changed_since = changed_since
|
|
37
|
+
@limit = limit
|
|
38
|
+
@unenforced = unenforced
|
|
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 @changed_since == other.changed_since
|
|
45
|
+
return false unless @limit == other.limit
|
|
46
|
+
return false unless @unenforced == other.unenforced
|
|
47
|
+
true
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Operations::ListAccountsRequest
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::ListAccountsRequest
|
|
9
|
+
def changed_since
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def changed_since=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def limit
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def limit=(str_)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def unenforced
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def unenforced=(str_)
|
|
25
|
+
end
|
|
26
|
+
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 ListAccountsResponse
|
|
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::AccountList, {}
|
|
15
|
+
|
|
16
|
+
sig { params(headers: T::Hash[Symbol, T::Array[::String]], result: Models::Shared::AccountList).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::ListAccountsResponse
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::ListAccountsResponse
|
|
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
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Operations
|
|
7
|
+
|
|
8
|
+
class RecordEnforcementRequest
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# The account_id the workspace sends with its assessments, as one path segment (percent-encode '|' and ':' if the client requires it). A value that does not match the account_id shape answers 400 invalid_request.
|
|
13
|
+
field :account_id, ::String, {'path_param': {'field_name': "account_id", 'style': "simple", 'explode': false}}
|
|
14
|
+
|
|
15
|
+
field :body, Models::Shared::EnforcementRequest, {'request': {'media_type': "application/json"}}
|
|
16
|
+
|
|
17
|
+
sig { params(account_id: ::String, body: Models::Shared::EnforcementRequest).void }
|
|
18
|
+
def initialize(account_id:, body:)
|
|
19
|
+
@account_id = account_id
|
|
20
|
+
@body = body
|
|
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 @account_id == other.account_id
|
|
27
|
+
return false unless @body == other.body
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Operations::RecordEnforcementRequest
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::RecordEnforcementRequest
|
|
9
|
+
def account_id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def account_id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def body
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def body=(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 RecordEnforcementResponse
|
|
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::Enforcement, {}
|
|
15
|
+
|
|
16
|
+
sig { params(headers: T::Hash[Symbol, T::Array[::String]], result: Models::Shared::Enforcement).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::RecordEnforcementResponse
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Operations::RecordEnforcementResponse
|
|
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
|
|
@@ -22,6 +22,8 @@ module NoResponse
|
|
|
22
22
|
autoload :GetAssessmentResponse, "no_response/models/operations/getassessment_response.rb"
|
|
23
23
|
autoload :ListAccountAssessmentsRequest, "no_response/models/operations/listaccountassessments_request.rb"
|
|
24
24
|
autoload :ListAccountAssessmentsResponse, "no_response/models/operations/listaccountassessments_response.rb"
|
|
25
|
+
autoload :ListAccountsRequest, "no_response/models/operations/listaccounts_request.rb"
|
|
26
|
+
autoload :ListAccountsResponse, "no_response/models/operations/listaccounts_response.rb"
|
|
25
27
|
autoload :ListIntegrationsResponse, "no_response/models/operations/listintegrations_response.rb"
|
|
26
28
|
autoload :ListWebhookDeliveriesRequest, "no_response/models/operations/listwebhookdeliveries_request.rb"
|
|
27
29
|
autoload :ListWebhookDeliveriesResponse, "no_response/models/operations/listwebhookdeliveries_response.rb"
|
|
@@ -29,6 +31,8 @@ module NoResponse
|
|
|
29
31
|
autoload :QueryAccountAssessmentsResponse, "no_response/models/operations/queryaccountassessments_response.rb"
|
|
30
32
|
autoload :RecordAssessmentOutcomeRequest, "no_response/models/operations/recordassessmentoutcome_request.rb"
|
|
31
33
|
autoload :RecordAssessmentOutcomeResponse, "no_response/models/operations/recordassessmentoutcome_response.rb"
|
|
34
|
+
autoload :RecordEnforcementRequest, "no_response/models/operations/recordenforcement_request.rb"
|
|
35
|
+
autoload :RecordEnforcementResponse, "no_response/models/operations/recordenforcement_response.rb"
|
|
32
36
|
autoload :RecordKeyUsageRequest, "no_response/models/operations/recordkeyusage_request.rb"
|
|
33
37
|
autoload :RecordKeyUsageResponse, "no_response/models/operations/recordkeyusage_response.rb"
|
|
34
38
|
autoload :ReplayWebhookDeliveryRequest, "no_response/models/operations/replaywebhookdelivery_request.rb"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# Terminal for the account's assessments created at or before deleted_at in the receiving endpoint's environment: delete what you hold from them and ignore later-arriving updates of them. deleted_at is no earlier than the creation of any assessment it erased. An assessment created after it belongs to the account assessed again: keep it, even when this event arrives after it.
|
|
8
|
+
class AccountDeleted
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# Your own opaque identifier for the account being checked, scoped to your workspace. Use an id you mint, with no direct identifier (email, phone, name or national id) in it. '|' is accepted so an Auth0 user id such as 'auth0|64abc' passes unchanged; '@', '+', '$' and whitespace are refused by the pattern, as is an exact-shape JWT; a hex digest such as a SHA-256 is allowed, because hashing an internal id is a common pseudonymous scheme. A value such as '07700900123' or 'jane.doe.gmail.com' cannot be told apart from an opaque id. It travels in bodies, and in a URL only as the path segment of GET /v1/accounts/{account_id} and its /assessments. An assessment requested by a provider hook at pre_registration, which has no account yet, carries the server-issued account_id pre: followed by its assessment_id.
|
|
13
|
+
field(
|
|
14
|
+
:account_id,
|
|
15
|
+
::String,
|
|
16
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("account_id"), required: true}}
|
|
17
|
+
)
|
|
18
|
+
# How many assessments the erasure deleted.
|
|
19
|
+
field(
|
|
20
|
+
:assessments_deleted,
|
|
21
|
+
::Integer,
|
|
22
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("assessments_deleted"), required: true}}
|
|
23
|
+
)
|
|
24
|
+
# When the erasure took effect, equal to deleted_at in the DELETE answer.
|
|
25
|
+
field(
|
|
26
|
+
:deleted_at,
|
|
27
|
+
::String,
|
|
28
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("deleted_at"), required: true}}
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
sig { params(account_id: ::String, assessments_deleted: ::Integer, deleted_at: ::String).void }
|
|
32
|
+
def initialize(account_id:, assessments_deleted:, deleted_at:)
|
|
33
|
+
@account_id = account_id
|
|
34
|
+
@assessments_deleted = assessments_deleted
|
|
35
|
+
@deleted_at = deleted_at
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
39
|
+
def ==(other)
|
|
40
|
+
return false unless other.is_a?(self.class)
|
|
41
|
+
return false unless @account_id == other.account_id
|
|
42
|
+
return false unless @assessments_deleted == other.assessments_deleted
|
|
43
|
+
return false unless @deleted_at == other.deleted_at
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AccountDeleted
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AccountDeleted
|
|
9
|
+
def account_id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def account_id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def assessments_deleted
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def assessments_deleted=(str_)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def deleted_at
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def deleted_at=(str_)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# The account.deleted event.
|
|
8
|
+
class AccountDeletedEvent
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# The event id, equal to the NR-Webhook-Id header and across redeliveries and every endpoint the event fans out to.
|
|
13
|
+
field :id, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("id"), required: true}}
|
|
14
|
+
# When the event was created. Equal across redeliveries; the signing timestamp header is per delivery.
|
|
15
|
+
field(
|
|
16
|
+
:created_at,
|
|
17
|
+
::String,
|
|
18
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("created_at"), required: true}}
|
|
19
|
+
)
|
|
20
|
+
# Terminal for the account's assessments created at or before deleted_at in the receiving endpoint's environment: delete what you hold from them and ignore later-arriving updates of them. deleted_at is no earlier than the creation of any assessment it erased. An assessment created after it belongs to the account assessed again: keep it, even when this event arrives after it.
|
|
21
|
+
field(
|
|
22
|
+
:data,
|
|
23
|
+
Models::Shared::AccountDeleted,
|
|
24
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("data"), required: true}}
|
|
25
|
+
)
|
|
26
|
+
# Always account.deleted.
|
|
27
|
+
field :type, ::String, {'format_json': {'letter_case': ::NoResponse::Utils.field_name("type"), required: true}}
|
|
28
|
+
# Present, and true, only on an event sent by POST /v1/webhooks/{endpoint_id}/test: its data is a fixed example assessment, not one of the workspace's, so a receiver acknowledges it and applies nothing. Real events have no test member.
|
|
29
|
+
field(
|
|
30
|
+
:test,
|
|
31
|
+
Crystalline::Nilable.new(Crystalline::Boolean.new),
|
|
32
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("test")}}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
sig {
|
|
36
|
+
params(
|
|
37
|
+
id: ::String,
|
|
38
|
+
created_at: ::String,
|
|
39
|
+
data: Models::Shared::AccountDeleted,
|
|
40
|
+
type: ::String,
|
|
41
|
+
test: T.nilable(T::Boolean)
|
|
42
|
+
)
|
|
43
|
+
.void
|
|
44
|
+
}
|
|
45
|
+
def initialize(id:, created_at:, data:, type: "account.deleted", test: nil)
|
|
46
|
+
@id = id
|
|
47
|
+
@created_at = created_at
|
|
48
|
+
@data = data
|
|
49
|
+
unless type == "account.deleted"
|
|
50
|
+
raise ArgumentError, "Invalid value for type"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
@type = "account.deleted"
|
|
54
|
+
@test = test
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
58
|
+
def ==(other)
|
|
59
|
+
return false unless other.is_a?(self.class)
|
|
60
|
+
return false unless @id == other.id
|
|
61
|
+
return false unless @created_at == other.created_at
|
|
62
|
+
return false unless @data == other.data
|
|
63
|
+
return false unless @type == other.type
|
|
64
|
+
return false unless @test == other.test
|
|
65
|
+
true
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AccountDeletedEvent
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AccountDeletedEvent
|
|
9
|
+
def id
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def id=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def created_at
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def created_at=(str_)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def data
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def data=(str_)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def type
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def type=(str_)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def test
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test=(str_)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# Body of the 200 answer to GET /v1/accounts: the calling workspace's accounts whose risk changed after changed_since, in the environment of the calling key, oldest change first. An account is listed when its risk_version advanced and it has a current risk, and each item is the account exactly as GET /v1/accounts/{account_id} answers it. An account appears once per page, at its latest change; when its risk changes again later, it appears again on a later page with the newer risk_version. next_cursor is always present: pass it back as changed_since to read the changes made after this page.
|
|
8
|
+
class AccountList
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
field(
|
|
13
|
+
:items,
|
|
14
|
+
Crystalline::Array.new(Models::Shared::Account),
|
|
15
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("items"), required: true}}
|
|
16
|
+
)
|
|
17
|
+
# Opaque cursor after the last change this page read, bound to the workspace and the environment of the calling key. Pass it back unchanged as changed_since. It is present on every page, the last one included: when nothing changed after changed_since it is the cursor that was sent, so a poller keeps calling with the latest next_cursor. A tampered or foreign cursor answers 400 invalid_cursor. Consumers do not parse it.
|
|
18
|
+
field(
|
|
19
|
+
:next_cursor,
|
|
20
|
+
::String,
|
|
21
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("next_cursor"), required: true}}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
sig { params(items: T::Array[Models::Shared::Account], next_cursor: ::String).void }
|
|
25
|
+
def initialize(items:, next_cursor:)
|
|
26
|
+
@items = items
|
|
27
|
+
@next_cursor = next_cursor
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
31
|
+
def ==(other)
|
|
32
|
+
return false unless other.is_a?(self.class)
|
|
33
|
+
return false unless @items == other.items
|
|
34
|
+
return false unless @next_cursor == other.next_cursor
|
|
35
|
+
true
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AccountList
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AccountList
|
|
9
|
+
def items
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def items=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def next_cursor
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def next_cursor=(str_)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module NoResponse
|
|
5
|
+
module Models
|
|
6
|
+
module Shared
|
|
7
|
+
# The account's decision for at least one flow changed. account is the account as GET /v1/accounts/{account_id} answers it for the revision that made the change: its new score, decision, reasons and decisions_by_flow, and the assessment the risk comes from. previous_decisions_by_flow are the decisions it replaced, so account.decisions_by_flow differs from them for at least one flow. On the account's first decision, previous_decisions_by_flow is allow for every flow. Events of one account are not ordered: account.risk_version orders them, so keep the account with the highest risk_version and ignore an event whose account is older than the one held.
|
|
8
|
+
class AccountRiskChanged
|
|
9
|
+
extend T::Sig
|
|
10
|
+
include Crystalline::MetadataFields
|
|
11
|
+
|
|
12
|
+
# Body of the 200 answer to GET /v1/accounts/{account_id}: the one current risk of one of the calling workspace'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).
|
|
13
|
+
field(
|
|
14
|
+
:account,
|
|
15
|
+
Models::Shared::Account,
|
|
16
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("account"), required: true}}
|
|
17
|
+
)
|
|
18
|
+
# The decision for each flow: the account's score under that flow's thresholds. A flow the workspace has not set uses its account_creation thresholds, so the flows differ only where it set them.
|
|
19
|
+
field(
|
|
20
|
+
:previous_decisions_by_flow,
|
|
21
|
+
Models::Shared::AccountDecisionsByFlow,
|
|
22
|
+
{'format_json': {'letter_case': ::NoResponse::Utils.field_name("previous_decisions_by_flow"), required: true}}
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
sig {
|
|
26
|
+
params(account: Models::Shared::Account, previous_decisions_by_flow: Models::Shared::AccountDecisionsByFlow)
|
|
27
|
+
.void
|
|
28
|
+
}
|
|
29
|
+
def initialize(account:, previous_decisions_by_flow:)
|
|
30
|
+
@account = account
|
|
31
|
+
@previous_decisions_by_flow = previous_decisions_by_flow
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
sig { params(other: T.untyped).returns(T::Boolean) }
|
|
35
|
+
def ==(other)
|
|
36
|
+
return false unless other.is_a?(self.class)
|
|
37
|
+
return false unless @account == other.account
|
|
38
|
+
return false unless @previous_decisions_by_flow == other.previous_decisions_by_flow
|
|
39
|
+
true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
class NoResponse::Models::Shared::AccountRiskChanged
|
|
5
|
+
extend ::Crystalline::MetadataFields::ClassMethods
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class NoResponse::Models::Shared::AccountRiskChanged
|
|
9
|
+
def account
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def account=(str_)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def previous_decisions_by_flow
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def previous_decisions_by_flow=(str_)
|
|
19
|
+
end
|
|
20
|
+
end
|